Johnny_Z

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  今天介绍一种MD5的加密方法,代码中写了比较详细的注释,直接上例子了。

 

前台代码
<%@ 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>

 

 

 

后台代码
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 ? "相等" : "不相等";
}
}

 

运行结果:

 

如有不足之处,请大家补充;若有其他的好的办法,也希望大家踊跃讨论!

posted on 2010-07-16 17:41  Johnny_Z  阅读(645)  评论(0编辑  收藏  举报