转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> JAVA开发 >> 正文
将Java加密技术同Windows结合起来         ★★★★

将Java加密技术同Windows结合起来

作者:闵涛 文章来源:闵涛的学习笔记 点击数:2019 更新时间:2009/4/22 23:27:43

   公共钥匙加密技术需要一个空间来存储数字证书和私钥。通过将钥匙和证书存储到一个文件中(称为keystore),Java Security Architecture实现了独立于平台的加密技术。

  Microsoft Windows把钥匙和证书存储到Windows注册表和文件系统中。这就是说,在Windows系统上运行安全的Java程序的用户必须在Java和Microsoft的钥匙和证书库之间输入和输出钥匙和证书。好消息是,你可以“哄骗”Java应用程序通过Microsoft本地函数来运用Microsoft的证书和钥匙库。

  通过将你的Java应用程序同Windows 钥匙/证书库结合起来,你虽然牺牲了平台独立性,但你得到了四个好处:减少了管理和支持的成本、更方便用户使用、更好的证书撤消校验、以及更好的钥匙和证书管理工具。

  一个Java程序必须通过四个不同的类实现与Windows加密术的集成: · TrustManager Provider:用这个类来实现与Windows证书库的集成并实现安全策略。

  · KeyManager Provider:用这个类来实现与Windows私钥库的集成。
  · RSA Signature Provider:数字签名需要访问私钥库。如果Java程序不能读取私钥(比如,如果私钥存在一个加密了的智能卡上了),那么签名操作就必须在Windows中进行。
  · RSA Cipher Provider:解密RSA加密的数据(如加密套接字协议层(SSL)对称的钥匙)需要访问私钥库。如果Java程序不能读取私钥(比如,如果私钥存在一个加密了的智能卡上了),那么RSA解密操作就必须在Windows中进行。

  我将讲述与Windows平台集成的TrustManager Provider、KeyManager Provider、RSA Signature Provider和RSA Cipher Provider的用法。TrustManager和KeyManager可以让你构建可运行的Windows支持的Java Secure Socket Extension(JSSE)应用程序。JSSE范例程序——EchoServer和EchoClient可以证明这一点。你不能覆盖JSSE的内置的RSA Cipher Provider,所以,只有当私钥可以从Windows钥匙库中输出时,JSSE应用程序才可以运行。

  如果你在编写一个运用RSA签名或RSA加密的Java应用程序,那么你可以运用Windows支持的RSA Signature Provider和Cipher Provider。这不需要从Windows钥匙库中输出私钥。对于其它三个提供者(provider),你可以单独使用每一个。

  该代码是用 beta版JDK 1.4.0-rc开发的,很稳定。不过,我们打算将该代码作为一个框架,进行进一步的开发。在将该代码用于生产环境前,你应该改进异常处理,确信在本地代码中没有内存泄露,并使密钥的暴露降低到最小。为了测试代码,你需要一个RSA数字证书。你可以从VeriSign网站www.verisign.com/client/enrollment得到一个临时证书,有效期是60天。具体操作请遵循该站点上的指南。不要选定标为“Protect your Private Key”的框。因为没有选定这个框,你的私钥就可以输出。

  下面的代码初试化了四个提供者:

MSTrustMgrProvider.install();
MSKeyMgrProvider.install();
MSRSASignProvider.install();
MSRSACipherProvider.install();
kmf = KeyManagerFactory
.getInstance("MSKMF");
tmf = TrustManagerFactory.
getInstance("MSTMF");
Cipher cipher =
Cipher.getInstance(
"RSA/ECB/PKCS1Padding");
Signature rsa =
Signature.getInstance(
"SHA1withRSA");

  所有的四个提供者都调用了10个本地的Microsoft函数:

  · MSgetCACerts()从Microsoft证书库返回一列认证授权中心(Certificate Authority (CA))签发的证书。
  · 如果一个证书没有被撤消,MSVerifyCertRevocation()返回true。
  · MSgetPrivateKey()为一个特定的别名(alias )返回私钥。(这里所说的一个别名就是带有一个RSA私钥和证书的一个身份。)钥匙从Microsoft钥匙库中输出。
  · MSgetCert()为一个特定的别名从Microsoft证书库中返回一个证书。
  · MSgetAliases()返回一组别名(带有私钥的一个身份的名字)。Microsoft钥匙库中的每个私钥都有一个别名。
  · MSrsaSignHash()返回哈希数据(hashed data)的RSA签名。
  · MSrsaDecrypt()用RSA算法来解密一个先前加密了的数据块。
  · MSrsaEncrypt()用Microsoft RSA provider来加密一个数据块。
  · MSrsaGetKeysize()返回Microsoft钥匙库中一个钥匙的RSA钥匙大小。
  · MSgetCRL()将一个证书撤消清单(Certificate Revocation List(CRL))下载到Microsoft Internet缓存中。

  一个约500行的用C语言代码编写的源文件mscryptofunctions.c中包含了所有这些函数。该代码可以在Windows 98/NT4/2000/XP上运行。

  公共钥匙加密算法

  公共钥匙加密有两个目的:加密和数字签名。公共钥匙加密运用一个包含两部分的钥匙(或一对钥匙):一个私钥和一个公钥。公钥带有开始和终止日期、一个序号、一个身份(称为Subject Distinguished Name)、和一个CA的签名(见列表1)。RSA是最常用的公共钥匙加密算法。

公共钥匙加密运用一个公钥和一个私钥。一个数字证书(如下所示)包含公钥、开始和结束日期、一个序号、一个身份和一个证书授权中心(CA)的签名。
Serial number:
6822 3C33 7945 3AC8 F8C5 398B 7469 94E1
Signature algorithm: md5RSA
Issuer: CN = VeriSign Class 1 CA Individual
Subscriber-Persona Not Validated,
OU = www.verisign.com/repository/RPA Incorp.
By Ref.,LIAB.LTD(c)98,
OU = VeriSign Trust Network, O = VeriSign, Inc.
Valid from: Wednesday, May 30, 2001 7:00:00 PM
Valid to: Monday, July 30, 2001 6:59:59 PM
Subject: E = boyter@txdirect.net,
CN = Brian Boyter,
OU = Digital ID Class 1 <\? Microsoft,
OU = Persona Not Validated,
OU = www.verisign.com/repository/RPA Incorp.
by ref.,LIAB.LTD(c)98,
OU = VeriSign Trust Network, O = VeriSign, Inc.
Public key: 3081 8902 8181 00BA B459 0F39 156E
C69E C238 BFD0 401D DBB9 D207 DFA4 5DBD 09F3
5CE6 B5E6 C357 88DD 808B 0699 5F68 A2A4 6A8A
3B21 6D3D D0A1 1E5F DAB1 FB8E F835 F84F 849B
29A4 6943 8D59 0669 7C81 1D00 03B7 1A02 4E7A
8596 11BD 7CC4 07A3 D7E5 9FF6 5684 B853 04F0
0938 A11E 5218 F9AB F034 070D C8C4 6652 C19B
4C57 E435 EFDC 85D4 B269 07B7 0102 0301 0001
Basic constraints: Subject Type=End Entity,
Path Length Constraint=None
Certificate policy:
Policy Qualifier Id=CPS Qualifier:
https://www.verisign.com/CPS
Policy Qualifier Info:
Organization=VeriSign, Inc.,
Notice Number=1
CRL Distribution Point Distribution Point Name:
Full Name:
URL=http://crl.verisign.com/class1.crl
Thumbprint algorithm: sha1
Thumbprint: 74A8 9F07 43AA 8FFC C4D5 AB09 3773 3AFF F7E7 DFFC

  公共钥匙加密中的加密是用公钥来完成的,解密是用私钥完成的。公共钥匙加密对于大量的加密来说运算很复杂,但它却被广泛用来分配密钥。密钥,或对称加密算法,如DES和RC4,通常用于大量的加密,但是密钥加密算法需要一些保密的方法来交换用于大量加密的钥匙。一种技术是生成一个随机数,用公共钥匙加密算法来加密那个随机数,然后将加密了的随机数发送给远端的同伴。发送者用远端同伴的公钥来加密随机数。接收者用它自己的私钥来解密这个随机数。任何截取了加密的随机数的第三方都不能解密那个随机数,因为他没有私钥。

  在数字签名中,用私钥来完成签名,用公钥来完成确认。被签名了的文件通常是经过哈希算法处理过的。哈希算法是一个单向算法,它可以减小文件的大小。运用MD5哈希算法,文件被简小到16字节。运用SHA1哈希算法,文件被简小到20字节。然后,就用签名人的私钥对经哈希算法处理过的文件进行加密。任何人都可以用签名人的公钥来解密哈希文件。

  你必须非常小心地保护私钥。Windows将私钥以有些令人迷惑的形式存储在文件系统中。一个恶意的侵犯者可以进入到你的计算机并找到你的私钥。任何得到了你的私钥的人都可以化装成你,在你不知道的情况下做出签署文件等行为。一种保护私钥的方法就是用一个加密的智能卡,该卡上存储了私钥。运用一个加密的智能卡,用户仍然可以进行公钥加密和签名活动,但没有人——甚至用户——可以读取私钥。智能卡有一个RSA加密和签名处理器,只有这个RSA处理器有权使用私钥。

  当一个SSL服务器向一个SSL客户端确认身份时,客户端必须根据下面这些标准来确定服务器的证书是否有效:
  · 证书必须有一个信任链,其根CA必须是客户端信任的。
  · 服务器证书,和信任链中所有的CA证书必须有有效的签名。每个证书都是由下面更高级的CA来签署的,除了根CA外,它签名自己的证书。
  · 当前的日期和时间必须在服务器证书的有效期内,而且也在信任链中所有证书的有效期内。每个证书都有一个有效期(证书可以有效使用的一个开始日期和时间以及结束日期和时间)。
  · 每个CA应该管理和公布一个CRL。客户端必须可以从信任链中的每个CA得到CRLs,来查看服务器证书或下属CA的一个证书是否已被其下面更高级的CA撤消了。
  · 证书必须可以有效用于其目的。钥匙的用途定义在证书中。例如,CA批准的仅用于数字签名的一个钥匙就不能用于SSL钥匙交换。

  Java安全实现环境中不进行证书撤消确认,就是说,它不进行CRL处理。我将向你展示如何运用Microsoft Windows的本地加密函数来检查证书信任链中的CRLs,从而为Java实现一个TrustManager和KeyManager。

  TrustManager

  javax.net.ssl.X509TrustManager有三个方法,你可以在MSTrustManagerlmpl.java中找到: · getAcceptedIssuers()为Microsoft证书库中的所有CAs返回一组证书。
  · checkClientTrusted()执行服务器的安全策略。
  · checkServerTrusted()执行客户端的安全策略。

  一个典型的TCP网络安全策略是:

  · 客户端开始连接。假设客户端只连接到“安全的”服务器。客户端应该要求服务器用一个数字证书向客户端证明身份。通过确认服务器的证书(信任链、签名是有效的,有效期、证书没有被撤消,而且证书是批准用于RSA钥匙交换的),客户端确认服务器的真实性。客户端通过有效的证书来信任服务器。
  · 服务器接收来自所有客户端的TCP连接,有些客户端可能是恶意的。服务器可以要求客户端用一个数字证书向服务器证明身份。那样的话,客户端的身份就可以被确认,而且多种信任级别也可以实现了。如果服务器不要求客户端证明身份,服务器应该假设所有的客户端都是恶意的。

  你可以在checkServerTrusted()中看到,实现客户端安全策略是很容易的。CheckServerTrusted()检查签名、信任链中证书的有效日期和CRLs。(我在后面会探讨证书撤消处理。)checkClientTrusted()方法与checkServerTrusted()是一样的。一般来说,这个安全策略对服务器来说并不够。一种增强服务器安全状态的方法就是要求客户端用数字证书来证明身份,只接受由一个特定的CA(如VeriSign CA)发布的证书,并且检验证书的Subject Distinguished Name中的特殊字段(如0=sun.com)。只需要几行Java代码就可以把这个过程添加到checkClientTrusted()中了。你需要定制checkClientTrusted()来实现你的安全策略(见列表2)。

checkClientTrusted()方法检查签名、信任链中证书的有效日期和CRLs。但是,对服务器来说,这个安全函数并不够。你可以通过定制checkClientTrusted()来增强安全策略。
public void checkClientTrusted(
X509Certificate chain[]) {
// DontKnowFlag indicates what to do if we're
// not sure if the certificate is revoked
// int DontKnowFlag=0; // reject the cert
// int DontKnowFlag=1; // accept the cert
int DontKnowFlag=2; // ask the user

// check for revoked certs in the cert chain
if (com.boyter.mscrypto.MSValidCertificate.
isCertChainValid(chain, DontKnowFlag))
return;

// client cert is not trusted
System.out.println("Client Certificate is not Trusted - aborting");
System.exit(2);
}

  Java提供了几个与证书链处理相关的类,在Java Certification Path API Programmer's Guide中有进一步说明。我对它们做过实验,最后决定不用它们,因为我认为它们太复杂了。

  TrustManager有第三个方法getAcceptedIssuers()。该方法为Microsoft证书库中所有CAs返回一组证书。Microsoft将这些证书存储在Registry中;你可以通过启动REGEDIT程序并查看HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates找到它们。GetAcceptedIssuers()方法执行了Microsoft的本地函数CertEnumCertificateslnStore()。CA证书被作为一组base64位编码的字符串传回到Java方法。Java.security.cert.CertificateFactory将base64编码的证书转换成Java证书。

  证书撤消

  有两种撤消证书的方法:Online Certificate Status Protocol(OCSP)和CRL。OCSP(见RFC2560)并没有得到广泛的支持,所以我只探讨用来确认一个证书的撤消状况的CRLs。CAs定期公布一个CRL(见RFC2459)。CRL是一列证书序号,由CA签署。如果一个证书的序号列在CRL中,那个证书就被撤消了,不再有效了。大多数证书在发布时,都有一个称为CRL Distribution Point(CDP)的扩展名。CDP通常是一个HTTP或Lightweight Directory Access Protocol(LDAP)URL,它指明该CRL存储在哪里。我的VeriSign证书的CDP是http://crl.verisign.com/class1.crl。该CRL有500多K,所以需要花些时间来下载。

  Java的确提供了类java.security.cert.LDAPCertStoreParameters,它可以用来从一个LDAP目录获取一个CRL,但这并不适用于VeriSign CRL(因为那个CRL存在一个Web服务器上,而不是一个LDAP服务器上)。Microsoft有一个比Java更丰富的API用来管理证书撤消。如果你浏览一个安全的网站(HTTPS),IE将会检验服务器的证书是否已被撤消(假设服务器的证书有一个CDP)。IE将从证书链中的CAs获取CRLs并把它们缓存到IE的Temporary Internet Files(临时Internet文件)目录中。在下一次需要来自那个CA的CRL时,IE将首先检查缓存。如果它在缓存中找到该CRL,IE会检查该CRL是否过期。(CRLs也有有效的from/to期限。VeriSign运用一个10天的有效期限。)如果CRL已经过期,IE将获取一个新的CRL。

  我考虑开发一个只用于Java的CRL获取、缓存和撤消确认过程——但是那样会需要大量的Java代码,需要支持几个URL协议(HTTP、LDAP、FTP、文件),需要用一个文件来存储CRL缓存,而且需要复制Microsoft提供的底层框架。目的是运用IE的证书撤消底层框架。

  Microsoft提供了一个函数CertVerifyRevocation(),它与IE缓存结合起来了并按需要下载和处理CRLs。我琢磨了好几周撤消过程,最后得到了一个可靠的算法。当CertVerifyRecocation()下载一个CRL时,下载有时会中断。这就使CertVerifyRevocation()返回假的、很难恢复的错误状况。我实现的过程显示在图1中。



图1. 证书撤消流程表

  其诀窍就是调用函数CryptRetrieveObjectByUrl()来从LDAP、HTTP或FTP服务器预取CRL到IE缓存中,然后调用CertVerifyRevocation()来检查这个证书是否已被撤消。虽然CryptRetrieveObjectByUrl()下载仍然要受到网络的影响,造成连接中断,但运用CryptRetrieveObjectByUrl()的好处就是你可以识别问题,报告一个有意义的错误信息,并且(如果你需要)可以提示用户接受或拒绝该证书。不幸的是,只有Windows 2000或更高版本中有CryptRetrieveObjectByUrl()。如果程序要在Windows 98或Windows NT4上运行,你就不能预取CRL。

  我也尝试运用Microsoft函数来下载CRLs,然后在Java中处理CRL。对于一个大的CRL(比如VeriSign CRL),这种方式很慢。

  列表3显示关于isCertRevoked()方法的Java代码片段。IsCertRevoked()方法调用了两个本地函数,MSgetCRL()和MSVerifyCertRevocation()。MSg

[1] [2] [3]  下一页


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台