📄 论java加密技术与windows的结合.txt
字号:
我也尝试运用Microsoft函数来下载CRLs,然后在Java中处理CRL。对于一个大的CRL(比如VeriSign CRL),这种方式很慢。
列表3显示关于isCertRevoked()方法的Java代码片段。IsCertRevoked()方法调用了两个本地函数,MSgetCRL()和MSVerifyCertRevocation()。MSgetCRL()调用Microsoft函数CryptRetrieveObjectByURL(),如果CRL不在缓存中,它可以使CRL被下载。你不需要把CRL传递到Java中,因为它从来不用在Java中。函数MSCertVerifyRevocation()调用Microsoft函数CertVerifyRevocatoin()来确定一个证书是否被撤消了。列表4显示关于MSgetCRL()和MSVerifyCertRevocation()的代码片段。警告:当我第一次在Windows 2000 Server PC上测试CertVerifyRevocation()时,它没有运行。在我将PC升级到Service Pack 2后,重新测试就很成功。
我们的确认程序中的isCertRevoked()方法调用了两个本地函数:MSgetCRL()和MSVerifyCertRevocation() (如列表4所示)。
boolean isCertRevoked(X509Certificate cert,
int DontKnowFlag) {
byte[] certblob = cert.getEncoded();
// Does the cert have a CDP (
// CRL distribution point)???
byte[] CDPblob = cert.getExtensionValue(
"2.5.29.31");
// yes there is a CDP - ASN parse the CDP
String[] URLarray = MSF.MSparseCDP(CDPblob);
for (int i=0; i<URLARRAY.LENGTH; i++) String URL = URLarray[i];
// go fetch that CRL
if (MSF.MSgetCRL(URL)) {
// url was fetched correctly
break;
}
// is the cert revoked???
int revocationStatus =
MSF.MSVerifyCertRevocation(certblob);
switch (revocationStatus) {
case 0: // cert is revoked
return AskUserWhatHeWantsToDo(DontKnowFlag);
case 1: // cert is not revoked
return false;
default:
}
// processing error - cannot determine
// if cert is revoked
return AskUserWhatHeWantsToDo(DontKnowFlag);
}
函数MSgetCRL()和MSVerifyCertRevocation()由方法isCertRevoked()调用(如列表3所示)。MSgetCRL()调用Microsoft函数CryptRetrieveObjectByURL(),如果在缓存中没有CRL,可以用该函数来下载它。函数MSVerifyCertRevocation()调用Microsoft函数CertVerifyRevocation()来查看一个证书是否已被撤消。
MSgetCRL(jstring jurl)
{
if (!CryptRetrieveObjectByUrl(
url, CONTEXT_OID_CRL, 0, timeout*1000,
(LPVOID)&crl, NULL, NULL, NULL, NULL)) {
printf("CryptRetrieveObjectByUrl failed\n");
// cached url is corrupted
DeleteUrlCacheEntry(url);
return JNI_FALSE;
}
return JNI_TRUE;
}
MSVerifyCertRevocation (jbyteArray jCert)
{
rgpvContext[0] = (PVOID)pCertContext;
if (CertVerifyRevocation(X509_ASN_ENCODING,
CERT_CONTEXT_REVOCATION_TYPE, 1, rgpvContext,
0, NULL, &status)) {
return 1; // cert is not revoked
}
if (status.dwError == CRYPT_E_REVOKED)
return 0; // cert is revoked
return -2; // processing error
}
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)){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -