Showing posts with label pkcs8. Show all posts
Showing posts with label pkcs8. Show all posts

Friday, 21 October 2016

Create and read PKCS #8 format private key in java program.

In this short article I will show you how to store private key in pkcs8 format in java and again read back the stored key in java.

PKCS #8 defines a standard syntax for storing private key information. There are 2 ways we can store private key in pkcs8 format.

1) unencrypted key
2) encrypted key

I will create both types of keys in java and store them in file. After that I will read them from file and create privatekey java object from stored file. We are using bouncy castle API for this program.

1) Create pkcs8 key

Code to create pkcs8 :
 import org.bouncycastle.openssl.PKCS8Generator;  
 import org.bouncycastle.openssl.jcajce.JcaPEMWriter;  
 import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;  
 import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder;  
 import org.bouncycastle.operator.OperatorCreationException;  
 import org.bouncycastle.operator.OutputEncryptor;  
 import org.bouncycastle.util.io.pem.PemObject;  
   
 import java.io.FileOutputStream;  
 import java.io.IOException;  
 import java.io.StringWriter;  
 import java.security.KeyPair;  
 import java.security.KeyPairGenerator;  
 import java.security.NoSuchAlgorithmException;  
 import java.security.SecureRandom;  
 import java.security.spec.InvalidKeySpecException;  
   
 public class App3 {  
   public static void main(String[] args) throws NoSuchAlgorithmException, IOException, OperatorCreationException, InvalidKeySpecException {  
   
     KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");  
     kpGen.initialize(2048, new SecureRandom());  
     KeyPair keyPair = kpGen.generateKeyPair();  
   
   
     //unencrypted form of PKCS#8 file  
     JcaPKCS8Generator gen1 = new JcaPKCS8Generator(keyPair.getPrivate(), null);  
     PemObject obj1 = gen1.generate();  
     StringWriter sw1 = new StringWriter();  
     try (JcaPEMWriter pw = new JcaPEMWriter(sw1)) {  
       pw.writeObject(obj1);  
     }  
     String pkcs8Key1 = sw1.toString();  
     FileOutputStream fos1 = new FileOutputStream("D:\\privatekey-unencrypted.pkcs8");  
     fos1.write(pkcs8Key1.getBytes());  
     fos1.flush();  
     fos1.close();  
   
     //encrypted form of PKCS#8 file  
     JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.PBE_SHA1_RC2_128);  
     encryptorBuilder.setRandom(new SecureRandom());  
     encryptorBuilder.setPasssword("abcde".toCharArray()); // password  
     OutputEncryptor encryptor = encryptorBuilder.build();  
   
     JcaPKCS8Generator gen2 = new JcaPKCS8Generator(keyPair.getPrivate(), encryptor);  
     PemObject obj2 = gen2.generate();  
     StringWriter sw2 = new StringWriter();  
     try (JcaPEMWriter pw = new JcaPEMWriter(sw2)) {  
       pw.writeObject(obj2);  
     }  
     String pkcs8Key2 = sw2.toString();  
     FileOutputStream fos2 = new FileOutputStream("D:\\privatekey-encrypted.pkcs8");  
     fos2.write(pkcs8Key2.getBytes());  
     fos2.flush();  
     fos2.close();  
   }  
 }  
   

 
So you can see that for unencrypted key we do not provide any encryptor object which contains information about algorithm, password etc. While creating encrypted key we do provide that details.

As an outcome of this program we will have below 2 files in our file system:






Lets open them in notepad and check the difference.

encrypted key file:























unencrypted key file:























You can see the difference in start and end tag of both the files.

2) Read pkcs8 key

Code to read pkcs8:
 import org.bouncycastle.util.encoders.Base64;  
 import javax.crypto.EncryptedPrivateKeyInfo;  
 import javax.crypto.SecretKeyFactory;  
 import javax.crypto.spec.PBEKeySpec;  
 import java.io.IOException;  
 import java.nio.file.Files;  
 import java.nio.file.Paths;  
 import java.security.InvalidKeyException;  
 import java.security.KeyFactory;  
 import java.security.NoSuchAlgorithmException;  
 import java.security.PrivateKey;  
 import java.security.spec.InvalidKeySpecException;  
 import java.security.spec.PKCS8EncodedKeySpec;  
   
 public class App4 {  
   
   public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {  
   
     String encrypted = new String(Files.readAllBytes(Paths.get("D:\\privatekey-encrypted.pkcs8")));  
     String unencrypted = new String(Files.readAllBytes(Paths.get("D:\\privatekey-unencrypted.pkcs8")));  
   
     //Create object from unencrypted private key  
     unencrypted = unencrypted.replace("-----BEGIN PRIVATE KEY-----", "");  
     unencrypted = unencrypted.replace("-----END PRIVATE KEY-----", "");  
     byte[] encoded = Base64.decode(unencrypted);  
     PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(encoded);  
     KeyFactory kf = KeyFactory.getInstance("RSA");  
     PrivateKey unencryptedPrivateKey = kf.generatePrivate(kspec);  
   
     //Create object from encrypted private key  
     encrypted = encrypted.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");  
     encrypted = encrypted.replace("-----END ENCRYPTED PRIVATE KEY-----", "");  
     EncryptedPrivateKeyInfo pkInfo = new EncryptedPrivateKeyInfo(Base64.decode(encrypted));  
     PBEKeySpec keySpec = new PBEKeySpec("abcde".toCharArray()); // password  
     SecretKeyFactory pbeKeyFactory = SecretKeyFactory.getInstance(pkInfo.getAlgName());  
     PKCS8EncodedKeySpec encodedKeySpec = pkInfo.getKeySpec(pbeKeyFactory.generateSecret(keySpec));  
     KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
     PrivateKey encryptedPrivateKey = keyFactory.generatePrivate(encodedKeySpec);  
   
     //comparing both private key for equality  
     System.out.println(unencryptedPrivateKey.equals(encryptedPrivateKey));  
   }  
 }  
   


output:








So here you can after generating back the private key object from file we have compared them for equality and they returned true because they have been created from same private key and stored in file.

That's it for now...

Please post your comments and doubts!!!









Sunday, 16 October 2016

Create PKCS#7/P7B Format in java program.

In this short article I will show you how to create pkcs7 format file to store certificate or chain of certificate.

A pkcs7 format  has a file extention of .p7b or .p7c. It can only contains certificates and chain certificates, not the private key.

I will use 3 certificates I have created in previous article and store them in pkcs7 format.

Code:
 import sun.security.pkcs.ContentInfo;  
 import sun.security.pkcs.PKCS7;  
 import sun.security.pkcs.SignerInfo;  
 import sun.security.x509.AlgorithmId;  
 import sun.security.x509.X509CertImpl;  
 import java.io.FileInputStream;  
 import java.io.FileOutputStream;  
 import java.io.IOException;  
 import java.security.cert.CertificateException;  
 import java.security.cert.X509Certificate;  
   
 public class App2 {  
   
   public static void main(String[] args) throws IOException, CertificateException {  
     //loading certificates stored as file  
     FileInputStream rootCAFile = new FileInputStream("D:\\rootCA.cer");  
     FileInputStream intermedCAFile = new FileInputStream("D:\\intermedCA.cer");  
     FileInputStream endUserCertFile = new FileInputStream("D:\\endUserCert.cer");  
   
     //create certificate objects from fileinputstream  
     X509Certificate rootCA = new X509CertImpl(rootCAFile);  
     X509Certificate intermedCA = new X509CertImpl(intermedCAFile);  
     X509Certificate endUserCert = new X509CertImpl(endUserCertFile);  
   
     //create the certificate hierarchy array  
     X509Certificate[] chain = new X509Certificate[3];  
     chain[0] = endUserCert;  
     chain[1] = intermedCA;  
     chain[2] = rootCA;  
   
     //create pkcs7 object with the cert chain created  
     PKCS7 pkcs7 = new PKCS7(new AlgorithmId[0], new ContentInfo(ContentInfo.DATA_OID, null),  
         chain, new SignerInfo[0]);  
   
     // store it as .p7b or .p7c format file  
     FileOutputStream fos = new FileOutputStream("D:\\bundle.p7b");  
     pkcs7.encodeSignedData(fos);  
     fos.close();  
   }  
 }  
   


As an outcome you will have below file in your file system.



Lets open the file and check out the content.



So you can see that it has packaged all the certificates we have provided in the cert chain.

That's it for now...
Stay tuned for my next article related to pkcs8 format....

Please post your comments and doubts!!!