1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > java security / SSL / TLS / md5 / sha / base64 / rsa / des / aes / 3des

java security / SSL / TLS / md5 / sha / base64 / rsa / des / aes / 3des

时间:2024-07-05 08:43:30

相关推荐

java security / SSL / TLS / md5 / sha / base64 / rsa / des / aes / 3des

java jdk keytool

C:\Program Files\Java\jdk1.7.0_11\bin\keytool.exe

[lindows@Loadrunner19 ~]$ ll /opt/soft/jdk1.7.0_11/bin/keytool

-rwxrwxrwx 1 lindows lindows 7957 Jan 12 18:05 /opt/soft/jdk1.7.0_11/bin/keytool

tomcat7 开启https ,使用JDK 7的keytool 生成tomcat证书

/blog/1532655

https单向/双向认证的tomcat配置攻略

/blog/1538719

C:\Program Files\Java\jdk1.7.0_11\bin>keytool -v -genkey -alias tomcat -keyalg RSA -keystore d:/tomcat.keystore

C:\Program Files\Java\jdk1.7.0_11\bin>keytool.exe -help

Dos代码 密钥和证书管理工具命令:-certreq生成证书请求-changealias更改条目的别名-delete删除条目-exportcert导出证书-genkeypair生成密钥对-genseckey生成密钥-gencert根据证书请求生成证书-importcert导入证书或证书链-importkeystore从其他密钥库导入一个或所有条目-keypasswd更改条目的密钥口令-list列出密钥库中的条目-printcert打印证书内容-printcertreq打印证书请求的内容-printcrl打印CRL文件的内容-storepasswd更改密钥库的存储口令使用"keytool-command_name-help"获取command_name的用法

C:\Program Files\Java\jdk1.7.0_11\bin>keytool.exe -genkey -help

Dos代码 keytool-genkeypair[OPTION]...生成密钥对选项:-alias<alias>要处理的条目的别名-keyalg<keyalg>密钥算法名称-keysize<keysize>密钥位大小-sigalg<sigalg>签名算法名称-destalias<destalias>目标别名-dname<dname>唯一判别名-startdate<startdate>证书有效期开始日期/时间-ext<value>X.509扩展-validity<valDays>有效天数-keypass<arg>密钥口令-keystore<keystore>密钥库名称-storepass<arg>密钥库口令-storetype<storetype>密钥库类型-providername<providername>提供方名称-providerclass<providerclass>提供方类名-providerarg<arg>提供方参数-providerpath<pathlist>提供方类路径-v详细输出-protected通过受保护的机制的口令使用"keytool-help"获取所有可用命令

linux jdk7 keytool

[lindows@Loadrunner19 ~]$/opt/soft/jdk1.7.0_11/bin/keytool --help

Shell代码 KeyandCertificateManagementToolCommands:-certreqGeneratesacertificaterequest-changealiasChangesanentry'salias-deleteDeletesanentry-exportcertExportscertificate-genkeypairGeneratesakeypair-genseckeyGeneratesasecretkey-gencertGeneratescertificatefromacertificaterequest-importcertImportsacertificateoracertificatechain-importkeystoreImportsoneorallentriesfromanotherkeystore-keypasswdChangesthekeypasswordofanentry-listListsentriesinakeystore-printcertPrintsthecontentofacertificate-printcertreqPrintsthecontentofacertificaterequest-printcrlPrintsthecontentofaCRLfile-storepasswdChangesthestorepasswordofakeystoreUse"keytool-command_name-help"forusageofcommand_name

[root@Loadrunner19 bin]#/usr/bin/keytool -?

Shell代码 Unrecognizedcommand:--helpUsage:keytool[COMMAND][--COMMAND]...Manageprivatekeysandpubliccertificates.Availablecommands:-genkeyGenerateaKeyEntry,eventuallycreatingakeystore.[-aliasALIAS][-keyalgALGORITHM][-keysizeKEY_SIZE][-sigalgALGORITHM][-dnameNAME][-keypassPASSWORD][-validityDAY_COUNT][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].-importAddKeyEntriesandTrustedCertificates.[-aliasALIAS][-fileFILE][-keypassPASSWORD][-noprompt][-trustcacerts][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].-selfcertGenerateaself-signedTrustedCertificate.[-aliasALIAS][-sigalgALGORITHM][-dnameNAME][-validityDAY_COUNT][-keypassPASSWORD][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].-identitydbNOTIMPLEMENTEDYET.ImportJDK1.1IdentityDatabase.[-fileFILE][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].-certreqIssueaCertificateSigningRequest(CSR).[-aliasALIAS][-sigalgALGORITHM][-fileFILE][-keypassPASSWORD][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v][-attributes].-exportExportaCertificatefromakeystore.[-aliasALIAS][-fileFILE][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-rfc][-v].-listPrintoneorallCertificatesinakeystoretoSTDOUT.[-aliasALIAS][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-rfc][-v].-printcertPrintahuman-readableformofaCertificateinaFILE.[-fileFILE][-v].-keycloneCloneaKeyEntryinakeystore.[-aliasALIAS][-destALIAS][-keypassPASSWORD][-newPASSWORD][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].-storepasswdChangethepasswordprotectingakeystore.[-newPASSWORD][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].-keypasswdChangethepasswordprotectingaKeyEntryinakeystore.[-aliasALIAS][-keypassPASSWORD][-newPASSWORD][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].-deleteDeleteaKeyEntryoraTrustedCertificatefromakeystore.[-aliasALIAS][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].-cacertImportaCA'sTrustedCertificate.[-fileFILE][-storetypeSTORE_TYPE][-keystoreURL][-storepassPASSWORD][-providerPROVIDER_CLASS_NAME][-v].Standardoptions:-helpprintthishelp,thenexit-versionprintversionnumber,thenexit-JOPTIONpassargumenttotheJavaruntimePleasereportbugsat/software/classpath/bugs.html

.ssl

JAVA 加密技术

/topic/426342

Java加密技术(一)

Java加密技术(二)

Java加密技术(三)

Java加密技术(四)

Java加密技术(五)

Java加密技术(六)

Java加密技术(七)

Java加密技术(八)

Java加密技术(九)

Java加密技术(十)

HTTPS和HTTP的区别

/blog/318912

/redirect.php?tid=184648&goto=lastpost

HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议

它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息。它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版。

它是由Netscape开发并内置于其浏览器中,用于对数据进行压缩和解压操作,并返回网络上传送回的结果。HTTPS实际上应用了Netscape的安全全套接字层(SSL)作为HTTP应用层的子层。(HTTPS使用端口443,而不是象HTTP那样使用端口80来和TCP/IP进行通信。)SSL使用 40 位关键字作为RC4流加密算法,这对于商业信息的加密是合适的。HTTPS和SSL支持使用X.509数字认证,如果需要的话用户可以确认发送者是谁。

HTTPS和HTTP的区别:

https协议需要到ca申请证书,一般免费证书很少,需要交费。

http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议

http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。

http的连接很简单,是无状态的

HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全

HTTPS解决的问题:

1 . 信任主机的问题. 采用https 的server 必须从CA 申请一个用于证明服务器用途类型的证书. 改证书只有用于对应的server 的时候,客户度才信任次主机. 所以目前所有的银行系统网站,关键部分应用都是https 的. 客户通过信任该证书,从而信任了该主机. 其实这样做效率很低,但是银行更侧重安全. 这一点对我们没有任何意义,我们的server ,采用的证书不管自己issue 还是从公众的地方issue, 客户端都是自己人,所以我们也就肯定信任该server.

2 . 通讯过程中的数据的泄密和被窜改

1. 一般意义上的https, 就是 server 有一个证书.

a) 主要目的是保证server 就是他声称的server. 这个跟第一点一样.

b) 服务端和客户端之间的所有通讯,都是加密的.

i. 具体讲,是客户端产生一个对称的密钥,通过server 的证书来交换密钥. 一般意义上的握手过程.

ii. 加下来所有的信息往来就都是加密的. 第三方即使截获,也没有任何意义.因为他没有密钥. 当然窜改也就没有什么意义了.

2. 少许对客户端有要求的情况下,会要求客户端也必须有一个证书.

a) 这里客户端证书,其实就类似表示个人信息的时候,除了用户名/密码, 还有一个CA 认证过的身份. 应为个人证书一般来说上别人无法模拟的,所有这样能够更深的确认自己的身份.

b) 目前少数个人银行的专业版是这种做法,具体证书可能是拿U盘作为一个备份的载体.

HTTPS 一定是繁琐的.

a) 本来简单的http协议,一个get一个response. 由于https 要还密钥和确认加密算法的需要.单握手就需要6/7 个往返.

i. 任何应用中,过多的round trip 肯定影响性能.

b) 接下来才是具体的http协议,每一次响应或者请求, 都要求客户端和服务端对会话的内容做加密/解密.

i. 尽管对称加密/解密效率比较高,可是仍然要消耗过多的CPU,为此有专门的SSL 芯片. 如果CPU 信能比较低的话,肯定会降低性能,从而不能serve 更多的请求.

ii. 加密后数据量的影响. 所以,才会出现那么多的安全认证提示

电信行业Http接口(通道)设计思路与实现过程

/topic/398334

本页不但包含安全的内容,也包含不安全的内容.是否显示不安全的内容?

https中夹带有http的问题,

/blog/445608

今天解决了一个困扰我们很久的一个问题(说是很久,但一直没有花时间去research,想想不影响功能使用,没什么啊。而真正解决问题,也就那二十来分钟,哎!人已经懒惰成这样了)。

问题描述:

我们利用ajax做了一套系统,但通过https访问的时候,IE总会弹出下面的对话框:

而在我们的代码中所有的访问都是通过https的,怎么会有不安全的元素呢?在网上google了一下,有人提到可能是iframe的问题。而在我们系统中确实用到了很多的iframe。修改code,去掉所有的iframe。再次run,上面的对话框没有了,终于找到原因了。但是我们的系统中是需要iframe啊?请看下面的code:

1 var iframe = document.createElement( " iframe " );

2 iframe.style.zIndex =- 1 ;

3 iframe.style.position = " absolute " ;

4 iframe.style.left = 0 ;

5 iframe.style.top = 0 ;

6 iframe.style.width = menu.getSize().x - 2 ;

7 iframe.style.height = menu.getSize().y - 4 ;

8 menu.getHtmlElement().appendChild(iframe);

从上面的code,可以看出代码中没有指定src属性,这样IE是没有办法知道这个iframe将引用的是安全内容还是不安全内容呢。所以会弹出上面的对话框。增加src属性,修改code:

var iframe=document.createElement("<iframe src='blank.html'>");//src是个只读属性,不能直接赋值,black.html是个空的静态页面。

再次run,对话框没有了,问题解决。

附录:

在IE下,如果div悬浮在select上面。select会透过div显示出来。这非常影响视觉效果。网上有很多的解决办法,其中一个就是在div中增加iframe。我们就是通过这个方法的,但又产生了这个问题。

md5

/view/7636.htm

MD5

目录 MD5简介 算法的应用 算法描述 具体的一个MD5实现 一些破解MD5的网站

(百万亿以上数据)

和 是一个网站(这三个网站都是国人做的)。

/ (对数字破解比较好)

(对字母破解比较好)

http://nz. (从1到4位数字)- 好像关了

http://us. (美英字典的破解收集和IP地址)

(估计是基础字典的破解)

(这个倒是说得很厉害,但是在实际中,很多次我在这里都找不到)

http://passcracking.ru

/md5

http://plain-text.info (这个是我比较喜欢一个.也请你提交一些已破解的MD5)

/tools/hashcrack.php (多种破解.我试过...没有一次破解出来.非常没用)

/md5/ - (破解挪威人(Norwegian)字典)

http://passcrack.spb.ru/

http://shm.pl/md5/

/

/md5/

/

/

http://md5.khrone.pl/

/md5/index.php

/

/

/

http://md5.xpzone.de/

http://md5.geeks.li/

/

/english.aspx

http://www./

http://md5.overclock.ch/biz/index.php?p=md5crack&l=en

http://alimamed.pp.ru/md5/ (如果你看不懂俄文,我告诉你,把你的MD5放到第2个格子)

http://md5crack.it-helpnet.de/index.php?op=add (德国的....)

http://cijfer.hua.fi/ (Projects->md5 reverse lookup)

http://shm.hard-core.pl/md5/

/index.php?view=cracker

/services/results.php (我试过破过几次在这里)

/ (需要捐献)

/cracker/

/index.php?main_page=product_info&cPath=3&products_id=7 这个是证明他们的破解商品的质量..好让你来买这个破解程序...但是...只要能破解到即可.你又不一定要买..

http://0ptix.co.nr/md5

lm:

http://sys9five.ath.cx:8080/hak5rtables/

http://lasecwww.epfl.ch/~oechslin/projects/ophcrack/

lm + ntlm:

http://plain-text.info

/tools/hashcrack.php

/services/results.php

/

/index.php?main_page=product_info&cPath=3&products_id=7

md4:

/tools/hashcrack.php

/services/results.php

/

sha1:

/tools/hashcrack.php

http://passcrack.spb.ru/

/

/services/results.php

/

/

http://passcracking.ru

/

16位和32位密码查询

MD5:670B14728AD9902AECBA32E22FA4F6BD

解密:000000

md5(13851897759,32) = 7d3be18db14b452a11e4940ede114004

md5(13851897759,16) = b14b452a11e4940e

md5(18651665725,32) = 584285834b0032b2f809cde51228bb8e

md5(18651665725,16) = 4b0032b2f809cde5

md5(,32) = be1fbc4210ef483dac295f1d7d424454

md5(,16) = 10ef483dac295f1d

md5(,32) = 1e0cca7301a54982fe7010c5a404d5bf

md5(,16) = 01a54982fe7010c5

/

/

收录概况:

本站数据量不断增长中,是否收费可能也发生变动。

收录举例:

热门查询:

下面是查询较多的

SSL

PKI

security

重放攻击(Replay attack)是一种网络攻击,它恶意的欺诈性的重复或拖延正常的数据传输。

/wiki/%E9%87%8D%E6%94%BE%E6%94%BB%E5%87%BB

/jiangbin00cn/archive//11/07/1872127.aspx

/question/50733410.html?fr=qrl

Java的简单MD5加密

/blog/505475

/** * MD5加密运算* @param str 要加密的字符串,不为null* @return result 加密后的MD5值*/public String getMD5(String str){MessageDigest messageDigest = null;try {messageDigest = MessageDigest.getInstance(&quot;MD5&quot;);messageDigest.reset(); // 重置,供再次使用messageDigest.update(str.getBytes(&quot;UTF-8&quot;)); // 使用指定的字节数组更新摘要,Char[]为编码为UTF-8} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}byte[] byteArr = messageDigest.digest(); // 重置摘要,通过诸如填充之类的最终操作完成哈希计算StringBuffer md5Buffer = new StringBuffer(); // 构造一个字符串缓冲区,通过Append追加,装载加密后的值/** 下面涉及到位运算,不懂,研究中。。。*/for (int i = 0; i < byteArr.length; i++) {if (Integer.toHexString(0xFF & byteArr[i]).length() == 1) {md5Buffer.append("0").append(Integer.toHexString(0xFF & byteArr[i]));} else {md5Buffer.append(Integer.toHexString(0xFF & byteArr[i]));}}String result = md5Buffer.toString(); // 从缓冲区得到运算结果return result;}

/p/richinutil/source/browse/trunk/richinutil/src/org/richin/crypto/util/MD5Util.java?r=80

package org.richin.crypto.util;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;/*** 使用java.security.MessageDigest类写的一个工具类用来获取MD5码* @author Talen* @see java.security.MessageDigest*/public class MD5Util {/** * 默认的密码字符串组合,apache校验下载的文件的正确性用的就是默认的这个组合 */ protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f' }; protected static MessageDigest messagedigest = null; static{ try{ messagedigest = MessageDigest.getInstance("MD5"); }catch(NoSuchAlgorithmException nsaex){ System.err.println(MD5Util.class.getName()+"初始化失败,MessageDigest不支持MD5Util。"); nsaex.printStackTrace(); } } /*** 向getMD5方法传入一个你需要转换的原始字符串,将返回字符串的MD5码* @param code 原始字符串* @return 返回字符串的MD5码*/public static String getMD5(String code) throws Exception {MessageDigest messageDigest = MessageDigest.getInstance("MD5");byte[] bytes = code.getBytes();byte[] results = messageDigest.digest(bytes);StringBuilder stringBuilder = new StringBuilder();for (byte result : results) {//将byte数组转化为16进制字符存入stringbuilder中stringBuilder.append(String.format("%02x", result));}return stringBuilder.toString();}/** * 适用于上G大的文件 * @param file * @return * @throws IOException */ public static String getFileMD5String(File file) throws IOException { FileInputStream in = new FileInputStream(file); FileChannel ch = in.getChannel(); MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); messagedigest.update(byteBuffer); return bufferToHex(messagedigest.digest()); } private static String bufferToHex(byte bytes[]) { return bufferToHex(bytes, 0, bytes.length); } private static String bufferToHex(byte bytes[], int m, int n) { StringBuffer stringbuffer = new StringBuffer(2 * n); int k = m + n; for (int l = m; l < k; l++) { appendHexPair(bytes[l], stringbuffer); } return stringbuffer.toString(); } private static void appendHexPair(byte bt, StringBuffer stringbuffer) { char c0 = hexDigits[(bt & 0xf0) >> 4]; char c1 = hexDigits[bt & 0xf]; stringbuffer.append(c0); stringbuffer.append(c1); } public static boolean checkPassword(String password, String md5PwdStr) { String s = getMD5String(password); return s.equals(md5PwdStr); } public static String getMD5String(String s) { return getMD5String(s.getBytes()); } public static String getMD5String(byte[] bytes) { messagedigest.update(bytes); return bufferToHex(messagedigest.digest()); } /** *//*** main方法用于测试*/public static void main(String[] args) {// TODO Auto-generated method stub//字符'a'的MD5码是0cc175b9c0f1b6a831c399e269772661,如果是,则成功。try {System.out.println(MD5Util.getMD5("a"));} catch (Exception e) {e.printStackTrace();}}} /*Hide detailsChange logr80 by aslanchin on Nov 17, Diff[No log message]Go to: Project members, sign in to write a code reviewOlder revisionsr45 by aslanchin on May 30, DiffAll revisions of this fileFile infoSize: 3662 bytes, 109 linesView raw file */

重庆沙海硬件加密机

/ourocx.jsp#

一、高安全性

密码全程防护,全程不出现明文

防御100%的已知的键盘钩子

防止重放攻击、防止中间人篡改

密钥安全:一次一密、非对称加密、私钥存储在服务器不可获取

客户端核心模块工作在驱动层,客户端程序防反汇编,防脱壳技术,抗逆向分析

二、易用性

客户端可在浏览器窗口上自动安装、升级

也有独立安装使用的一键点击安装包

后台操作维护方便,基于HTTPS的WEB管理界面

三、高可用性

支持HA,保证业务连续性

沙海信息防护系统针对不同层次客户规模需求提供不同规格的产品供用户选择

四、兼容性

支持WIN2000-WIN7全系列操作系统、IE5-IE8全系列浏览器

全面兼容主流防病毒及防火墙软件

兼容集中监控软件或实时监控平台

五、可审计性

支持内部行为审计(管理员操作日志)

支持外部行为审计(客户信息日志)

支持回滚日志及远程SYSLOG日志服务器

安全编码规范

版本号:V2.4.2

目录

1目标

2安全编码原则

3安全设计中的重要问题分布

4安全编码规范

4.1验证用户

1、身份验证

2、密码管理遵循的原则

4.2保护敏感数据

1、前端保护敏感数据

2、后端保护敏感数据

3、传输保护

4.3防止会话劫持和保护cookie

1、会话管理

2、cookie管理

4.4提供安全配置

4.5验证输入

4.6授权用户

4.7访问控制

4.8审核和记录活动和事件

1、错误处理

2、日志记录

4.9数据库安全性

4.10加密

4.11输出编码

5安全编码示例

5.1输入验证和数据合法性校验

避免SQL注入

避免XML注入

避免跨站点脚本(XSS)

5.2声明和初始化

避免类初始化的相互依赖

5.3表达式

不可忽略方法的返回值

不要引用空指针

使用Arrays.equals()来比较数组的内容

5.4数字类型和操作

防止整数溢出

避免除法和取模运算分母为零

5.5类和方法操作

数据成员声明为私有,提供可访问的包装方法

敏感类不允许复制

比较类的正确做法

不要硬编码敏感信息

验证方法参数

不要使用过时、陈旧或低效的方法

数组引用问题

不要产生内存泄露

5.6异常处理

不要忽略捕获的异常

不允许暴露异常的敏感信息

不允许抛出RuntimeException, Exception,Throwable

不要捕获NullPointerException或其他父类异常

5.7多线程编程

确保共享变量的可见性

确保共享变量的操作是原子的

不要调用Thread.run(),不要使用Thread.stop()以终止线程

确保执行阻塞操作的线程可以终止

相互依存的任务不要在一个有限的线程池执行

5.8输入输出

程序终止前删除临时文件

检测和处理文件相关的错误

及时释放资源

5.9序列化

不要序列化未加密的敏感数据

在序列化过程中避免内存和资源泄漏

反序列化要在程序最小权限的安全环境中

6安全编码检查

6.1输入和输出

6.2API程序

6.3跨站脚本

6.4响应截断

6.5重定向

6.6SQL和数据库

6.7SSL

6.8会话管理

6.9操作系统命令

6.10记录

6.11架构组件分析

6.12JavaScript/XMLHTTP

1目标

使用本规范可以实现:

1.确定安全Web应用程序的重要体系结构和设计问题。

2.设计时考虑重要部署问题。

3.制定能增强Web应用程序输入验证的策略。

4.设计安全的身份验证和会话管理机制。

5.选择适当的授权模型。

6.实现有效的帐户管理方法,并保护用户会话。

7.对隐私、认可、防止篡改和身份验证信息进行加密。

8.防止参数操作。

9.设计审核和记录策略。

2安全编码原则

1.程序只实现指定的功能

2.永不要信任用户输入,对用户输入数据做有效性检查

3.必须考虑意外情况并进行处理

4.不要试图在发现错误之后继续执行

5.尽可能使用安全函数进行编程

6.小心、认真、细致地编程

3安全设计中的重要问题分布

图1列出了安全设计方法中必须解决的重要问题:验证用户、保护敏感数据、防止会话劫持和保护cookie、提供安全配置、验证输入、授权用户、访问控制、审核和记录活动和事件以及数据库安全。本文档分类总结归纳出解决以上重要问题必须遵循的一些基本原则,遵循基本原则可以很大程度地提高系统的安全性,减少漏洞,预防攻击。

图1

4安全编码规范

4.1验证用户

1、身份验证

1、验证控制的执行代码放在服务器上

2、对所有的验证控件都使用一个集中的工具,包括调用外部认证服务的库

3、确保身份验证凭证不是以明文的形式在线传输的

4、保护身份验证cookie

5、只使用HTTP POST请求发送身份验证凭据等敏感信息,只接受通过HTTP“POST”方法传递的信息,不可接受通过HTTP“GET”方法传递的信息

6、所有验证控件应该安全地失败

7、验证失败时进行模糊提示,失败响应不应该表明身份认证数据的哪一部分是不正确的的。例如,只是都使用“无效的用户名和/或密码”,而不是“无效的用户名”或“密码无效”。显示界面和源代码中的错误响应必须是真正的一致。

8、对最终用户账户使用账户锁定策略:在无效登录尝试超过预定的次数(例如,五次尝试是最常见的)后强制将账户禁用或将事件写入日志。该账户必须禁用足够长的时间来阻止对凭证的蛮力猜测,但不应比允许执行拒绝服务攻击的时间更长(请注意,账户锁定策略不能用于拒绝服务攻击)

9、一个用户账号的最后一次使用(成功或不成功)应该在用户下次成功登录时报告给他们

10、尽可能建立和利用标准的,被测试过的认证服务

2、密码管理遵循的原则

1、强制要求密码的长度。八个字符是常用的,但16更好或考虑使用多单词组成词组

2、在用户的屏幕上输入的密码被遮蔽(例如,基于Web形式使用“密码”输入型)

3、密码重置和更改的操作需要与创建账户和身份验证相同的控制水平,密码重置发生时通知用户,同时密码重置的问题应该支持足够随机的答案。(例如,“最喜爱的书”是一个坏问题,因为“圣经”是一个非常普通的答案)

4、临时密码和链接应该有一个短的到期时间,并在下次使用时强制执行临时密码的更改

5、防止密码重复使用

6、建议对密码字段禁用“记住我”功能

7、注意密码的储存,不要在用户存储中存储密码,将其加密储存在服务器上,一般它以保密性强的单向密码哈希被储存(不要使用MD5算法)。使用强密码,并将随机salt值与该密码结合。对于重要的系统入口,可有多个密码,如:管理员密码,管理认证码。分别把他们存放在不同的位置:数据库与文件中,这种多密码大大增强系统的安全性(其中对密码的加密方法,见下文的加密)

8、建议设置密码有效期:密码不应固定不变,而应作为常规密码维护的一部分,通过设置密码有效期对密码进行更改。在应用程序设计阶段,应该考虑提供这种类型的功能

4.2保护敏感数据

1、前端保护敏感数据

1、cookie中不要存放敏感信息,所有敏感信息存放在服务器。如果保存了敏感数据,应该确保整个cookie加密

2、如果状态数据必须存储在客户端,在服务器端使用加密和完整性检查,以便跟踪状态篡改

3、对包含敏感信息的网页禁用客户端缓存

2、后端保护敏感数据

1、保护所有存储在服务器上的敏感数据的缓存或临时副本,对敏感数据执行适当的访问控制,以免来自未授权的访问所访问,一旦不再需要那些临时工作文件,就立即清除它们

2、应用程序应该支持对不再被需要的敏感数据的清除。(如个人资料或某些财务数据)

2、加密高度敏感的储存信息,如身份验证数据,即使在服务器端也要加密。并始终使用已审核好的算法

3、防止用户下载服务器端的源代码

5、删除不必要的应用程序和系统文件,因为这可以给攻击者揭示有用的信息

3、传输保护

1、不要在HTTP GET请求参数中包括敏感信息

2、实现对所有敏感信息的传输进行加密,这应包括用于保护连接的TLS和可能是由离散加密敏感文件的一个补充或基于非HTTP连接

3、TLS证书应有效的(而不是过期的),并且有正确的域名

4、失败的TLS连接不应该回滚到一个不安全的连接

5、给所有连接指定字符编码

4.3防止会话劫持和保护cookie

1、会话管理

1、确保会话ID足够复杂以满足相关强度的要求

2、检查会话是如何储存的:例如,在数据库,在内存中等,以确定其安全性,必要时可以进行加密

3、设置会话的HTTP闲置超时

4、当无效的会话ID出现时,应有相应的处理程序

5、会话标识符在服务器上创建

6、会话管理控制应该使用审核好的算法,以确保足够随机的会话标识符

7、对任何重新验证都要生成一个新的会话标识符

8、不允许同时登录相同的用户ID

9、建议为敏感操作附加除cookie之外的额外的强随机令牌,这种方法可以用来防止跨站请求伪造攻击

2、cookie管理

1、为涉及敏感信息而保密要求高的cookie和保密性要求不高的cookie分别设置不同的域和路径

2、如果在登录前建立一个会话,关闭那个会话,并在成功登录后建立一个新会话

3、尽可能使用SSL保护会话身份验证cookie,不要通过HTTP连接传递身份验证cookie。在授权cookie内将其标记为安全的,那么它将只在浏览器和服务器通过https或其他安全协议链接时才被传输

4、将cookie设置为HttpOnly属性

4.4提供安全配置

1、确保服务器,框架和系统组件运行批准的最新版本,并且有为使用的版本发行的所有补丁

2、关闭目录列表

3、限制Web服务器,进程和服务账户具有可能的最少特权

4、发生异常时,要安全地失败

5、删除所有不必要的功能和文件

6、在部署之前,删除测试代码或不打算用于生产上的任何功能

7、禁用不必要的HTTP方法,如WebDAV扩展。如果必需有一个支持文件处理的扩展的HTTP方法,那么要利用一个良好的审核认证机制

8、应用程序的安全配置存储应能以可读的形式输出,以便支持审计

9、实施一个软件变更控制系统来管理和记录在开发和生产中代码的变更

4.5验证输入

1、在验证前将数据编码为一个共同的字符集,如UTF-8(规范化,标准化)。标准化是指将数据转化为标准形式的过程。文件路径和URL尤其倾向于标准化问题,许多广为人知的漏洞利用都直接源自标准化缺陷

2、验证预期的数据类型、范围、长度

3、使用服务器端代码执行其自身的验证。以免攻击者绕过客户端或关闭客户端脚本例程(例如,通过禁用JavaScript脚本)

4、所有的验证失败都导致输入拒绝,拒绝已知的有害的输入

5、在处理数据前,验证客户提供的所有数据,包括所有的参数。确保所有可以被恶意用户修改的输入,例如:HTTP头(例如cookies名称和值),URLs,输入字段,隐藏字段,下拉列表和其他Web组件,都被正确地验证。一定要包括从JavaScript,Flash或其他嵌入式代码的自动返回值

6、只要有可能,按照允许字符的白名单,对所有的输入进行验证:

如果任何有潜在危险的字符必须允许作为输入,确保执行了额外的控制来过滤输入。

常见的危险字符的例子包括:<>“”%()&+ \ \“\”;

谨慎检查是否为空字节(00%),检查新行字符(\ R \ N%0D%0A);

检查“点-点-斜线”(.. / .. \)路径改变字符;

过滤输入示例:使用URL编码或HTML编码来包装数据,并将其作为文本而不是可执行脚本来处理。HtmlEncode方法去除HTML字符,而UrlEncode方法对URL进行编码,使其成为有效的URL请求。

7、建议使用一个应用程序的集中输入验证例程,考虑集中式验证方法,例如,通过使用共享库中的公共验证和筛选代码。这可确保验证规则应用的一致性,此外,还能减少开发的工作量,且有助于以后的维护工作

4.6授权用户

1、确保应用程序已明确定义了用户角色和其对应的权利

2、确保在操作中使用最少的特权,限制用户对系统级资源的访问

3、确保授权机制工作正常,安全地失败,并不能绕过

4、确保授权机制对每一个请求进行了检查

5、确保开发/调试的后门程序不在生产代码中出现,以免泄露敏感信息

6、实现最少的权限,限制用户只有对那些执行他们的任务所需要的功能,数据和系统信息具有权限

4.7访问控制

1、只使用可信任的系统对象,如服务器端会话对象,来做访问授权的决策

2、访问控制应该安全失败

3、对于GET方式的请求,不能仅仅依赖“referer”头作为检查手段,因为它是可以被欺骗的。对于POST方式的请求,在通常范围内检查“referer”头可以保证一定程度的安全性

4、对每个请求执行授权控制,包括服务器端脚步制作的请求,还有来自富客户端技术如AJAX和Flash的请求

5、限制只有被授权的用户才可以访问文件或其他资源,包括在应用程序的直接控制之外的资源

6、限制只有被授权的用户才可以访问被保护的URL和功能,访问服务、应用程序数据和与安全相关的配置信息(如果应用程序不能访问它的安全配置信息,那么拒绝所有的访问),以及进行直接对象引用

7、服务器端执行和表示层表示的访问控制规则必须匹配

8、限制单个用户或设备可以在一个给定的时间内执行的操作数量。操作/时间限制应高于实际业务需求,但也要足够的低,以防止自动攻击

9、如果允许长的身份验证会话,定期重新验证用户的授权,以确保他们的特权没有改变,如果特权改变了,注销用户,并迫使他们重新验证

10、实现账户的审计,强制禁用不可用的账户(例如,一个账户的密码到期后超过了30天)

11、应用程序必须支持账户的禁用(在系统受到威胁时使凭证失效或禁用账户,则可以避免遭受进一步的攻击),以及当授权终止时终止会话

12、服务账户或支持连接到/或来自外部系统的连接,应该被授予可能最少的特权

13、建议使用一个单一的站点范围内的组件检查访问授权

4.8审核和记录活动和事件

1、错误处理

1、应用程序应该处理应用错误(而不是依赖于服务器的配置),使用不显示调试或堆栈跟踪信息的错误处理程序,在错误响应中不要泄露敏感信息,包括系统的详细信息,会话标识符或账户信息

2、确保应用程序是以安全的方式失败的

3、实施一般性错误消息,并使用自定义错误页面,确保异常和错误情况被正确的处理了,并正确释放分配的内存,释放资源

2、日志记录

1、所有的记录控制应该在一个可信任的系统(例如,服务器)上执行并且记录的控制应该支持指定的安全事件的成功和失败

2、确保日志中包含一些重要的日志的事件数据,但不要在日志中存放敏感信息,包括不必要的系统详细信息,会话标识符或密码

3、确保包括不可信任的数据的日志条目在预定的日志查看界面或软件中不会作为代码执行

4、限制只有授权的个人才可以访问日志,并且对所有的日志操作使用一个主程序

5、确保存在一种机制来进行日志分析

6、记录所有的输入验证失败

7、记录所有验证尝试,尤其是失败的

8、记录所有的访问控制失败的信息

9、记录所有明显的篡改事件,包括状态数据的异常改变

10、记录连接到无效或过期的会话令牌的尝试

11、记录所有系统异常

12、记录所有的行政职能,包括安全配置设置的更改

13、记录所有后端的TLS连接失败的信息

14、记录加密模块故障

15、使用加密哈希函数来验证日志条目的完整性

4.9数据库安全性

1、使用强类型参数化查询

2、使用PreparedStatement预编译语句,传入的任何内容就不会和原来的语句发生任何匹配的关系

3、使用输入验证和输出编码,同时确保解决元字符。如果这些都失败了,不要运行数据库命令

4、应用程序访问数据库时,其应使用尽可能低水平的特权

5、对数据库访问使用加密连接

6、在应用程序中,连接字符串不应该使用硬编码。连接字符串应该储存在一个可信任的系统的单独的配置文件中,并且他们应该被加密。

7、使用储存过程来抽象数据访问

8、删除或更改所有默认的数据库管理密码。使用强密码或实施多因子身份认证

9、关闭所有不必要的数据库功能(例如,不必要的存储过程或服务,使用工具包,只安装最低要求的功能和选项设置(受攻击面减少))

10、禁用任何不需要的默认账户

11、建议应用程序应该为每个信任的区别(例如,用户、只读用户、访客、管理员)用不同的凭据连接到数据库

4.10加密

1、用来对应用程序用户保密的加密功能必须在一个可信任的系统上执行

2、对连接字符串进行加密,防止用户非法得到数据库连接密码

3、加密模块应该安全地失败

4、所有的随机数,随机文件名,随机GUID,以及随机字符串,当需要它们的随机值是不可猜测时,应该使用加密模块批准的随机数生成器产生

5、妥善管理加密密钥

6、不要自创加密方法,以免减弱保护能力

7、使用正确的算法和密钥大小,密钥越大,安全性越高

数据加密标准:

(DES) 64位密钥(8个字节);

TripleDES 128位密钥或192位密钥(16或24个字节);

AES 128位密匙、192位密匙或256位密匙(16、24或32个字节);

RSA 384 – 16,384位密钥(48 – 2,048个字节);

对于大量数据加密,应使用TripleDES对称加密算法;对于加密等级要求高,并且要高效快捷的加密一个区段时,应使用AES算法。要对将暂时存储的数据加密,可以考虑使用较快但较弱的算法,如DES。对于数字签名,应使用RSA或DSA算法。对于哈希,应使用SHA1算法。对于用户键入的哈希,应使用基于哈希的消息验证(HMAC-SHA1)算法。

8、确保加密密钥的安全:使用DPAPI来回避密钥管理;定期回收密钥,以防密码的泄露。

4.11输出编码

1、在受信任的系统上执行所有的编码(例如,服务器)

2、对所有字符进行编码,除非他们被称为对web编译器是安全的

3、对出站编码的每种类型都运用一个标准的,被测试过的方法:

输出的种类以及其对应的防御手段:

1)支持HTML代码的输出:过滤。输出前要确保代码中不含有跨站攻击脚本。

2)对不支持HTML的输出:HTML编码。在输出到页面前要进行HtmlEncode编码,部分服务器控件或者XSLT转换本身就支持HtmlEncode编码,可不必进行重复编码。

3)对于URL的输出:URL编码。要对输出URL进行UrlEncode处理。

4)页面内容的输出:转换特殊符号的编码形式,防止因特殊符号而出现错误,或跨站。

a.对于js脚本的输出,要确保输出代码中不包含跨站脚本,注意“‘”和“”“的输出,以免被组合成危险的js代码。

b.对于style样式的输出,要确保样式的正确性。

c.对于xml数据的输出,要确保数据中是否有XML不允许的字符,要对特殊字符进行转换才能输出。

5安全编码示例(代码)

5.1输入验证和数据合法性校验

程序接受数据可能来源于未经验证的用户,网络连接和其他不受信任的来源,如果未对程序接受数据进行校验,则可能会引发安全问题。

避免SQL注入

使用PreparedStatement预编译SQL,解决SQL注入问题,传递给PreparedStatement对象的参数可以被强制进行类型转换,确保在插入或查询数据时与底层的数据库格式匹配。

public void doPrivilegedAction(

String username, char[] password

) throws SQLException {

Connection connection = getConnection();

if (connection == null) {

// Handle error

}

try {

String pwd = hashPassword(password);

// Ensure that the length of user name is legitimate

if ((username.length() > 8) {

// Handle error

}

String sqlString =

"select * from db_user where username=? and password=?";

PreparedStatement stmt = connection.prepareStatement(sqlString);

stmt.setString(1, username);

stmt.setString(2, pwd);

ResultSet rs = stmt.executeQuery();

if (!rs.next()) {

throw new SecurityException("User name or password incorrect");

}

// Authenticated, proceed

} finally {

try {

connection.close();

} catch (SQLException x) {

// forward to handler

}

}

}

使用存储过程

String custname = request.getParameter("customerName"); // This should REALLY be validated

try {

CallableStatement cs = connection.prepareCall("{call sp_getAccountBalance(?)}");

cs.setString(1, custname);

ResultSet results = cs.executeQuery();

// … result set handling

} catch (SQLException se) {

// … logging and error handling

}

避免XML注入

通过StringBulider或StringBuffer拼接XML文件时,需对输入数据进行合法性校验。

对数量quantity进行合法性校验,控制只能传入0-9的数字:

if (!Pattern.matches("[0-9]+", quantity)) {

// Format violation

}

String xmlString = "<item>\n<description>Widget</description>\n" +

"<price>500</price>\n" +

"<quantity>" + quantity + "</quantity></item>";

outStream.write(xmlString.getBytes());

outStream.flush();

或者

class CustomResolver implements EntityResolver {

public InputSource resolveEntity(String publicId, String systemId)

throws SAXException, IOException {

// check for known good entities

String entityPath = "/home/username/java/xxe/file";

if (systemId.equals(entityPath)) {

System.out.println("Resolving entity: " + publicId +

" " + systemId);

return new InputSource(entityPath);

} else {

return new InputSource(); // Disallow unknown entities

// by returning a blank path

}

}

}

class XXE {

private static void receiveXMLStream(InputStream inStream,

DefaultHandler defaultHandler)

throws ParserConfigurationException, SAXException, IOException {

SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser saxParser = factory.newSAXParser();

// To set the Entity Resolver, an XML reader needs to be created

XMLReader reader = saxParser.getXMLReader();

reader.setEntityResolver(new CustomResolver());

reader.setErrorHandler(defaultHandler);

InputSource is = new InputSource(inStream);

reader.parse(is);

}

public static void main(String[] args)

throws ParserConfigurationException, SAXException, IOException {

receiveXMLStream(new FileInputStream("evil.xml"),

new DefaultHandler());

}

}

避免跨站点脚本(XSS)

对产生跨站的参数进行严格过滤,禁止传入<SCRIPT>标签

//定义需过滤的字段串<script>

String s = "\uFE64" + "script" + "\uFE65";

//过滤字符串标准化

s = Normalizer.normalize(s, Form.NFKC);

//使用正则表达式匹配inputStr是否存在<script>

Pattern pattern = pile(inputStr);

Matcher matcher = pattern.matcher(s);

if (matcher.find()) {

// Found black listed tag

throw new IllegalStateException();

} else {

// ...

}

5.2声明和初始化

避免类初始化的相互依赖

例:

错误的写法:

public class Cycle {

private final int balance;

private static final Cycle c = new Cycle();

private static final int deposit = (int) (Math.random() * 100); // Random deposit

public Cycle() {

balance = deposit - 10; // Subtract processing fee

}

public static void main(String[] args) {

System.out.println("The account balance is: " + c.balance);

}

}

类加载时初始化指向Cycle类的静态变量c,而类Cycle的无参构造方法又依赖静态变量deposit,导致无法预期的结果。

正确的写法:

public class Cycle {

private final int balance;

private static final int deposit = (int) (Math.random() * 100); // Random deposit

private static final Cycle c = new Cycle(); // Inserted after initialization of required fields

public Cycle() {

balance = deposit - 10; // Subtract processing fee

}

public static void main(String[] args) {

System.out.println("The account balance is: " + c.balance);

}

}

5.3表达式

不可忽略方法的返回值

忽略方法的放回值可能会导致无法预料的结果。

错误的写法:

public void deleteFile(){

File someFile = new File("someFileName.txt");

someFile.delete();

}

正确的写法:

public void deleteFile(){

File someFile = new File("someFileName.txt");

if (!someFile.delete()) {

// handle failure to delete the file

}

}

或者

public class Replace {

public static void main(String[] args) {

String original = "insecure";

original = original.replace('i', '9');

System.out.println(original);

}

}

不要引用空指针

当一个变量指向一个NULL值,使用这个变量的时候又没有检查,这时会导致。NullPointerException。

在使用变量前一定要做是否为NULL值的校验。

使用Arrays.equals()来比较数组的内容

数组没有覆盖的Object. equals()方法,调用Object. equals()方法实际上是比较数组的引用,而不是他们的内容。程序必须使用两个参数Arrays.equals()方法来比较两个数组的内容

public void arrayEqualsExample() {

int[] arr1 = new int[20]; // initialized to 0

int[] arr2 = new int[20]; // initialized to 0

Arrays.equals(arr1, arr2); // true

}

5.4数字类型和操作

防止整数溢出

使用java.lang.Number. BigInteger类进行整数运算,防止整数溢出。

publicclassBigIntegerUtil {

privatestaticfinalBigIntegerbigMaxInt= BigInteger.valueOf(Integer.MAX_VALUE);

privatestaticfinalBigIntegerbigMinInt= BigInteger.valueOf(Integer.MIN_VALUE);

publicstaticBigInteger intRangeCheck(BigInteger val)throwsArithmeticException {

if(pareTo(bigMaxInt) == 1 || pareTo(bigMinInt) == -1) {

thrownewArithmeticException("Integer overflow");

}

returnval;

}

publicstaticintaddInt(intv1,intv2)throwsArithmeticException {

BigInteger b1 = BigInteger.valueOf(v1);

BigInteger b2 = BigInteger.valueOf(v2);

BigInteger res =intRangeCheck(b1.add(b2));

returnres.intValue();

}

publicstaticintsubInt(intv1,intv2)throwsArithmeticException {

BigInteger b1 = BigInteger.valueOf(v1);

BigInteger b2 = BigInteger.valueOf(v2);

BigInteger res =intRangeCheck(b1.subtract(b2));

returnres.intValue();

}

publicstaticintmultiplyInt(intv1,intv2)throwsArithmeticException {

BigInteger b1 = BigInteger.valueOf(v1);

BigInteger b2 = BigInteger.valueOf(v2);

BigInteger res =intRangeCheck(b1.multiply(b2));

returnres.intValue();

}

publicstaticintdivideInt(intv1,intv2)throwsArithmeticException {

BigInteger b1 = BigInteger.valueOf(v1);

BigInteger b2 = BigInteger.valueOf(v2);

BigInteger res =intRangeCheck(b1.divide(b2));

returnres.intValue();

}

}

避免除法和取模运算分母为零

要避免因为分母为零而导致除法和取模运算出现异常。

if (num2 == 0) {

// handle error

} else {

result1= num1 /num2;

result2= num1 % num2;

}

5.5类和方法操作

数据成员声明为私有,提供可访问的包装方法

攻击者可以用意想不到的方式操纵public或protected的数据成员,所以需要将数据成员为private,对外提供可控的包装方法访问数据成员。

敏感类不允许复制

包含私人的,机密或其他敏感数据的类是不允许被复制的,解决的方法有两种:

1、类声明为final

final class SensitiveClass {

// ...

}

2、Clone方法抛出CloneNotSupportedException异常

class SensitiveClass {

// ...

public final SensitiveClass clone()

throws CloneNotSupportedException {

throw new CloneNotSupportedException();

}

}

比较类的正确做法

如果由同一个类装载器装载,它们具有相同的完全限定名称,则它们是两个相同的类。

不正确写法:

// Determine whether object auth has required/expected class object

if (auth.getClass().getName().equals(

"com.application.auth.DefaultAuthenticationHandler")) {

// ...

}

正确写法:

// Determine whether object auth has required/expected class name

if (auth.getClass() == com.application.auth.DefaultAuthenticationHandler.class) {

// ...

}

或者

// Determine whether objects x and y have the same class

if (x.getClass() == y.getClass()) {

// Objects have the same class

}

不要硬编码敏感信息

硬编码的敏感信息,如密码,服务器IP地址和加密密钥,可能会泄露给攻击者。

敏感信息均必须存在在配置文件或数据库中。

验证方法参数

验证方法的参数,可确保操作方法的参数产生有效的结果。不验证方法的参数可能会导致不正确的计算,运行时异常,违反类的不变量,对象的状态不一致。

对于跨信任边界接收参数的方法,必须进行参数合法性校验

private Object myState = null;

//对于修改myState方法的入参,进行非空和合法性校验

void setState(Object state) {

if (state == null) {

// Handle null state

}

if (isInvalidState(state)) {

// Handle invalid state

}

myState = state;

}

不要使用过时、陈旧或低效的方法

在程序代码中使用过时的、陈旧的或低效的类或方法可能会导致错误的行为。

数组引用问题

某个方法返回一个对敏感对象的内部数组的引用,假定该方法的调用程序不改变这些对象。即使数组对象本身是不可改变的,也可以在数组对象以外操作数组的内容,这种操作将反映在返回该数组的对象中。如果该方法返回可改变的对象,外部实体可以改变在那个类中声明的public变量,这种改变将反映在实际对象中。

不正确的写法:

public class XXX {

private String[] xxxx;

public String[] getXXX() {

return xxxx;

}

}

正确的写法:

public class XXX {

private String[] xxxx;

public String[] getXXX() {

String temp[] = Arrays.copyof(…); //或其他数组复制方法

return temp;

}

}

不要产生内存泄露

垃圾收集器只收集不可达的对象,因此,存在未使用的可到达的对象,仍然表示内存管理不善。过度的内存泄漏可能会导致内存耗尽,拒绝服务(DoS)。

5.6异常处理

不要忽略捕获的异常

对于捕获的异常要进行相应的处理,不能忽略已捕获的异常

不正确写法:

class Foo implements Runnable {

public void run() {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

//此处InterruptedException被忽略

}

}

}

正确写法:

class Foo implements Runnable {

public void run() {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

Thread.currentThread().interrupt(); // Reset interrupted status

}

}

}

不允许暴露异常的敏感信息

没有过滤敏感信息的异常堆栈往往会导致信息泄漏,

不正确的写法:

try {

FileInputStream fis =

new FileInputStream(System.getenv("APPDATA") + args[0]);

} catch (FileNotFoundException e) {

// Log the exception

throw new IOException("Unable to retrieve file", e);

}

正确的写法:

class ExceptionExample {

public static void main(String[] args) {

File file = null;

try {

file = new File(System.getenv("APPDATA") +

args[0]).getCanonicalFile();

if (!file.getPath().startsWith("c:\\homepath")) {

log.error("Invalid file");

return;

}

} catch (IOException x) {

log.error("Invalid file");

return;

}

try {

FileInputStream fis = new FileInputStream(file);

} catch (FileNotFoundException x) {

log.error("Invalid file");

return;

}

}

}

或者

class ExceptionExample {

public static void main(String[] args) {

FileInputStream fis = null;

try {

switch(Integer.valueOf(args[0])) {

case 1:

fis = new FileInputStream("c:\\homepath\\file1");

break;

case 2:

fis = new FileInputStream("c:\\homepath\\file2");

break;

//...

default:

System.out.println("Invalid option");

break;

}

} catch (Throwable t) {

MyExceptionReporter.report(t); // Sanitize

}

}

}

不允许抛出RuntimeException, Exception,Throwable

不正确的写法:

boolean isCapitalized(String s) {

if (s == null) {

throw new RuntimeException("Null String");

}

}

private void doSomething() throws Exception {

//...

}

正确写法:

boolean isCapitalized(String s) {

if (s == null) {

throw new NullPointerException();

}

}

private void doSomething() throws IOException {

//...

}

不要捕获NullPointerException或其他父类异常

不正确的写法:

boolean isName(String s) {

try {

String names[] = s.split(" ");

if (names.length != 2) {

return false;

}

return (isCapitalized(names[0]) && isCapitalized(names[1]));

} catch (NullPointerException e) {

return false;

}

}

正确的写法:

boolean isName(String s) /* throws NullPointerException */ {

String names[] = s.split(" ");

if (names.length != 2) {

return false;

}

return (isCapitalized(names[0]) && isCapitalized(names[1]));

}

5.7多线程编程

确保共享变量的可见性

对于共享变量,要确保一个线程对它的改动对其他线程是可见的。

线程可能会看到一个陈旧的共享变量的值。为了共享变量是最新的,可以将变量声明为volatile或同步读取和写入操作。

将共享变量声明为volatile:

final class ControlledStop implements Runnable {

private volatile boolean done = false;

@Override public void run() {

while (!done) {

try {

// ...

Thread.currentThread().sleep(1000); // Do something

} catch(InterruptedException ie) {

Thread.currentThread().interrupt(); // Reset interrupted status

}

}

}

public void shutdown() {

done = true;

}

}

同步读取和写入操作:

final class ControlledStop implements Runnable {

private boolean done = false;

@Override public void run() {

while (!isDone()) {

try {

// ...

Thread.currentThread().sleep(1000); // Do something

} catch(InterruptedException ie) {

Thread.currentThread().interrupt(); // Reset interrupted status

}

}

}

public synchronized boolean isDone() {

return done;

}

public synchronized void shutdown() {

done = true;

}

}

确保共享变量的操作是原子的

除了要确保共享变量的更新对其他线程可见的,还需要确保对共享变量的操作是原子的,这时将共享变量声明为volatile往往是不够的。需要使用同步机制或Lock

同步读取和写入操作:

final class Flag {

private volatile boolean flag = true;

public synchronized void toggle() {

flag ^= true; // Same as flag = !flag;

}

public boolean getFlag() {

return flag;

}

}

//使用读取锁确保读取和写入操作的原子性

final class Flag {

private boolean flag = true;

private final ReadWriteLock lock = new ReentrantReadWriteLock();

private final Lock readLock = lock.readLock();

private final Lock writeLock = lock.writeLock();

public void toggle() {

writeLock.lock();

try {

flag ^= true; // Same as flag = !flag;

} finally {

writeLock.unlock();

}

}

public boolean getFlag() {

readLock.lock();

try {

return flag;

} finally {

readLock.unlock();

}

}

}

不要调用Thread.run(),不要使用Thread.stop()以终止线程

确保执行阻塞操作的线程可以终止

public final class SocketReader implements Runnable {

private final SocketChannel sc;

private final Object lock = new Object();

public SocketReader(String host, int port) throws IOException {

sc = SocketChannel.open(new InetSocketAddress(host, port));

}

@Override public void run() {

ByteBuffer buf = ByteBuffer.allocate(1024);

try {

synchronized (lock) {

while (!Thread.interrupted()) {

sc.read(buf);

// ...

}

}

} catch (IOException ie) {

// Forward to handler

}

}

public static void main(String[] args)

throws IOException, InterruptedException {

SocketReader reader = new SocketReader("somehost", 25);

Thread thread = new Thread(reader);

thread.start();

Thread.sleep(1000);

thread.interrupt();

}

}

相互依存的任务不要在一个有限的线程池执行

有限线程池指定可以同时执行在线程池中的线程数量的上限。程序不得使用有限线程池线程执行相互依赖的任务。可能会导致线程饥饿死锁,所有的线程池执行的任务正在等待一个可用的线程中执行一个内部队列阻塞

CPU饥饿案例一

AIX 检查系统日志是否cpu饥饿

Ecsvr3/user/IBM/WebSphere/AppServer6/profiles/EMALL03/logs/WCSCluster_emall03_mbr2$ grep 检测到 SystemOut*,看时间是在凌晨和早上,这时间应该在做批处理support,WAS SystemOut日志出现CPU饥饿错误,说明当时该两个节点处理负荷高,处理能力下降。

解决:相互依存的任务不要在一个有限的线程池执行 /可能会导致线程饥饿死锁

有限线程池指定可以同时执行在线程池中的线程数量的上限。程序不得使用有限线程池线程执行相互依赖的任务。可能会导致线程饥饿死锁,所有的线程池执行的任务正在等待一个可用的线程中执行一个内部队列阻塞

CPU饥饿案例二

潘琦 880365 /C店查询场景 , CPU 饥饿问题:

解决:查询重复的冗余数据,导致数据库CPU高,进而导致其他WAS集群应用空闲饥饿状态,去掉就可以了 。

5.8输入输出

程序终止前删除临时文件

检测和处理文件相关的错误

Java的文件操作方法往往有一个返回值,而不是抛出一个异常,表示失败。因此,忽略返回值文件操作的程序,往往无法检测到这些操作是否失败。Java程序必须检查执行文件I / O方法的返回值。

不正确的写法:

File file = new File(args[0]);

file.delete();

正确的写法:

File file = new File("file");

if (!file.delete()) {

log.error("Deletion failed");

}

及时释放资源

垃圾收集器无法释放非内存资源,如打开的文件描述符与数据库的连接。因此,不释放资源,可能导致资源耗尽攻击。

try {

final FileInputStream stream = new FileInputStream(fileName);

try {

final BufferedReader bufRead =

new BufferedReader(new InputStreamReader(stream));

String line;

while ((line = bufRead.readLine()) != null) {

sendLine(line);

}

} finally {

if (stream != null) {

try {

stream.close();

} catch (IOException e) {

// forward to handler

}

}

}

} catch (IOException e) {

// forward to handler

}

5.9序列化

不要序列化未加密的敏感数据

序列化允许一个对象的状态被保存为一个字节序列,然后重新在稍后的时间恢复,它没有提供任何机制来保护序列化的数据。敏感的数据不应该被序列化的例子包括加密密钥,数字证书。

解决方法:

1、对于数据成员可以使用transient,声明该数据成员是瞬态的。

2、重写序列化相关方法writeObject、readObject、readObjectNoData,防止被子类恶意重写

class SensitiveClass extends Number {

// ...

protected final Object writeObject(java.io.ObjectOutputStream out) throws NotSerializableException {

throw new NotSerializableException();

}

protected final Object readObject(java.io.ObjectInputStream in) throws NotSerializableException {

throw new NotSerializableException();

}

protected final Object readObjectNoData(java.io.ObjectInputStream in) throws NotSerializableException {

throw new NotSerializableException();

}

}

在序列化过程中避免内存和资源泄漏

不正确的写法:

class SensorData implements Serializable {

// 1 MB of data per instance!

public static SensorData readSensorData() {...}

public static boolean isAvailable() {...}

}

class SerializeSensorData {

public static void main(String[] args) throws IOException {

ObjectOutputStream out = null;

try {

out = new ObjectOutputStream(

new BufferedOutputStream(new FileOutputStream("ser.dat")));

while (SensorData.isAvailable()) {

// note that each SensorData object is 1 MB in size

SensorData sd = SensorData.readSensorData();

out.writeObject(sd);

}

} finally {

if (out != null) {

out.close();

}

}

}

}

正确写法:

class SerializeSensorData {

public static void main(String[] args) throws IOException {

ObjectOutputStream out = null;

try {

out = new ObjectOutputStream(

new BufferedOutputStream(new FileOutputStream("ser.dat")));

while (SensorData.isAvailable()) {

// note that each SensorData object is 1 MB in size

SensorData sd = SensorData.readSensorData();

out.writeObject(sd);

out.reset(); // reset the stream

}

} finally {

if (out != null) {

out.close();

}

}

}

}

反序列化要在程序最小权限的安全环境中

6安全编码检查(代码)

在开发的过程中,每个开发者能力与风格存在差异,为了保障软件开发质量,需要进行编码的安全检查,在安全编码检查过程中,需要对使用以下代码的部分进行重点检查。

6.1输入和输出

以下读取数据的应用程序,可以导致路径转义和DOS服务攻击风险。

Java.io

java.util.zip

java.util.jar

FileInputStream

ObjectInputStream

FilterInputStream

PipedInputStream

SequenceInputStream

StringBufferInputStream

BufferedReader

ByteArrayInputStream

CharArrayReader

File

ObjectInputStream

PipedInputStream

StreamTokenizer

getResourceAsStream

java.io.FileReader

java.io.FileWriter

java.io.RandomAccessFile

java.io.File

java.io.FileOutputStream

mkdir

renameTo

6.2API程序

使用以下API程序,导致HTTP请求中存在等安全风险。

javax.servlet.*

getParameterNames

getParameterValues

getParameter

getParameterMap

getScheme

getProtocol

getContentType

getServerName

getRemoteAddr

getRemoteHost

getRealPath

getLocalName

getAttribute

getAttributeNames

getLocalAddr

getAuthType

getRemoteUser

getCookies

isSecure

HttpServletRequest

getQueryString

getHeaderNames

getHeaders

getPrincipal

getUserPrincipal

isUserInRole

getInputStream

getOutputStream

getWriter

addCookie

addHeader

setHeader

setAttribute

putValue

javax.servlet.http.Cookie

getName

getPath

getDomain

getComment

getMethod

getPath

getReader

getRealPath

getRequestURI

getRequestURL

getServerName

getValue

getValueNames

getRequestedSessionId

6.3跨站脚本

使用以下代码,可能导致出现跨站脚本风险。

javax.servlet.ServletOutputStream.print

javax.servlet.jsp.JspWriter.print

java.io.PrintWriter.print

6.4响应截断

使用以下代码,可以导致出现HTTP响应截断风险。

javax.servlet.http.HttpServletResponse.sendRedirect

addHeader, setHeader

6.5重定向

使用以下代码,可以导致出现URL重定向风险。

sendRedirect

setStatus

addHeader, setHeader

6.6SQL和数据库

使用以下SQL语言与代码,可以导致出现SQL注入和数据库操纵风险。

jdbc

executeQuery

select

insert

update

delete

execute

executestatement

createStatement

java.sql.ResultSet.getString

java.sql.ResultSet.getObject

java.sql.Statement.executeUpdate

java.sql.Statement.executeQuery

java.sql.Statement.execute

java.sql.Statement.addBatch

java.sql.Connection.prepareStatement

java.sql.Connection.prepareCall

6.7SSL

使用以下代码,可以导致出现SSL相关风险。

.ssl

SSLContext

SSLSocketFactory

TrustManagerFactory

HttpsURLConnection

KeyManagerFactory

6.8会话管理

使用以下代码,可以导致出现会话管理安全风险。

getSession

invalidate

getId

6.9操作系统命令

使用以下代码,可以导致出现执行操作系统命令风险。

java.lang.Runtime.exec

java.lang.Runtime.getRuntime

6.10记录

java.io.PrintStream.write

log4j

jLo

Lumberjack

MonoLog

qflog

just4log

log4Ant

JDLabAgent

6.11架构组件分析

使用以下架构组件,跟踪组件版本可以发现已知风险。

### Ajax

XMLHTTP

### Struts

org.apache.struts

### Spring

org.springframework

### Java Server Faces (JSF)

import javax.faces

### Hibernate

import org.hibernate

### Castor

org.exolab.castor

### JAXB

javax.xml

### JMS

JMS

6.12JavaScript/XMLHTTP

使用以下JavaScript,操纵用户状态或控制浏览器可能导致风险。

eval

document.cookie

document.referrer

document.attachEvent

document.body

document.body.innerHtml

document.body.innerText

document.close

document.create

document.createElement

document.execCommand

document.forms[0].action

document.location

document.open

document.URL

document.URLUnencoded

document.write

document.writeln

location.hash

location.href

location.search

window.alert

window.attachEvent

window.createRequest

window.execScript

window.location

window.open

window.navigate

window.setInterval

window.setTimeout

window.createRequest

7安全编码规范细则(功能)

7.1验证用户

1、身份验证

2、密码管理遵循的原则

7.2保护敏感数据

1、前端保护敏感数据

2、后端保护敏感数据

3、传输保护

7.3防止会话劫持和保护cookie

7.4提供安全配置

7.5验证输入

7.6授权用户

7.7访问控制

7.8审核和记录活动和事件

7.9数据库安全性

7.10加密

7.11输出编码

<!DOCTYPE HTML><html lang="en-US"><head><meta name="keywords" content="" /><meta name="description" content="" /><script src="/portal/RES/soaNewStyle/original/js/jquery.js"></script><link type="text/css" href="s*****.com/infoResource/news/portal/soaNST/soaNST3/css/soa.article.css" rel="stylesheet"><link type="text/css" href="s*****.com/infoResource/news/portal/soaNST/soaNST3/css/soa.aside.css" rel="stylesheet"><link type="text/css" href="s*****.com/infoResource/news/portal/soaNST/soaNST3/css/soa.public.css" rel="stylesheet"><script src="s*****.com/infoResource/news/portal/soaNST/soaNST3/js/jquery.js"></script><title>欢迎访问**内部门户</title><link rel="shortcut icon" href="/portal/RES/css/images/favicon.ico" type="image/x-icon" /><link disabled="true" charset="gb2312" title="defualt" href="skin/default/datepicker.css" type="text/css" rel="stylesheet"></head><body>、、、</body></html>

ddd

JAVA中简单调用MD5算法进行加密.

/blog/967263

D:\workspace\test\src\com\iteye\lindows\test\MD5Test.java

package com.iteye.lindows.test;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;/*** @author Lindows*/public class MD5Test {public static byte[] getKeyedDigest(byte[] buffer, byte[] key) {try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update(buffer);return md5.digest(key);} catch (NoSuchAlgorithmException e) {}return null;}public static String getKeyedDigest(String strSrc, String key) {try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update(strSrc.getBytes("UTF8"));String result = "";byte[] temp;temp = md5.digest(key.getBytes("UTF8"));for (int i = 0; i < temp.length; i++) {result += Integer.toHexString((0x000000ff & temp[i]) | 0xffffff00).substring(6);}return result;} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return null;}public static void main(String[] args) {String MD5Created = null;String s = "000000";// 下面第二个参数请填空字符串MD5Created = MD5Test.getKeyedDigest(s, "");System.out.println("key:" + s + ",md5:" + MD5Created);// key:000000,md5:670b14728ad9902aecba32e22fa4f6bd}}

HTTP使用BASIC认证的原理及实现方法

/23071790/viewspace-709367/

一.BASIC认证概述

在HTTP协议进行通信的过程中,HTTP协议定义了基本认证过程以允许HTTP服务器对WEB浏览器进行用户身份证的方法,当一个客户端向HTTP服务器进行数据请求时,如果客户端未被认证,则HTTP服务器将通过基本认证过程对客户端的用户名及密码进行验证,以决定用户是否合法。客户端在接收到HTTP服务器的身份认证要求后,会提示用户输入用户名及密码,然后将用户名及密码以BASE64加密,加密后的密文将附加于请求信息中,如当用户名为anjuta,密码为:123456时,客户端将用户名和密码用“:”合并,并将合并后的字符串用BASE64加密为密文,并于每次请求数据时,将密文附加于请求头(Request Header)中。HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证,如果用户名及密码正确,则根据客户端请求,返回客户端所需要的数据;否则,返回错误代码或重新要求客户端提供用户名及密码。

二.BASIC认证的过程

1.客户端向服务器请求数据,请求的内容可能是一个网页或者是一个其它的MIME类型,此时,假设客户端尚未被验证,则客户端提供如下请求至服务器:

Get /index.html HTTP/1.0

Host:

2.服务器向客户端发送验证请求代码401,服务器返回的数据大抵如下:

HTTP/1.0 401 Unauthorised

Server: SokEvo/1.0

WWW-Authenticate: Basic realm=""

Content-Type: text/html

Content-Length: xxx

3.当符合http1.0或1.1规范的客户端(如IE,FIREFOX)收到401返回值时,将自动弹出一个登录窗口,要求用户输入用户名和密码。

4.用户输入用户名和密码后,将用户名及密码以BASE64加密方式加密,并将密文放入前一条请求信息中,则客户端发送的第一条请求信息则变成如下内容:

Get /index.html HTTP/1.0

Host:

Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxx

注:xxxx....表示加密后的用户名及密码。

5.服务器收到上述请求信息后,将Authorization字段后的用户信息取出、解密,将解密后的用户名及密码与用户数据库进行比较验证,如用户名及密码正确,服务器则根据请求,将所请求资源发送给客户端:

三.BASIC认证的缺点

HTTP基本认证的目标是提供简单的用户验证功能,其认证过程简单明了,适合于对安全性要求不高的系统或设备中,如大家所用路由器的配置页面的认证,几乎都采取了这种方式。其缺点是没有灵活可靠的认证策略,如无法提供域(domain或realm)认证功能,另外,BASE64的加密强度非常低,可以说仅能防止sohu的搜索把它搜到了。当然,HTTP基本认证系统也可以与SSL或者Kerberos结合,实现安全性能较高(相对)的认证系统

四.BASIC认证的JAVA实现代码

HttpSession session=request.getSession();

String user=(String)session.getAttribute("user");

String pass;

if(user==null){

try{

response.setCharacterEncoding("GBK");

PrintWriter ut=response.getWriter();

String authorization=request.getHeader("authorization");

if(authorization==null||authorization.equals("")){

response.setStatus(401);

response.setHeader("WWW-authenticate","Basic realm=\"请输入管理员密码\"");

out.print("对不起你没有权限!!");

return;

}

String userAndPass=newString(newBASE64Decoder().decodeBuffer(authorization.split(" ")[1]));

if(userAndPass.split(":").length<2){

response.setStatus(401);

response.setHeader("WWW-authenticate","Basic realm=\"请输入管理员密码\"");

out.print("对不起你没有权限!!");

return;

}

user=userAndPass.split(":")[0];

pass=userAndPass.split(":")[1];

if(user.equals("111")&&pass.equals("111")){

session.setAttribute("user",user);

RequestDispatcher dispatcher=request.getRequestDispatcher("index.jsp");

dispatcher.forward(request,response);

}else{

response.setStatus(401);

response.setHeader("WWW-authenticate","Basic realm=\"请输入管理员密码\"");

out.print("对不起你没有权限!!");

return;

}

}catch(Exception ex){

ex.printStackTrace();

}

}else{

RequestDispatcher dispatcher=request.getRequestDispatcher("index.jsp");

dispatcher.forward(request,response);

}

loadrunner md5 方式一

D:\TestCase\0126_md5\testcase_md5_generated\Actions.java

/** LoadRunner Java script. (Build: _build_number_)* * Script Description: * */import lrapi.lr;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;public class Actions{public static byte[] getKeyedDigest(byte[] buffer, byte[] key) {try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update(buffer);return md5.digest(key);} catch (NoSuchAlgorithmException e) {}return null;}public static String getKeyedDigest(String strSrc, String key) {try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.update(strSrc.getBytes("UTF8"));String result = "";byte[] temp;temp = md5.digest(key.getBytes("UTF8"));for (int i = 0; i < temp.length; i++) {result += Integer.toHexString((0x000000ff & temp[i]) | 0xffffff00).substring(6);}return result;} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return null;}public int init() throws Throwable {return 0;}//end of initpublic int action() throws Throwable {String MD5Created = null;String s = "000000"; //参数化数据// String s = lr.decrypt("56a6e6a036cd94e0011f"); // 若还原lr.decrypt,选中字符串鼠标右键Restore value xxxx即可。C:\Program Files\HP\LoadRunner\bin\PasswordEncoder.exe//MD5Created = MD5Test.getKeyedDigest(s, ""); // 左边第二个参数请填空字符串MD5Created = getKeyedDigest(s, "");System.out.println("key:" + s + ",md5:" + MD5Created); // key:000000,md5:670b14728ad9902aecba32e22fa4f6bdreturn 0;}//end of actionpublic int end() throws Throwable {return 0;}//end of end}

SSL与TLS 区别 以及介绍

/blog/840561

SSL:(Secure Socket Layer,安全套接字层),位于可靠的面向连接的网络层协议和应用层协议之间的一种协议层。SSL通过互相认证、使用数字签名确保完整性、使用加密确保私密性,以实现客户端和服务器之间的安全通讯。该协议由两层组成:SSL记录协议和SSL握手协议。

TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS记录协议和TLS握手协议。

SSL是Netscape开发的专门用户保护Web通讯的,目前版本为3.0。最新版本的TLS 1.0是IETF(工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。两者差别极小,可以理解为SSL 3.1,它是写入了RFC的。

SSL (Secure Socket Layer)

为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络

上之传输过程中不会被截取。目前一般通用之规格为40 bit之安全标准,美国则已推出128 bit之更高安全

标准,但限制出境。只要3.0版本以上之I.E.或Netscape浏览器即可支持SSL。

当前版本为3.0。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。

SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。 SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。

SSL协议提供的服务主要有:

1)认证用户和服务器,确保数据发送到正确的客户机和服务器;

2)加密数据以防止数据中途被窃取;

3)维护数据的完整性,确保数据在传输过程中不被改变。

SSL协议的工作流程:

服务器认证阶段:1)客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;2)服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;3)客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;4)服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。

用户认证阶段:在此之前,服务器已经通过了客户认证,这一阶段主要完成对客户的认证。经认证的服务器发送一个提问给客户,客户则返回(数字)签名后的提问和其公开密钥,从而向服务器提供认证。

从SSL 协议所提供的服务及其工作流程可以看出,SSL协议运行的基础是商家对消费者信息保密的承诺,这就有利于商家而不利于消费者。在电子商务初级阶段,由于运作电子商务的企业大多是信誉较高的大公司,因此这问题还没有充分暴露出来。但随着电子商务的发展,各中小型公司也参与进来,这样在电子支付过程中的单一认证问题就越来越突出。虽然在SSL3.0中通过数字签名和数字证书可实现浏览器和Web服务器双方的身份验证,但是SSL协议仍存在一些问题,比如,只能提供交易中客户与服务器间的双方认证,在涉及多方的电子交易中,SSL协议并不能协调各方间的安全传输和信任关系。在这种情况下,Visa和 MasterCard两大信用卡公组织制定了SET协议,为网上信用卡支付提供了全球性的标准。

TLS:安全传输层协议

(TLS:Transport Layer Security Protocol)

安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。较低的层为 TLS 记录协议,位于某个可靠的传输协议(例如 TCP)上面。 TLS 记录协议提供的连接安全性具有两个基本特性:

私有――对称加密用以数据加密(DES 、RC4 等)。对称加密所产生的密钥对每个连接都是唯一的,且此密钥基于另一个协议(如握手协议)协商。记录协议也可以不加密使用。

可靠――信息传输包括使用密钥的 MAC 进行信息完整性检查。安全哈希功能( SHA、MD5 等)用于 MAC 计算。记录协议在没有 MAC 的情况下也能操作,但一般只能用于这种模式,即有另一个协议正在使用记录协议传输协商安全参数。

TLS 记录协议用于封装各种高层协议。作为这种封装协议之一的握手协议允许服务器与客户机在应用程序协议传输和接收其第一个数据字节前彼此之间相互认证,协商加密算法和加密密钥。 TLS 握手协议提供的连接安全具有三个基本属性:

可以使用非对称的,或公共密钥的密码术来认证对等方的身份。该认证是可选的,但至少需要一个结点方。

共享加密密钥的协商是安全的。对偷窃者来说协商加密是难以获得的。此外经过认证过的连接不能获得加密,即使是进入连接中间的攻击者也不能。

协商是可靠的。没有经过通信方成员的检测,任何攻击者都不能修改通信协商。

TLS 的最大优势就在于:TLS 是独立于应用协议。高层协议可以透明地分布在 TLS 协议上面。然而, TLS 标准并没有规定应用程序如何在 TLS 上增加安全性;它把如何启动 TLS 握手协议以及如何解释交换的认证证书的决定权留给协议的设计者和实施者来判断。

协议结构

TLS 协议包括两个协议组―― TLS 记录协议和 TLS 握手协议――每组具有很多不同格式的信息。在此文件中我们只列出协议摘要并不作具体解析。具体内容可参照相关文档。

TLS 记录协议是一种分层协议。每一层中的信息可能包含长度、描述和内容等字段。记录协议支持信息传输、将数据分段到可处理块、压缩数据、应用 MAC 、加密以及传输结果等。对接收到的数据进行解密、校验、解压缩、重组等,然后将它们传送到高层客户机。

TLS 连接状态指的是 TLS 记录协议的操作环境。它规定了压缩算法、加密算法和 MAC 算法。

TLS 记录层从高层接收任意大小无空块的连续数据。密钥计算:记录协议通过算法从握手协议提供的安全参数中产生密钥、 IV 和 MAC 密钥。 TLS 握手协议由三个子协议组构成,允许对等双方在记录层的安全参数上达成一致、自我认证、例示协商安全参数、互相报告出错条件。

关系就是。。。。并列关系

最新版本的TLS(Transport Layer Security,传输层安全协议)是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。在TLS与SSL3.0之间存在着显著的差别,主要是它们所支持的加密算法不同,所以TLS与SSL3.0不能互操作。

1.TLS与SSL的差异

1)版本号:TLS记录格式与SSL记录格式相同,但版本号的值不同,TLS的版本1.0使用的版本号为SSLv3.1。

2)报文鉴别码:SSLv3.0和TLS的MAC算法及MAC计算的范围不同。TLS使用了RFC-2104定义的HMAC算法。SSLv3.0使用了相似的算法,两者差别在于SSLv3.0中,填充字节与密钥之间采用的是连接运算,而HMAC算法采用的是异或运算。但是两者的安全程度是相同的。

3)伪随机函数:TLS使用了称为PRF的伪随机函数来将密钥扩展成数据块,是更安全的方式。

4)报警代码:TLS支持几乎所有的SSLv3.0报警代码,而且TLS还补充定义了很多报警代码,如解密失败(decryption_failed)、记录溢出(record_overflow)、未知CA(unknown_ca)、拒绝访问(access_denied)等。

5)密文族和客户证书:SSLv3.0和TLS存在少量差别,即TLS不支持Fortezza密钥交换、加密算法和客户证书。

6)certificate_verify和finished消息:SSLv3.0和TLS在用certificate_verify和finished消息计算MD5和SHA-1散列码时,计算的输入有少许差别,但安全性相当。

7)加密计算:TLS与SSLv3.0在计算主密值(master secret)时采用的方式不同。

8)填充:用户数据加密之前需要增加的填充字节。在SSL中,填充后的数据长度要达到密文块长度的最小整数倍。而在TLS中,填充后的数据长度可以是密文块长度的任意整数倍(但填充的最大长度为255字节),这种方式可以防止基于对报文长度进行分析的攻击。

2.TLS的主要增强内容

TLS的主要目标是使SSL更安全,并使协议的规范更精确和完善。TLS 在SSL v3.0 的基础上,提供了以下增强内容:

1)更安全的MAC算法;

2)更严密的警报;

3)“灰色区域”规范的更明确的定义;

3.TLS对于安全性的改进

1)对于消息认证使用密钥散列法:TLS 使用“消息认证代码的密钥散列法”(HMAC),当记录在开放的网络(如因特网)上传送时,该代码确保记录不会被变更。SSLv3.0还提供键控消息认证,但HMAC比SSLv3.0使用的(消息认证代码)MAC 功能更安全。

2)增强的伪随机功能(PRF):PRF生成密钥数据。在TLS中,HMAC定义PRF。PRF使用两种散列算法保证其安全性。如果任一算法暴露了,只要第二种算法未暴露,则数据仍然是安全的。

3)改进的已完成消息验证:TLS和SSLv3.0都对两个端点提供已完成的消息,该消息认证交换的消息没有被变更。然而,TLS将此已完成消息基于PRF和HMAC值之上,这也比SSLv3.0更安全。

4)一致证书处理:与SSLv3.0不同,TLS试图指定必须在TLS之间实现交换的证书类型。

5)特定警报消息:TLS提供更多的特定和附加警报,以指示任一会话端点检测到的问题。TLS还对何时应该发送某些警报进行记录。

md5(32001881700052507189,32) = 71d5587077abfa5ae4843f13a98a38a3

md5(32001881700052507189,16) = 77abfa5ae4843f13

end

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。