winforms 再次关闭和启动应用程序时,无法再解密密码字符串

ctrmrzij  于 2022-11-17  发布在  其他
关注(0)|答案(1)|浏览(133)

我正在学习C#,并试图实现一个登录函数。我有一个注册表,一个登录表和我的数据(包括这个用户信息)被保存到一个XML文件。
我有以下类:

public static class UserController
{
    // Inspiration from https://stackoverflow.com/questions/12657792/how-to-securely-save-username-password-local
    private static readonly byte[] entropy = new byte[20];

    public static string EncryptString(string password)
    {
        // Convert Password to byte[]
        byte[] data = Encoding.UTF8.GetBytes(password);

        // use RandomNumberGenerator instead of using RNGCryptoServiceProvider which is obsolete 
        //https://stackoverflow.com/questions/72418725/rngcryptoserviceprovider-is-obsolete
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(entropy);
        }

        // Protect (Encrypt) the String
        byte[] ciphertext = ProtectedData.Protect(data, entropy, DataProtectionScope.CurrentUser);

        // return as Base64
        return Convert.ToBase64String(ciphertext);
    }

    public static string DecryptString(string password)
    {
        byte[] plaintext = ProtectedData.Unprotect(Convert.FromBase64String(password), entropy, DataProtectionScope.CurrentUser);
        return Encoding.UTF8.GetString(plaintext);
    }

    public static bool CheckLoginCredentials(string username, string password)
    {
        bool isOK = false;
        var myUser = XmlHandler.GetUserFromXml(username);
        if (myUser != null)
        {
            // Decrypt Password
            string plainpassword = DecryptString(myUser.Password);
            if (username == myUser.UserName && password == plainpassword)
                isOK = true;
        }
        return isOK;
    }
}

当我在注册表单中创建一个用户(用DecryptString()加密他的密码),然后用这个用户登录时,一切都正常。但是,如果我关闭应用程序并尝试再次登录,DecryptString()就无法再将密码解密为纯文本。
为什么?我得把钥匙放在什么地方吗?
错误消息:

Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException
  HResult=0x8007000D
  Nachricht = The data is invalid.
  Quelle = System.Security.Cryptography.ProtectedData
  Stapelüberwachung:
   bei System.Security.Cryptography.ProtectedData.ProtectOrUnprotect(Byte[] inputData, Byte[] optionalEntropy, DataProtectionScope scope, Boolean protect)
   bei System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope)
   bei Semesterprojekt_ContactManager.UserController.DecryptString(String password) in C:\Install\xxx\UserController.cs: Zeile37
   bei Semesterprojekt_ContactManager.UserController.CheckLoginCredentials(String username, String password) in C:\Install\xxx\UserController.cs: Zeile54
   bei Semesterprojekt_ContactManager.Login_View.CmdLogin_Click(Object sender, EventArgs e) in C:\Install\xxx\Login_View.cs: Zeile22
   bei System.Windows.Forms.Control.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   bei System.Windows.Forms.Control.WndProc(Message& m)
   bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
   bei System.Windows.Forms.Button.WndProc(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, WM msg, IntPtr wparam, IntPtr lparam)
gtlvzcf8

gtlvzcf81#

生成entropy的要点在于它是随机的-它不太可能在一行中包含两次相同的值,因此在重新启动应用程序后,您不能使用来解密密码。
然而,你不需要解密密码-你只需要通过哈希验证它的正确性,例如BCrypt.NET

相关问题