天天看點

java jceks 密鑰_Java不同類型密鑰庫之PKCS12和JCEKS

密鑰庫是一個存放加密密鑰和證書的存儲設施,它們經常用于SSL通信來标明伺服器和客戶機的身份,一個密鑰庫可以是一份檔案或硬體裝置。Java中

不同類型的密鑰庫 包含:PrivateKey、SecretKey、JKS、PKCS12、JCEKS等。其中JKS的詳細介紹可參考《

Java不同密鑰庫類型之JKS 》。本文所講訴的為 PKCS12和JCEKS的用法。

以下為譯文:

JCEKS

JCEKS 是Java平台的一個密鑰庫格式,将密鑰存儲在密鑰庫中以防止加密密鑰的暴露。在JCEKS中存儲和裝載不同條目的過程類似于JKS,隻需在調用KeyStore.getInstance()時更改相應的JCEKS密鑰庫類型。

存儲密鑰

密鑰可以通過一下代碼存儲到JCEKS中:

try{

KeyStore keyStore = KeyStore.getInstance("JCEKS");

keyStore.load(null, null);

KeyGenerator keyGen = KeyGenerator.getInstance("DES");

keyGen.init(56);;

Key key = keyGen.generateKey();

keyStore.setKeyEntry("secret", key, "password".toCharArray(), null);

keyStore.store(new FileOutputStream("output.jceks"), "password".toCharArray());

} catch (Exception ex) {

ex.printStackTrace();

}

加載密鑰

代碼如下:

try{

KeyStore keyStore = KeyStore.getInstance("JCEKS");

keyStore.load(new FileInputStream("output.jceks"), "password".toCharArray());

Key key = keyStore.getKey("secret", "password".toCharArray());

System.out.println(key.toString());

} catch (Exception ex) {

ex.printStackTrace();

}

輸出代碼:

[email protected]

PKCS12

PKCS12 是公鑰加密标準,它規定了可包含所有私鑰、公鑰和證書。其以二進制格式存儲,也稱為 PFX 檔案,在windows中可以直接導入到密鑰區。注意,PKCS12的密鑰庫保護密碼同時也用于保護Key。

建立PKCS12密鑰庫

在把一個條目存入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();

}

需要注意的是,在調用keyStore.load(null, null)時,兩個null是作為輸入密鑰流和密碼傳遞的。這是因為我們沒有可用的密鑰庫。運作這段代碼後,目前工作目錄中應該會輸出一個名為output.p12的檔案。

存儲密鑰

代碼如下:

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();

}

存儲私鑰

密鑰庫包含可用于網絡上的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();

}

别忘了調用keyStore.store()來儲存密鑰,否則條目在程式退出時會丢失。

存儲證書

存儲證書可以調用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();

}

存儲的證書可以通過調用提供别名的KeyStore.getCertificate() 來提取,例如:

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

加載私鑰

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();

}

代碼輸出:

[email protected]

加載證書鍊

如果一個證書鍊存在密鑰庫中,我們可以通過調用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();

}

輸出:

[

[

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

注:如何在Java中建立證書鍊?可參考: 點此進入

加載證書

加載證書可以通過調用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();

}

輸出:

[

[

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

導入導出密鑰和證書

PKCS12密鑰庫可以用于導入導出密鑰和證書,下面的代碼示範了從PKCS12導出一個私鑰并導入到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();

}