详解对密码执行散列和 salt 运算方法
credentials.cs
using system;
using system.io;using system.text;
using system.security.cryptography;
namespace bookstore.common{
/// <summary>
/// credentials 的摘要说明。
/// 原理:
/// 对密码执行散列运算
/// 若要避免以明文形式存储密码,一种常见的安全做法是对密码执行散列运算。如以下代码所示,使用 system.security.cryptography 命名空间(他实现 160 位 sha-1 标准)对密码进行散列运算。有关更多信息,请参见 sha1 成员。
/// 对散列执行 salt 运算
/// 虽然对密码执行散列运算的一个好的开端,但若要增加免受潜在攻击的安全性,则能够对密码散列执行 salt 运算。salt 就是在已执行散列运算的密码中插入的一个随机数字。这一策略有助于阻止潜在的攻击者利用预先计算的字典攻击。字典攻击是攻击者使用密钥的任何可能组合来破解密码的攻击。当您使用 salt 值使散列运算进一步随机化后,攻击者将需要为每个 salt 值创建一个字典,这将使攻击变得很复杂且成本极高。
/// salt 值随散列存储在一起,并且未经过加密。所存储的 salt 值能够在随后用于密码验证。
/// </summary>
public class credentials
{
private static string key = "!48%0d-f=cj>,s&2"; //密钥(增加密码复杂度,似乎比较多余)
private const int saltlength = 4; //定义salt值的长度
/// <summary>
/// 对密码进行hash 和 salt
/// </summary>
/// <param name="password">用户输入的密码</param>
/// <returns></returns>
public static byte[] hashandsalt(string password)
{
return createdbpassword(hashpassword(password));
}
/// <summary>
/// 对用户输入的密码加上密钥key后进行sha1散列
/// </summary>
/// <param name="password">用户输入的密码</param>
/// <returns>返回 160 位 sha-1 散列后的的byte[](160位对应20个字节)</returns>
private static byte[] hashpassword( string password )
{
//创建sha1的对象实例sha1
sha1 sha1 = sha1.create();
//计算输入数据的哈希值
return sha1.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 值,数据库中的密码的后4个字节为salt 值
byte[] saltvalue = new byte[saltlength];
int saltoffset = storedpassword.length - saltlength;
for (int i = 0; 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="array1"></param>
/// <param name="array2"></param>
/// <returns>true:相等/false:不等</returns>
private static bool comparebytearray(byte[] array1, byte[] array2)
{
if (array1.length != array2.length)
{
return false;
}
for (int i = 0; i < array1.length; i++)
{
if (array1[i] != array2[i])
{
return false;
}
}
return true;
}
/// <summary>
/// 对要存储的密码进行salt运算
/// </summary>
/// <param name="unsaltedpassword">没有进行过salt运算的hash散列密码</param>
/// <returns>经过salt的密码(经过salt的密码长度为:20+4=24,存储密码的字段为binary(24))</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,0);
saltvalue.copyto(rawsalted,unsaltedpassword.length);
//将合并后的rawsalted数组再进行sha1散列的到saltedpassword数组(长度为20字节)
sha1 sha1 = sha1.create();
byte[] saltedpassword = sha1.computehash(rawsalted);
//将salt值数组在添加到saltedpassword数组后拼接成dbpassword数组(长度为24字节)
byte[] dbpassword = new byte[saltedpassword.length + saltvalue.length];
saltedpassword.copyto(dbpassword,0);
saltvalue.copyto(dbpassword,saltedpassword.length);
return dbpassword;
}
}
}
转载于:https://www.cnblogs.com/88223100/archive/2008/04/25/1171310.html
详解对密码执行散列和 salt 运算方法相关推荐
- Hashed password with salted value——利用salt对密码进行散列
在没有学习web安全密码学部分的时候,我自己全部的密码都是同一个,而且是7位数字组成的.还好我本身没有什么财产好损失,不过都不会再犯这种愚蠢错误了. 我们为什么需要对密码进行hash化,又为什么要在h ...
- R语言tidyr包Unite()函数实战详解:多个数据列合并为一列
R语言tidyr包Unite()函数实战详解:多个数据列合并为一列 目录 R语言tidyr包Unite()函数实战详解:多个数据列合并为一列
- 前端中全部盒子靠左对齐_图文详解ul中li内容垂直居中和水平居中的方法
在页面布局时,经常会用到li标签,它可用于列表,导航,选项卡等等,那你知道如何让ul中的li居中吗?这篇文章就和大家讲讲如何让ul中的li水平居中以及如何让li内容垂直居中.感兴趣的朋友继续往下看吧. ...
- linux系统rc路由配置_详解CentOS 6.4 添加永久静态路由所有方法汇总
CentOS添加永久静态路由,具体如下: 在使用双网卡,同时使用2个网关的时候就需要加一条静态路由了.当然还有很多时候会需要加路由. 操作系统版本centos-6.4 64bit 一:使用route ...
- Python基础知识详解 从入门到精通(八)魔法方法
目录 Python基础知识详解 从入门到精通(八)魔法方法 什么是魔法方法 基础魔法方法(较为常用) 比较操作符 算数运算符 反运算(类似于运算方法) 增量赋值运算 一元操作符 类型转换 上下文管理( ...
- 详解Python中pyautogui库的最全使用方法
这篇文章主要介绍了详解Python中pyautogui库的最全使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值 在使用Python做脚本的话,有两个库可以使用,一个 ...
- win7计算机凭证,windows凭证管理,详解win7电脑添加和管理windows凭证的方法
今天小编给大家详解win7电脑添加和管理windows凭证的方法,使用win7系统过程中,如果你频繁的登录某些服务器,如果每次都要输入用户和密码就会觉得比较麻烦,其实可通过以下的方法添加凭据,便可不需 ...
- tomcat7修改内存 win_详解Windows下调整Tomcat启动参数的实现方法
Windows下调整Tomcat启动参数 Tomcat默认可以使用的内存为128MB,对于访问数比较多.比较吃内存的应用来说,这是不够的.我们可以通过调整Java虚拟机的启动参数来增加Tomcat可使 ...
- linux 服务器拦截http请求,详解Linux屏蔽浏览器上http请求警报的方法
众所周知,在Linux系统中浏览器的页面上是不允许出现http请求的,如果出现了http请求就会发生错误,并且Linux系统会向用户发出警报.下面,U大侠小编就给大家详解Linux屏蔽浏览器上http ...
- mysql mgr 三节点_详解MySQL 5.7 MGR单主确定主节点方法
我们行MGR年底要上线了,每天都要看官方文档学习,做测试,坚持每天写一个小知识点,有想一起学习的么~ MySQL 5.7 MGR单主确定主节点是哪个,我们可以通过成员ID来判断,然后结合read_on ...
最新文章
- 栈与队列5——汉诺塔问题(方案二)
- ansible(1)——安装
- UE4学习-场景介绍、基本操作、快捷键
- 认识Linux下的各种系统服务
- PyTorch之torch.nn.Softmax()
- Git 仓库基础操作
- hdu6107 倍增法st表
- ApplePay支付使用
- NSNotificationCenter消息通信机制介绍(KVO)
- anroid Remote Service 使用注意事项
- Setup Factory 卸载 Invalid Start mode :archive filename
- 北京地区中波频率表2015版 (转载)
- 元宇宙产业委员会联席秘书长李正海做元宇宙顶层设计预研项目探讨报告
- PyTorch(13)---优化器_随机梯度下降法
- VB中ByVal与ByRef有什么区别
- Burpsuite的基本使用介绍
- 洛谷入门篇的相关题解
- php请求纯文本,php – 使用纯文本回退发送HTML简报
- mysql gps数据查询_Mysql数据库中计算两GPS坐标的距离
- 一文说透安全沙箱技术
热门文章
- 1t硬盘怎么分区最好_新买的固态硬盘该不该分区?分区后性能如何?真是后悔知道晚了!...
- android 关掉屏幕旋转,防止在Android中屏幕旋转时解除对话框
- C/C++[算法入门]
- 算法:回溯八 Combinations指定个数组合
- python无法打开txt_在Python中打开“.txt”文件
- 线性回归模型的评价指标
- github第一次使用--创建hello-world
- 继承、关联、聚合、组合的代码表示
- 频谱感知2:衰落信道上未知信号的能量检测
- Springboot配置devtools实现热部署