如何提高账户密码存储的安全性——PasswordSalt的使用

使用 Salt + Hash 将密码加密后再存储进数据库

如果你需要保存密码(比如网站用户的密码),你要考虑如何保护这些密码数据,象下面那样直接将密码写入数据库中是极不安全的,因为任何可以打开数据库的人,都将可以直接看到这些密码

解决的办法是将密码加密后再存储进数据库,比较常用的加密方法是使用哈希函数(Hash Function)。哈希函数的具体定义,大家可以在网上或者相关书籍中查阅到,简单地说,它的特性如下:

(1)原始密码经哈希函数计算后得到一个哈希值

(2)改变原始密码,哈希函数计算出的哈希值也会相应改变

(3) 同样的密码,哈希值也是相同的

(4) 哈希函数是单向、不可逆的。也就是说从哈希值,你无法推算出原始的密码是多少

有了哈希函数,我们就可以将密码的哈希值存储进数据库。用户登录网站的时候,我们可以检验用户输入密码的哈希值是否与数据库中的哈希值相同。

(二) 几种常见的破解密码的方法

最简单、常见的破解方式当属字典破解(Dictionary Attack)和暴力破解(Brute Force Attack)方式。这两种方法说白了就是猜密码。

字典破解和暴力破解都是效率比较低的破解方式。如果你知道了数据库中密码的哈希值,你就可以采用一种更高效的破解方式,查表法(Lookup Tables)。还有一些方法,比如逆向查表法(Reverse Lookup Tables)、彩虹表(Rainbow Tables)等,都和查表法大同小异。现在我们来看一下查表法的原理。

查表法不像字典破解和暴力破解那样猜密码,它首先将一些比较常用的密码的哈希值算好,然后建立一张表,当然密码越多,这张表就越大。当你知道某个密码的哈希值时,你只需要在你建立好的表中查找该哈希值,如果找到了,你就知道对应的密码了。

(三) 为密码加盐(Salt)

从上面的查表法可以看出,即便是将原始密码加密后的哈希值存储在数据库中依然是不够安全的。那么有什么好的办法来解决这个问题呢?答案是加盐。

盐(Salt)是什么?就是一个随机生成的字符串。我们将盐与原始密码连接(concat)在一起(放在前面或后面都可以),然后将concat后的字符串加密。采用这种方式加密密码,查表法就不灵了(因为盐是随机生成的)。

(四) 在.NET中的实现

在.NET中,生成盐可以使用RNGCryptoServiceProvider类,当然也可以使用GUID。哈希函数的算法我们可以使用SHA(Secure Hash Algorithm)家族算法,当然哈希函数的算法有很多,比如你也可以采用MD5。这里顺便提一下,美国政府以前广泛采用SHA-1算法,在2005年被我国山东大学的王小云教授发现了安全漏洞,所以现在比较常用SHA-1加长的变种,比如SHA-256。在.NET中,可以使用SHA256Managed类。

下面来看一段代码演示如何在.NET中实现给密码加盐加密。加密后的密码保存在MySQL数据库中。

下面的代码演示如何注册一个新帐户。盐的生成可以使用新Guid,也可以使用RNGCryptoServiceProvider 类。将byte[]转换为string,可以使用Base64String(我在以前的博客中介绍过Base 64 Encoding 编码),也可以使用下面的ToHexString方法。

protected void ButtonRegister_Click(object sender, EventArgs e)
{
    string username = TextBoxUserName.Text;
    string password = TextBoxPassword.Text;
    // random salt
    string salt = Guid.NewGuid().ToString();

    // random salt
    // you can also use RNGCryptoServiceProvider class
    //System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
    //byte[] saltBytes = new byte[36];
    //rng.GetBytes(saltBytes);
    //string salt = Convert.ToBase64String(saltBytes);
    //string salt = ToHexString(saltBytes);

    byte[] passwordAndSaltBytes = System.Text.Encoding.UTF8.GetBytes(password + salt);
    byte[] hashBytes = new System.Security.Cryptography.SHA256Managed().ComputeHash(passwordAndSaltBytes);

    string hashString = Convert.ToBase64String(hashBytes);

    // you can also use ToHexString to convert byte[] to string
    //string hashString = ToHexString(hashBytes);

    var db = new TestEntities();
    usercredential newRecord = usercredential.Createusercredential(username, hashString, salt);
    db.usercredentials.AddObject(newRecord);
    db.SaveChanges();
}

string ToHexString(byte[] bytes)
{
    var hex = new StringBuilder();
    foreach (byte b in bytes)
    {
        hex.AppendFormat("{0:x2}", b);
    }
    return hex.ToString();
}
protected void ButtonSignIn_Click(object sender, EventArgs e)
{
string username = TextBoxUserName.Text;
string password = TextBoxPassword.Text;

var db = new TestEntities();
usercredential record = db.usercredentials.Where(x => string.Compare(x.UserName, username, true) == 0).FirstOrDefault();
if (record == default(usercredential))
{
throw new ApplicationException("invalid user name and password");
}

string salt = record.Salt;
byte[] passwordAndSaltBytes = System.Text.Encoding.UTF8.GetBytes(password + salt);
byte[] hashBytes = new System.Security.Cryptography.SHA256Managed().ComputeHash(passwordAndSaltBytes);
string hashString = Convert.ToBase64String(hashBytes);

if (hashString == record.PasswordHash)
{
// user login successfully
}
else
{
throw new ApplicationException("invalid user name and password");
}
}
时间: 2024-10-12 19:31:48

如何提高账户密码存储的安全性——PasswordSalt的使用的相关文章

Linux 中提高的 SSH 的安全性

SSH 是远程登录 Linux 服务器的最常见的方式.且 SSH 登录的时候要验证的,相对来讲会比较安全.那只是相对,下面会介绍一些方式提高 SSH 的安全性 SSH 的验证 而SSH 登录时有两种验证方式 1. 密码认证,要求用户每次登录服务器的时候都要输入密码 2. 密钥认证,客户端的公钥先保存在服务器的.ssh/authorized_keys中,登录时使用该公钥自动验证,认证成功就不用输入密码都能登录 密码认证的问题 密码简单容易被人攻破, 密码复杂难记,又比较容易输错. 容易被人用暴力破

How Javascript works (Javascript工作原理) (十二) 网络层探秘及如何提高其性能和安全性

个人总结:阅读完这篇文章需要20分钟,这篇文章主要讲解了现代浏览器在网络层传输所用到的一些技术. 这是 JavaScript 工作原理的第十二章. 正如在之前关于渲染引擎的文章中所讲的那样,我们相信好的和伟大的 JavaScript 开发者之间的差别在于后者不仅仅只是理解了语言的具体细节还了解其内部构造和运行环境. 网络简史 49 年前,ARPAnet 诞生了.它是早期的报文分组交换网络及第一个实现 TCP/IP 协议套件的网络.该网络连通了加利福亚大堂和斯坦福研究所.20 年后,Tim Ber

Linux软RAID基本操作介绍

RAID全称是 "A Case for Redundant Arrays of Inexpensive Disks (RAID)",称为"廉价磁盘冗余阵列",由加州大学伯克利大学在1987年发表的论文中而来.RAID的主要思想就是把若干小容量物理磁盘组成一个大容量虚拟存储设备,以提高磁盘存储的读.写效率,并提供冗余以提高数据存储的安全性. 根据应用方向的不同,RAID也分为不同级别,常用的有RAID-0.RAID-1.RAID-5.RAID-10. RAID-0也称

软RAID 0的技术概要及实现

1 什么是RAID,RAID的级别和特点 : 什么是RAID呢?全称是 “A Case for Redundant Arrays of Inexpensive Disks (RAID)”,在1987年,由加州大学伯克利大学发表的论文而来,其实就是这个标题的缩写就是RAID;中译为“磁盘阵列”: RAID就是把几个物理磁盘组合在一起成为一个大的虚拟物理磁盘,主要目的和用途主要有:把若干小容量物理磁盘组成一个大容量虚拟存储设备(以前的物理磁盘的容量都比较小):提高物理存储效率(读.写),或提供冗余以

使用nodeJS的 crypto模块来为你的密码hash加盐

这篇文章将向你解释如何使用Node.js的Crypto模块对你的密码进行加盐hash.在这里,我们将不会对不懂的密码存储方式进行详细的比较.我们将要做的是知道在Node.js中使用加盐hash在进行密码存储的机制.放心,这是最好的存储密码的方式,在没有出现其他更好的方法之前. 这是什么技术 加盐是这样一直技术:将用户输入的密码和一个随机的字符串(这个字符串就是盐)通过hash结合,通过hash算法生成一个hash值,然后将结果存储在数据库中. 为什么要进行加盐Hash 因为相同密码的hash值是

[译]在Linux上的提高MySQL/MariaDB安全性的12条建议

MySQL 是世界上最流行的开源数据库系统,而MariaDB(MySQL的一个分支)是世界上发展最快的开源数据库系统.安装MySQL服务器之后,它的默认配置是不安全的,保护它是一般数据库管理中的基本任务之一. 这将有助于加强和提升整体Linux服务器安全性,因为攻击者总是扫描系统任何部分的漏洞,而数据库过去一直是关键的目标.一个常见的例子是暴力破解MySQL数据库的root密码. 在本指南中,将讲解在 Linux 很有用的 MySQL / MariaDB 安全性最佳实践. MySQL 安全性安装

[html5]localStorage的原理和HTML5本地存储安全性

http://zccst.iteye.com/blog/2194344 HTML5本地存储的前身就是Cookie,HTML5的本地存储是使用localStorage对象将WEB数据持久化在本地.相比较而言HTML5本地存储中每个域的存储大小默认是5M,比起Cookie的4K要大的多.而且存储和读取数据的代码极为简练: Window.localStorage.setItem(key,value);//存储数据 Window.localStorage.getItem(key);//读取数据 Wind

企业电子邮件注册后怎样提高安全性?

有研究表明,大约有94%的公司承认,他们在防止邮件外泄公司机密方面显得力不从心,那么,企业在注册电子邮箱后,怎么做才能提高其安全性呢?以网易企业邮箱为例,一般企业在注册电子邮箱之后可以进行以下操作,来提高企业邮箱的安全性. 首先,设置客户端授权密码.可以为每个客户端设置专属的授权密码,用授权密码代替邮箱密码登陆邮箱.这样做即使出现邮箱密码丢失的情况,邮件也不会泄露,而且客户端授权密码是可以自由选择开启或者关闭的,这个设置可以从登陆邮箱开始,就为邮箱安全拉上一道防线. 其次,通过管理后台实现邮箱人

虚拟机在 OpenStack 里没有共享存储条件下的在线迁移[转]

原文链接:http://www.ibm.com/developerworks/cn/cloud/library/1508_wangyx_openstacklivemigrate/ 迁移(Migration)就是把一个虚拟机从一台物理主机搬到另一台物理主机,动态(Live)就是在迁移过程中虚拟机正常工作不影响用户的使用.对系统管理员来说,动态迁移是个非常有用的工具,当计划对一个物理主机进行更新或者升级(update/upgrade)的时候,管理员不需要关闭这个物理主机上的虚拟机,只是在更新或者升级