您现在的位置是: 软件 > 开发者网络 > 程序方舟 > Java专栏 > 正文


-FreeHand MX全新体验
-注册表知识群集
-Delphi经典编程100例
-PHP编程实录

论Java加密技术与Windows的结合
2003-05-08· ·独行客··天极论坛

上一页  1 2 3 4 5  下一页

  KeyManager

  javax.net.ssl.X509KeyManager有六个方法:
  · getClientAliases()返回一组客户端别名。(这里的一个别名就是带有一个RSA私钥和证书的一个身份。)
  · getServerAliases()返回一组服务器别名。
  · chooseClientAlias()从一组别名中选择一个客户端别名。
  · chooseServerAlias()从一组别名中选择一个服务器别名。
  · getCertificateChain()为一个证书返回有序的证书链。
  · getPrivateKey()为一个别名返回私钥。

  Microsoft将私钥和它们相关的证书存储在文件系统中。我的私钥和证书存储在目录C:\Documents和Settings\Administrator\Application Data\Microsoft中。你不需要知道钥匙存储在哪里,因为Microsoft提供了一个API用来访问钥匙和证书库。

  KeyManager的getClientAliases()和getServerAliases()方法执行Microsoft本地的函数CertEnumCertificateslnStore(),查看Microsoft的“My”证书库中的所有证书。“My”证书库中的证书应该有一个与它们相关连的私钥。每个证书/私钥组合都有一个特殊的标识符,称为CONTAINER;这就相当于Java中的“别名”(见列表5)。

CertEnumCertificatesInStore()方法查看Microsoft中“My”证书库中所有的证书;每个证书都有一个相关的私钥。每个证书/私钥组合都有一个标识符,称为CONTAINER,这就相当于Java中的别名。
JobjectArray MSgetAliases (jstring jcertStore) {

// open Microsoft certificate store
hSystemStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0, 0, CERT_SYSTEM_STORE_CURRENT_USER,
certStore);

// read all the certificates
while(pCertContext=
CertEnumCertificatesInStore(
hSystemStore, pCertContext)) {

// get the cert key container name
CertGetCertificateContextProperty(
pCertContext, CERT_KEY_PROV_INFO_PROP_ID,
alias, &propLen);

// add to list of aliases
AddDataToList(&list, alias, strlen(alias)+1);
}
return jaliases;
}


列表5

  方法chooseClientAlias()和chooseServerAlias()从一列别名中返回一个客户端(或服务器)别名。如果只有一个别名,在选择别名时就不会有歧义。因为Java的创始人对于选择运用哪个别名并没有提供任何特殊的指导,我就选择了清单中第一个别名。另一个选择合适的客户端别名的方法就是提示用户从一列可能的别名中选择一个别名。(在SSL客户端,你通常可以这么做,但在服务器上不行。)

  KeyManager的getCertificateChain()方法为一个证书返回有序的证书链。该方法通过调用getAcceptedIssuers()方法得到一列可信任的证书签发者。首先我们找到证书签发者的Distinguished Name(DN),然后我们查看是否有哪个可信任的签发者有那个DN。几个签发者可以有同一个DN。对于具有签发者DN的每个证书,我们提取公钥并尝试在原始证书上确认签名。如果没有一个签发者有正确的DN和正确的公钥,证书链就被破坏了,出现一个异常。如果我们找到了正确的签发者签发的证书,我们就重复上述过程来查找和确认那个证书的签发者。重复该过程,直到我们达到根CA。对于一个根CA,Subject DN和签发者DN是一样的(见列表6)。

方法getCertChain()为一个证书返回有序的证书链。
MSCryptoFunctions MSF = new MSCryptoFunctions();
X509Certificate[] getCertChain(
X509Certificate cert) {

try {
getCACerts();

Principal subject = cert.getSubjectDN();
Principal issuer = cert.getIssuerDN();
CertChainList.add(cert);

// stop if issuer==subject (root CA)
while (!(issuer.equals(subject))) {

match = false;
X509CertSelector xcs =
new X509CertSelector();
xcs.setCertificateValid(new Date());

Collection certcollection =
CACerts.getCertificates(xcs);

//
// the next 7 lines are inserted to work
// around a problem with X509CertSelector.
// we should be able to do this with
// xcs.setSubject(issuer.toString());
//
Iterator iter = certcollection.iterator();
while ( iter.hasNext() ) {
X509Certificate cacert =
(X509Certificate) (iter.next());
if (!cacert.getSubjectDN().equals(issuer))
iter.remove();
}

issuerArray =
new X509Certificate[
certcollection.size()];
issuerArray = (X509Certificate[])
certcollection.toArray(issuerArray);

for (int i=0; i<\<>issuerArray.length; i++)
if (verifySignature(issuerArray[i], cert)){
match = true;
cert = issuerArray[i];
subject = cert.getSubjectDN();
issuer = cert.getIssuerDN();
CertChainList.add(cert);
break;
}
if (!match) {
return null; // cert chain broken
}
}
} catch (Exception e) {
e.printStackTrace();
}

X509Certificate[] CertChain =
new X509Certificate[CertChainList.size()];
CertChainList.toArray(CertChain);

return CertChain;
}

  getPrivateKey()方法为一个别名返回私钥,假设私钥可以从Microsoft钥匙库中输出。记住,有时私钥是不能输出的。(例如,如果你用了一个加密了的智能卡,那么就没人可以从智能卡上读取私钥了。)如果不能输出私钥,getPrivateKey()就返回一个虚拟的私钥。所以,如果getPrivateKey()不能得到私钥,我们就骗Java,让它认为得到了私钥。getPrivateKey()也缓存别名,所以,当一个Java程序试图执行一个RSA数字签名函数时,我们就会知道运用哪个私钥了(缓存的别名),而且Microsoft加密提供者就可以执行我们想要的RSA签名或解密函数了(见列表7)。

方法getPrivateKey()为一个别名返回私钥,假设私钥可以从Windows钥匙库中输出。
MSCryptoFunctions MSF = new MSCryptoFunctions();
public PrivateKey getPrivateKey(String alias) {

// get the private key from MS Windows for
// this alias
byte[] keyblob = MSF.MSgetPrivateKey(alias);

if (keyblob == null) { // generate a dummy key
byte[] modblob = new byte[128];
for(i=0; i<128; i++)
modblob[i] = 127;
mod = new BigInteger(modblob);
exp = mod;

} else { // use the key that got exported
for(i=0; i
modblob[i] = keyblob[19-i+(keysize/16)*2];
expblob[i] = keyblob[19-i+(keysize/16)*9];
}
mod = new BigInteger(1, modblob);
exp = new BigInteger(1, expblob);
}
RSAPrivateKeySpec privKeySpec =
new RSAPrivateKeySpec(mod, exp);
KeyFactory kf = KeyFactory.getInstance("RSA");
privkey = kf.generatePrivate(privKeySpec);
return privkey;
}

上一页  1 2 3 4 5  下一页

■ 相关内容
 支持Java:未来手机发展的一个方向
 2003:无线Java应用年
 用Java绘制K线图
 Java Transaction API概述
 三个漏洞使Windows易受Java攻击
 Java 在Client/Server 网络中的应用
 JSP调用JavaBean在网页上动态生成柱状图
 利用Java实现串口全双工通讯
感谢 访问天极网,如果您觉得该文章涉及版权问题,请看这里!