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);
我读了一张表上的加密文本。我喜欢解密它。请帮我解决这个问题。提前感谢
代码段链接
在您真正弄清楚异常之前,让我在这里停止您的发言。
无论使用何种加密,反向存储密码都是一个可怕的想法。该方案存在内存擦除程序和其他一百万个问题。
密码是散列的,而不是加密的。不同之处在于,如果实现得当,散列很难逆转。使用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。