我正在尝试加密和解密字符串,并且我可以成功完成。之后,我将加密的byte[]
转换为字符串以保存在数据库中。
但是当我尝试再次将字符串转换回byte[]
时,我的代码将引发错误。
为了测试代码,我创建了一个字符串变量来保存加密的字符串。
如何再次将字符串成功转换回byte[]
?
static void Main(string[] args)
{
Console.WriteLine("Enter text that needs to be encrypted..");
string data = Console.ReadLine();
EncryptAesManaged(data);
Console.ReadLine();
}
static void EncryptAesManaged(string raw)
{
string EncryptionKey = "sruohfaymonerishfiahbihbgrG546";
byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(raw);
try
{
using (AesManaged aes = new AesManaged())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(EncryptionKey);
aes.Key = pdb.GetBytes(32);
aes.IV = pdb.GetBytes(16);
// Encrypt string
byte[] encrypted = Encrypt(raw, aes.Key, aes.IV);
// Print encrypted string
string passe = System.Text.Encoding.UTF8.GetString(encrypted);
Console.WriteLine($"Encrypt:{passe}");
Console.WriteLine(System.Text.Encoding.UTF8.GetBytes(passe));
// Decrypt the bytes to a string.
string decrypted = Decrypt(System.Text.Encoding.UTF8.GetBytes(passe), aes.Key, aes.IV);
// Print decrypted string. It should be same as raw data
Console.WriteLine($"Decrypted data: {decrypted}");
}
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
}
Console.ReadKey();
}
static byte[] Encrypt(String plainText, byte[] Key, byte[] IV)
{
byte[] encrypted;
using (AesManaged aes = new AesManaged())
{
// Create encryptor
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
// Create MemoryStream
using (MemoryStream ms = new MemoryStream())
{
// Create crypto stream using the CryptoStream class. This class is the key to encryption
// and encrypts and decrypts data from any given stream. In this case, we will pass a memory stream
// to encrypt
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
// Create StreamWriter and write data to a stream
using (StreamWriter sw = new StreamWriter(cs))
sw.Write(plainText);
encrypted = ms.ToArray();
}
}
}
return encrypted;
}
static string Decrypt(byte[] cipherText, byte[] Key, byte[] IV)
{
string plaintext = null;
// Create AesManaged
using (AesManaged aes = new AesManaged())
{
// Create a decryptor
ICryptoTransform decryptor = aes.CreateDecryptor(Key, IV);
// Create the streams used for decryption.
using (MemoryStream ms = new MemoryStream(cipherText))
{
// Create crypto stream
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
// Read crypto stream
using (StreamReader reader = new StreamReader(cs))
plaintext = reader.ReadToEnd();
}
}
}
return plaintext;
}
答案 0 :(得分:2)
问题就在这里
string passe = System.Text.Encoding.UTF8.GetString(encrypted);
^---------------------------------^
然后在这里
string decrypted = Decrypt(System.Text.Encoding.UTF8.GetBytes(passe), aes.Key, aes.IV);
^--------------------------------^
我假设这是您的模拟,将其存储到数据库中,然后取回并存储为字符串。
但是,您几乎可以肯定这样做是破坏了字符串。
Encoding.UTF8.GetString(bytes)
不会不将包含任意字节的字节数组转换为字符串。取而代之的是,它将转换为应该的字节数组,该字节数组包含组成UTF8编码的字符串的字节回到该字符串。
如果字节数组包含任意字节,例如对文本进行加密的结果,则此步骤及其伴随的Encoding.UTF8.GetBytes
几乎可以确定会破坏数据和/或丢失字节。
相反,您应该使用另一种将字节数组转换为字符串并返回的方法。
一种方法是使用Base64编码,您可以用以下代码替换上面的两行:
string passe = Convert.ToBase64String(encrypted);
...
string decrypted = Decrypt(Convert.FromBase64String(passe), aes.Key, aes.IV);
这将导致您的程序先加密,然后再解密字符串。
此外,您可能需要考虑将字节直接存储到数据库中。取决于您的数据库引擎,可能会很好地支持直接存储字节数组,而不用担心任何类型的字符串转换。