C#中的AES加密并比较文件级别的结果
AES encryption in c# and compare result in file level
AES 的新手,我访问了几个关于它的线程,例如:Dan Esparza 的例子,Zeeshan Amber 在这个线程 Simple encryption algorithm in c#.net , and smdrager at Simple encryption algorithm in c#.net
我尝试在我的案例中使用一些例子,但我发现了一些不正确的地方,让我解释一下:
- 我想加密一个二进制文件(名为 "exa" )。
- 我使用 git 检查输出文件是否与输入文件不同。
- 我将输入文件读取到流(字节[]或字符串)。
- 紧接着,立即使用 File.WriteAllBytes() 写入不同的文件。 (确保读取字节正确,成功)
- 然后,我用了 Dan Esparza、smdrager、Zeeshan Amber 的例子
- 每次完成后,我都会将内存中的解密字节与原始字节进行比较,看字节是否不同。
- 我把解密结果保存到文件里比较了。
- 结果都令人失望,所有文件都失败了,但在某些情况下字节比较没问题。
smdrager的例子
byte[] orgBytes = File.ReadAllBytes("exa");
byte[] encQuote = EncryptByteToBytes(orgBytes , "password" );
byte[] endByte = DecryptToByte(encQuote, "password");
File.WriteAllBytes("exaOutputBytes", endByte);
字节数比较失败,文件比较也失败
orgBytes.Length : 55732
endByte.Length : 55744
Dan Esparza 的例子
在这种情况下,字节输入将失败,因此,我使用 ASCII 文本读取。
string original = File.ReadAllText("exa" , Encoding.ASCII );
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
myRijndael.GenerateKey();
myRijndael.GenerateIV();
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes(original, myRijndael.Key, myRijndael.IV);
// Decrypt the bytes to a string.
string roundtrip = DecryptStringFromBytes(encrypted, myRijndael.Key, myRijndael.IV);
File.WriteAllText("exaOutputString", roundtrip , Encoding.ASCII);
字节比较很好,无论是长度还是每个字节的内容。但是文件比较还是失败了。
齐山琥珀的例子
我使用密码和 iv 与示例相同。
Crypt cryptObj = new Crypt();
string encryStr = cryptObj.Encrypt(original, "AGARAMUDHALA", "EZHUTHELLAM", "SHA1", 3, "@1B2c3D4e5F6g7H8", 256);
string decryStr = cryptObj.Decrypt(encryStr, "AGARAMUDHALA", "EZHUTHELLAM", "SHA1", 3, "@1B2c3D4e5F6g7H8", 256);
本例与Dan Esparza一样,文件比较失败
我认为问题应该出在我的文件importing/exporting,可能是文件中的特殊字符、EOL 或BOM。我在写文件的时候也尝试了不同的编码,但是没有发现。
有没有人有什么想法?
我不知道为什么在 encryption/decryption 过程中需要密码,为什么在基本上使用字节(文件)时需要 encrypt/decrypt 字符串。
这里是一个使用字节和key/iv(伪)随机生成的例子:
using System;
using System.IO;
using System.Security.Cryptography;
namespace AesDemo
{
class Program
{
static void Main(string[] args)
{
byte[] key = null;
byte[] iv = null;
byte[] bytesToEncrypt = null;
byte[] encryptedBytes = null;
byte[] decryptedBytes = null;
// generate key and iv to use for encryption/decryption.
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.GenerateKey();
aesAlg.GenerateIV();
key = aesAlg.Key;
iv = aesAlg.IV;
}
// original bytes
bytesToEncrypt = File.ReadAllBytes(@"c:\exe");
Console.WriteLine("Bytes read: {0}",bytesToEncrypt.Length);
// encrypt
encryptedBytes = CryptoAes.Encrypt(bytesToEncrypt, key, iv);
Console.WriteLine("Encrypted bytes length: {0}", encryptedBytes.Length);
// decrypt
decryptedBytes = CryptoAes.Decrypt(encryptedBytes, key, iv);
Console.WriteLine("Decrypted bytes length: {0}", decryptedBytes.Length);
// compare
Console.WriteLine("Decrypted bytes same as original bytes: {0}", Convert.ToBase64String(decryptedBytes) == Convert.ToBase64String(bytesToEncrypt));
Console.ReadLine();
}
}
internal sealed class CryptoAes
{
/// <summary>
/// Encrypts data with symetric key
/// </summary>
/// <param name="data">Data to be encrypted</param>
/// <param name="key">Symetric key</param>
/// <param name="iv">Initialization vector</param>
/// <returns>Encrypted data</returns>
public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
byte[] encryptedData = null;
if (data == null)
throw new ArgumentNullException("data");
if (data == key)
throw new ArgumentNullException("key");
if (data == iv)
throw new ArgumentNullException("iv");
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.Key = key;
aesAlg.IV = iv;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
encryptedData = encryptor.TransformFinalBlock(data, 0, data.Length);
}
return encryptedData;
}
/// <summary>
/// Decrypts data with symetric key
/// </summary>
/// <param name="data">Encrypted data</param>
/// <param name="key">Symetric key</param>
/// <param name="iv">Initialization vector</param>
/// <returns>Decrypted data</returns>
public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
byte[] decryptedData = null;
if (data == null)
throw new ArgumentNullException("data");
if (data == key)
throw new ArgumentNullException("key");
if (data == iv)
throw new ArgumentNullException("iv");
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.Key = key;
aesAlg.IV = iv;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
decryptedData = decryptor.TransformFinalBlock(data, 0, data.Length);
}
return decryptedData;
}
}
}
ASE文件加密
internal const string Inputkey = "560A18CD-6346-4CF0-A2E8-671F9B6B9EA9";
///<summary>
/// Arvind - 23/11/2017.
///
/// Encrypts a file using Rijndael algorithm.
///</summary>
///<param name="inputFile"></param>
///<param name="outputFile"></param>
public static void EncryptFile(string inputFile, string outputFile)
{
try
{
string password = @"+kdkdkdjd8656589$**hh$^JHJBKLJJH#$$$__+0-f5546%$$^5434+"; // Secret Key
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
Rijndael RMCrypto = NewRijndaelManaged(password);
var encryptor = RMCrypto.CreateEncryptor(RMCrypto.Key, RMCrypto.IV);
CryptoStream cs = new CryptoStream(fsCrypt,
encryptor,
CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
catch (Exception ex)
{
throw new ApplicationException("Encryption failed!" + ex.Message);
}
}
/// <summary>
/// Create a new RijndaelManaged class and initialize it
/// </summary>
/// <param name="salt" />The pasword salt
/// <returns></returns>
private static RijndaelManaged NewRijndaelManaged(string salt)
{
if (salt == null) throw new ArgumentNullException("salt");
var saltBytes = Encoding.ASCII.GetBytes(salt);
var key = new Rfc2898DeriveBytes(Inputkey, saltBytes);
var aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
return aesAlg;
}
**File decryption**
///<summary>
/// Arvind - 23/11/2017.
///
/// Decrypts a file using Rijndael algorithm.
///</summary>
///<param name="inputFile"></param>
///<param name="outputFile"></param>
public static void DecryptDatabaseFile(string inputFile, string outputFile)
{
try
{
string password = System.Configuration.ConfigurationManager.AppSettings["encryptionKey"];
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
var aesAlg = NewRijndaelManaged(password);
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
CryptoStream cs = new CryptoStream(fsCrypt,
decryptor,
CryptoStreamMode.Read);
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
int data;
while ((data = cs.ReadByte()) != -1)
fsOut.WriteByte((byte)data);
fsOut.Close();
cs.Close();
fsCrypt.Close();
}
catch (Exception ex)
{
throw new ApplicationException("decryption Fail!!" + ex.Message);
}
}
AES 的新手,我访问了几个关于它的线程,例如:Dan Esparza 的例子,Zeeshan Amber 在这个线程 Simple encryption algorithm in c#.net , and smdrager at Simple encryption algorithm in c#.net
我尝试在我的案例中使用一些例子,但我发现了一些不正确的地方,让我解释一下:
- 我想加密一个二进制文件(名为 "exa" )。
- 我使用 git 检查输出文件是否与输入文件不同。
- 我将输入文件读取到流(字节[]或字符串)。
- 紧接着,立即使用 File.WriteAllBytes() 写入不同的文件。 (确保读取字节正确,成功)
- 然后,我用了 Dan Esparza、smdrager、Zeeshan Amber 的例子
- 每次完成后,我都会将内存中的解密字节与原始字节进行比较,看字节是否不同。
- 我把解密结果保存到文件里比较了。
- 结果都令人失望,所有文件都失败了,但在某些情况下字节比较没问题。
smdrager的例子
byte[] orgBytes = File.ReadAllBytes("exa");
byte[] encQuote = EncryptByteToBytes(orgBytes , "password" );
byte[] endByte = DecryptToByte(encQuote, "password");
File.WriteAllBytes("exaOutputBytes", endByte);
字节数比较失败,文件比较也失败
orgBytes.Length : 55732
endByte.Length : 55744
Dan Esparza 的例子
在这种情况下,字节输入将失败,因此,我使用 ASCII 文本读取。
string original = File.ReadAllText("exa" , Encoding.ASCII );
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
myRijndael.GenerateKey();
myRijndael.GenerateIV();
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes(original, myRijndael.Key, myRijndael.IV);
// Decrypt the bytes to a string.
string roundtrip = DecryptStringFromBytes(encrypted, myRijndael.Key, myRijndael.IV);
File.WriteAllText("exaOutputString", roundtrip , Encoding.ASCII);
字节比较很好,无论是长度还是每个字节的内容。但是文件比较还是失败了。
齐山琥珀的例子
我使用密码和 iv 与示例相同。
Crypt cryptObj = new Crypt();
string encryStr = cryptObj.Encrypt(original, "AGARAMUDHALA", "EZHUTHELLAM", "SHA1", 3, "@1B2c3D4e5F6g7H8", 256);
string decryStr = cryptObj.Decrypt(encryStr, "AGARAMUDHALA", "EZHUTHELLAM", "SHA1", 3, "@1B2c3D4e5F6g7H8", 256);
本例与Dan Esparza一样,文件比较失败
我认为问题应该出在我的文件importing/exporting,可能是文件中的特殊字符、EOL 或BOM。我在写文件的时候也尝试了不同的编码,但是没有发现。
有没有人有什么想法?
我不知道为什么在 encryption/decryption 过程中需要密码,为什么在基本上使用字节(文件)时需要 encrypt/decrypt 字符串。
这里是一个使用字节和key/iv(伪)随机生成的例子:
using System;
using System.IO;
using System.Security.Cryptography;
namespace AesDemo
{
class Program
{
static void Main(string[] args)
{
byte[] key = null;
byte[] iv = null;
byte[] bytesToEncrypt = null;
byte[] encryptedBytes = null;
byte[] decryptedBytes = null;
// generate key and iv to use for encryption/decryption.
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.GenerateKey();
aesAlg.GenerateIV();
key = aesAlg.Key;
iv = aesAlg.IV;
}
// original bytes
bytesToEncrypt = File.ReadAllBytes(@"c:\exe");
Console.WriteLine("Bytes read: {0}",bytesToEncrypt.Length);
// encrypt
encryptedBytes = CryptoAes.Encrypt(bytesToEncrypt, key, iv);
Console.WriteLine("Encrypted bytes length: {0}", encryptedBytes.Length);
// decrypt
decryptedBytes = CryptoAes.Decrypt(encryptedBytes, key, iv);
Console.WriteLine("Decrypted bytes length: {0}", decryptedBytes.Length);
// compare
Console.WriteLine("Decrypted bytes same as original bytes: {0}", Convert.ToBase64String(decryptedBytes) == Convert.ToBase64String(bytesToEncrypt));
Console.ReadLine();
}
}
internal sealed class CryptoAes
{
/// <summary>
/// Encrypts data with symetric key
/// </summary>
/// <param name="data">Data to be encrypted</param>
/// <param name="key">Symetric key</param>
/// <param name="iv">Initialization vector</param>
/// <returns>Encrypted data</returns>
public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
byte[] encryptedData = null;
if (data == null)
throw new ArgumentNullException("data");
if (data == key)
throw new ArgumentNullException("key");
if (data == iv)
throw new ArgumentNullException("iv");
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.Key = key;
aesAlg.IV = iv;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
encryptedData = encryptor.TransformFinalBlock(data, 0, data.Length);
}
return encryptedData;
}
/// <summary>
/// Decrypts data with symetric key
/// </summary>
/// <param name="data">Encrypted data</param>
/// <param name="key">Symetric key</param>
/// <param name="iv">Initialization vector</param>
/// <returns>Decrypted data</returns>
public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
byte[] decryptedData = null;
if (data == null)
throw new ArgumentNullException("data");
if (data == key)
throw new ArgumentNullException("key");
if (data == iv)
throw new ArgumentNullException("iv");
using (RijndaelManaged aesAlg = new RijndaelManaged())
{
aesAlg.Key = key;
aesAlg.IV = iv;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
decryptedData = decryptor.TransformFinalBlock(data, 0, data.Length);
}
return decryptedData;
}
}
}
ASE文件加密
internal const string Inputkey = "560A18CD-6346-4CF0-A2E8-671F9B6B9EA9";
///<summary>
/// Arvind - 23/11/2017.
///
/// Encrypts a file using Rijndael algorithm.
///</summary>
///<param name="inputFile"></param>
///<param name="outputFile"></param>
public static void EncryptFile(string inputFile, string outputFile)
{
try
{
string password = @"+kdkdkdjd8656589$**hh$^JHJBKLJJH#$$$__+0-f5546%$$^5434+"; // Secret Key
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
Rijndael RMCrypto = NewRijndaelManaged(password);
var encryptor = RMCrypto.CreateEncryptor(RMCrypto.Key, RMCrypto.IV);
CryptoStream cs = new CryptoStream(fsCrypt,
encryptor,
CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
catch (Exception ex)
{
throw new ApplicationException("Encryption failed!" + ex.Message);
}
}
/// <summary>
/// Create a new RijndaelManaged class and initialize it
/// </summary>
/// <param name="salt" />The pasword salt
/// <returns></returns>
private static RijndaelManaged NewRijndaelManaged(string salt)
{
if (salt == null) throw new ArgumentNullException("salt");
var saltBytes = Encoding.ASCII.GetBytes(salt);
var key = new Rfc2898DeriveBytes(Inputkey, saltBytes);
var aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);
return aesAlg;
}
**File decryption**
///<summary>
/// Arvind - 23/11/2017.
///
/// Decrypts a file using Rijndael algorithm.
///</summary>
///<param name="inputFile"></param>
///<param name="outputFile"></param>
public static void DecryptDatabaseFile(string inputFile, string outputFile)
{
try
{
string password = System.Configuration.ConfigurationManager.AppSettings["encryptionKey"];
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
var aesAlg = NewRijndaelManaged(password);
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
CryptoStream cs = new CryptoStream(fsCrypt,
decryptor,
CryptoStreamMode.Read);
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
int data;
while ((data = cs.ReadByte()) != -1)
fsOut.WriteByte((byte)data);
fsOut.Close();
cs.Close();
fsCrypt.Close();
}
catch (Exception ex)
{
throw new ApplicationException("decryption Fail!!" + ex.Message);
}
}