安全生产Java安全性.docx
《安全生产Java安全性.docx》由会员分享,可在线阅读,更多相关《安全生产Java安全性.docx(40页珍藏版)》请在冰豆网上搜索。
![安全生产Java安全性.docx](https://file1.bdocx.com/fileroot1/2023-2/3/0a8d9973-171d-47f5-8e2d-f63fb98a848c/0a8d9973-171d-47f5-8e2d-f63fb98a848c1.gif)
安全生产Java安全性
Java安全性
本教程是关于什么方面的?
第1页(共5页)
恐怕没有什么软件工程主题的重要性比应用程序安全性更紧迫了。
无论是来自内部或外部的攻击都会带来巨大损失,某些攻击会使软件公司对造成的损失承担赔偿责任。
随着计算机(尤其是因特网)技术的发展,安全性攻击正在变得越来越成熟和频繁。
利用各种最新技术和工具是应用程序安全性的一个关键;另一个关键是由经过考验的技术(如数据加密、认证和授权)构筑的牢固的基础。
Java平台的基本语言和库扩展都提供了用于编写安全应用程序的极佳基础。
本教程讨论了密码术基础知识与如何用Java编程语言实现密码术,并提供了样本代码来说明这些概念。
在这个两部分教程的第一部分中,我们讨论库扩展(现在是JDK1.4库的一部分)中的内容,这些库扩展被称为Java密码术扩展(JavaCryptographyExtension(JCE))和Java安全套接字扩展(JavaSecureSocketsExtension(JSSE))。
此外,本教程还介绍了CertPathAPI,这是JDK1.4中新增加的特性。
在本教程第二部分(请参阅参考资料)中,我们将把讨论范围扩大到由Java平台中Java认证和授权服务(JavaAuthenticationandAuthorizationService(JAAS))管理的访问控制。
我应该学习本教程吗?
第2页(共5页)
这是一篇中级教程;它假设您知道如何阅读和编写基本的Java程序,包括应用程序和applet。
如果您已经是Java程序员并且对密码术(关于诸如私钥和公钥加密、RSA、SSL、证书之类的主题)以及支持它们的Java库(JCE、JSSE)感到好奇,那么本教程就是为您准备的。
本教程不要求您已经具有任何密码术、JCE或JSSE等方面的知识背景。
本教程介绍了基本密码构件概念。
每个概念都附有Java实现考虑事项、代码示例和示例执行的结果。
工具、代码样本和安装需求
第3页(共5页)
您将需要以下几项以完成本教程中的编程练习:
∙JDK1.4,标准版
∙本教程源代码和类,以便您能够随着我们的进度理解示例
∙用于RSA示例的BouncyCastleCrypto库
∙支持Java1.4插件的浏览器
您可以使用JDK1.3.x,但必须自行安装JCE和JSSE。
关于代码示例的说明
第4页(共5页)
代码示例直接将已加密的数据显示到屏幕上。
大多数情况下,这会产生奇形怪状的控制字符,其中的一些偶尔可能会引起屏幕格式化问题。
这不是良好的编程实践(将它们转换成可显示的ASCII字符或十进制表示会更好),但我们这样做是为了保持代码示例及其输出的简洁。
在示例执行章节的大多数情况下,我们修改了实际字符串以便与本教程中的字符集需求兼容。
还有,我们在大多数示例中查询和显示了用于给定算法的实际安全性提供程序库。
这样做是为了让用户更好地了解哪个功能是调用哪个库实现的。
为什么这样做呢?
因为,在大多数安装中都安装了许多这样的提供程序。
关于作者
第5页(共5页)
BradRubin是BradRubin&AssociatesInc.的负责人,该公司是一家专门从事无线网络和Java应用程序安全性和教育的计算机安全性咨询公司。
Brad在IBM(位于明尼苏达州的Rochester)工作了14年,他从AS/400的第一个发行版就开始从事其所有方面的硬件和软件开发。
他是促使IBM转而支持Java平台的关键人物,并且是IBM最大的Java应用程序―称为SanFrancisco(现在是WebSphere的一部分)的商业应用程序框架产品―的首席架构设计师。
他还是ImationCorp.数据存储部门的首席技术官,以及该公司研发组织的领导。
Brad拥有计算机和电子工程学位,以及威斯康星大学麦迪逊分校计算机科学博士头衔。
他目前在明尼苏达大学教授电子和计算机工程高级设计课程,并将于2002年秋季开设和教授该大学的计算机安全性课程。
可通过BradRubin@BradR与Brad联系。
Java安全性编程概念
Java平台是如何使安全编程更方便的
第1页(共5页)
Java编程语言和环境有许多特性使安全编程更方便:
∙无指针,这意味着Java程序不能对地址空间中的任意内存位置寻址。
∙字节码验证器,在编译成.class文件之后运行,在执行之前检查安全性问题。
例如,访问超出数组大小的数组元素的尝试将被拒绝。
因为缓冲区溢出攻击是造成大多数系统漏洞的主要原因,所以这是一种重要的安全性特性。
∙对资源访问的细颗粒度控制,用于applet和应用程序。
例如,可以限制applet对磁盘空间的读或写,或者可以授权它仅从特定目录读数据。
可以根据对代码签名的人(请参阅代码签名的概念)以及代码来源处的http地址来进行授权。
这些设置都出现在java.policy文件中。
∙大量库函数,这些函数用于主要密码构件和SSL(本教程的主题)以及认证和授权(在本系列的第二篇教程中讨论)。
此外,有众多的第三方库可用于额外的算法。
什么是安全编程技术?
第2页(共5页)
简单地说,有多种编程风格和技术可以帮助确保应用程序更安全。
考虑下列两个一般示例:
∙存储/删除密码。
如果密码是存储在JavaString对象中的,则直到对它进行垃圾收集或进程终止之前,密码会一直驻留在内存中。
即使进行了垃圾收集,它仍会存在于空闲内存堆中,直到重用该内存空间为止。
密码String在内存中驻留得越久,遭到窃听的危险性就越大。
更糟的是,如果实际内存减少,则操作系统会将这个密码String换页调度到磁盘的交换空间,因此容易遭受磁盘块窃听攻击。
为了将这种泄密的可能性降至最低(但不是消除),您应该将密码存储在char数组中,并在使用后对其置零。
(String是不可变的,所以无法对其置零。
)
∙智能序列化。
当为存储器或传输任何私有字段而序列化对象时,缺省情况下,这些对象都呈现在流中。
因此,敏感数据很容易被窃听。
可以使用transient关键字来标记属性,这样在流中将忽略该属性。
当在本教程中需要用到这些技术以及其它技术时,我们将更详细地讨论它们。
JDK1.4中集成了安全性
第3页(共5页)
在JDK1.4之前,许多安全性功能必须作为扩展添加到基本Java代码分发版中。
严格的美国出口限制要求这种功能的分离。
现在,新的宽松法规使安全性特性和基本语言更紧密的集成成为可能。
下列软件包(在1.4发行版之前作为扩展使用)现在集成到了JDK1.4中:
∙JCE(Java密码术扩展)
∙JSSE(Java安全套接字扩展)
∙JAAS(Java认证和授权服务)
JDK1.4还引入了两种新功能:
∙JGSS(Java通用安全性服务(JavaGeneralSecurityService))
∙CertPathAPI(Java证书路径API(JavaCertificationPathAPI))
JCE、JSSE和CertPathAPI是本教程讨论的主题。
在本系列的下一篇教程中,我们将重点介绍JAAS。
这两篇教程都不讨论JGSS(它提供一般框架以在两个应用程序之间安全地交换消息)。
第三方库充实了安全性
第4页(共5页)
我们可以用第三方库(也称为提供程序)来增强当前Java语言中已经很丰富的功能集。
提供程序添加了额外的安全性算法。
作为库示例,我们将使用BouncyCastle提供程序(请参阅参考资料)。
BouncyCastle库提供了其它密码算法,包括本教程什么是公钥密码术?
和什么是数字签名?
中讨论的流行的RSA算法。
尽管您的目录名和java.security文件可能有一点不同,但仍可用以下模板安装BouncyCastle提供程序。
要安装这个库,请下载bcprov-jdk14-112.jar文件并将它放到j2sdk1.4.0\jre\lib\ext和ProgramFiles\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=.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
展望
第5页(共5页)
在本章中,我们已经介绍了Java语言提供的有助于确保编程保持安全的特性(无论是完全集成的还是基于扩展的)。
我们提供了一些安全编程技术的通用示例以帮助您熟悉这个概念。
我们介绍了过去是作为扩展的但现在集成到版本1.4发行版中的安全性技术;我们也注意到两种新的安全性技术。
我们还说明了了第三方库通过提供新技术能够增强安全性程序。
在本教程余下的部分,我们将让您熟悉这些旨在提供安全的消息传递的概念(因为它们应用于Java编程):
∙消息摘要。
这是一种与消息认证码结合使用以确保消息完整性的技术。
∙私钥加密。
被设计用来确保消息机密性的技术。
∙公钥加密。
允许通信双方不必事先协商秘钥即可共享秘密消息的技术。
∙数字签名。
证明另一方的消息确定来自正确通信方的位模式。
∙数字证书。
通过让第三方认证机构认证消息,向数字签名添加另一级别安全性的技术。
∙代码签名。
由可信的实体将签名嵌入被传递的代码中的概念。
∙SSL/TLS。
在客户机和服务器之间建立安全通信通道的协议。
传输层安全性(TransportLayerSecurity(TLS))是安全套接字层(SecureSocketsLayer(SSL))的替代品。
当我们讨论上述每个主题时,都将提供示例和样本代码。
确保消息的完整性
概述
第1页(共7页)
我们将在本章中了解消息摘要,它获取消息中的数据并生成一个被设计用来表示该消息“指纹”的位块。
我们还将讨论JDK1.4支持的与消息摘要相关的算法、类和方法,并为消息摘要和消息认证特性提供代码示例和样本的执行代码。
什么是消息摘要?
第2页(共7页)
消息摘要是一种确保消息完整性的功能。
消息摘要获取消息作为输入并生成位块(通常是几百位长),该位块表示消息的指纹。
消息中很小的更改(比如说,由闯入者和窃听者造成的更改)将引起指纹发生显著更改。
消息摘要函数是单向函数。
从消息生成指纹是很简单的事情,但生成与给定指纹匹配的消息却很难。
消息摘要可强可弱。
校验和(消息的所有字节异或运算的结果)是弱消息摘要函数的一个示例。
很容易修改一个字节以生成任何期望的校验和指纹。
大多数强函数使用散列法。
消息中1位更改将引起指纹中巨大的更改(理想的比例是更改指纹中50%的位)。
算法、类和方法
第3页(共7页)
JDK1.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():
读取消息摘要。
如果密钥被用作消息摘要生成过程的一部分,则将该算法称为消息认证码。
JDK1.4支持HMAC/SHA-1和HMAC/MD5消息认证码算法。
Mac类使用由KeyGenerator类产生的密钥操作消息认证码。
消息认证码示例中使用了下列方法:
∙KeyGenerator.getInstance("HmacMD5")和.generateKey():
生成密钥。
∙Mac.getInstance("HmacMD5"):
创建MAC对象。
∙.init(MD5key):
初始化MAC对象。
∙.update(plaintext)和.doFinal():
用明文字符串计算MAC对象。
消息摘要代码示例
第4页(共7页)
importjava.security.*;
importjavax.crypto.*;
//
//GenerateaMessageDigest
publicclassMessageDigestExample{
publicstaticvoidmain(String[]args)throwsException{
//
//checkargsandgetplaintext
if(args.length!
=1){
System.err.println("Usage:
javaMessageDigestExampletext");
System.exit
(1);
}
byte[]plainText=args[0].getBytes("UTF8");
//
//getamessagedigestobjectusingtheMD5algorithm
MessageDigestmessageDigest=MessageDigest.getInstance("MD5");
//
//printouttheproviderused
System.out.println("\n"+messageDigest.getProvider().getInfo());
//
//calculatethedigestandprintitout
messageDigest.update(plainText);
System.out.println("\nDigest:
");
System.out.println(newString(messageDigest.digest(),"UTF8"));
}
}
消息摘要样本执行的结果
第5页(共7页)
D:
\IBM>javaMessageDigestExample"Thisisatest!
"
SUN(DSAkey/parametergeneration;DSAsigning;SHA-1,MD5digests
;SecureRandom;X.509certificates;JKSkeystore;PKIXCertPathValidator
;PKIXCertPathBuilder;LDAP,CollectionCertStores)
Digest:
D93,.x2%$kd8xdp3di5*
消息认证码示例
第6页(共7页)
importjava.security.*;
importjavax.crypto.*;
//
//GenerateaMessageAuthenticationCode
publicclassMessageAuthenticationCodeExample{
publicstaticvoidmain(String[]args)throwsException{
//
//checkargsandgetplaintext
if(args.length!
=1){
System.err.println
("Usage:
javaMessageAuthenticationCodeExampletext");
System.exit
(1);
}
byte[]plainText=args[0].getBytes("UTF8");
//
//getakeyfortheHmacMD5algorithm
System.out.println("\nStartgeneratingkey");
KeyGeneratorkeyGen=KeyGenerator.getInstance("HmacMD5");
SecretKeyMD5key=keyGen.generateKey();
System.out.println("Finishgeneratingkey");
//
//getaMACobjectandupdateitwiththeplaintext
Macmac=Mac.getInstance("HmacMD5");
mac.init(MD5key);
mac.update(plainText);
//
//printouttheproviderusedandtheMAC
System.out.println("\n"+mac.getProvider().getInfo());
System.out.println("\nMAC:
");
System.out.println(newString(mac.doFinal(),"UTF8"));
}
}
消息认证样本执行
第7页(共7页)
D:
\IBM>javaMessageAuthenticationCodeExample"Thisisatest!
"
Startgeneratingkey
Finishgeneratingkey
SunJCEProvider(implementsDES,TripleDES,Blowfish,PBE,Diffie-Hellman,
HMAC-MD5,HMAC-SHA1)
MAC:
Dkdj47x4#.@kd#n8a-x>
注:
因为代码用线程行为定时来生成优质的伪随机数,所以密钥生成很费时。
一旦生成了第一个数,其它数的生成就快得多了。
还请注意,与消息摘要不同的是,消息认证码使用密码提供程序。
(有关提供程序的更多信息,请参阅第三方库充实了安全性。
)
保持消息的机密性
概述
第1页(共7页)
在本节中,我们将研究私钥加密的使用并主要讨论诸如密码块、填充、序列密码和密码方式之类的概念。
我们将迅速地讨论密码算法、类和方法的细节并用代码示例和样本执行来说明这个概念。
什么是私钥密码术?
第2页(共7页)
消息摘要可以确保消息的完整性,但不能用来确保消息的机密性。
要确保机密性,我们需要使用私钥密码术来交换私有消息。
Alice和Bob各有一个只有他们两人知道的共享密钥,并且约定使用一种公用密码算法或密码。
也就是说,他们保持密钥的私有性。
当Alice想给Bob发送消息时,她加密原始消息(称为明文)以创建密文,然后将密文发送给Bob。
Bob接收了来自Alice的密文并用自己的私钥对它解密,以重新创建原始明文消息。
如果窃听者Eve侦听该通信,她仅得到密文,因此消息的机密性得以保持。
您可以加密单一位或位块(称为块)。
块(称为密码块)通常是64位大小。
如果消息大小不是64位的整数倍,那么必须填充短块(关于填充的更多信息请参阅什么是填充?
)。
单一位加密在硬件实现中更常见。
单一位的密码被称为序列密码。
私钥加密的强度取决于密码算法和密钥的长度。
如果算法比较好,那么攻击它的唯一方法就是使用尝试每个可能密钥的蛮力攻击,它平均要尝试(1/2)*2*n次,其中n是密钥的位数。
在美国出口法规很严时,只允许出口40位密钥。
这种密钥长度相当弱。
美国官方标准(DES算法)使用56位密钥,但随着处理器速度的增加,它变得越来越弱。
现在,通常首选128位密钥。
如果每秒可以尝试一百万个密钥,那么,使用128位密钥,找到密钥所需的平均时间是宇宙年龄的许多倍!
什么是填充?
第3页(共7页)
如前所述,如果使用分组密码而消息长度不是块长度的整数倍,那么,必须用字节填充最后一个块以凑成完整的块大小。
有许多方法填充块,譬如全用零或一。
在本教程中,我们将对私钥加密使用PKCS5填充,而对公钥加密使用PKCS1。
使用PKCS5时,由一个其值表示剩余字节数的重复字节来填充短块。
我们不会在本教程中更深入地讨论填充算法,但您需要了解的信息是,JDK1.4支持下列填充技术:
∙无填充
∙PKCS5
∙OAEP
∙SSL3
BouncyCastle库(请参阅第三方库充实了安全性和参考资料)支持其它填充技术。
方式:
确定加密是如何工作的
第4页(共7页)
可以以各种方式使用给定密码。
方式允许您确定加密是如何工作的。
例如,您可以允许一个块的加密依赖于前一个块的加密,也可以使块的加密独立于任何其它块的加密。
根据您的需求选择方式,并且您必须考虑各方面的权衡(安全性、并行处理能力以及明文和密文的容错等)。
方式的选择超出了本教程的讨论范围(请参阅参考资料以进行更深入的阅读),但再次指出,您要了解的信息是,Java平台支持下列方法:
∙ECB(电子密码本(ElectronicCodeBook))
∙CBC(密码块链接(CipherBlockChaining))
∙CFB(密码反馈方式(CipherFeedbackMode))
∙OFB(输出反馈方式(OutputFeedbackMode))
∙PCBC(填充密码块链接(PropagatingCipherBlockChaining))
算法、类和方法
第5页(共7页)
JDK1.4支持下列私钥算法:
∙DES。
DES(数据加密标准)是由IBM于上世纪70年代发明的,美国政府将其采纳为标准。
它是一种56位分组密码。
∙TripleDES。
该算法被用来解决使用DES技术的56位时密钥日益减弱的强度,其方法是:
使用两