Windows-MY是Windows上一种由Windows操作系统管理的密钥库。它存储用户密钥和证书,这些密钥和证书可用于执行加密操作,例如签名验证、数据加密等。由于它是一种本地密钥库,因此Java没有通用的API来访问它。
为了帮助Java应用程序访问存储在Windows-MY密钥库中的密钥和证书,Java提供了一个单独的API——SunMSCAPI。SunMSCAPI提供程序构建在CAPI之上,并帮助Java平台应用程序使用现有的Java技术安全和加密API访问CAPI加密服务。这意味着Java平台应用程序现在可以使用SunMSCAPI提供程序执行以下操作:
- 访问存储在CAPI中的私钥和证书
- 使用CAPI的加密算法实现
下面我们将介绍如何使用Java操作Windows-MY密钥库。
首先,您必须将SunMSCAPI提供程序添加到安全提供程序列表中,以便在创建KeyStore实例时可以找到它。在位于<JAVA_HOME>\lib\security的java.security文件中,添加以下条目:
security.provider.10=sun.security.mscapi.SunMSCAPI
更改上面的数字10以适合您的平台。然后我们可以开始使用Windows-MY。
加载密钥库
要加载密钥库,我们只需要创建一个普通的KeyStore实例并提供密钥库类型Windows-MY。
try{ KeyStore keyStore = KeyStore.getInstance("Windows-MY"); keyStore.load(null, null); // 加载密钥库 } catch (Exception ex){ ex.printStackTrace(); }
这里,密钥库输入为null,密码也为null。由于我们正在操作本机Windows-MY密钥库,因此我们不需要放入密钥库输入流和密码。底层API将自动找到密钥库。
存储私钥和证书链
Windows-MY可用于存储私钥及其关联的证书链。在本教程中,我们将使用CertAndKeyGen生成密钥和证书链。在实际应用程序中,您可能需要使用更复杂的运算。
try{ KeyStore keyStore = KeyStore.getInstance("Windows-MY"); keyStore.load(null, null); // 加载密钥库 // 生成私钥和证书链 CertAndKeyGen certAndKeyGen = new CertAndKeyGen("RSA", "SHA256withRSA"); certAndKeyGen.generate(1024); Key key = certAndKeyGen.getPrivateKey(); X509Certificate cert = certAndKeyGen.getSelfCertificate(new X500Name("CN=JavaSecurity"), 365*24*60*60); X509Certificate[] chain = new X509Certificate[]{cert}; keyStore.setKeyEntry("mykey", key, null, chain); keyStore.store(null, null); } catch (Exception ex){ ex.printStackTrace(); }
存储证书
Windows-MY允许存储没有相应私钥的证书。
try{ KeyStore keyStore = KeyStore.getInstance("Windows-MY"); keyStore.load(null, null); // 加载密钥库 // 生成证书 CertAndKeyGen certAndKeyGen = new CertAndKeyGen("RSA", "SHA256withRSA"); certAndKeyGen.generate(1024); X509Certificate cert = certAndKeyGen.getSelfCertificate(new X500Name("CN=JavaSecurity1"), 365*24*60*60); keyStore.setCertificateEntry("mycertificate", cert); keyStore.store(null, null); } catch (Exception ex){ ex.printStackTrace(); }
加载证书链
要加载证书链,我们只需要知道证书链别名。
try{ KeyStore keyStore = KeyStore.getInstance("Windows-MY"); keyStore.load(null, null); // 加载密钥库 Certificate[] chain = keyStore.getCertificateChain("mykey"); for(Certificate cert : chain){ System.out.println(cert); } } catch (Exception ex){ ex.printStackTrace(); }
输出如下所示:
[ [ 版本:V3 主题:CN=JavaSecurity 签名算法:SHA256withRSA,OID = 1.2.840.113549.1.1.11 密钥:Sun RSA 公钥,1024 位 模数:115158915868692318987927322981993098184851087646271166814185733840839228006539416470914033601611753480811872595928340327418479810582683258819388853614402750121845039521565991998963853516232149701424900757572697209325472744440054065298957644144270547136759177167201092105624782153655544642521014196719366849149 公钥指数:65537 有效期:[从:2016年1月9日星期六 19:23:49 CST, 到:2017年1月8日星期日 19:23:49 CST] 颁发者:CN=JavaSecurity 序列号:[ 5fff31ae] ] 算法:[SHA256withRSA] 签名: 0000: 9C 1D 36 4E 31 CA CD A5 06 13 A5 7E A8 7B 0C 7F ..6N1........... 0010: 71 D9 0A 2B 19 82 28 D3 E0 9D A1 FD 5E 5E 8C CB q..+..(.....^^.. 0020: 77 77 AF 4B E1 29 27 D5 CE 77 8E 68 2C DA A4 30 ww.K.)'..w.h,..0 0030: CA 5F 66 5E B7 C8 4E 81 15 CB A9 56 5D 34 76 28 ._f^..N....V]4v( 0040: 42 59 65 C1 E2 7E D6 6D 1A A3 66 83 D2 1E C9 10 BYe....m..f..... 0050: 9F 05 75 E3 83 7D D2 70 FA 28 49 42 57 38 18 4B ..u....p.(IBW8.K 0060: E7 C9 17 8D 13 7C 81 F5 2C 5D 04 2E 15 04 77 60 ........,]....w` 0070: 85 7B 45 E7 A6 A7 C9 62 63 D4 26 50 83 38 74 AD ..E....bc.&P.8t. ]
加载证书
加载证书的过程类似于加载证书链的过程。只需要一个别名。
try{ KeyStore keyStore = KeyStore.getInstance("Windows-MY"); keyStore.load(null, null); // 加载密钥库 Certificate cert = keyStore.getCertificate("mycertificate"); System.out.println(cert); } catch (Exception ex){ ex.printStackTrace(); }
输出如下所示:
[ [ 版本:V3 主题:CN=JavaSecurity1 签名算法:SHA256withRSA,OID = 1.2.840.113549.1.1.11 密钥:Sun RSA 公钥,1024 位 模数:162643520607141934155239883471718040795513791129599245958918873228051267022145247869395776267777056508288312204117354041940752871832185392623715702004286759226626992223635150724845988723904884906298676925643542124198797189444002248973385583978516838174284232569476559210240169899741977273703497762888592391581 公钥指数:65537 有效期:[从:2016年1月9日星期六 19:35:04 CST, 到:2017年1月8日星期日 19:35:04 CST] 颁发者:CN=JavaSecurity1 序列号:[ 65f0f6d6] ] 算法:[SHA256withRSA] 签名: 0000: BE 9F 8C 5D 02 A7 49 35 AE 66 75 2F C5 F2 2B D2 ...]..I5.fu/..+. 0010: BF 8D 37 F8 A3 DE 33 9C F8 64 96 67 E8 00 F6 B5 ..7...3..d.g.... 0020: 13 C6 CF 95 63 B2 14 BE 4D D1 AD 26 FF BF 5C BC ....c...M..&..\. 0030: F0 4F DD E7 A4 BC 9E 88 E5 23 CB 4C 0D B4 C6 8F .O.......#.L.... 0040: 4D B5 69 F5 EF 7F 90 66 29 59 9D 87 37 B9 A3 51 M.i....f)Y..7..Q 0050: 54 1C BF AF 54 6C 4B 72 47 3A 2A 3C B0 E9 08 C1 T...TlKrG:*<.... 0060: E1 A8 98 1A 7F CC F5 D1 5A 12 3F 70 A3 5A E6 F3 ........Z.?p.Z.. 0070: 3D 23 FD 04 45 3F EA 26 3B D8 D2 72 B6 A4 47 AA =#..E?.&;..r..G. ]
如果您想了解Java中其他类型的密钥库,可以查看Java中不同类型的密钥库——概述。
And about Windows 10.
Exists the "Windows-MY"?