今天介绍一种MD5的加密方法,代码中写了比较详细的注释,直接上例子了。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<%
@ Page Language
=
"
C#
"
AutoEventWireup
=
"
true
"
CodeFile
=
"
Encrypt.aspx.cs
"
Inherits
=
"
Encrypt
"
%>
<! DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN " " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " >
< html xmlns = " http://www.w3.org/1999/xhtml " >
< head runat = " server " >
< title ></ title >
</ head >
< body >
< form id = " form1 " runat = " server " >
< div >
原始密码: & nbsp; & nbsp; & nbsp; < asp:TextBox ID = " txtOriginal " runat = " server " Width = " 260px " ></ asp:TextBox >
< asp:Button ID = " btnEncrypt " runat = " server " Text = " 加密 "
onclick = " btnEncrypt_Click " />
< asp:TextBox ID = " txtPwd1 " runat = " server " Width = " 260px " ></ asp:TextBox >
< br />
加密后密码: < asp:TextBox ID = " txtPwd2 " runat = " server " Width = " 260px " ></ asp:TextBox >
< asp:Button ID = " btnCompare " runat = " server " Text = " 比较 "
onclick = " btnCompare_Click " />
< asp:TextBox ID = " txtNow " runat = " server " Width = " 260px " ></ asp:TextBox >
</ div >
</ form >
</ body >
</ html >
<! DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN " " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " >
< html xmlns = " http://www.w3.org/1999/xhtml " >
< head runat = " server " >
< title ></ title >
</ head >
< body >
< form id = " form1 " runat = " server " >
< div >
原始密码: & nbsp; & nbsp; & nbsp; < asp:TextBox ID = " txtOriginal " runat = " server " Width = " 260px " ></ asp:TextBox >
< asp:Button ID = " btnEncrypt " runat = " server " Text = " 加密 "
onclick = " btnEncrypt_Click " />
< asp:TextBox ID = " txtPwd1 " runat = " server " Width = " 260px " ></ asp:TextBox >
< br />
加密后密码: < asp:TextBox ID = " txtPwd2 " runat = " server " Width = " 260px " ></ asp:TextBox >
< asp:Button ID = " btnCompare " runat = " server " Text = " 比较 "
onclick = " btnCompare_Click " />
< asp:TextBox ID = " txtNow " runat = " server " Width = " 260px " ></ asp:TextBox >
</ div >
</ form >
</ body >
</ html >
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using
System;
using System.Security.Cryptography;
using System.Text;
public partial class Encrypt : System.Web.UI.Page
{
private const int saltLength = 4 ; // 偶数,随机值的位数,4位的“盐”
protected void Page_Load( object sender, EventArgs e)
{
}
/// <summary>
/// 生成要存储在数据库中的秘密
/// </summary>
/// <param name="password"> 用户输入的秘密 </param>
/// <returns> 生成的秘密字符串 </returns>
public static string CreateDbPassword( string password)
{
string strSaltValue = CreateSaltValue(); // 创建随即的4位“盐”
return CreateSaltedPassword(strSaltValue, CreateHashPassword(password)); // 先返回16进制哈希密码,再返回加了“盐”后的总共36位16进制哈希密码
}
/// <summary>
/// 比较秘密是否相同
/// </summary>
/// <param name="storedPassword"> 存在数据库中的秘密 </param>
/// <param name="password"> 用户提供的秘密 </param>
/// <returns> 是否相同 </returns>
public static bool ComparePasswords( string storedPassword, string password)
{
string hashPassword = CreateHashPassword(password); // 根据输入的密码创建16进制哈希密码
if (storedPassword == null || storedPassword.Length != 32 + saltLength) return false ; // 如果加密后的密码为空或者不够36位,则返回
string saltValue = storedPassword.Substring( 32 , saltLength); // 截取已加密密码的后四位,即:“盐”
string saltPassword = CreateSaltedPassword(saltValue, hashPassword); // 创建加“盐”的16进制哈希密码
return (saltPassword == storedPassword);
}
/// <summary>
/// 根据提供的秘码生成对应的Hash值
/// </summary>
/// <param name="password"> 秘码 </param>
/// <returns> Hash值字符串 </returns>
private static string CreateHashPassword( string password)
{
System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider(); // 创建MD5抽象类, 哈希算法的所有实现均从中继承
byte [] hexHashPassword = md5.ComputeHash(Encoding.ASCII.GetBytes(password)); // 先转换密码为ASCII字节数组,然后计算指定字节数组的哈希值,哈希值是一段数据唯一且极其紧凑的数值表示形式
string strHashPaword = HexToStr(hexHashPassword); // 将哈希值转换为16进制
return strHashPaword;
}
/// <summary>
/// 把字节数组转换成对应的字符串
/// </summary>
/// <param name="buf"></param>
/// <returns></returns>
private static string HexToStr( byte [] buf)
{
string aa = "" ;
string sTemp = "" ;
for ( int i = 0 ; i < buf.Length; i ++ )
{
sTemp = System.Convert.ToString(buf[i], 16 ); // 将字节数组转换为16进制
aa += sTemp.PadLeft( 2 , ' 0 ' ); // 转换后的16进制为两位,若不够则左边补零
}
return aa;
}
/// <summary>
/// 生成随机值 字符串
/// </summary>
/// <returns></returns>
private static string CreateSaltValue()
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); // 使用加密服务提供程序 (CSP) 提供的实现来实现加密随机数生成器 (RNG)。此类不能继承。
byte [] saltValue = new byte [saltLength / 2 ]; // 创建字节数组
rng.GetBytes(saltValue); // 生成随即数,赋值给字节数组
string strSaltValue = HexToStr(saltValue); // 转换为16进制
return strSaltValue;
}
/// <summary>
/// 生成带有随机值的密码
/// </summary>
/// <param name="saltValue"> 随机值 </param>
/// <param name="hashPassword"> 秘密的Hash值 </param>
/// <returns> 带有随机值的密码字符串 </returns>
private static string CreateSaltedPassword( string saltValue, string hashPassword)
{
System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider(); // 创建MD5抽象类, 哈希算法的所有实现均从中继承
string tempPassword = hashPassword + saltValue; // 经过加密后的密码再加上“盐”
byte [] hexSaltPassword = md5.ComputeHash(Encoding.ASCII.GetBytes(tempPassword)); // 将加了盐密码先转换密码为ASCII字节数组,然后计算指定字节数组的哈希值,哈希值是一段数据唯一且极其紧凑的数值表示形式
string strSaltPassword = HexToStr(hexSaltPassword); // 将加了盐的哈希密码转换为16进制
string dbPassword = strSaltPassword + saltValue; // 再将密码再加上“盐”,此时密码长度为36位,至此加密完成
return dbPassword;
}
/// <summary>
/// 加密按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnEncrypt_Click( object sender, EventArgs e)
{
string pwd = txtOriginal.Text.Trim(); // 这里的字符串没有经过太多处理,只是测试
txtPwd1.Text = CreateDbPassword(pwd); // 调用加密函数
}
/// <summary>
/// 比较按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnCompare_Click( object sender, EventArgs e)
{
bool isTrue;
isTrue = ComparePasswords(txtPwd2.Text.Trim(), txtOriginal.Text.Trim()); // 判断加密后的密码,与原始密码加密后是否相等
txtNow.Text = isTrue ? " 相等 " : " 不相等 " ;
}
}
using System.Security.Cryptography;
using System.Text;
public partial class Encrypt : System.Web.UI.Page
{
private const int saltLength = 4 ; // 偶数,随机值的位数,4位的“盐”
protected void Page_Load( object sender, EventArgs e)
{
}
/// <summary>
/// 生成要存储在数据库中的秘密
/// </summary>
/// <param name="password"> 用户输入的秘密 </param>
/// <returns> 生成的秘密字符串 </returns>
public static string CreateDbPassword( string password)
{
string strSaltValue = CreateSaltValue(); // 创建随即的4位“盐”
return CreateSaltedPassword(strSaltValue, CreateHashPassword(password)); // 先返回16进制哈希密码,再返回加了“盐”后的总共36位16进制哈希密码
}
/// <summary>
/// 比较秘密是否相同
/// </summary>
/// <param name="storedPassword"> 存在数据库中的秘密 </param>
/// <param name="password"> 用户提供的秘密 </param>
/// <returns> 是否相同 </returns>
public static bool ComparePasswords( string storedPassword, string password)
{
string hashPassword = CreateHashPassword(password); // 根据输入的密码创建16进制哈希密码
if (storedPassword == null || storedPassword.Length != 32 + saltLength) return false ; // 如果加密后的密码为空或者不够36位,则返回
string saltValue = storedPassword.Substring( 32 , saltLength); // 截取已加密密码的后四位,即:“盐”
string saltPassword = CreateSaltedPassword(saltValue, hashPassword); // 创建加“盐”的16进制哈希密码
return (saltPassword == storedPassword);
}
/// <summary>
/// 根据提供的秘码生成对应的Hash值
/// </summary>
/// <param name="password"> 秘码 </param>
/// <returns> Hash值字符串 </returns>
private static string CreateHashPassword( string password)
{
System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider(); // 创建MD5抽象类, 哈希算法的所有实现均从中继承
byte [] hexHashPassword = md5.ComputeHash(Encoding.ASCII.GetBytes(password)); // 先转换密码为ASCII字节数组,然后计算指定字节数组的哈希值,哈希值是一段数据唯一且极其紧凑的数值表示形式
string strHashPaword = HexToStr(hexHashPassword); // 将哈希值转换为16进制
return strHashPaword;
}
/// <summary>
/// 把字节数组转换成对应的字符串
/// </summary>
/// <param name="buf"></param>
/// <returns></returns>
private static string HexToStr( byte [] buf)
{
string aa = "" ;
string sTemp = "" ;
for ( int i = 0 ; i < buf.Length; i ++ )
{
sTemp = System.Convert.ToString(buf[i], 16 ); // 将字节数组转换为16进制
aa += sTemp.PadLeft( 2 , ' 0 ' ); // 转换后的16进制为两位,若不够则左边补零
}
return aa;
}
/// <summary>
/// 生成随机值 字符串
/// </summary>
/// <returns></returns>
private static string CreateSaltValue()
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); // 使用加密服务提供程序 (CSP) 提供的实现来实现加密随机数生成器 (RNG)。此类不能继承。
byte [] saltValue = new byte [saltLength / 2 ]; // 创建字节数组
rng.GetBytes(saltValue); // 生成随即数,赋值给字节数组
string strSaltValue = HexToStr(saltValue); // 转换为16进制
return strSaltValue;
}
/// <summary>
/// 生成带有随机值的密码
/// </summary>
/// <param name="saltValue"> 随机值 </param>
/// <param name="hashPassword"> 秘密的Hash值 </param>
/// <returns> 带有随机值的密码字符串 </returns>
private static string CreateSaltedPassword( string saltValue, string hashPassword)
{
System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider(); // 创建MD5抽象类, 哈希算法的所有实现均从中继承
string tempPassword = hashPassword + saltValue; // 经过加密后的密码再加上“盐”
byte [] hexSaltPassword = md5.ComputeHash(Encoding.ASCII.GetBytes(tempPassword)); // 将加了盐密码先转换密码为ASCII字节数组,然后计算指定字节数组的哈希值,哈希值是一段数据唯一且极其紧凑的数值表示形式
string strSaltPassword = HexToStr(hexSaltPassword); // 将加了盐的哈希密码转换为16进制
string dbPassword = strSaltPassword + saltValue; // 再将密码再加上“盐”,此时密码长度为36位,至此加密完成
return dbPassword;
}
/// <summary>
/// 加密按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnEncrypt_Click( object sender, EventArgs e)
{
string pwd = txtOriginal.Text.Trim(); // 这里的字符串没有经过太多处理,只是测试
txtPwd1.Text = CreateDbPassword(pwd); // 调用加密函数
}
/// <summary>
/// 比较按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnCompare_Click( object sender, EventArgs e)
{
bool isTrue;
isTrue = ComparePasswords(txtPwd2.Text.Trim(), txtOriginal.Text.Trim()); // 判断加密后的密码,与原始密码加密后是否相等
txtNow.Text = isTrue ? " 相等 " : " 不相等 " ;
}
}
运行结果:
如有不足之处,请大家补充;若有其他的好的办法,也希望大家踊跃讨论!