RSA加密和保存到数据库(c#)

本文关键字:数据库 加密 保存 RSA | 更新日期: 2023-09-27 18:29:08

我没有关于密码学的深入信息,但当我收集到一些信息时,作为一种非对称解决方案,我想使用RSA,这是我找到的代码,我想将加密的密码存储到数据库中,并在我想获得用户信息时对其进行解密,我的意思是,这两个操作不会分别发生,只要我愿意,我就可以从数据库中选择并解密之前保存的数据。我知道生成的密钥有问题,但由于对这个主题的了解不足,我无法处理它。我在解密时得到以下异常。

参数不正确。在System.Security.Cryptography.CryptographicException.SthrowCryptographicException(Int32小时)位于System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle pKeyContext,Byte[]pbEncryptedKey,Int32 cbEncryptedKey、Boolean fOAEP、ObjectHandleOnStack ohRetDecryptedKey)在System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[]rgb,布尔值fOAEP)

加密类别:

public static class AsymmetricEncryption
{
    private static bool _optimalAsymmetricEncryptionPadding = false;
    public static void GenerateKeys(int keySize, out string publicKey, out string publicAndPrivateKey)
    {
        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            publicKey = provider.ToXmlString(false);
            publicAndPrivateKey = provider.ToXmlString(true);
        }
    }
    public static string EncryptText(string text, int keySize, string publicKeyXml)
    {
        var encrypted = Encrypt(Encoding.UTF8.GetBytes(text), keySize, publicKeyXml);
        return Convert.ToBase64String(encrypted);
    }
    public static byte[] Encrypt(byte[] data, int keySize, string publicKeyXml)
    {
        if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
        int maxLength = GetMaxDataLength(keySize);
        if (data.Length > maxLength) throw new ArgumentException(String.Format("Maximum data length is {0}", maxLength), "data");
        if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
        if (String.IsNullOrEmpty(publicKeyXml)) throw new ArgumentException("Key is null or empty", "publicKeyXml");
        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            provider.FromXmlString(publicKeyXml);
            return provider.Encrypt(data, _optimalAsymmetricEncryptionPadding);
        }
    }
    public static string DecryptText(string text, int keySize, string publicAndPrivateKeyXml)
    {
        var decrypted = Decrypt(Convert.FromBase64String(text), keySize, publicAndPrivateKeyXml);
        return Encoding.UTF8.GetString(decrypted);
    }
    public static byte[] Decrypt(byte[] data, int keySize, string publicAndPrivateKeyXml)
    {
        if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
        if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
        if (String.IsNullOrEmpty(publicAndPrivateKeyXml)) throw new ArgumentException("Key is null or empty", "publicAndPrivateKeyXml");
        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            provider.FromXmlString(publicAndPrivateKeyXml);
            return provider.Decrypt(data, _optimalAsymmetricEncryptionPadding);
        }
    }
    public static int GetMaxDataLength(int keySize)
    {
        if (_optimalAsymmetricEncryptionPadding)
        {
            return ((keySize - 384) / 8) + 7;
        }
        return ((keySize - 384) / 8) + 37;
    }
    public static bool IsKeySizeValid(int keySize)
    {
        return keySize >= 384 &&
                keySize <= 16384 &&
                keySize % 8 == 0;
    }
}

加密用法:

const int keySize = 1024;
string publicAndPrivateKey;
string publicKey;
AsymmetricEncryption.GenerateKeys(keySize, out publicKey, out publicAndPrivateKey);
string text = "text for encryption";
string encrypted = AsymmetricEncryption.EncryptText(text, keySize, publicKey);

解密用法:

const int keySize = 1024;
string publicAndPrivateKey;
string publicKey;
AsymmetricEncryption.GenerateKeys(keySize, out publicKey, out publicAndPrivateKey);
string text = "text for encryption";
string encrypted = AsymmetricEncryption.DecryptText(text, keySize, publicKey);

我读了一张表上的加密文本。我喜欢解密它。请帮我解决这个问题。提前感谢

代码段链接

RSA加密和保存到数据库(c#)

在您真正弄清楚异常之前,让我在这里停止您的发言。

无论使用何种加密,反向存储密码都是一个可怕的想法。该方案存在内存擦除程序和其他一百万个问题。

密码是散列的,而不是加密的。不同之处在于,如果实现得当,散列很难逆转。使用BCrypt或SHA2或SHA3或其他一些好的哈希算法,使用适当的salt。

这里有一个例子,但在生产中使用之前,请咨询有知识的人,我可能有错误,方法是为了简单而编码的,可能太简单

public string GetHash(string secret, string salt = null)
{
  var hasher = SHA256Managed.Create();
  salt = salt ?? Guid.NewGuid().ToString("N"); // 128 bit salt 
  var hashResult = hasher.ComputeHash(Encoding.UTF8.GetBytes(salt+"|"+what));
  return "SHA256|" + salt + "|" + Convert.ToBase64String(hashResult);
}

现在,您可以将从该函数中获得的字符串存储在数据库中,下次密码输入时(我希望通过HTTPS),您可以通过从存储在DB:中的字符串中获取salt来进行检查

public bool CheckSecretHash(string secret, string hashFromDB){
  var hashParts = hashFromDB.Split('|'); // string[3]
  var rehash = GetHash(secret, hashParts[1]);
  return hashFromDB == rehash;
}

加分:挑战回应。始终使用HTTPS。