明文保存password的程序在非常多方面easy造成password的泄漏。尽管用户输入的password一般时明文形式。可是应用程序必须保证password不是以明文形式存储的。

限制password泄漏危急的一个有效的方法是使用散列函数。它使得程序中能够间接的对用户输入的password和原来的password进行比較,而不须要保存明文或者对password进行解密后比較。这种方法使password泄漏的风险降到最低,同一时候没有引入其它缺点。



[加密散列函数]

散列函数产生的值称为哈希值或者消息散列,散列函数是计算可行函数,但反过来是计算不可行的。其实,password能够被编码为一个哈希值,但哈希值不能被解码成相应的password。两个password是否同样,能够通过推断它们的哈希值是否相等。

一个好的实践是对明文加盐之后再进行哈希值的计算。

盐是一个唯一的序列或者随机生成的数据片段。通常和哈希值一起存放。盐的作用是防止哈希值的暴力破解,前提是盐足够长以产生足够的熵(长度较短的盐值不足以减少暴力攻击的速度)。

每一个password必须有自己的唯一的盐,假设多个password共用同一个盐的话。两个用户可能会有同样的password。

散列函数和盐的长度的选择是安全和性能的一个均衡。

选择强度高的散列函数以增强暴力破解的难度的同一时候,也会添加password验证的时间。增强盐的长度能够增大暴力破解的难度,但同一时候会添加额外的存储空间。

Java的MessageDigest类提供了多种加密散列函数的实现。但要避免使用有缺陷的散列函数,比如MD5。而像SHA-1和SHA-2之类由美国国家安全局维护的散列函数,眼下是安全的。实践中。非常多应用使用SHA-256散列函数。由于这个函数兼顾了性能和安全。



[不符合安全要求的代码演示样例]

以下的代码使用对称加密算法对存储在password.bin文件里的密码进行加密和解密操作。

public final class Password {

	private void setPassword(byte[] pass) throws Exception {
// arbitrary encryption scheme
byte[] encryted = encrypt(pass);
clearArray(pass); // encrypted password to password.bin
saveBytes(encrypted, "password.bin");
clearArray(encrypted);
} boolean checkPassword(byte[] pass) throws Exception {
// load the encrypted password
byte[] encrypted = loadBytes("password.bin");
byte[] decrpyted = decrypt(encrypted);
boolean arraysEqual = Arrays.equals(decrypted, pass);
clearArray(decrypted);
clearArray(pass);
return arraysEqual;
} private void clearArray(byte[] a) {
for (int i=0; i<a.length; ++i) {
a[i] = 0;
}
}
}

攻击者可能对上述bin文件进行解密。然后获得password,尤其当攻击者知道程序中使用的密钥和加密方式时。

password甚至必须不让系统管理员或者特权用户知道。

因此,使用加密方式对防止password泄漏危急的作用有限。



[不符合安全的代码演示样例]

以下代码基于MessageDigest类使用SHA-256散列函数来对照字符串。而不是使用明文。但它使用的是String对象来存储password。

public final class Password {

	private void setPassword(String pass) throws Exception {
byte[] salt = generateSalt(12);
MessageDigest msgDigest = MessageDigest.getInstance("SHA-256");
// encode the string and salt
byte[] hashVal = msgDigest.digest((pass + salt).getBytes());
saveBytes(salt, "salt.bin");
// save the hash value to password.bin
saveBytes(hashVal, "password.bin");
} boolean checkPassword(String pass) throws Exception {
byte[] salt = loadBytes("salt.bin");
MessageDigest msgDigest = MessageDigest.getInstance("SHA-256");
// encode the string and salt
byte[] hashVal1 = msgDigest.digest((pass + salt).getBytes());
// load the hash value stored in password.bin
byte[] hashVal2 = loadBytes("password.bin");
return Arrays.equals(hashVal1, hashVal2);
} private byte[] generateSalt(int n) {
// generate a random byte array of length n
}
}

即使攻击者知道程序使用SHA-256散列函数和12字节的盐,他还是不能从password.bin和salt.bin中获取获取真实的密码。

尽管上面的代码攻克了password被解密的问题,可是这段代码使用String对象来存放明文的password,因此。可參见“#00限制敏感数据的生命周期”进行改进。



[符合安全要求的解决方式]

以下的代码使用byte数组来存储明文password。

public final class Password {

	private void setPassword(byte[] pass) throws Exception {
byte[] salt = generateSalt(12);
byte[] input = appendArrays(pass, salt);
MessageDigest msgDigest = MessageDigest.getInstance("SHA-256");
// encode the string and salt
byte[] hashVal = msgDigest.digest(input);
clearArray(pass);
clearArray(input);
saveBytes(salt, "salt.bin"); // save the hash value to password.bin
saveBytes(hashVal, "password.bin");
clearArray(salt);
clearArray(hashVal);
} boolean checkPassword(byte[] pass) throws Exception {
byte[] salt = loadBytes("salt.bin");
byte[] input = appendArrays(pass, salt);
MessageDigest msgDigest = MessageDigest.getInstance("SHA-256");
// encode the string and salt
byte[] hashVal1 = msgDigest.digest(input);
clearArray(pass);
clearArray(input); // load the hash value stored in password.bin
byte[] hashVal2 = loadBytes("password.bin");
boolean arraysEqual = Arrays.equals(hashVal1, hashVal2);
clearArray(hashVal1);
clearArray(hashVal2);
return arraysEqual;
} private byte[] generateSalt(int n) {
// generate a random byte array of length n
} private byte[] appendArray(byte[] a, byte[] b) {
// return a new array of a[] appended to b[]
} private void clearArray(byte[] a) {
for (int i=0; i<a.length; ++i) {
a[i] = 0;
}
}
}

在setPassword()和checkPassword()函数中,明文password在使用后马上清空。

因此,攻击者在明文password清空后必须花费很多其它精力才干获取明文password。提供有保证的password清空是极具挑战的,它可能是平台相关的,甚至可能因为复制垃圾回收/动态分页/其它执行在Java语言之下的平台机制而变得不可行。



[适用性]

没有经过安全散列运算就进行存储的passwordeasy被非法的用户获取到。违背本条约将导致程序easy被非法利用。

像password管理器这种应用程序可能须要取得原始password并将其填写到第三方应用中。这一点是同意的,即使它违背了本条约。password管理器是由单一用户訪问的,并且通常是经过用户许可的才干够保存用户的password。同一时候依据要求进行password的展示。

因此,安全的决定因素取决于用户个人的能力而非程序的功能。

——欢迎转载。请注明出处 http://blog.csdn.net/asce1885 ,未经本人允许请勿用于商业用途,谢谢——

【Java编码准则】の #13使用散列函数保存password的更多相关文章

  1. 【Java编码准则】の #02不要在client存储未加密的敏感信息

    当构建CS模式的应用程序时,在client側存储敏感信息(比如用户私要信息)可能导致非授权的信息泄漏. 对于Web应用程序来说,最常见的泄漏问题是在client使用cookies存放server端获取 ...

  2. 【Java编码准则】の #01限制内存中敏感数据的生命周期

    当竞争对手的应用程序与我们的应用程序执行在同一个系统上时,我们的应用程序在内存中的敏感数据是非常easy被竞争对手获取的.假设我们的应用程序符合以下几种情况之中的一个,那么竞争对手能够获取到我们应用的 ...

  3. 【Java编码准则】の #11不要使用Object.equals()来比較密钥值

    java.lang.Object.equals()函数默认情况下是不能用来比較组合对象的,比如密钥值.非常多Key类没有覆写equals()函数,因此,组合对象的比較必须单独比較里面的各个类型以保证正 ...

  4. 【Java编码准则】の #12不要使用不安全或者强度弱的加密算法

    安全性要求高的应用程序必须避免使用不安全的或者强度弱的加密算法,现代计算机的计算能力使得攻击者通过暴力破解能够攻破强度弱的算法.比如,数据加密标准算法DES是极度不安全的,使用类似EFF(Electr ...

  5. idea安装 阿里巴巴Java编码准则插件

    首先还是打开熟悉的idea 在marketplace 输入 alibaba 我这是已经安装过了 下载完成之后重启idea生效 如果需要那就手动的扫描 当然已经自动的扫描了 如果你的代码不符合阿里的标准 ...

  6. Java编码优化

    Java编码优化 1.尽可能使用局部变量 调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度较快,其他变 量,如静态变量.实例变量等,都在堆中创建,速度较慢.另外,栈中创建的变量,随 着方 ...

  7. java中文乱码解决之道(四)-----java编码转换过程

    前面三篇博客侧重介绍字符.编码问题,通过这三篇博客各位博友对各种字符编码有了一个初步的了解,要了解java的中文问题这是必须要了解的.但是了解这些仅仅只是一个开始,以下博客将侧重介绍java乱码是如何 ...

  8. 资料推荐--Google Java编码规范

    之前已经推荐过Google的Java编码规范英文版了: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html 虽然这篇文章的 ...

  9. Java编码规范

    1. Java命名约定 除了以下几个特例之外,命名时应始终采用完整的英文描述符.此外,一般应采用小写字母,但类名.接口名以及任何非初始单词的第一个字母要大写.1.1 一般概念 n 尽量使用完整 ...

随机推荐

  1. Yii2.0 使用createcommand从数据库查询出来的int类型变成了string型

    在给客户端写接口文档时,会给每个返回的字段标上数据类型,客户端会根据标注的类型来解析数据,如果标注的类型错误,会导致客户端解析出错,造成崩溃. 一直以来我都是用的Yii进行项目的开发,之前使用Yii1 ...

  2. Python之Excel编程

    excel编程:excel中是unicode编码方式 需要使用xrld,xlwt和openpyxl这三个模块,需先通过pip install下载     xlrd 读取模块:xls,xlsx     ...

  3. sublime text 3将px换算为rem的插件的安装及使用

    标签: rem这个单位对于移动端来说是比较强大的,所以这里给大家介绍sublime text 3将px换算为rem的插件的安装及使用,只要安装了这个插件,输入多少px,sublime就会提示相应的re ...

  4. YYH的营救计划(NOIP模拟赛Round 6)

    题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!YYH感动的热泪盈眶,开起了门…… YYH的父亲下班回家,街坊邻居说YYH被一群陌生人强行押上了警车!YYH的父 ...

  5. R语言绘制相对性关系图

    准备 第一步就是安装R语言环境以及RStudio 图绘制准备 首先安装库文件,敲入指令,回车 install.packages('corrplot') 然后安装excel导入的插件,点击右上角impo ...

  6. struct timeval和gettimeofday()

    http://www.cppblog.com/lynch/archive/2011/08/05/152520.html struct timeval结构体在time.h中的定义为: struct ti ...

  7. 使用 WideCharToMultiByte Unicode 与 UTF-8互转

    1.简述 最近在发送网络请求时遇到了中文字符乱码的问题,在代码中调试字符正常,用抓包工具抓的包中文字符显示正常,就是发送到服务器就显示乱码了,那就要将客户端和服务器设置统一的编码(UTF-8),而我们 ...

  8. 生成一个空白BMP的简单代码【转】

    转自:http://blog.chinaunix.net/uid-15063109-id-4275395.html 做图像处理时,有时需要临时生成图使用.以下是生成320x240 24位图的一个简单的 ...

  9. python 独立环境安装

    python 即使是单独编译安装的,库文件的安装还是会与其它python的库存放到相同的地方 使用同版本库不会有问题,但是需要升级库的时候,就会出现冲突,导致依赖这个旧库的python出现问题 这时候 ...

  10. Centos 6.3nginx安装

    1. 增加源: vi /etc/yum.repos.d/nginx.repo CentOS: [nginx] name=nginx repo baseurl=http://nginx.org/pack ...