我从另一个问题中找到了以下AES加密类。该类(按原样)工作得很好,但是,我一直在尝试根据自己的喜好修改类,这是我遇到这些错误的地方。请注意,它是我尝试加密的二进制文件。
首先,我将解释我想要做出的改变。
1)我想将Encrypt函数的参数从字符串更改为字节数组。我认为这将是一个非常简单的任务(只需快速执行File.ReadAllBytes并将字节数组传递给Encrypt函数)但事实并非如此。
2)我希望decrypt函数返回一个字节数组。与上述问题相同,我无法使其正常工作。
我希望有人能够给我一个加密和解密二进制文件的工作示例,类似于我在下面设置的内容:
private void button1_Click(object sender, EventArgs e)
{
SimpleAES sa = new SimpleAES();
OpenFileDialog ofd = new OpenFileDialog();
string s = string.Empty;
byte[] b = null;
if (ofd.ShowDialog() == DialogResult.OK)
{
textBox1.Text = ofd.FileName;
b = File.ReadAllBytes(ofd.FileName);
b = sa.Encrypt(ByteToString(b);
}
File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\TestData123.exe", b);
}
private void button2_Click(object sender, EventArgs e)
{
SimpleAES sa = new SimpleAES();
byte[] b = File.ReadAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\TestData123.exe");
string s = sa.Decrypt(b);
File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\TestData123.exe");
File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\TestData.exe", b);
}
public byte[] StringToByte(string s)
{
Byte[] b = new byte[s.Length];
for (int i = 0; i < s.Length; i++)
{
char c = Convert.ToChar(s.Substring(i, 1));
b[i] = Convert.ToByte(c);
}
return b;
}
public string ByteToString(byte[] input)
{
StringBuilder ss = new System.Text.StringBuilder();
for (int i = 0; i < input.Length; i++)
{
// Convert each byte to char
char c = Convert.ToChar(input[i]);
ss.Append(Convert.ToString(c));
}
return ss.ToString();
}
这是我正在使用的AES类:
using System;
using System.Data;
using System.Security.Cryptography;
using System.IO;
public class SimpleAES
{
// Change these keys
private byte[] Key = { 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 };
private byte[] Vector = { 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 221, 112, 79, 32, 114, 156 };
private ICryptoTransform EncryptorTransform, DecryptorTransform;
private System.Text.UTF8Encoding UTFEncoder;
public SimpleAES()
{
//This is our encryption method
RijndaelManaged rm = new RijndaelManaged();
//Create an encryptor and a decryptor using our encryption method, key, and vector.
EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector);
DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector);
//Used to translate bytes to text and vice versa
UTFEncoder = new System.Text.UTF8Encoding();
}
/// -------------- Two Utility Methods (not used but may be useful) -----------
/// Generates an encryption key.
static public byte[] GenerateEncryptionKey()
{
//Generate a Key.
RijndaelManaged rm = new RijndaelManaged();
rm.GenerateKey();
return rm.Key;
}
/// Generates a unique encryption vector
static public byte[] GenerateEncryptionVector()
{
//Generate a Vector
RijndaelManaged rm = new RijndaelManaged();
rm.GenerateIV();
return rm.IV;
}
/// ----------- The commonly used methods ------------------------------
/// Encrypt some text and return a string suitable for passing in a URL.
public string EncryptToString(string TextValue)
{
return ByteArrToString(Encrypt(TextValue));
}
/// Encrypt some text and return an encrypted byte array.
public byte[] Encrypt(string TextValue)
{
//Translates our text value into a byte array.
Byte[] bytes = UTFEncoder.GetBytes(TextValue);
//Used to stream the data in and out of the CryptoStream.
MemoryStream memoryStream = new MemoryStream();
/*
* We will have to write the unencrypted bytes to the stream,
* then read the encrypted result back from the stream.
*/
#region Write the decrypted value to the encryption stream
CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write);
cs.Write(bytes, 0, bytes.Length);
cs.FlushFinalBlock();
#endregion
#region Read encrypted value back out of the stream
memoryStream.Position = 0;
byte[] encrypted = new byte[memoryStream.Length];
memoryStream.Read(encrypted, 0, encrypted.Length);
#endregion
//Clean up.
cs.Close();
memoryStream.Close();
return encrypted;
}
/// The other side: Decryption methods
public string DecryptString(string EncryptedString)
{
return Decrypt(StrToByteArray(EncryptedString));
}
/// Decryption when working with byte arrays.
public string Decrypt(byte[] EncryptedValue)
{
#region Write the encrypted value to the decryption stream
MemoryStream encryptedStream = new MemoryStream();
CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write);
decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length);
decryptStream.FlushFinalBlock();
#endregion
#region Read the decrypted value from the stream.
encryptedStream.Position = 0;
Byte[] decryptedBytes = new Byte[encryptedStream.Length];
encryptedStream.Read(decryptedBytes, 0, decryptedBytes.Length);
encryptedStream.Close();
#endregion
return UTFEncoder.GetString(decryptedBytes);
}
/// Convert a string to a byte array. NOTE: Normally we'd create a Byte Array from a string using an ASCII encoding (like so).
// System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
// return encoding.GetBytes(str);
// However, this results in character values that cannot be passed in a URL. So, instead, I just
// lay out all of the byte values in a long string of numbers (three per - must pad numbers less than 100).
public byte[] StrToByteArray(string str)
{
if (str.Length == 0)
throw new Exception("Invalid string value in StrToByteArray");
byte val;
byte[] byteArr = new byte[str.Length / 3];
int i = 0;
int j = 0;
do
{
val = byte.Parse(str.Substring(i, 3));
byteArr[j++] = val;
i += 3;
}
while (i < str.Length);
return byteArr;
}
// Same comment as above. Normally the conversion would use an ASCII encoding in the other direction:
// System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
// return enc.GetString(byteArr);
public string ByteArrToString(byte[] byteArr)
{
byte val;
string tempStr = "";
for (int i = 0; i <= byteArr.GetUpperBound(0); i++)
{
val = byteArr[i];
if (val < (byte)10)
tempStr += "00" + val.ToString();
else if (val < (byte)100)
tempStr += "0" + val.ToString();
else
tempStr += val.ToString();
}
return tempStr;
}
}
非常感谢大家!
答案 0 :(得分:1)
根据要求编辑您提供的代码。
private static byte[] Key = { 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 };
private static byte[] Vector = { 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 221, 112, 79, 32, 114, 156 };
private static RijndaelManaged _rijndaelManaged;
static void Main(string[] args)
{
var allBytes = File.ReadAllBytes("hello.bin");
_rijndaelManaged = new RijndaelManaged { Key = Key, IV = Vector };
byte[] encBytes = Encrypt(allBytes, Key, Vector);
byte[] decBytes = Decrypt(encBytes, Key, Vector);
using (var mstream = new MemoryStream(decBytes))
using (var breader = new BinaryReader(mstream))
{
Console.WriteLine(breader.ReadString());
}
}
private static byte[] Decrypt(byte[] encBytes, byte[] key, byte[] vector)
{
byte[] decBytes;
using (var mstream = new MemoryStream())
using (var crypto = new CryptoStream(mstream, _rijndaelManaged.CreateDecryptor(key, vector), CryptoStreamMode.Write))
{
crypto.Write(encBytes, 0, encBytes.Length);
crypto.FlushFinalBlock();
mstream.Position = 0;
decBytes = new byte[mstream.Length];
mstream.Read(decBytes, 0, decBytes.Length);
}
return decBytes;
}
private static byte[] Encrypt(byte[] allBytes, byte[] key, byte[] vector)
{
byte[] encBytes;
using (var mstream = new MemoryStream())
using (var crypto = new CryptoStream(mstream, _rijndaelManaged.CreateEncryptor(key, vector), CryptoStreamMode.Write))
{
crypto.Write(allBytes, 0, allBytes.Length);
crypto.FlushFinalBlock();
mstream.Position = 0;
encBytes = new byte[mstream.Length];
mstream.Read(encBytes, 0, encBytes.Length);
}
return encBytes;
}
正如Eoin解释的那样,你所要做的就是删除将字节转换回字符串的行。我发布了整个工作代码,因为我不确定输入文件是否是二进制文件导致任何问题。它没有。
答案 1 :(得分:1)
埃文,
我认为你可能会在这里复杂化。在没有进行任何检查的情况下,我认为问题在于您的StringToByte
&amp; ByteToString
方法。您应该使用其中一个System.Text.Encoding
类进行字符串 - >字节转换(就像AES类一样)
但如果您只需要将源字节[]加密到目标字节[],则可以执行以下操作并完全忘记字符串。
更改SimpleAES加密&amp;解密签名如下
public byte[] Encrypt(Byte[] bytes) //Change To take in a byte[]
{
//Translates our text value into a byte array.
//Byte[] bytes = UTFEncoder.GetBytes(TextValue); <-- REMOVE THIS LINE
... do stuff with `bytes`
}
public byte[] Decrypt(byte[] EncryptedValue) //now returns a byte array instead of a string
{
//return UTFEncoder.GetString(decryptedBytes); <-- JUST RETURN THE BYTE[] INSTEAD
return decryptedBytes;
}
现在您只需输入它并输入byte []
并接收加密的byte []
。
您可以使用。
在调试器中验证这一点SimpleAES sa = new SimpleAES();
byte[] plainBytes = new byte[] { 0x01, 0xFF, 0x53, 0xC2};
byte[] encBytes = sa.Encrypt(plainBytes);
byte[] decBytes = sa.Decrypt(encBytes);
//BREAK HERE
//Compare the values of decBytes & plainBytes