Java密钥库的不同类型 -- PKCS12

原文:https://www.pixelstech.net/article/1420427307-Different-types-of-keystore-in-Java----PKCS12

转载:https://www.cnblogs.com/yangchongxing/p/13837017.html

Different types of keystore in Java -- PKCS12

Java密钥库的不同类型 -- PKCS12

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

JKCS12是一种活动文件格式,用于将加密对象存储为单个文件。它可以用来存储密钥、私钥和证书。它是RSA实验室发布的标准格式,它不仅可以用于java,而且可以用于C、C++或C等的其他库。这种文件格式经常用于从和向其他密钥存储类型导入和导出条目。

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

接下来我们将解释可以在PKCS12密钥库上执行的操作。

Create PKCS12 keystore

创建PKCS12密钥库

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 :

在将条目存储到PKCS12密钥库之前,必须先加载密钥库。这意味着我们必须首先创建一个密钥库。创建PKCS12密钥库的最简单方法是:

try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(null, null);
     
    keyStore.store(new FileOutputStream("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.

注意,当调用keyStore.load(null, null),传递两个null作为输入密钥库流和密码。这是因为我们还没有密钥库。运行此程序后,当前工作目录中应该有一个名为output.p12的密钥库文件。

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.

PKCS12允许在有限的基础上存储密钥。密钥经常用于加密/解密数据。为了方便地传输密钥,可以将它们存储在PKCS12这样的密钥库中并进行传输。

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(new FileOutputStream("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.

在Java中无法提取PKCS12密钥库中存储的具有AES算法的密钥。由于PKCS12是一个可移植的标准,其他库可能支持提取密钥。

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.

私钥及其关联的证书链可以存储在PKCS12密钥库中。密钥库包含私钥,证书可用于跨web的SSL通信。

try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
//  keyStore.load(new FileInputStream("output.p12"),"password".toCharArray());
    keyStore.load(null, null);;
     
    CertAndKeyGen gen = new CertAndKeyGen("RSA","SHA1WithRSA");
    gen.generate(1024);
      
    Key key=gen.getPrivateKey();
    X509Certificate cert=gen.getSelfCertificate(new X500Name("CN=ROOT"), (long)365*24*3600);
      
    X509Certificate[] chain = new X509Certificate[1];
    chain[0]=cert;
      
    keyStore.setKeyEntry("private", key, "password".toCharArray(), chain);
      
    keyStore.store(new FileOutputStream("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.

使用CertAndKeyGen生成RSA私钥,并生成相关证书。然后调用keyStore.setEntry()把私钥条目存入密钥库. 别忘了调用keyStore.store(),否则当程序退出时条目将丢失。

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.

PKCS12密钥库还允许在不存储相应私钥的情况下单独存储证书。存储证书调用KeyStore.setCertificateEntry()。

try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
//  keyStore.load(new FileInputStream("output.p12"),"password".toCharArray());
    keyStore.load(null, null);;
     
    CertAndKeyGen gen = new CertAndKeyGen("RSA","SHA1WithRSA");
    gen.generate(1024);
      
    X509Certificate cert=gen.getSelfCertificate(new X500Name("CN=ROOT"), (long)365*24*3600);
      
    keyStore.setCertificateEntry("cert", cert);
      
    keyStore.store(new FileOutputStream("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 :

存储的证书可以通过别名调用KeyStore.getCertificate()提取。例如:

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.

PKCS12密钥库与其他密钥库(如JKS)的一个区别是,PKCS12的私钥可以在没有空指针异常的情况下提取。使用正确密码可以正确提取私钥。

try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(new FileInputStream("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:

上述代码的输出为:

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.

如果一个证书链存储在密钥库中,则可以通过调用KeyStore.getCertificateChain()加载。下面的代码被用来提取私钥的证书链。

try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(new FileInputStream("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 :

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

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.

加载证书也很简单,通过调用KeyStore.getCertificate(),如果提供的别名映射到证书链,则只返回叶证书。

try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(new FileInputStream("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:

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

PKCS12密钥库可用于导入和导出密钥和证书。由于私钥可以从PKCS12 keystore中提取,因此可以从PKCS12 keystore导出条目,然后导入到其他keystore类型,如JKS。

try{
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(new FileInputStream("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(new FileOutputStream("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.

如果您希望拥有可移植的密钥库类型,并且将来可能希望将其与其他非Java库一起使用,那么PKCS12 keystore是推荐的keystore类型。

posted @ 2020-10-18 20:40  翠微  阅读(2982)  评论(0编辑  收藏  举报