本文转自: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 运算方法的更多相关文章

  1. js数据结构之hash散列的详细实现方法

    hash散列中需要确定key和value的唯一确定关系. hash散列便于快速的插入删除和修改,不便于查找最大值等其他操作 以下为字符和数字的hash散列: function HashTable () ...

  2. Flask学习记录之使用Werkzeug散列密码

    数据库中直接存放明文密码是很危险的,Werkzeug库中的security能够方便的实现散列密码的计算 security库中 generate_password_hash(password,metho ...

  3. Shiro入门学习之散列算法与凭证配置(六)

    一.散列算法概述 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5.SHA等,一般进行散列时最好提供一个salt(“盐”),什么意思?举个栗子 ...

  4. JDK8;HashMap:再散列解决hash冲突 ,源码分析和分析思路

    JDK8中的HashMap相对JDK7中的HashMap做了些优化. 接下来先通过官方的英文注释探究新HashMap的散列怎么实现 先不给源码,因为直接看源码肯定会晕,那么我们先从简单的概念先讲起   ...

  5. 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链

    散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...

  6. DotNet加密方式解析--散列加密

    没时间扯淡类,赶紧上车吧. 在现代社会中,信息安全对于每一个人都是至关重要的,例如我们的银行账户安全.支付宝和微信账户安全.以及邮箱等等,说到信息安全,那就必须得提到加密技术,至于加密的一些相关概念, ...

  7. .NET加密方式解析--散列加密

    在现代社会中,信息安全对于每一个人都是至关重要的,例如我们的银行账户安全.支付宝和微信账户安全.以及邮箱等等,说到信息安全,那就必须得提到加密技术,至于加密的一些相关概念,在这里就不说了. 这一次将会 ...

  8. Java 散列集笔记

    散列表 散列表(hash table)为每个对象计算一个整数,称为散列码(hash code). 若需要自定义类,就要负责实现这个类的hashCode方法.注意自己实现的hashCode方法应该与eq ...

  9. [No0000132]正确使用密码加盐散列[译]

    如果你是一个 web 开发工程师,可能你已经建立了一个用户账户系统.一个用户账户系统最重要的部分是如何保护密码.用户账户数据库经常被黑,如果你的网站曾经被攻击过,你绝对必须做点什么来保护你的用户的密码 ...

随机推荐

  1. angular环境安装与配置

    1.安装npm和nodejs,下载地址:https://nodejs.org/en/download/ node -v npm -v   2.配置淘宝代理,下载node_modules npm con ...

  2. [luoguP2031] 脑力达人之分割字串(DP)

    传送门 想了个4次方算法,没想到也A了,数据真是水. 其实两个字符串匹配那部分可以用kmp优化 ——代码 #include <cstdio> #include <cstring> ...

  3. noip模拟赛 排列

    [问题描述] 给出一个随机的排列,请你计算最大值减最小值的差小于等于0~n-1的区间分别有多少个. 输入格式 输入文件名为sum.in. 第一行一个数T(<=10),表示数据组数 对于每一组数据 ...

  4. codeforces 371D

    #include<stdio.h> #define N 210000 struct node { int x,next; __int64 count,vec; }pre[N]; int n ...

  5. Javaweb中文乱码问题

    request.setCharacterEncoding("utf-8");必须写在获得参数之前,即request.getParameter();之前

  6. (12)GrabCut前景提取

    import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('opencv-python-foregr ...

  7. PHP htmlentities 和 htmlspecialchars的区别

    一直对这两个转换htm字符为html实体的函数混淆不清,查询了一下文档,总结如下 htmlentities: Convert all applicable characters to HTML ent ...

  8. SfM环境的搭建windows8.1+vs2010

    SfM即Structure form Motion,这个算法的实现,作者Noah Snavely给出了一个具体的实现. 目前最新下载https://github.com/snavely/bundler ...

  9. 用Docker创建Nexus

    步骤如下: 1. 创建持久化目录 $ mkdir /some/dir/nexus-data && chown -R 200 /some/dir/nexus-data 2. 创建镜像并运 ...

  10. SIGSEGV 和 SIGBUS & gdb看汇编

    参考这篇文章: http://blog.chinaunix.net/uid-24599332-id-2122898.html SIGBUS和SIGSEGV也许是我们在平时遇到的次数最多的两个内存错误信 ...