C# Rijndael 解密不适用于 jpgs
C# Rijndael Decryption doesn't work with jpgs
当我尝试加密和解密一个简单的字符串时,一切都非常顺利..
但是当我将一个 jpg 编码成一个字节数组并对该字节数组执行完全相同的操作时,解密不再起作用(字节数组与原始字节数组完全不同,无法再显示)...
是不是字节数组太大了?
或者有人能解决我的问题吗?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Encrypter2
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine();
// Create a new instance of the Rijndael
// class. This generates a new key and initialization
// vector (IV).
byte[] originalFile = File.ReadAllBytes(@"C:/Users/Elron/Documents/Visual Studio 2015/Projects/FileEncrypt/FileEncrypt/bin/Debug/harambe.jpg");
using (Rijndael myRijndael = Rijndael.Create())
{
// Encrypt the string to an array of bytes
// Encrypted byte[]
byte[] encrypted = EncryptStringToBytes(originalFile, myRijndael.Key, myRijndael.IV);
using (FileStream fs = File.Create(@"C:/Users/Elron/Documents/Visual Studio 2015/Projects/FileEncrypt/FileEncrypt/bin/Debug/harambeEncrypted.jpg"))
{
//Add some information to the file.
fs.Write(encrypted, 0, encrypted.Length);
}
// Decrypted byte[]
byte[] roundtrip = DecryptStringFromBytes(encrypted, myRijndael.Key, myRijndael.IV);
using (FileStream fs = File.Create(@"C:/Users/Elron/Documents/Visual Studio 2015/Projects/FileEncrypt/FileEncrypt/bin/Debug/harambeDecrypted.jpg"))
{
//Add some information to the file.
fs.Write(roundtrip, 0, roundtrip.Length);
}
// Display the original data and the decrypted data.
// Encrypted string
Console.ReadKey();
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.Message);
}
}
static byte[] EncryptStringToBytes(byte[] plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an Rijndael object
// with the specified key and IV.
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
string toEncrypt = Encoding.Default.GetString(plainText);
swEncrypt.Write(toEncrypt);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
static byte[] DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
byte[] returnText;
// Create an Rijndael object
// with the specified key and IV.
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
ASCIIEncoding asc = new ASCIIEncoding();
returnText = asc.GetBytes(plaintext);
}
}
}
}
return returnText;
}
}
}
我认为您在加密和解密方法中使用了不同的编码
static byte[] DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
...
ASCIIEncoding asc = new ASCIIEncoding();
returnText = asc.GetBytes(plaintext);
...
}
和
static byte[] EncryptStringToBytes(byte[] plainText, byte[] Key, byte[] IV)
{
...
string toEncrypt = Encoding.Default.GetString(plainText);
swEncrypt.Write(toEncrypt);
...
}
您不能将任意字节数组视为字符串。您获取字节,将它们转换为字符串,然后将字符串写入 StreamWriter,后者将字符串转换回字节。这将是对一堆任意字节的有损操作。
您的方法EncryptStringToBytes
是一个错误的概念。您应该有一个不关心字符串的方法 EncryptBytes
(和 DecryptBytes
)。然后你可以传入一个字节数组并将其直接输入到 CryptoStream
中。如何解释这些字节不是加密算法的关注点。
所以你可以调整你的方法如下:
static byte[] EncryptBytes(byte[] bytes, byte[] Key, byte[] IV)
{
// Check arguments.
if (bytes == null || bytes.Length <= 0)
throw new ArgumentNullException("bytes");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Create an Rijndael object
// with the specified key and IV.
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor,
CryptoStreamMode.Write))
{
csEncrypt.Write(bytes,0,bytes.Length);
csEncrypt.FlushFinalBlock();
return msEncrypt.ToArray();
}
}
}
}
和
static byte[] DecryptBytes(byte[] encryptedBytes, byte[] Key, byte[] IV)
{
// Check arguments.
if (encryptedBytes == null || encryptedBytes.Length <= 0)
throw new ArgumentNullException("encryptedBytes");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Create an Rijndael object
// with the specified key and IV.
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor,
CryptoStreamMode.Write))
{
csDecrypt.Write(encryptedBytes,0,encryptedBytes.Length);
csDecrypt.FlushFinalBlock();
return msDecrypt.ToArray();
}
}
}
}
然后进行往返测试:
using(var rijndael = Rijndael.Create())
{
var stringToEncrypt = "foobar";
var bytesToEncrypt = Encoding.UTF8.GetBytes(stringToEncrypt);
var encryptedBytes = EncryptBytes(bytesToEncrypt, rijndael.Key, rijndael.IV);
var decryptedBytes = DecryptBytes(encryptedBytes, rijndael.Key, rijndael.IV);
var originalString = Encoding.UTF8.GetString(decryptedBytes);
Debug.Assert(string.Equals(stringToEncrypt, originalString,
StringComparison.InvariantCulture));
}
希望到此为止,我们已经清楚地了解了我们如何从加密中分离出字符串编码问题,以及您现在可以如何将这些方法重新用于任何类型的二进制数据。
当我尝试加密和解密一个简单的字符串时,一切都非常顺利..
但是当我将一个 jpg 编码成一个字节数组并对该字节数组执行完全相同的操作时,解密不再起作用(字节数组与原始字节数组完全不同,无法再显示)...
是不是字节数组太大了?
或者有人能解决我的问题吗?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Encrypter2
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine();
// Create a new instance of the Rijndael
// class. This generates a new key and initialization
// vector (IV).
byte[] originalFile = File.ReadAllBytes(@"C:/Users/Elron/Documents/Visual Studio 2015/Projects/FileEncrypt/FileEncrypt/bin/Debug/harambe.jpg");
using (Rijndael myRijndael = Rijndael.Create())
{
// Encrypt the string to an array of bytes
// Encrypted byte[]
byte[] encrypted = EncryptStringToBytes(originalFile, myRijndael.Key, myRijndael.IV);
using (FileStream fs = File.Create(@"C:/Users/Elron/Documents/Visual Studio 2015/Projects/FileEncrypt/FileEncrypt/bin/Debug/harambeEncrypted.jpg"))
{
//Add some information to the file.
fs.Write(encrypted, 0, encrypted.Length);
}
// Decrypted byte[]
byte[] roundtrip = DecryptStringFromBytes(encrypted, myRijndael.Key, myRijndael.IV);
using (FileStream fs = File.Create(@"C:/Users/Elron/Documents/Visual Studio 2015/Projects/FileEncrypt/FileEncrypt/bin/Debug/harambeDecrypted.jpg"))
{
//Add some information to the file.
fs.Write(roundtrip, 0, roundtrip.Length);
}
// Display the original data and the decrypted data.
// Encrypted string
Console.ReadKey();
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.Message);
}
}
static byte[] EncryptStringToBytes(byte[] plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an Rijndael object
// with the specified key and IV.
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
string toEncrypt = Encoding.Default.GetString(plainText);
swEncrypt.Write(toEncrypt);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
static byte[] DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
byte[] returnText;
// Create an Rijndael object
// with the specified key and IV.
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
ASCIIEncoding asc = new ASCIIEncoding();
returnText = asc.GetBytes(plaintext);
}
}
}
}
return returnText;
}
}
}
我认为您在加密和解密方法中使用了不同的编码
static byte[] DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
...
ASCIIEncoding asc = new ASCIIEncoding();
returnText = asc.GetBytes(plaintext);
...
}
和
static byte[] EncryptStringToBytes(byte[] plainText, byte[] Key, byte[] IV)
{
...
string toEncrypt = Encoding.Default.GetString(plainText);
swEncrypt.Write(toEncrypt);
...
}
您不能将任意字节数组视为字符串。您获取字节,将它们转换为字符串,然后将字符串写入 StreamWriter,后者将字符串转换回字节。这将是对一堆任意字节的有损操作。
您的方法EncryptStringToBytes
是一个错误的概念。您应该有一个不关心字符串的方法 EncryptBytes
(和 DecryptBytes
)。然后你可以传入一个字节数组并将其直接输入到 CryptoStream
中。如何解释这些字节不是加密算法的关注点。
所以你可以调整你的方法如下:
static byte[] EncryptBytes(byte[] bytes, byte[] Key, byte[] IV)
{
// Check arguments.
if (bytes == null || bytes.Length <= 0)
throw new ArgumentNullException("bytes");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Create an Rijndael object
// with the specified key and IV.
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor,
CryptoStreamMode.Write))
{
csEncrypt.Write(bytes,0,bytes.Length);
csEncrypt.FlushFinalBlock();
return msEncrypt.ToArray();
}
}
}
}
和
static byte[] DecryptBytes(byte[] encryptedBytes, byte[] Key, byte[] IV)
{
// Check arguments.
if (encryptedBytes == null || encryptedBytes.Length <= 0)
throw new ArgumentNullException("encryptedBytes");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Create an Rijndael object
// with the specified key and IV.
using (Rijndael rijAlg = Rijndael.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor,
CryptoStreamMode.Write))
{
csDecrypt.Write(encryptedBytes,0,encryptedBytes.Length);
csDecrypt.FlushFinalBlock();
return msDecrypt.ToArray();
}
}
}
}
然后进行往返测试:
using(var rijndael = Rijndael.Create())
{
var stringToEncrypt = "foobar";
var bytesToEncrypt = Encoding.UTF8.GetBytes(stringToEncrypt);
var encryptedBytes = EncryptBytes(bytesToEncrypt, rijndael.Key, rijndael.IV);
var decryptedBytes = DecryptBytes(encryptedBytes, rijndael.Key, rijndael.IV);
var originalString = Encoding.UTF8.GetString(decryptedBytes);
Debug.Assert(string.Equals(stringToEncrypt, originalString,
StringComparison.InvariantCulture));
}
希望到此为止,我们已经清楚地了解了我们如何从加密中分离出字符串编码问题,以及您现在可以如何将这些方法重新用于任何类型的二进制数据。