(一) 为什么要用哈希函数来加密密码

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

解决的办法是将密码加密后再存储进数据库,比较常用的加密方法是使用哈希函数(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,也可以使用下面的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"); }
}总结:单单使用哈希函数来为密码加密是不够的,需要为密码加盐来提高安全性,盐的长度不能过短,并且盐的产生应该是随机的。 

本文转自:http://www.csharpwin.com/csharpspace/13412r9615.shtml

转载于:https://www.cnblogs.com/xizz/p/5007531.html

C# 使用Salt+Hash来为密码加密相关推荐

  1. salt盐度与用户密码加密机制

    1 加Salt散列 2 ASP.NET 2.0 Membership中与密码散列有关的代码 声明:本文所罗列之源代码均通过Reflector取自.NET Framework类库,引用这些代码仅出于学习 ...

  2. 用户密码加密存储十问十答,一文说透密码安全存储

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者 | 程序员赵鑫 来源 | cnblogs.com/xinzh ...

  3. 深入解析Express下采用bcryptjs进行密码加密

    本篇文章主要介绍了Express下采用bcryptjs进行密码加密的方法,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指正. bcrypt,是一个跨平 ...

  4. 使用密钥加密码加密_创建基于密码的加密密钥

    使用密钥加密码加密 本文讨论了创建基于密码的加密PBE密钥. 首先提醒您以前的要点–通常,在实际操作中,应将PBE密钥用作主密钥,该主密钥仅用于解锁工作密钥. 这具有三个主要优点: 您可以有多个密码, ...

  5. 学习Spring Boot:(十四)spring-shiro的密码加密

    前言 前面配置了怎么使用 shiro ,这次研究下怎么使用spring shiro的密码加密,并且需要在新增.更新用户的时候,实现生成盐,加密后的密码进行入库操作. 正文 配置凭证匹配器 @Beanp ...

  6. 浅析ASP.NET 2.0的用户密码加密机制

    摘要: 1 加Salt散列 2 ASP.NET 2.0 Membership中与密码散列有关的代码 声明:本文所罗列之源代码均通过Reflector取自.NET Framework类库,Anders ...

  7. Shiro自定义realm实现密码验证及登录、密码加密注册、修改密码的验证

    一:先从登录开始,直接看代码 @RequestMapping(value="dologin",method = {RequestMethod.GET, RequestMethod. ...

  8. 使用md5+salt+hash散列查询

    一.说明 1.分析 通过MD5+salt+hash散列进行用户登录查询. 重点:(1)加密存储到数据库(2)验证登录用户信息和数据库信息是否一致 2.目录结构 二.范例 1.调用类 (1)代码块 pa ...

  9. 加盐密码哈希:如何正确使用 (密码加密的经典文章)

    https://crackstation.net/hashing-security.htm http://blog.jobbole.com/61872/ 本文由 伯乐在线 - 蒋生武 翻译.未经许可, ...

最新文章

  1. Mysql的“Table ‘mysql.servers‘ doesn‘t exist”的解决方法
  2. 分析Windows和Linux动态库
  3. 界面原型创建工具Axure 基本操作
  4. shopnc 商城源码阅读笔记--开篇概述
  5. Parent Equipment 和IBASE relationship创建时的检查逻辑
  6. EntityFramework Core上下文实例池原理
  7. 电池供电的电容麦_电容话筒受潮了怎么办?
  8. arcgis在面内创建随机点
  9. 1473. A + B 格式
  10. 设备接入服务,看完这篇给你整的明明白白
  11. azure机器学习_如何在Azure机器学习中使用JSON数据
  12. 漫画:为什么下载电影进度总是卡在 99% 就不动了?
  13. 第4章 最基础的分类算法-k近邻算法 kNN 学习笔记 中
  14. Python基于共现提取《釜山行》人物关系
  15. kindle刷机ttl_kindle咕咪版如何刷成普通kindle版本?
  16. Profinet简介
  17. LOJ#2339. 「WC2018」通道(边分治+虚树)
  18. 制作多关卡系统 func_brush
  19. C#使用iTextSharp将数据导出成PDF
  20. python用四个圆画成花_【元旦手工】最美元旦手工花手工教程,赶紧提前收藏吧!...

热门文章

  1. 中国研制成功人工智能探地雷达 可为地下空间做“体检”
  2. sipp介绍与脚本撰写(一)
  3. 初识OpenGL (-)纹理过滤(Texture Filtering)
  4. UE4 VR 重置摄像机朝向
  5. 网站页面静态化(一)初识
  6. 贝壳找房APP安装包瘦身
  7. 惯性力偶矩公式中j_理论力学(I)习题详解达朗贝尔原理.pdf
  8. 欧冠 欧洲杯免费直播平台
  9. 区块链核心技术演进之路-算法演进
  10. 个人笔记使用(wolai,OneNote)