Find if a certificate is self signed or CA signed - java

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.

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

Edit: there are two better answers on this question today:
https://stackoverflow.com/a/57927684/377270
https://stackoverflow.com/a/14515875/377270
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.

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."

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
"

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.

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.

Related

Java: How to check whether a certificate is self-signed

Looking for a direct way how to check whether a certificate is self-signed (not self-issued).
The certificate don't have the Authority and Subject Key Identifiers.
From this answer (https://security.stackexchange.com/questions/93162/how-to-know-if-certificate-is-self-signed), it is possible to check it via openssl command:
openssl verify -CAfile /cert/to/check.pem /cert/to/check.pem
I need to check it in the simplest way possible, probably with java.security package. Is this even possible?

How to generate Java PKCS12 store to connect to regular SSL website?

we run a standard web API over https with a regular purchased SSL certificate. Our clients just access it via https, the certificate is trusted via default system RootCA.
A new client is using a Java communication server that requires the certificate in a PKCS12 keystore. How can we generate the PKS12 keystore from our key/csr/crt/pem files?
I did some research, most examples are requiring a private key. Of course I do not want to share our private key with the client.
Can a PKCS12 keystore be created without private key, similar to standard RootCA in browsers?
Thanks, bluepuma
YES-ish.
Although PFX-now-PKCS12 was designed primarily to store or transfer a privatekey and cert and chain cert(s) as a clump, and most commonly is used for that, it is capable of storing one or more 'lone' cert(s) not matched to any privatekey. And you are correct the client wanting to connect to you should have in their truststore ideally the root cert for your server cert's chain, or alternatively your server cert itself, but decidedly not your privatekey.
openssl can actually create such a PKCS12:
openssl pkcs12 -export -in certfile.pem [-name $name] -nokeys -out blah.p12
# if you don't specify -name it defaults to 1 (the digit one) which can be mildly confusing
# instead of being prompted for the password you can use -passout with several forms
# described on the openssl man page, but consider the warning below
But the result won't work in Java if they use the standard (Sun/Oracle/OpenJDK) cryptoproviders, which (in 8+) support lone cert(s) in a PKCS12 as 'trustedCert' entries in Java only if the(each) certbag has a special Sun-defined attribute which the Java providers write when they create such a file, but OpenSSL doesn't.
Instead use Java's keytool in 8:
jre8/bin/keytool -importcert -keystore blah.p12 -storetype pkcs12 -file $certfile [-alias $name]
or in 9+ where pkcs12 is now the default:
jre9+/bin/keytool -importcert -keystore blah.p12 -file $certfile [-alias $name]
If you don't specify the alias it defaults to mykey. In both cases you can add -storepass $pw to avoid being prompted for it, but as a result the password will be visible on your screen, in the command history of your shell or other command processor it is has one, and in most cases to other processes run on your system concurrently, (any of) which may be a security issue or not. You can also add -noprompt to avoid the confirmation prompt.
But user207421 is (roughly) correct that using such a truststore can break other SSL/TLS connection(s) made from their system, at least from the same JVM, unless the individual calls specify individual, separate truststores, and if they had coded that they would know how to handle (and ask for) a simpler certificate format, such as PEM.

How to generate keystore only with C/O/OU/CN by JAVA keytool

I'm using java keytool to generate keystore for server.
It contains
1.CN
2.OU
3.O
4.L
5.ST
6.C
But customize CA only has
1.CN
2.OU
3.O
4.C
How to generate keystore only with C/O/OU/CN by JAVA keytool?
It's not clear to me what you mean by 'customize CA'.
If you are talking about the selfsigned cert created automatically by -genkeypair, which doesn't actually involve any CA although it does have a name in Subject and Issuer, the latter of which would normally be a CA name:
if using prompting answer the applicable questions and enter nothing (just CR) for the others
if using -dname specify the desired attributes and don't specify the others
If you mean requesting a cert from a CA, you can control what goes in the request (CSR) with -dname, but the CA can ignore that; only the CA controls what goes in the cert, and since you haven't said anything about who the CA is, it's impossible to even attempt to answer.

Corporate Java Webstart Distribution: use site-wide accepted certificate to sign a code-signing certificate

We are at a big organization with a several applications that are developed for internal and external use. One of those application is distributed as Java Webstart application and after a lot of trial and error we now have proper signing and packaging in place.
The only problem: we use a self-signed certificate. Users see a warning about an unknown/unverified vendor and this is just not nice.
Fortunately, the IT department of the organization has one certificate that is accepted on all workstations (via a site-wide policy, I assume). If we use this accepted certificate to sign the JARs and create the Webstart archive, everything should be fine. Naturally, the IT department does not want to distribute the accepted certificate to all developers or put it on the build server, because this would be against the purpose and introduce a lot of vulnerabilities.
What would be the right way to generate a code-signing certificate signed by this accepted certificate?
My assumption, based on what I know from normal openssl procedures to generate certificates used in web servers:
Generate a CSR with
Send CSR to IT security
IT generates a certificate from the CSR with accepted certificate. This certificate should have a short validity (1 week / 1 month / 1 quarter ?)
Import into java keytool for signing
Make sure keytool is only available to authorized users
Would this work? Are there any objections in terms of security or organizational obstacles?
If the above is correct, I would need some pointers especially with item 3. I found a somewhat related question: How do you sign Certificate Signing Request with your Certification Authority?.
Any help is appreciated.
If the corporation has its own CA root cert, which yes had to be pushed to every client/relier by some means such as GPO or installing all systems (or maybe their JREs?) from a customized image, then your approach is almost correct:
generate keypair and CSR
send CSR to corporate CA, they send you back cert
combine cert with keypair in keystore and use keystore
You can do all steps but the last with OpenSSL, but it's extra work:
1: openssl req -newkey or openssl genpkey|genrsa|etc then openssl req -new
3: openssl pkcs12 -export plus keytool -importkeystore -srcstoretype pkcs12
Since you want to end up with a Java keystore it's easier to just use Java throughout:
1: keytool -genkeypair then keytool -certreq
3: keytool -importcert
keytool is a program available on every machine that has any JRE installed; you can't effectively restrict it. It is the keystore file containing your keypair (and specifically your privatekey) that must be protected. Use a strong password; set file/dir permissions/ACL; keep a secure backup; all the usual.
On the other hand, if the corporation has a code-signing cert (and key) which is trusted because the cert was obtained from (issued by) a well-known CA like Verisign, they almost certainly cannot issue you a subordinate certificate. Only a CA cert (with its key) can issue subordinate certs, and while technically it is possible for a trusted CA to issue your corporation a CA cert, if you then issue any bad certs it reflects on them and can put them out of business (see DigiNotar) and they don't want that.

Verify certificate against Java certificate store via CLI

How can I verify an X509 (or DER-formatted) certificate against the Java certificate store via the command line?
I've looked into using the keytool utility, but it looks like it only handles import/export/display functionality (no verification).
EDIT: It looks as though keytool can be used for verification, but only if an import is attempted. I suppose a better way of asking this questions is whether or not a more passive approach (as in: not modifying the keystore) is available. Thanks!
You can use keytool to export the needed certificates (those that are in the chain for the one you need to verify) from the Java keystore into X.509 files. Then, concatenate them together into one file. Finally, use openssl to do the verification.
openssl verify -CAfile concatenated-certs.crt cert-to-verify.crt
Not a perfect solution since it involves popping the certs out of the truststore, but it ought to work given what you are starting with.
This page could be oversimplifying:
http://java.sun.com/docs/books/tutorial/security/toolfilex/rstep1.html
But it doesn't look like even import with keytool does a true verification of a certificate. I'm not seeing any description of verifying the signature of the incoming certificate against the signature of another trusted certificate.
jarsigner will verify a signature on a signed jar, but doesn't do anything to verify the signature on the certificate used to sign the jar.
I'm afraid you'd either have to write a tool to do the verfication, or look for a commercial tool that does it. I would think that some of the PKI tool kits would have a certificate verification tool that would do this.

Categories