[转]C#用SHA对密码加密

原文地址: http://ainux.blog.hexun.com/2815875_d.html


现在加密技术很多,比如SHA,MD5(已经被破解了),小可想和大家讨论一下在.NET框架中简单应用SHA算法加密用户登录密码的方法。
这里我采用的是SHA1(安全散列算法),是将不定长的字符串转换成160位(20字节)字节流散列算法。
这里讲的加密一般分以下几个步骤:

密码的建立:
1)对用户的原始密码进行第一次哈希,得到UnsaltedPassword:
User password ====hash====> UnsaltedPassword (20B)
2)随机产生一个N字节的密钥值(salt value),拼接到上面哈希后的字节流后面即
UnsaltedPassword(20B) | Salt value(NB)
3)将以上(20 + N)Byte的字节流再经过一次哈希,得到SaltedPassword
UnsaltedPassword(20B) | Salt value(NB) ====hash====> SaltedPassword
4)将SaltedPassword(20B) | Salt value(NB)存入数据库

密码的验证:
1)从数据库中获得加密后用户密码 dbPassword,取其最后N字节作为Salt value
2)重复上面1) 3) 4)将用户输入的密码结合Salt value进行哈希加密,和dbPassword进行比较以确定用户输入密码是否正确


 

private void btnLogon_Click(object sender, EventArgs e)
{
    
//创建SHA1类的实例,SHA1是抽象类(abstract)所以不能直接实例化
    SHA1 sha1 = SHA1.Create(); 
    
//Unicode.GetBytes获得string的Unicode(双字节字符)字节流
    byte[] hashedPassword = sha1.ComputeHash(Encoding.Unicode.GetBytes(txtPassword.Text));
    
//UserDate 可以理解为用户信息的抽象
    UserData user = userSystem.GetByName(txtUsername.Text, hashedPassword);
    
if (user == null)
    
{
        
//登录失败处理
    }

}


public UserData GetByName(string userName, byte[] password)
{
    UserData userData;
    
using (Users usersDataAccess = new Users())
    
{
        userData 
= usersDataAccess.LoadUserByUserName(userName);
    }

    
byte[] dbPassword = UserData.UserPassword;

    
if (ComparePasswords(dbPassword, password))
        
return userData;
    
else
        
return null;
}



// 比较密码
private bool ComparePasswords(byte[] storedPassword, byte[] hashedPassword)
{
    
if (storedPassword == null || hashedPassword == null || hashedPassword.Length != storedPassword.Length - saltLength)
    
return false;
    
// 获得存储的密钥值
    byte[] saltValue = new byte[saltLength];
    
int saltOffset = storedPassword.Length - saltLength;
    
for (int i = 0; i < saltLength; i++)
        saltValue[i] 
= storedPassword[saltOffset + i];
        
byte[] saltedPassword = CreateSaltedPassword(saltValue, hashedPassword);

 
// 比较存贮的密码序列和计算后的密码序列
        return CompareByteArray(storedPassword, saltedPassword);
    }


private byte[] CreateSaltedPassword(byte[] saltValue, byte[] unsaltedPassword)
{
    
// 在哈希值末尾添加密钥
    byte[] rawSalted = new byte[unsaltedPassword.Length + saltValue.Length];
    unsaltedPassword.CopyTo(rawSalted, 
0);
    saltValue.CopyTo(rawSalted, unsaltedPassword.Length);

    
// 计算哈希值
    SHA1 sha1 = SHA1.Create();
    
byte[] saltedPassword = sha1.ComputeHash(rawSalted);

    
// 在哈希值末尾添加密钥
    byte[] dbPassword = new byte[saltedPassword.Length + saltValue.Length];
    saltedPassword.CopyTo(dbPassword, 
0);
    saltValue.CopyTo(dbPassword, saltedPassword.Length);

    
return dbPassword;
}


// 比较两个 byte 数组的内容
private 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;
}



// 创建在数据库中存储的的哈希值(转入参数为经过一次哈希的用户输入密码的字节流)
public byte[] CreateDbPassword(byte[] unsaltedPassword)
{
    
//Create a salt value
    byte[] saltValue = new byte[saltLength];
    RNGCryptoServiceProvider rng 
= new RNGCryptoServiceProvider();
    rng.GetBytes(saltValue);

    
return CreateSaltedPassword(saltValue, unsaltedPassword);
}


posted on 2006-07-05 09:58  林晓可  阅读(3129)  评论(0编辑  收藏  举报

导航