选择显示字体大小

详解对密码执行散列和 salt 运算方法

  大家对密码执行散列和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 命名空间(它实现 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;
              }
 
       }
}

  


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons