0

使用下面相同的方法对相同的明文进行两次加密,但加密后的密文不一样。为什么?

我想在将用户信息保存到数据库时加密我的密码,并使用下面的加密方法。但是我想完成编辑用户功能,输入旧密码和新密码后,根据选择的用户ID找出用户,并加密旧密码,尝试验证输入的旧密码是否与存储在数据库中的密码匹配。但即使我输入了正确的密码,它们也不会匹配。那么有什么方法可以加密密码并验证它们是否相同使用相同的方法加密密码。

    //encrypt the plainText
    public static string Encrypt(string plainText)
    {
        if (plainText == null || plainText == "")
            throw new ArgumentNullException("plainText");
        var temp = Encoding.UTF8.GetBytes(plainText);

        byte[] encrypted = ProtectedData.Protect(temp, null, DataProtectionScope.CurrentUser);
        return Convert.ToBase64String(encrypted);
    }
4

3 回答 3

3

根据ProtectedData 类的 MSDN 文档,看起来它正在使用特定于机器或用户的密钥执行 2 路加密。这意味着如果正在检查密钥的机器或用户与最初加密它的机器不同,您将得到垃圾结果。如果您只想检查密码的有效性,我建议您使用单向 esecure 哈希算法,而不是支持解密的 2-way 加密。StackOverflow 上的其他帖子讨论了使用安全散列算法(什么是 .NET 框架中最安全的散列算法?)。

编辑:我没有在不同用户下的不同系统上测试过这段代码,但我希望它会更普遍地工作,因为我不希望它基于机器或用户密钥。

System.Security.Cryptography.SHA256Managed sha = new System.Security.Cryptography.SHA256Managed();
byte[] hashed = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(args[0]));
Console.WriteLine("Hash of {0}={1}", args[0], Convert.ToBase64String(hashed));

编辑2:我还要补充一点,我对密码学的理解也表明你应该在你的散列值中包含一些“盐”。换句话说,在对密码字符串进行散列之前(输入和检查时)在密码字符串的末尾添加一些内容(如用户名),以便具有相同密码的用户不会以相同的散列值结束,例如.

于 2013-09-10T14:25:33.447 回答
1

输出中的一些随机性实际上是加密的一个特征

你有两个选择:

  • 如果您需要从加密形式恢复密码作为您要求的一部分,请像您一样使用加密,但在比较预期密码和输入密码之前解密结果。

  • 如果您真的不需要恢复密码,请改用哈希算法(使用合适的盐)。您将能够比较两个散列值。

于 2013-09-10T14:34:54.023 回答
0

这是我在控制台应用程序中拼凑的东西。密码不匹配,但如您所见,您可以很好地解密它们:)

class Program
{
    private static string salt = "My Salt Brings All The Boys To The Yard... Wait A Second.....";
    static void Main(string[] args)
    {
        for (int i = 0; 0 < 20; i++)
        {
            string password = "Guess my password!";

            string cipher = Encrypt(password, salt);

            string decipher = Decrypt(cipher, salt);

            Console.WriteLine(decipher);
            Thread.Sleep(500);
        }
        Console.ReadKey();

    }

    static public string Encrypt(string password, string salt)
    {
        byte[] passwordBytes = Encoding.Unicode.GetBytes(password);
        byte[] saltBytes = Encoding.Unicode.GetBytes(salt);

        byte[] cipherBytes = ProtectedData.Protect(passwordBytes, saltBytes, DataProtectionScope.CurrentUser);

        return Convert.ToBase64String(cipherBytes);
    }

    static public string Decrypt(string cipher, string salt)
    {
        byte[] cipherBytes = Convert.FromBase64String(cipher);
        byte[] saltBytes = Encoding.Unicode.GetBytes(salt);

        byte[] passwordBytes = ProtectedData.Unprotect(cipherBytes, saltBytes, DataProtectionScope.CurrentUser);

        return Encoding.Unicode.GetString(passwordBytes);
    }
}
于 2013-09-10T14:27:02.760 回答