| « | July 2026 | » | | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | |
| 公告 |
| 暂无公告... |
| Blog信息 |
|
blog名称:天地无用 日志总数:55 评论数量:43 留言数量:1 访问次数:198730 建立时间:2008年4月17日 |

| |
|
密码术基础(转) 软件技术
kkk888929 发表于 2008/4/21 13:49:37 |
|
Java 与系统安全,第一部分:密码术基础
第一章 关于本教程
■本教程是关于什么方面的? 恐怕没有什么软件工程主题的重要性比应用程序安全性更紧迫了。无论是来自内部或外部的攻击都会带来巨大损失,某些攻击会使软件公司对造成的损失承担赔偿责任。随着计算机(尤其是因特网)技术的发展,安全性攻击正在变得越来越成熟和频繁。利用各种最新技术和工具是应用程序安全性的一个关键;另一个关键是由经过考验的技术(如数据加密、认证和授权)构筑的牢固的基础。 Java 平台的基本语言和库扩展都提供了用于编写安全应用程序的极佳基础。本教程讨论了密码术基础知识与如何用Java 编程语言实现密码术,并提供了样本代码来说明这些概念。 在这个两部分教程的第一部分中,我们讨论库扩展(现在是JDK 1.4 库的一部分)中的内容,这些库扩展被称为Java 密码术扩展(Java Cryptography Extension(JCE))和Java 安全套接字扩展(Java Secure Sockets Extension (JSSE))。此外,本教程还介绍了CertPath API,这是JDK 1.4 中新增加的特性。在本教程第二部分(请参阅参考资料)中,我们将把讨论范围扩大到由Java 平台中Java 认证和授权服务(Java Authentication and Authorization Service (JAAS))管理的访问控制。
■我应该学习本教程吗? 这是一篇中级教程;它假设您知道如何阅读和编写基本的Java 程序,包括应用程序和applet。 如果您已经是Java 程序员并且对密码术(关于诸如私钥和公钥加密、RSA、SSL、证书之类的主题)以及支持它们的Java 库(JCE、JSSE)感到好奇,那么本教程就是为您准备的。本教程不要求您已经具有任何密码术、JCE 或JSSE 等方面的知识背景。 本教程介绍了基本密码构件概念。每个概念都附有Java 实现考虑事项、代码示例和示例执行的结果。
■工具、代码样本和安装需求 您将需要以下几项以完成本教程中的编程练习: JDK 1.4,标准版 本教程源代码和类,以便您能够随着我们的进度理解示例 用于RSA 示例的Bouncy Castle Crypto 库 支持Java 1.4 插件的浏览器 您可以使用JDK 1.3.x,但必须自行安装JCE 和JSSE。
■关于代码示例的说明 代码示例直接将已加密的数据显示到屏幕上。大多数情况下,这会产生奇形怪状的控制字符,其中的一些偶尔可能会引起屏幕格式化问题。这不是良好的编程实践(将它们转换成可显示的ASCII 字符或十进制表示会更好),但我们这样做是为了保持代码示例及其输出的简洁。 在示例执行章节的大多数情况下,我们修改了实际字符串以便与本教程中的字符集需求兼容。还有,我们在大多数示例中查询和显示了用于给定算法的实际安全性提供程序库。这样做是为了让用户更好地了解哪个功能是调用哪个库实现的。为什么这样做呢?因为,在大多数安装中都安装了许多这样的提供程序。
■关于作者 Brad Rubin 是Brad Rubin & Associates Inc. 的负责人,该公司是一家专门从事无线网络和Java 应用程序安全性和教育的计算机安全性咨询公司。Brad 在IBM(位于明尼苏达州的Rochester)工作了14 年,他从AS/400 的第一个发行版就开始从事其所有方面的硬件和软件开发。他是促使IBM 转而支持Java 平台的关键人物,并且是IBM 最大的Java 应用程序—称为SanFrancisco(现在是WebSphere 的一部分)的商业应用程序框架产品—的首席架构设计师。他还是Imation Corp. 数据存储部门的首席技术官,以及该公司研发组织的领导。 Brad 拥有计算机和电子工程学位,以及威斯康星大学麦迪逊分校计算机科学博士头衔。他目前在明尼苏达大学教授电子和计算机工程高级设计课程,并将于2002 年秋季开设和教授该大学的计算机安全性课程。可通过BradRubin@BradRubin.com 与Brad 联系。
第二章 Java安全性编程概念
■Java 平台是如何使安全编程更方便的 Java 编程语言和环境有许多特性使安全编程更方便: ·无指针,这意味着Java 程序不能对地址空间中的任意内存位置寻址。 ·字节码验证器,在编译成.class 文件之后运行,在执行之前检查安全性问题。例如,访问超出数组大小的数组元素的尝试将被拒绝。因为缓冲区溢出攻击是造成大多数系统漏洞的主要原因,所以这是一种重要的安全性特性。 ·对资源访问的细颗粒度控制,用于applet 和应用程序。例如,可以限制applet 对磁盘空间的读或写,或者可以授权它仅从特定目录读数据。可以根据对代码签名的人(请参阅代码签名的概念)以及代码来源处的http 地址来进行授权。这些设置都出现在java.policy 文件中。 ·大量库函数,这些函数用于主要密码构件和SSL(本教程的主题)以及认证和授权(在本系列的第二篇教程中讨论)。此外,有众多的第三方库可用于额外的算法。
■什么是安全编程技术? 简单地说,有多种编程风格和技术可以帮助确保应用程序更安全。考虑下列两个一般示例: ·存储/删除密码。如果密码是存储在Java String 对象中的,则直到对它进行垃圾收集或进程终止之前,密码会一直驻留在内存中。即使进行了垃圾收集,它仍会存在于空闲内存堆中,直到重用该内存空间为止。密码String 在内存中驻留得越久,遭到窃听的危险性就越大。 更糟的是,如果实际内存减少,则操作系统会将这个密码String 换页调度到磁盘的交换空间,因此容易遭受磁盘块窃听攻击。 为了将这种泄密的可能性降至最低(但不是消除),您应该将密码存储在char 数组中,并在使用后对其置零。(String 是不可变的,所以无法对其置零。) ·智能序列化。当为存储器或传输任何私有字段而序列化对象时,缺省情况下,这些对象都呈现在流中。因此,敏感数据很容易被窃听。可以使用transient 关键字来标记属性,这样在流中将忽略该属性。 当在本教程中需要用到这些技术以及其它技术时,我们将更详细地讨论它们。
■JDK 1.4 中集成了安全性 在JDK 1.4 之前,许多安全性功能必须作为扩展添加到基本Java 代码分发版中。严格的美国出口限制要求这种功能的分离。 现在,新的宽松法规使安全性特性和基本语言更紧密的集成成为可能。下列软件包(在1.4 发行版之前作为扩展使用)现在集成到了JDK 1.4 中: ·JCE(Java 密码术扩展) ·JSSE(Java 安全套接字扩展) ·JAAS(Java 认证和授权服务) JDK 1.4 还引入了两种新功能: ·JGSS(Java 通用安全性服务(Java General Security Service)) ·CertPath API(Java 证书路径API (Java Certification Path API)) ·JCE、JSSE 和CertPath API 是本教程讨论的主题。在本系列的下一篇教程中,我们将重点介绍JAAS。这两篇教程都不讨论JGSS(它提供一般框架以在两个应用程序之间安全地交换消息)。
■第三方库充实了安全性 我们可以用第三方库(也称为提供程序)来增强当前Java 语言中已经很丰富的功能集。提供程序添加了额外的安全性算法。 作为库示例,我们将使用Bouncy Castle 提供程序(请参阅参考资料)。Bouncy Castle 库提供了其它密码算法,包括本教程什么是公钥密码术?和什么是数字签名?中讨论的流行的RSA 算法。 尽管您的目录名和java.security 文件可能有一点不同,但仍可用以下模板安装Bouncy Castle 提供程序。要安装这个库,请下载bcprov-jdk14-112.jar 文件并将它放到j2sdk1.4.0\jre\lib\ext 和Program Files\Java\J2re1.4.0\lib\ext 目录中。在两个java.security 文件(他们位于上述相同的目录下,但位于“security”子目录而不是“ext”)中,将下面的行: security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider 添加至这些行的末尾: security.provider.1=sun.security.provider.Sun security.provider.2=com.sun.net.ssl.internal.ssl.Provider security.provider.3=com.sun.rsajca.Provider security.provider.4=com.sun.crypto.provider.SunJCE security.provider.5=sun.security.jgss.SunProvider security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider
■展望 在本章中,我们已经介绍了Java 语言提供的有助于确保编程保持安全的特性(无论是完全集成的还是基于扩展的)。我们提供了一些安全编程技术的通用示例以帮助您熟悉这个概念。我们介绍了过去是作为扩展的但现在集成到版本1.4 发行版中的安全性技术;我们也注意到两种新的安全性技术。我们还说明了了第三方库通过提供新技术能够增强安全性程序。 在本教程余下的部分,我们将让您熟悉这些旨在提供安全的消息传递的概念(因为它们应用于Java 编程): ·消息摘要。这是一种与消息认证码结合使用以确保消息完整性的技术。 ·私钥加密。被设计用来确保消息机密性的技术。 ·公钥加密。允许通信双方不必事先协商秘钥即可共享秘密消息的技术。 ·数字签名。证明另一方的消息确定来自正确通信方的位模式。 ·数字证书。通过让第三方认证机构认证消息,向数字签名添加另一级别安全性的技术。 ·代码签名。由可信的实体将签名嵌入被传递的代码中的概念。 ·SSL/TLS。在客户机和服务器之间建立安全通信通道的协议。传输层安全性(Transport Layer Security (TLS))是安全套接字层(Secure Sockets Layer (SSL))的替代品。 当我们讨论上述每个主题时,都将提供示例和样本代码。
第三章 确保消息的完整性
■概述 我们将在本章中了解消息摘要,它获取消息中的数据并生成一个被设计用来表示该消息“指纹”的位块。我们还将讨论JDK 1.4 支持的与消息摘要相关的算法、类和方法,并为消息摘要和消息认证特性提供代码示例和样本的执行代码。
■什么是消息摘要? 消息摘要是一种确保消息完整性的功能。消息摘要获取消息作为输入并生成位块(通常是几百位长),该位块表示消息的指纹。消息中很小的更改(比如说,由闯入者和窃听者造成的更改)将引起指纹发生显著更改。 消息摘要函数是单向函数。从消息生成指纹是很简单的事情,但生成与给定指纹匹配的消息却很难。 消息摘要可强可弱。校验和(消息的所有字节异或运算的结果)是弱消息摘要函数的一个示例。很容易修改一个字节以生成任何期望的校验和指纹。大多数强函数使用散列法。消息中1 位更改将引起指纹中巨大的更改(理想的比例是更改指纹中50% 的位)。 ■算法、类和方法 JDK 1.4 支持下列消息摘要算法: ·MD2 和MD5,它们都是128 位算法 ·SHA-1 是160 位算法 ·SHA-256、SHA-383 和SHA-512 提供更长的指纹,大小分别是256 位、383 位和512 位 MD5 和SHA-1 是最常用的算法。 MessageDigest 类操作消息摘要。消息摘要代码示例中使用下列方法: ·MessageDigest.getInstance("MD5"):创建消息摘要。 ·.update(plaintext):用明文字符串计算消息摘要。 ·.digest():读取消息摘要。 如果密钥被用作消息摘要生成过程的一部分,则将该算法称为消息认证码。JDK 1.4 支持HMAC/SHA-1 和HMAC/MD5 消息认证码算法。 Mac 类使用由KeyGenerator 类产生的密钥操作消息认证码。消息认证码示例中使用了下列方法: ·KeyGenerator.getInstance("HmacMD5") 和.generateKey():生成密钥。 ·Mac.getInstance("HmacMD5"):创建MAC 对象。 ·.init(MD5key):初始化MAC 对象。 ·.update(plaintext) 和.doFinal():用明文字符串计算MAC 对象。
■消息摘要代码示例 import java.security.*; import javax.crypto.*; // // Generate a Message Digest public class MessageDigestExample { public static void main (String[] args) throws Exception { // // check args and get plaintext if (args.length !=1) { System.err.println("Usage: java MessageDigestExample text"); System.exit(1); } byte[] plainText = args[0].getBytes("UTF8"); // // get a message digest object using the MD5 algorithm MessageDigest messageDigest = MessageDigest.getInstance("MD5"); // // print out the provider used System.out.println( "\n" + messageDigest.getProvider().getInfo() ); // // calculate the digest and print it out messageDigest.update( plainText); System.out.println( "\nDigest: " ); System.out.println( new String( messageDigest.digest(), "UTF8") ); } }
■消息摘要样本执行的结果 D:\IBM>java MessageDigestExample "This is a test!"
SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests ; SecureRandom; X.509 certificates; JKS keystore; PKIX CertPathValidator ; PKIX CertPathBuilder; LDAP, Collection CertStores)
Digest: D93,.x2%$kd8xdp3di5* ■消息认证码示例 import java.security.*; import javax.crypto.*; // // Generate a Message Authentication Code public class MessageAuthenticationCodeExample { public static void main (String[] args) throws Exception { // // check args and get plaintext if (args.length !=1) { System.err.println ("Usage: java MessageAuthenticationCodeExample text"); System.exit(1); } byte[] plainText = args[0].getBytes("UTF8"); // // get a key for the HmacMD5 algorithm System.out.println( "\nStart generating key" ); KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5"); SecretKey MD5key = keyGen.generateKey(); System.out.println( "Finish generating key" ); // // get a MAC object and update it with the plaintext Mac mac = Mac.getInstance("HmacMD5"); mac.init(MD5key); mac.update(plainText); // // print out the provider used and the MAC System.out.println( "\n" + mac.getProvider().getInfo() ); System.out.println( "\nMAC: " ); System.out.println( new String( mac.doFinal(), "UTF8") ); } } ■消息认证样本执行 D:\IBM>java MessageAuthenticationCodeExample "This is a test!"
Start generating key Finish generating key
SunJCE Provider (implements DES, Triple DES, Blowfish, PBE, Diffie-Hellman, HMAC-MD5, HMAC-SHA1)
MAC: Dkdj47x4#.@kd#n8a-x>
注:因为代码用线程行为定时来生成优质的伪随机数,所以密钥生成很费时。一旦生成了第一个数,其它数的生成就快得多了。 还请注意,与消息摘要不同的是,消息认证码使用密码提供程序。(有关提供程序的更多信息,请参阅第三方库充实了安全性。) |
|
|