How to create certificate pfx file in java? - java

I need to create certificate pfx file with password in java. I search in google and can create certificate "cer" file in http://www.java2s.com/Tutorial/Java/0490__Security/CreatingaSelfSignedVersion3Certificate.htm
I add code in main
FileOutputStream fos = null;
fos = new FileOutputStream("public.cer");
fos.write(cert.getEncoded());
fos.close();
this only work without password.

Normally a .pfx or pkcs12 its a keystore to save a public, private key pairs. Besides if you use a RSA key pair with public certificate as in your link sample, normally this certificate must be issued by a certificate authority, anyway I suppose that you're making an attempt to save a selfsigned certificate, to do so you have to use java.security.KeyStore class not a FileOutputStream directly, I give you a sample:
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
....
X509Certificate cert = // your certificate...
// generate a keystore instance
KeyStore ks = KeyStore.getInstance("PKCS12");
// save your cert inside the keystore
ks.setCertificateEntry("YourCertAlias", cert);
// create the outputstream to store the keystore
FileOutputStream fos = new FileOutputStream("/your_path/keystore.pfx");
// store the keystore protected with password
ks.store(fos, "yourPassword".toCharArray());
....
As I said normally in the keystore you store the key pairs, normally using: setKeyEntry(String alias, byte[] key, Certificate[] chain) or setKeyEntry(String alias, Key key, char[] password, Certificate[] chain) however with the code above you can store a certificate in keystore protecting it with a password. For more info take a look at: java keystore api.
Hope this helps,

Related

How do you convert PKCS#12 String to Certificate and PrivateKey?

I am receiving the following String from a certificate stored in Azure Key Vault. I am using the Secret API in order to retrieve both the certificate and the private key related to this cert.
Initially the certificate was uploaded using a .pfx file to Azure Key vault. Now I need to create a Certificate and a PrivateKey to allow client authentication to a 3rd party system and I am using the given String retrieved from the API, however I am note sure how to get around that in Java.
I took some hints from this link in C# however I am pretty certain that this method doesn't work like that in Java. In particular an X509Certificate or a Certificate in general doesn't hold any information about the PrivateKey in Java, unlike C#, and I am not sure how to extract that information from given String in Java.
This works as expected to retrieve the certificate from the String retrieved from the API
String secret = azureSecret.getValue();
byte[] certkey = Base64.getDecoder().decode(secret);
ByteArrayInputStream inputStream = new ByteArrayInputStream(certkey);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(inputStream);
The azureSecret.getValue() format is like the following however I am not sure how to get PrivateKey out of the given String
MIIKvgIBaaZd6Euf3EYwYdHrIIKYzCC...
YES, Java X509Certificate and Certificate is only the certificate. Instead use KeyStore which can contain multiple entries each of which is either a 'trusted' certificate (for someone else), or a privatekey plus certificate plus other chain cert(s) (if applicable) for yourself, or (not relevant here) a 'secret' (symmetric) key. PKCS12 is supported as one type of KeyStore along with others not relevant here, so after the base64-decoding you already have do something like:
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(inputstreamfromvaultvalue, password);
// then
PrivateKey pkey = (PrivateKey) ks.getKey(alias, password);
// and
Certificate cert = ks.getCertificate(alias); // if you only need the leaf cert
// or
Certificate[] chain = ks.getCertificateChain(alias); // usually
But if you want to do client authentication in TLS/SSL (including HTTPS), you give the JSSE KeyManager the whole keystore object not the individual pieces (privatekey and certificates). Similarly to verify the peer in TLS/SSL, you give TrustManager a keystore containing trusted certificates, usually root CAs and often defaulted to a built-in set of public root CAs.

Insert Public Key into a KeyStore programatically

I want to generate a key pair and insert the public and private keys into different keystores, to be used as KeyStore and TrustStore in an SSL Socket connection. I generate the KeyPair using a KeyPairGenerator, and I already have generated a signing certificate for the chain using java's keytool. Then I can insert the private key into a KeyStore like this:
PublicKey publicKey;
PrivateKey privateKey;
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, "storepass".toCharArray());
keyStore.setKeyEntry("privatekey", privateKey, "keypass".toCharArray(), chain);
Using this keystore I can create a KeyManager for the SSL connection. But to create a TrustManager, I need the public key stored into a KeyStore as well, so I tried storing the public key in a key store:
PublicKey publicKey;
KeyStore trustStore = KeyStore.getInstance("JKS");
keyStore.load(null, "storepass".toCharArray());
trustStore.setKeyEntry("publickey", publicKey, "public".toCharArray(), chain);
This returns an error: java.security.KeyStoreException: Cannot store non-PrivateKeys
So I tried using setCertificateEntry(), but this doesn't work since it's a PublicKey object and I need a Certificate. So my question is, how can I store the PublicKey in a KeyStore programatically? Using keytool is not an option.

Rename JKS alias with java programmatically

I would like to know how can I rename an alias of a keystore, programmatically in java, not using keytool.
I have my java.security.KeyStore object, containing an certain alias. How can I rename it?
The KeyStore API does not provide a rename operation for aliases. But what you can do is:
Save the content (key pair, certificates) of the keystore entry that you want to rename.
Delete the entry.
Create a new entry with the saved content and the new alias.
As Java code:
Key privateKey = keyStore.getKey(alias, password.toCharArray());
Certificate[] certs = keyStore.getCertificateChain(alias);
keyStore.setKeyEntry(newAlias, privateKey, password.toCharArray(), certs);
keyStore.deleteEntry(alias);
Of course this does not work if the private key is stored on a hardware device (smartcard or HSM) and therefore is not readable.
If the keystore entry contains a trusted certificate, the code looks a bit different:
Certificate cert = keyStore.getCertificate(alias);
keyStore.setCertificateEntry(newAlias, cert);
keyStore.deleteEntry(alias);

Storing an X.509 certificate into a keystore using java code

I have an X.509 certificate created using bouncycastle library. How can I store it into a java Keystore?
I tried this code
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
// get user password and file input stream
char[] password = getPassword();
java.io.FileInputStream fis =
new java.io.FileInputStream("keyStoreName");
ks.load(fis, password);
fis.close();
I found this code here, but the key store created using this way does not work with keytool, it tells me the keystore is corrupted.
Use KeyStore.setCertificateEntry(alias, cert) and give it an alias name of your choice. Then, use KeyStore.store(...) to save the keystore (typically using a FileOutputStream).

loading a certificate from keystore

Load a certificate and keys from keystore which is password protected and then use it for cert verification and digital signing
To read the certificate is really trivial.
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate) factory.generateCertificate(new FileInputStream("file.pem"));
This is with standard APIs (in try/catch) etc and you have loaded your certificate.
Now the toString method of certificate is not suitable for you since it just captures the "user's" view of the certificate e.g. you would use it for println for instance
Can't you send the certificate object itself?
Not sure what your server expects so you can look into the various methods of certificate
X509Certificate
I use this code
PEMReader pr=new PEMReader(new StringReader(trust_certs));
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
Object o;
int i=0;
while((o=pr.readObject())!=null){
if(o instanceof X509Certificate){
i++;
X509Certificate c=(X509Certificate)o;
trustStore.setCertificateEntry(Integer.toString(i), c);
}
}
http://www.bouncycastle.org/docs/docs1.6/org/bouncycastle/openssl/PEMReader.html
A pem file is read as any other text file. Read the Java tutorial about IO (and concentrate on character streams, since a pem file contains text, and on File IO, since this is what you want to do)

Categories