[转]c# 对密码执行散列和 salt 运算方法
本文转自:http://www.cnblogs.com/CnBlogFounder/archive/2008/07/04/1235690.html
大家对密码执行散列和Salt运算一定不陌生。两个Visual Studio企业版示例都是用的这个方法来加密这个方法的。
结合示例代码,我总结了一个包含对密码进行加密,比较等静态方法的类。
使用说明:先用HashAndSalt方法对密码进行加密,然后存储到数据库中。
在用户登录时用ComparePasswords方法在对用户输入的密码和用户注册时存储在数据库中的密码进行比较,判断用户输入的密码是否正确。
Credentials.cs using System;
using System.IO;
using System.Text;
using System.Security.Cryptography; namespace BookStore.Common
{
/// <summary>
/// Credentials 的摘要说明。
/// 原理:
/// 对密码执行散列运算
/// 若要避免以明文形式存储密码,一种常见的安全做法是对密码执行散列运算。如以下代码所示,使用 System.Security.Cryptography 命名空间(它实现 60 位 SHA- 标准)对密码进行散列运算。有关更多信息,请参见 SHA 成员。
/// 对散列执行 Salt 运算
/// 虽然对密码执行散列运算的一个好的开端,但若要增加免受潜在攻击的安全性,则可以对密码散列执行 Salt 运算。Salt 就是在已执行散列运算的密码中插入的一个随机数字。这一策略有助于阻止潜在的攻击者利用预先计算的字典攻击。字典攻击是攻击者使用密钥的所有可能组合来破解密码的攻击。当您使用 Salt 值使散列运算进一步随机化后,攻击者将需要为每个 Salt 值创建一个字典,这将使攻击变得非常复杂巧本极高。
/// Salt 值随散列存储在一起,并且未经过加密。所存储的 Salt 值可以在随后用于密码验证。
/// </summary>
public class Credentials
{
private static string key = "!8%0d-F=cj>,s&"; //密钥(增加密码复杂度,好像比较多余)
private const int saltLength = ; //定义salt值的长度 /// <summary>
/// 对密码进行Hash 和 Salt
/// </summary>
/// <param name="Password">用户输入的密码</param>
/// <returns></returns>
public static byte[] HashAndSalt(string Password)
{
return CreateDbPassword(HashPassword(Password));
} /// <summary>
/// 对用户输入的密码加上密钥key后进行SHA散列
/// </summary>
/// <param name="Password">用户输入的密码</param>
/// <returns>返回 60 位 SHA- 散列后的的byte[](60位对应0个字节)</returns>
private static byte[] HashPassword( string Password )
{
//创建SHA的对象实例sha
SHA sha = SHA.Create();
//计算输入数据的哈希值
return sha.ComputeHash( Encoding.Unicode.GetBytes( Password + key ) );
} /// <summary>
/// 比较数据库中的密码和所输入的密码是否相同
/// </summary>
/// <param name="storedPassword">数据库中的密码</param>
/// <param name="Password">用户输入的密码</param>
/// <returns>true:相等/false:不等</returns>
public static bool ComparePasswords(byte[] storedPassword, string Password)
{
//首先将用户输入的密码进行Hash散列
byte[] hashedPassword = HashPassword(Password); if (storedPassword == null || hashedPassword == null || hashedPassword.Length != storedPassword.Length - saltLength)
{
return false;
} //获取数据库中的密码的salt 值,数据库中的密码的后个字节为salt 值
byte[] saltValue = new byte[saltLength];
int saltOffset = storedPassword.Length - saltLength;
for (int i = ; i < saltLength; i++){
saltValue[i] = storedPassword[saltOffset + i];
} //用户输入的密码用户输入的密码加上salt 值,进行salt
byte[] saltedPassword = CreateSaltedPassword(saltValue, hashedPassword); //比较数据库中的密码和经过salt的用户输入密码是否相等
return CompareByteArray(storedPassword, saltedPassword);
} /// <summary>
/// 比较两个ByteArray,看是否相等
/// </summary>
/// <param name="array"></param>
/// <param name="array"></param>
/// <returns>true:相等/false:不等</returns>
private static bool CompareByteArray(byte[] array, byte[] array)
{
if (array.Length != array.Length)
{
return false;
}
for (int i = ; i < array.Length; i++)
{
if (array[i] != array[i])
{
return false;
}
}
return true;
} /// <summary>
/// 对要存储的密码进行salt运算
/// </summary>
/// <param name="unsaltedPassword">没有进行过salt运算的hash散列密码</param>
/// <returns>经过salt的密码(经过salt的密码长度为:0+=,存储密码的字段为Binary())</returns>
private static byte[] CreateDbPassword(byte[] unsaltedPassword)
{
//获得 salt 值
byte[] saltValue = new byte[saltLength];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(saltValue); return CreateSaltedPassword(saltValue, unsaltedPassword);
} /// <summary>
/// 创建一个经过salt的密码
/// </summary>
/// <param name="saltValue">salt 值</param>
/// <param name="unsaltedPassword">没有进行过salt运算的hash散列密码</param>
/// <returns>经过salt的密码</returns>
private static byte[] CreateSaltedPassword(byte[] saltValue, byte[] unsaltedPassword)
{
//将salt值数组添加到hash散列数组后拼接成rawSalted数组中
byte[] rawSalted = new byte[unsaltedPassword.Length + saltValue.Length];
unsaltedPassword.CopyTo(rawSalted,);
saltValue.CopyTo(rawSalted,unsaltedPassword.Length); //将合并后的rawSalted数组再进行SHA散列的到saltedPassword数组(长度为0字节)
SHA sha = SHA.Create();
byte[] saltedPassword = sha.ComputeHash(rawSalted); //将salt值数组在添加到saltedPassword数组后拼接成dbPassword数组(长度为字节)
byte[] dbPassword = new byte[saltedPassword.Length + saltValue.Length];
saltedPassword.CopyTo(dbPassword,);
saltValue.CopyTo(dbPassword,saltedPassword.Length); return dbPassword;
} }
}
[转]c# 对密码执行散列和 salt 运算方法的更多相关文章
- js数据结构之hash散列的详细实现方法
hash散列中需要确定key和value的唯一确定关系. hash散列便于快速的插入删除和修改,不便于查找最大值等其他操作 以下为字符和数字的hash散列: function HashTable () ...
- Flask学习记录之使用Werkzeug散列密码
数据库中直接存放明文密码是很危险的,Werkzeug库中的security能够方便的实现散列密码的计算 security库中 generate_password_hash(password,metho ...
- Shiro入门学习之散列算法与凭证配置(六)
一.散列算法概述 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5.SHA等,一般进行散列时最好提供一个salt(“盐”),什么意思?举个栗子 ...
- JDK8;HashMap:再散列解决hash冲突 ,源码分析和分析思路
JDK8中的HashMap相对JDK7中的HashMap做了些优化. 接下来先通过官方的英文注释探究新HashMap的散列怎么实现 先不给源码,因为直接看源码肯定会晕,那么我们先从简单的概念先讲起 ...
- 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链
散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...
- DotNet加密方式解析--散列加密
没时间扯淡类,赶紧上车吧. 在现代社会中,信息安全对于每一个人都是至关重要的,例如我们的银行账户安全.支付宝和微信账户安全.以及邮箱等等,说到信息安全,那就必须得提到加密技术,至于加密的一些相关概念, ...
- .NET加密方式解析--散列加密
在现代社会中,信息安全对于每一个人都是至关重要的,例如我们的银行账户安全.支付宝和微信账户安全.以及邮箱等等,说到信息安全,那就必须得提到加密技术,至于加密的一些相关概念,在这里就不说了. 这一次将会 ...
- Java 散列集笔记
散列表 散列表(hash table)为每个对象计算一个整数,称为散列码(hash code). 若需要自定义类,就要负责实现这个类的hashCode方法.注意自己实现的hashCode方法应该与eq ...
- [No0000132]正确使用密码加盐散列[译]
如果你是一个 web 开发工程师,可能你已经建立了一个用户账户系统.一个用户账户系统最重要的部分是如何保护密码.用户账户数据库经常被黑,如果你的网站曾经被攻击过,你绝对必须做点什么来保护你的用户的密码 ...
随机推荐
- Spring security 5 Authorize Configuration
1. Spring Security 核心请求,认证配置类 WebSecurityConfigurerAdapter protected void configure(HttpSecurity htt ...
- 【DIP, 图像增强】
第四章 图像增强 图像增强是按特定的需要突出一幅图像中的某些信息,同时削弱或者去除某些不需要的信息的处理方法.其主要目的是使处理后的图像对某种特定的应用来说,比原始图像更加适用.因此这类处理是为了某种 ...
- Spring MVC学习总结(8)——Swagger入门详解
前言 Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.本文简单介绍了在项目中集成swagger的方法和一些常见问题.如果想深入分析项目源码,了解更多内容,见参考资料. S ...
- iOS攻城狮修炼之路
自己总结的学习iOS的笔记,打造一个全面的知识体系,iOS攻城狮修炼之路[持续更新中] iOS学习笔记01-APP相关 iOS学习笔记02-UIScrollView iOS学习笔记03-UITable ...
- jquery ajax获取json并解析,获取的json是object对象格式
首先我们使用的是ajax方式,推荐一个学习网址: http://blog.csdn.net/shiyaru1314/article/details/51065410 这个博主写的特别好.现在来看我们的 ...
- D. Palindromic characteristics
time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standa ...
- 洛谷—— P3811 【模板】乘法逆元
https://www.luogu.org/problem/show?pid=3811 题目背景 这是一道模板题 题目描述 给定n,p求1~n中所有整数在模p意义下的乘法逆元. 输入输出格式 输入格式 ...
- - > 并查集模板
思路:在博客园里,有对并查集思路的详解,模板神马的只是饭后甜点: 这儿有只野生模板君飘过,请各位OIer尽快捕捉 #include<iostream> #include<cstdio ...
- vsftpd conf 解釋
Linux中vsFTP位置约定:/usr/sbin/vsftpd ---- VSFTPD的主程序/etc/rc.d/init.d/vsftpd ---- 启动脚本/etc/vsftpd/vsftpd. ...
- Project Euler:Problem 42 Coded triangle numbers
The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangl ...