25

I have a web app, which allows user to upload pkcs12. I store the pkcs12 as binary in database. Is there any way for me to know if the certificate in the pkcs12 is self signed or CA signed?

I am running a Java web app on tomcat and have openssl at my disposal.

Nishan
  • 2,821
  • 4
  • 27
  • 36
  • Check my [answer](http://security.stackexchange.com/a/144514/132597) on security stackexchange. – reddot Dec 06 '16 at 13:08

6 Answers6

26

Following email thread precisely tells the right way to verify if the base64 encoded certificate (i.e. PEM) is self signed or not: http://marc.info/?l=openssl-users&m=116177485311662&w=4

Following is the code snippet:

openssl verify -CAfile self_signed_cert.pem self_signed_cert.pem

should return:

self_signed_cert.pem: OK

OR compare the issuer and subject. If they are same, it is self signed

openssl x509 -in cert.pem -inform PEM -noout -subject -issuer
Robert Siemer
  • 32,405
  • 11
  • 84
  • 94
NitinB
  • 261
  • 3
  • 3
  • 1
    but openssl verify -CAfile other_ca.pem self_signed_cert.pem also returns OK, see https://stackoverflow.com/questions/65904954/verify-x509-certificate-with-openssl-to-be-valid-and-signed-by-trusted-cas – Galdor Jan 26 '21 at 16:12
15

Edit: there are two better answers on this question today:

However, I think there's something more important to address -- why would one want to know about self-signed certificates. What's the goal? What problem is being solved? Probably trying to split certificates into two piles, self-signed and not-self-signed, is the wrong approach for most situations. The better approach is almost certainly going to be verifying that any given certificate has a valid signature chain from a trusted certificate authority, and that any connections associated with a given certificate matches the certificate.

Here's the rest of my original answer. It's probably not what you want.


It's a bit hacky, but the openssl x509 command can report both the issuer and the subject. If the subject and issuer are the same, it is self-signed; if they are different, then it was signed by a CA. (Strictly speaking, a great many self-signed certificates are also signed by a CA -- themselves.)

While testing this theory, I ran a handful of tests; it runs something like:

cd /etc/ssl/certs
for f in *.0 ; do openssl x509 -in $f -issuer | head -1 > /tmp/$f.issuer ; openssl x509 -in $f -subject | head -1 > /tmp/$f.subject ; done
 cd /tmp
 sed -i -e s/issuer=// *.issuer
 sed -i -e s/subject=// *.subject
 cd /etc/ssl/certs/
 for f in *.0 ; do diff -u /tmp/$f.issuer /tmp/$f.subject ; done

Hope this helps.

sarnold
  • 102,305
  • 22
  • 181
  • 238
  • 1
    You can improve this by just doing `openssl x509 -in $f -issuer -subject`, and removing the `head` and second `openssl` commands. – glyphobet Jan 08 '13 at 15:23
  • You said "if they are different, then it was signed by a CA". I think it's important to notice that it doesn't actually. Usually, a certificate is signed by more than one certificate in chain. Ex:Your main certificate is signed by the second one than is itself signed by another certificate and so on. It is important to check all certificates in the chain to ensure the first certificate validation. Else it is a great Technic. thanks! – muchwow Nov 13 '13 at 02:28
  • @jumojer, that's a good point -- this is by no means a _verifier_, this is only a way to tell self-signed apart from CA-signed. – sarnold Nov 13 '13 at 18:23
  • 1
    "-noout" would be a little cleaner than "| head -1" – rsaxvc May 18 '16 at 03:47
  • 1
    What if someone created a certificate with the "issuer" field set to some known CA and then signed it by his own private key? This doesn't seem like a correct bullet-proof way to recognize self-signed certs. You should check whether the signature comes from the same key that is in the certificate itself. – Youda008 Oct 18 '19 at 12:27
  • @Youda008, thanks for the comment; [mattjm's answer](https://stackoverflow.com/a/57927684/377270) appears to be a better solution. – sarnold Oct 18 '19 at 19:28
  • @jumojer: yes there are usually multiple CA certs forming a chain (and you check all of them to validate) -- some of them are _intermediate_ or _subordinate_ CAs and the last/top one is a _root_ CA but they are all CAs, and your end-entity aka leaf cert is issued&signed by an intermediate CA and is thus CA-issued/signed. – dave_thompson_085 Oct 18 '19 at 20:11
  • 1
    "why would one want to know about self-signed certificates". In a big shop you will want to scan known devices to keep up to date of the amount, type of, health and expiry of certificates. If you have a policy to not have self signed certificates in the shop, but you know, it happens, you might want to flag these specifically. – sastorsl Jun 04 '20 at 07:55
7

The accepted answer here isn't strictly correct. Old question, but this is the first result in google for "how to tell if a certificate is self signed" so it needs to be cleared up.

A cert is almost always self-signed if the issuer and subject match, but it's not guaranteed. A certificate can be "self-issued" where it has the same issuer/subject but is signed by a private key that isn't paired with the public key in the cert.

The first part of the answer above from NitinB is the right way to check for a self-signed cert:

openssl verify -CAfile self_signed_cert.pem self_signed_cert.pem

"All self-signed certs are self-issued, but not all self-issued certs are self-signed."

Citation: https://www.rfc-editor.org/rfc/rfc5280

"Self-issued certificates are CA certificates in which the issuer and subject are the same entity. Self-issued certificates are generated to support changes in policy or operations. Self- signed certificates are self-issued certificates where the digital signature may be verified by the public key bound into the certificate."

Community
  • 1
  • 1
mattjm
  • 71
  • 1
  • 2
1

Have you tried the BouncyCastle lib?

http://www.bouncycastle.org/wiki/display/JA1/Frequently+Asked+Questions

" There are specific example programs for dealing with Attribute Certificates, PKCS12, SMIME and OpenPGP. They can be found in the packages:

org.bouncycastle.jce.examples org.bouncycastle.mail.smime.examples org.bouncycastle.openpgp.examples Another useful source of examples is the test packages:

org.bouncycastle.crypto.test org.bouncycastle.jce.provider.test org.bouncycastle.cms.test org.bouncycastle.mail.smime.test org.bouncycastle.openpgp.test org.bouncycastle.cert.test org.bouncycastle.pkcs.test org.bouncycastle.tsp.test "

0

Java is unable to analyze PKCS12 so that you have to convert it to keystore using openssl.

Here the keystore has both private key and X509 certificate(or you can choose only to store certificate). Then get the issuer from keystore using standard JAVA API and manually verify issuer.

frogcdcn
  • 391
  • 1
  • 4
  • 14
  • 1
    This is wrong. Java has handled PKCS12 keystores (at least including privatekey) since at least j6 in 2006, although _commandline keytool_ does so _by default_ only since 8u60 which was in 2015 slightly after this answer. `openssl` can convert pkcs12 only to separate PEM objects for CERTIFICATE(s) and PRIVATE KEY, but Java can't use either of those as a keystore -- although it can import ONLY the former _into_ a keystore and use that. – dave_thompson_085 Oct 18 '19 at 20:20
0

Details could be found in https://www.openssl.org/docs/man3.0/man3/X509_verify.html

X509_self_signed() checks whether certificate cert is self-signed. For success the issuer and subject names must match, the components of the authority key identifier (if present) must match the subject key identifier etc. The signature itself is actually verified only if verify_signature is 1, as for explicitly trusted certificates this verification is not worth the effort.

Prateek
  • 11