Different types of keystore in Java -- PKCS12

来源:互联网 发布:乌鲁木齐seo免费诊断 编辑:程序博客网 时间:2024/05/18 03:05

PKCS12 is an active file format for storing cryptography objects as a single file. It can be used to store secret key, private key and certificate.It is a standardized format published by RSA Laboratories which means it can be used not only in Java but also in other libraries in C, C++ or C# etc. This file format is frequently used to import and export entries from or to other keystore types.

Next we will explain the operations which can be performed on PKCS12 keystore.

Create PKCS12 keystore

Before storing an entry into a PKCS12 keystore, the keystore has to be loaded first. This means we have to have a keystore created first. The simplest way of creating a PKCS12 keystore is :

1
2
3
4
5
6
7
8
try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(null,null);
     
    keyStore.store(newFileOutputStream("output.p12"),"password".toCharArray());
}catch(Exception ex){
    ex.printStackTrace();
}

Note, when calling keyStore.load(null, null), two nulls are passed as the input keystore stream and password. This is because we don't have the keystore available yet. After running this program, there should be a keystore file named output.p12 in current working directory.

Store secret key

PKCS12 allows to store secret keys on a limited base. Secret keys are frequently used to encrypt/decrypt data. To transfer the keys conveniently, they can be stored in a keystore like PKCS12 and transferred.

1
2
3
4
5
6
7
8
9
10
11
12
13
try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(null,null);
     
    KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    keyGen.init(128);
    Key key = keyGen.generateKey();
    keyStore.setKeyEntry("secret", key, "password".toCharArray(),null);
     
    keyStore.store(newFileOutputStream("output.p12"),"password".toCharArray());
}catch(Exception ex){
    ex.printStackTrace();
}

Some secret keys with algorithm AES stored on PKCS12 keystore cannot be extracted in Java. Since PKCS12 is a portable standard, other libraries may support extracting secret keys.

Store private key

The private key and its associated certificate chain can be stored in PKCS12 keystore. The keystore contains private keys and certificates can be used in SSL communications across the web.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
//  keyStore.load(new FileInputStream("output.p12"),"password".toCharArray());
    keyStore.load(null,null);;
     
    CertAndKeyGen gen = newCertAndKeyGen("RSA","SHA1WithRSA");
    gen.generate(1024);
      
    Key key=gen.getPrivateKey();
    X509Certificate cert=gen.getSelfCertificate(newX500Name("CN=ROOT"), (long)365*24*3600);
      
    X509Certificate[] chain = newX509Certificate[1];
    chain[0]=cert;
      
    keyStore.setKeyEntry("private", key, "password".toCharArray(), chain);
      
    keyStore.store(newFileOutputStream("output.p12"),"password".toCharArray());
}catch(Exception ex){
    ex.printStackTrace();
}

A RSA private key is generated with the CertAndKeyGen and the associated certificate is also generated. Then the key entry is stored in the keyStore by calling keyStore.setEntry(). Don't forget to save the keyStore by calling keyStore.store(), otherwise the entry will be lost when the program exits.

Store certificate

PKCS12 keystore also allows to store certificate by itself without the corresponding private key stored. To store the certificate, the KeyStore.setCertificateEntry() can be called.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
//  keyStore.load(new FileInputStream("output.p12"),"password".toCharArray());
    keyStore.load(null,null);;
     
    CertAndKeyGen gen = newCertAndKeyGen("RSA","SHA1WithRSA");
    gen.generate(1024);
      
    X509Certificate cert=gen.getSelfCertificate(newX500Name("CN=ROOT"), (long)365*24*3600);
      
    keyStore.setCertificateEntry("cert", cert);
      
    keyStore.store(newFileOutputStream("output.p12"),"password".toCharArray());
}catch(Exception ex){
    ex.printStackTrace();
}

The stored certificate can be extracted by calling KeyStore.getCertificate() with the supplied alias. For example :

1
Certificate cert = keyStore.getCertificate("cert");

Load private key

One difference between PKCS12 keystore and other keystores such as JKS is that PKCS12's private key can be extracted without NullPointerException. The private key can be correctly extracted with the correct password provided.

1
2
3
4
5
6
7
8
9
try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(newFileInputStream("output.p12"),"password".toCharArray());
     
    Key pvtKey = keyStore.getKey("private","password".toCharArray());
    System.out.println(pvtKey.toString());
}catch(Exception ex){
    ex.printStackTrace();
}

The output of the above code is:

1
sun.security.rsa.RSAPrivateCrtKeyImpl@ffff2466

Load certificate chain

If a certificate chain is stored in a keystore, it can be loaded by calling KeyStore.getCertificateChain(). Below code is used to extract the associated certificate chain for the associated private key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(newFileInputStream("output.p12"),"password".toCharArray());
     
    Key pvtKey = keyStore.getKey("private","password".toCharArray());
    System.out.println(pvtKey.toString());
     
    java.security.cert.Certificate[] chain =  keyStore.getCertificateChain("private");
    for(java.security.cert.Certificate cert:chain){
        System.out.println(cert.toString());
    }
}catch(Exception ex){
    ex.printStackTrace();
}

The output is :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
[
  Version: V3
  Subject: CN=ROOT
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
 
  Key:  Sun RSA public key, 1024 bits
  modulus: 107262652552256813768678166856978781385254195794582600239703451044252881438814396239031781495369251659734172714120481593881055888193254336293673302267462500060447786562885955334870856482264000504019061160524587434562257067298291769329550807938162702640388267016365640782567817416484577163775446236245223552189
  public exponent: 65537
  Validity: [From: Mon Jan 05 13:03:29 SGT 2015,
               To: Tue Jan 05 13:03:29 SGT 2016]
  Issuer: CN=ROOT
  SerialNumber: [    5e5ca8a4]
 
]
  Algorithm: [SHA1withRSA]
  Signature:
0000: 22 21 BF 73 A6 6D 12 9B   F7 49 6C 0E B3 50 6A 9D  "!.s.m...Il..Pj.
0010: FA 30 43 22 32 FF 54 95   80 2E B3 8B 6F 59 D4 B5  .0C"2.T.....oY..
0020: 6C A6 AE 89 B7 18 9A A8   35 7D 65 37 BF ED A3 F4  l.......5.e7....
0030: E7 DB 5D 5F 9B DA 4B FA   39 04 9B 4D DB C2 3E FA  ..]_..K.9..M..>.
0040: 3B C2 63 F8 1E BE 03 F3   BD 1C D4 8A 8E 3C 51 68  ;.c..........

To understand how to create certificate chain in Java, please refer to Generate certificate in Java -- Certificate chain.

Load certificate

Loading certificate is simple as well by calling KeyStore.getCertificate(), if the alias supplied is mapping to a certificate chain, only the leaf certificate will be returned.

1
2
3
4
5
6
7
8
9
10
try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(newFileInputStream("output.p12"),"password".toCharArray());
     
    java.security.cert.Certificate cert =  keyStore.getCertificate("private");
    
    System.out.println(cert);
}catch(Exception ex){
    ex.printStackTrace();
}

The output looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
[
  Version: V3
  Subject: CN=ROOT
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
 
  Key:  Sun RSA public key, 1024 bits
  modulus: 107262652552256813768678166856978781385254195794582600239703451044252881438814396239031781495369251659734172714120481593881055888193254336293673302267462500060447786562885955334870856482264000504019061160524587434562257067298291769329550807938162702640388267016365640782567817416484577163775446236245223552189
  public exponent: 65537
  Validity: [From: Mon Jan 05 13:03:29 SGT 2015,
               To: Tue Jan 05 13:03:29 SGT 2016]
  Issuer: CN=ROOT
  SerialNumber: [    5e5ca8a4]
 
]
  Algorithm: [SHA1withRSA]
  Signature:
0000: 22 21 BF 73 A6 6D 12 9B   F7 49 6C 0E B3 50 6A 9D  "!.s.m...Il..Pj.
0010: FA 30 43 22 32 FF 54 95   80 2E B3 8B 6F 59 D4 B5  .0C"2.T.....oY..
0020: 6C A6 AE 89 B7 18 9A A8   35 7D 65 37 BF ED A3 F4  l.......5.e7....
0030: E7 DB 5D 5F 9B DA 4B FA   39 04 9B 4D DB C2 3E FA  ..]_..K.9..M..>.
0040: 3B C2 63 F8 1E BE 03 F3   BD 1C D4 8A 8E 3C 51 68  ;.c..........

Import and export keys and certificates

The PKCS12 keystore can be used to import and export keys and certificates. Since private keys can be extracted from PKCS12 keystores, so the entries can be exported from PKCS12 keystore and then be imported to other keystore types such as JKS.

Below code snippet demonstrate export a private key entry from PKCS12 and import it to JSK keystore:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(newFileInputStream("output.p12"),"password".toCharArray());
     
    Key pvtKey = keyStore.getKey("private","password".toCharArray());
    java.security.cert.Certificate[] chain =  keyStore.getCertificateChain("private");
     
    KeyStore jksStore = KeyStore.getInstance("JKS");
    jksStore.load(null,null);;
    jksStore.setKeyEntry("jksPrivate", pvtKey, "newpassword".toCharArray(), chain);
    jksStore.store(newFileOutputStream("output.jks"),"password".toCharArray());
}catch(Exception ex){
    ex.printStackTrace();
}

PKCS12 keystore is the recommended keystore type if you want to have a portable keystore type and you may want to use it with other non-Java libraries in the future.

For more information on other keystores, please refer to Different types of keystore in Java -- Overview

0 0
原创粉丝点击