C#AES解密 [英] c# AES Decryption
问题描述
我与SagePay形式的工作,目前转换他们有VB例子为C#。我已经取得了良好进展,所以我的项目的加密部分工作正常(SagePay可以将其解密)。
我遇到的问题是,当我试图对字符串进行解密,它变成垃圾。如果有人这样做之前我真的很感激一些帮助,我的解密代码。我已经包括加密代码,工作和前两行是从另一种方法进行设置和调用。
我还没有添加VB代码,但如果这是必需的,我可以添加它。 。不想,如果不需要一个巨大的后
实用方法:
公共字符串byteArrayToHexString(字节[] BA)
{
返回BitConverter.ToString(BA).Replace( - ,);
}
公共静态的byte [] StringToByteArray(十六进制字符串)
{
返回Enumerable.Range(0,hex.Length)
。凡( X =&X的催化剂%2 == 0)
。选择(X => Convert.ToByte(hex.Substring(X,2),16))
.ToArray();
}
主要加密与第一对夫妇行是调用它从提取的方法更大的方法。
字符串隐窝=blahblahblah
串EncryptAndEncode =@+ byteArrayToHexString(aesEncrypt(地下室) );
私人字节[] aesEncrypt(字符串inputText的)
{
RijndaelManaged的AES =新RijndaelManaged的();
//设置为重点
AES.Padding = PaddingMode.PKCS7模式,填充和块的大小;
AES.Mode = CipherMode.CBC;
AES.KeySize = 128;
AES.BlockSize = 128;
//转换键和文字输入字节数组
字节[] = keyAndIvBytes UTF8Encoding.UTF8.GetBytes(tR7nR6wZHGjYMCuV);
字节[] = inputBytes UTF8Encoding.UTF8.GetBytes(inputText的); // AbHLlc5uLone0D1q
//创建流和加密对象
的MemoryStream MemoryStream的=新的MemoryStream();
的CryptoStream的CryptoStream =新的CryptoStream(的MemoryStream,AES.CreateEncryptor(keyAndIvBytes,keyAndIvBytes),CryptoStreamMode.Write);
//执行加密
cryptoStream.Write(inputBytes,0,inputBytes.Length);
cryptoStream.FlushFinalBlock();
//获取加密流成字节数组
字节[] = outBytes memoryStream.ToArray();
//关闭流
memoryStream.Close();
cryptoStream.Close();
AES.Clear();
返回outBytes;
}
解码和解密方法
公共字符串DecodeAndDecrypt(字符串〜应变)
{
// ** HEX解码那么AES解密,CBC与PKCS5填充阻断 - 默认**
串DecodeAndDecrypt = aesDecrypt(StringToByteArray(strIn.Substring(1)));
回报(DecodeAndDecrypt);
}
私人字符串aesDecrypt(字节[] inputBytes)
{
RijndaelManaged的AES =新RijndaelManaged的();
字节[] = keyAndIvBytes UTF8Encoding.UTF8.GetBytes(tR7nR6wZHGjYMCuV);
字节[] = outputBytes inputBytes; // Convert.FromBase64String(inputBytes);
//设置的模式,填充和块大小
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.KeySize = 128;
AES.BlockSize = 128;
//创建流,并解密对象
的MemoryStream MemoryStream的=新的MemoryStream(outputBytes);
的CryptoStream的CryptoStream =新的CryptoStream(的MemoryStream,AES.CreateEncryptor(keyAndIvBytes,keyAndIvBytes),CryptoStreamMode.Read);
//执行解密
cryptoStream.Read(outputBytes,0,outputBytes.Length);
Trace.WriteLine(outputBytes);
//关闭流
memoryStream.Close();
cryptoStream.Close();
AES.Clear();
//返回System.Text.Encoding.UTF8.GetString(outputBytes);
字符串明文= Encoding.UTF8.GetString(outputBytes,
0,
outputBytes.Length);
返回明文;
}
实际上有多个问题你的代码。首先在你的解密方法,你要创建一个加密,这应该是一个解密。其次,你正在阅读的整个街区,包括你的算法的填充到缓冲区中,当你做解密。下面是固定的项目类,并应返回正确的结果。然而,我建议你找存储密钥,把你的代码和生成的方式找你edoing一个更好的方式,它是一种没有没有。你应该产生具有RNG(RNGCryptoServiceProvider)的键,然后用安全散列算法散列它如SHA512,使用输出的关键。然后,你需要找到一个好地方来存储的话,我会去了解一下加密你的web.config文件。
公共静态类EncryptionHelper
{
私人静态的byte [] keyAndIvBytes;
静态EncryptionHelper()
{
//你需要这个存储的更安全的方式,我希望这不是
//真正的关键
keyAndIvBytes = UTF8Encoding.UTF8.GetBytes(tR7nR6wZHGjYMCuV);
}
公共静态字符串ByteArrayToHexString(字节[] BA)
{
返回BitConverter.ToString(BA).Replace( - ,);
}
公共静态的byte [] StringToByteArray(十六进制字符串)
{
返回Enumerable.Range(0,hex.Length)
。凡( X =&X的催化剂%2 == 0)
。选择(X => Convert.ToByte(hex.Substring(X,2),16))
.ToArray();
}
公共静态字符串DecodeAndDecrypt(字符串密文)
{
串DecodeAndDecrypt = AesDecrypt(StringToByteArray(密文));
回报(DecodeAndDecrypt);
}
公共静态字符串EncryptAndEncode(字符串明文)
{
返回ByteArrayToHexString(AesEncrypt(明文));
}
公共静态字符串AesDecrypt(字节[] inputBytes)
{
字节[] = outputBytes inputBytes;
字符串明文=的String.Empty;使用(MemoryStream的MemoryStream的=新的MemoryStream(outputBytes))
{使用(CryptoStream的CryptoStream的=新的CryptoStream(的MemoryStream,GetCryptoAlgorithm()
。CreateDecryptor的(keyAndIvBytes,keyAndIvBytes),CryptoStreamMode
.Read))
{使用
(StreamReader的srDecrypt =新的StreamReader(CryptoStream的))
{
明文= srDecrypt.ReadToEnd();
}
}
}
返回明文;
}
公共静态的byte [] AesEncrypt(字符串inputText的)
{
字节[] = inputBytes UTF8Encoding.UTF8.GetBytes(inputText的); // AbHLlc5uLone0D1q
字节[]的结果= NULL;使用(MemoryStream的MemoryStream的=新的MemoryStream())
{$ B $使用B
(CryptoStream的CryptoStream的=新的CryptoStream(的MemoryStream,GetCryptoAlgorithm()。CreateEncryptor(keyAndIvBytes,keyAndIvBytes),CryptoStreamMode.Write))
{
cryptoStream.Write(inputBytes,0,inputBytes.Length);
cryptoStream.FlushFinalBlock();
结果= memoryStream.ToArray();
}
}
返回结果;
}
私有静态RijndaelManaged的GetCryptoAlgorithm()
{
RijndaelManaged的算法=新RijndaelManaged的();
//设置的模式,填充和块大小
algorithm.Padding = PaddingMode.PKCS7;
algorithm.Mode = CipherMode.CBC;
algorithm.KeySize = 128;
algorithm.BlockSize = 128;
返回算法;
}
}
调用很容易:
字符串隐窝=blahblahblah;
串EncryptAndEncode = EncryptionHelper.EncryptAndEncode(地下室);
Console.WriteLine(EncryptAndEncode);
Console.WriteLine(EncryptionHelper.DecodeAndDecrypt(EncryptAndEncode));
到Console.ReadLine();
I am working with SagePay Forms and currently converting the VB examples they have to c#. I have made good progress so the encryption part of my project works fine (SagePay can decrypt it).
The issue I am having is that when I attempt to decrypt the string, it turns to garbage. If anyone has done this before I would really appreciate some help with my decryption code. I have included the encryption code which works and the first two lines are the setup and call from another method.
I haven't added the VB code but if this is required I could add it. Didn't want a huge post if not required.
Utility Methods:
public string byteArrayToHexString(byte[] ba)
{
return BitConverter.ToString(ba).Replace("-", "");
}
public static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
Main Encryption Method with first couple of lines being the calling of it extracted from a larger method.
string crypt = "blahblahblah"
string EncryptAndEncode = "@" + byteArrayToHexString(aesEncrypt(crypt));
private byte[] aesEncrypt(string inputText)
{
RijndaelManaged AES = new RijndaelManaged();
//set the mode, padding and block size for the key
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.KeySize = 128;
AES.BlockSize = 128;
//convert key and plain text input into byte arrays
Byte[] keyAndIvBytes = UTF8Encoding.UTF8.GetBytes("tR7nR6wZHGjYMCuV");
Byte[] inputBytes = UTF8Encoding.UTF8.GetBytes(inputText);//AbHLlc5uLone0D1q
//create streams and encryptor object
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, AES.CreateEncryptor(keyAndIvBytes, keyAndIvBytes), CryptoStreamMode.Write);
//perform encryption
cryptoStream.Write(inputBytes, 0, inputBytes.Length);
cryptoStream.FlushFinalBlock();
//get encrypted stream into byte array
Byte[] outBytes = memoryStream.ToArray();
//close streams
memoryStream.Close();
cryptoStream.Close();
AES.Clear();
return outBytes;
}
Decoding and Decrypting methods
public string DecodeAndDecrypt(string strIn)
{
//** HEX decoding then AES decryption, CBC blocking with PKCS5 padding - DEFAULT **
string DecodeAndDecrypt = aesDecrypt(StringToByteArray(strIn.Substring(1)));
return (DecodeAndDecrypt);
}
private string aesDecrypt(Byte[] inputBytes)
{
RijndaelManaged AES = new RijndaelManaged();
Byte[] keyAndIvBytes = UTF8Encoding.UTF8.GetBytes("tR7nR6wZHGjYMCuV");
Byte[] outputBytes = inputBytes;//Convert.FromBase64String(inputBytes);
//set the mode, padding and block size
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.KeySize = 128;
AES.BlockSize = 128;
//create streams and decryptor object
MemoryStream memoryStream = new MemoryStream(outputBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, AES.CreateEncryptor(keyAndIvBytes, keyAndIvBytes), CryptoStreamMode.Read);
//perform decryption
cryptoStream.Read(outputBytes, 0, outputBytes.Length);
Trace.WriteLine(outputBytes);
//close streams
memoryStream.Close();
cryptoStream.Close();
AES.Clear();
//return System.Text.Encoding.UTF8.GetString(outputBytes);
string plainText = Encoding.UTF8.GetString(outputBytes,
0,
outputBytes.Length);
return plainText;
}
There are actually multiple problems with your code. First in your decrypt method you're creating an encryptor, that should be a decryptor. Secondly you're reading the entire block including the padding of your algorithm into the buffer when you do the decryption. Below is a class with the items fixed and should be returning the proper result. I do however suggest you find a better way of storing the key, putting in your code and generating it the way you'r edoing it is a no no. You should generate your key with an RNG (RNGCryptoServiceProvider) then hash it with a secure hashing algorithm such as SHA512, use that output for your key. You then need to find a good place to store it, I would look into encrypting your web.config file.
public static class EncryptionHelper
{
private static byte[] keyAndIvBytes;
static EncryptionHelper()
{
// You'll need a more secure way of storing this, I hope this isn't
// the real key
keyAndIvBytes = UTF8Encoding.UTF8.GetBytes("tR7nR6wZHGjYMCuV");
}
public static string ByteArrayToHexString(byte[] ba)
{
return BitConverter.ToString(ba).Replace("-", "");
}
public static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public static string DecodeAndDecrypt(string cipherText)
{
string DecodeAndDecrypt = AesDecrypt(StringToByteArray(cipherText));
return (DecodeAndDecrypt);
}
public static string EncryptAndEncode(string plaintext)
{
return ByteArrayToHexString(AesEncrypt(plaintext));
}
public static string AesDecrypt(Byte[] inputBytes)
{
Byte[] outputBytes = inputBytes;
string plaintext = string.Empty;
using (MemoryStream memoryStream = new MemoryStream(outputBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, GetCryptoAlgorithm().CreateDecryptor(keyAndIvBytes, keyAndIvBytes), CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(cryptoStream))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
return plaintext;
}
public static byte[] AesEncrypt(string inputText)
{
byte[] inputBytes = UTF8Encoding.UTF8.GetBytes(inputText);//AbHLlc5uLone0D1q
byte[] result = null;
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, GetCryptoAlgorithm().CreateEncryptor(keyAndIvBytes, keyAndIvBytes), CryptoStreamMode.Write))
{
cryptoStream.Write(inputBytes, 0, inputBytes.Length);
cryptoStream.FlushFinalBlock();
result = memoryStream.ToArray();
}
}
return result;
}
private static RijndaelManaged GetCryptoAlgorithm()
{
RijndaelManaged algorithm = new RijndaelManaged();
//set the mode, padding and block size
algorithm.Padding = PaddingMode.PKCS7;
algorithm.Mode = CipherMode.CBC;
algorithm.KeySize = 128;
algorithm.BlockSize = 128;
return algorithm;
}
}
Calling it is easy:
string crypt = "blahblahblah";
string EncryptAndEncode = EncryptionHelper.EncryptAndEncode(crypt);
Console.WriteLine(EncryptAndEncode);
Console.WriteLine(EncryptionHelper.DecodeAndDecrypt(EncryptAndEncode));
Console.ReadLine();
这篇关于C#AES解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!