I want to read issuer String from user's public key with Bouncy Castle. Is there example code or something from which I can learn?
If you can obtain the certificate object, then you can do the following:
((X509Certificate) certificate).getIssuerX500Principal().getName();
The public key itself does not have an issuer - only a certificate has. And you can get the public key from the certificate, but not vice-versa.
Update: Since it appears that you want to verify the validity of your users, the public key alone does not provide this info. Public keys are used for encryption / digital signature verification, but for the rest of PKI you need the certificate. Actually, verifying the issuer that is written in the certificate gives you no guarantee whatsoever. You need to check:
the certificate revocation lists - i.e. whether the certificate is not revoked. This is done either via the provided CRLs or via the ocsp protocol.
the expiration of the certificate
The public key object doesn't say who generated it. It just contains what you need to encrypt (or verify) with the public key.
If you got the public key from a certificate (java.security.cert.X509Certificate), then you can get the certificate issuer from that by using getIssuerX500Principal().
The certificate is a binding of an identity to a public key. As part of that, the certificate indicates who it was issued by. So you can verify whether you trust that issuer and, therefore, the binding.
Also, the key pair very likely wasn't generated by the certificate issuer. The subject just proved to the issuer that it did possess the associated private key.
Related
I've been asked to create a jks keystore based on a certificate we had created. I've read a bit on the topic, but I'm still confused on a few items:
Is the private key of a certificate supposed to be stored in a .jks keystone?
If yes - where does this get entered in? Using the keytool, it doesn't require one for creating a jks file.
If no - what is the purpose of a jks file? Why would my application need it instead of just reading in a certificate directly? And why does the keytool require a password to create a jks if it just contains a public key?
The purpose of a key store is to protect the privacy and integrity of cryptographic keys using password-based algorithms. Privacy means that the keys are kept secret; they can only be used by someone who knows the password; this is useful for private keys and secret keys. Integrity means that alteration of the keys can be detected by someone who knows the password; this is useful for public keys and secret keys.
Whether you should include the private key or not depends on what you are trying to do. If you are creating a key store for your server so that it can authenticate itself to clients, for example, then it should contain the private key. If you created a self-signed certificate, and want to give clients a key store so that they can authenticate your service, then it should not contain the private key.
If you have a pre-existing key pair, and want to import it to a JKS format key store, the easiest way might be to use OpenSSL to create a PKCS #12 format key store, then use keytool to convert that to a JKS key store. Normally, keytool expects to do key pair generation itself, and so the private key will be stored there from the beginning.
You should verify the integrity of a public key or a certificate before you use it to encrypt a message or verify a signature. Otherwise, an attacker can replace the key with one he owns and act as a man in the middle. If you simply read a public key from a file, you don't know it really belongs to your intended recipient. But if you store a password-based message authentication code with the public key, you can ensure that it hasn't been tampered with.
Is the private key of a certificate supposed to be stored in a .jks keystone?
Yes, if you own the certificate and it is stored there.
If yes - where does this get entered in? Using the keytool, it doesn't require one for creating a jks file.
That's because you can also use it as a truststore, which only contains trusted certificates.
To get the private key in there you will need to first convert it and its certificate to a PKCS#12 file using openssl, as answered in numerous questions here such as this.
If no - what is the purpose of a jks file? Why would my application need it instead of just reading in a certificate directly?
Because your application also needs the private key of the certificate.
And why does the keytool require a password to create a jks if it just contains a public key?
A keystore has a password because it is a security-related entity.
I'm required to create a program that validate any given X509 Certificate Version3 if it is trusted or not by verifying the signature. In order to to do that, I need to be able to know the issuer's public key who has signed that given certificate. I know how to output the issuer information using getIssuerDN() method but what I don't know is how to get the issuer's public key when I only know its name !
The only solution I have so far is to maintain a list of public keys for the most common Certificate Authorities on the web, and just search through it. Although this solution is doable, it seems impractical to me.
Therefore, is there another idea to get the Issuer's public key from a certificate directly and then complete the process of verification ?
Here is my code for getting the Issuer's name but NOT its public key.
URL url = new URL("https link here!");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.connect();
Certificate cert[] = con.getServerCertificates();
X509Certificate x509cert = (X509Certificate) cert[0];
String[] st= x509cert.getIssuerDN().toString().split(",");
System.out.println("Issuer CN is: "+st[0].toString());
I'm required to create a program that validate any given X509 Certificate Version3 if it is trusted or not by verifying the signature. In order to to do that, I need to be able to know the issuer's public key who has signed that given certificate.
No. Either you or whoever gave you the assignment doesn't understand PKI. The idea is that you already trust some issuers by virtue of already having their certificates, e.g. in the cacerts file distributed with the JRE, and therefore their public keys. If the certificate you're asked to verify is traceable to one of these issuers and it passes all other verifications, you can trust it. Mere verification via the public key alone is not sufficient.
I would like to know if there is a way ( in JAVA ) to compare the CA issued certificate for a corresponding CSR against the CSR itself. To be more precise; DN comparison or the comparing the Public Key?
I doubt if the public key entity of the CSR could be compared with that of the Certificate's public Key. Is that possible?
You could use the CA issued certificate to validate the digital signature in the CSR. Every CSR is signed by the private key corresponding to the public key in the CSR. If you can use the public key from the certificate to validate the signature, you can ensure they are related.
You could also compare the public key in the CSR with the public key in the certificate. I would avoid DN comparison, as some CA software allows the registration authority to modify the DN prior to issuing the certificate. So, you could conceivably end up with a cert that has a DN that differs from the one in the CSR, even though they are directly related.
I am working on a java based licensing project. I have a digital certificate file and the data for which the signature was generated. Is there some API or means to get the public key from these information? Basically Public Key from the data and digital certificate information.
If you digital signature is of format PKCS#7 - not detached, then there is a possibility that the sender would have included the certificate as a part of the digital signature.
You will be required to parse the signature to get the certificate.
The Bouncy Castle API has a SignedData class which has a method for getting certificate(s).
Your question is very vague IMHO.
I have a digital certificate file and
the data for which the signature was
generated
If the certificate file has the public key used to verify the signature then you can load it using standard java apis (assuming X509 Certificates).
FileInputStream fin = new FileInputStream("PathToCertificate");
CertificateFactory f = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)f.generateCertificate(fin);
PublicKey pk = certificate.getPublicKey();
Once you have the public key you can use it to verify the signature.
Is this what you want?
The certificate must bear a reference to the id of the key used to certify your data. From this key, should be able to contact the corresponding certificate authority and obtain the public key by providing its id. It may be available from a public repository too.
The id of the certificate authority should also appear on this certificate.
There are APIs available for sure, but the question is, which framework are you using for digital signatures? Do you have its name? Do you know the certificate type?
through the bouncycastle wiki page I was able to understand how to create a X.509 root certificate and a certification request, but I do not quite understand how to proceed concept- and programming wise after that.
Lets assume party A does a cert request and gets his client certificate from the CA. How can some party B validate A's certificate? What kind of certificate does A need? A root certificate? A 'normal' client certificate?
And how does the validation work on programming level, if we assume that A has successfully send his certificate in DER or PEM format to B?
Any help is much appreciated.
Best Regards,
Rob
From a programmer's perspective, you need a few things to validate an X.509 certificate.
A set of "trust anchors"—the root certificates of CAs that you rely on. These should be protected from tampering, so that an attacker doesn't replace a CA certificate with his own fake. The public keys in these certificates are used to verify the digital signatures on other certificates.
A collection of Intermediate certificates. The application might keep a collection of these, but most protocols, like SSL and S/MIME, that use certificates have a standard way to provide extra certificates. Storing these doesn't require any special care; their integrity is protected by the signature of a root CA.
Revocation information. Even if a certificate was issued by a CA, it might have been revoked prematurely because the private key was disclosed, or the end entity changed their identity. (For example, a person switches jobs and a certificate with their old company's name in it is revoked.) CRLs or a web-service like OCSP can be used to get an update about the status of a certificate.
With these inputs available, you can use the built-in PKIX support to construct and validate a certificate path.
/* Givens. */
InputStream trustStoreInput = ...
char[] password = ...
List<X509Certificate> chain = ...
Collection<X509CRL> crls = ...
/* Construct a valid path. */
KeyStore anchors = KeyStore.getInstance(KeyStore.getDefaultType());
anchors.load(trustStoreInput, password);
X509CertSelector target = new X509CertSelector();
target.setCertificate(chain.get(0));
PKIXBuilderParameters params = new PKIXBuilderParameters(anchors, target);
CertStoreParameters intermediates = new CollectionCertStoreParameters(chain)
params.addCertStore(CertStore.getInstance("Collection", intermediates));
CertStoreParameters revoked = new CollectionCertStoreParameters(crls);
params.addCertStore(CertStore.getInstance("Collection", revoked));
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
/*
* If build() returns successfully, the certificate is valid. More details
* about the valid path can be obtained through the PKIXBuilderResult.
* If no valid path can be found, a CertPathBuilderException is thrown.
*/
PKIXBuilderResult r = (PKIXBuilderResult) builder.build(params);
An important thing to note is that if a path cannot be found, you don't get much information about the reason. This can be frustrating, but it is that way by design. In general, there are many potential paths. If they all fail for different reasons, how would the path builder decide what to report as the reason?
Ok, the idea behind CAs is as follows:
CAs are people everyone trusts. To this end, a selection of Trusted CAs is available in your browser/email client/even on my mobile. In your case, your public root key (certificate) should be in your application.
Users send requests to the CA for a certificate in PEM format with the public key. CAs do some (I leave this ambiguous deliberately) form of verification of the end user, such as charging them money or in the case of enhanced verification (green) certs, background checks.
If the CA doesn't think the user's request is valid, they communicate this somehow.
If they do, they sign the public key and produce a certificate containing this information. This is where you process the cert-req and turn it into an X.509 cert.
Other users come across our fictitious user and want to know if they can trust them. So, they take a look at the certificate and find it is digitally signed by someone they have in their trust list. So, the fact that they trust the root CA and only the root CA could sign (via their private key) this user's public key and the CA trusts the user, we deduce that the new user can trust mr fictitious.
On a programmatic level, you implement this by reading the X.509 certificate and working out who the CA is supposed to be. Given that CA's fingerprint, you find it in your database and verify the signature. If it matches, you have your chain of trust.
This works because, as I've said, only the CA can create the digital signature but anyone can verify it. It is exactly the reverse of the encryption concept. What you do is "encrypt with the private key" the data you wish to sign and verify that the "decrypt with the public key" equals the data you've got.