I am trying to decrypt a simple AES string BqvGk+lyQ+pyhSqwV3MfRg== (which translates as Hello World) upon user input with a hardcoded key but I get an error. Could the be an issue when it's trying to read the base64 string from terminal? Not sure how to fix that.
at EncryptionDecryptionUsingSymmetricKey.AesOperation.DecryptString(String key) in \\visualstudio\AES_Decryptor\AES_Decryptor\Program.cs:line 32
at EncryptionDecryptionUsingSymmetricKey.AesOperation.Main(String[] args) in \\visualstudio\AES_Decryptor\AES_Decryptor\Program.cs:line 21
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace EncryptionDecryptionUsingSymmetricKey
{
public class AesOperation
{
static void Main(string[] args)
{
var key = "b14ca5898a4e4133bbce2ea2315a1916";
Console.WriteLine("[+] Decrypt: ");
var str = Console.ReadLine();
var decryptedString = AesOperation.DecryptString(key);
Console.WriteLine($"[+] Original payload: {decryptedString}");
}
private static object DecryptString(string key)
{
throw new NotImplementedException();
}
public static string DecryptString(string key, string cipherText)
{
byte[] iv = new byte[16];
byte[] buffer = Convert.FromBase64String(cipherText);
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(buffer))
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader((Stream)cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
}
}
This method is working. When I run:
void Main()
{
var key = "b14ca5898a4e4133bbce2ea2315a1916";
var decryptedString = DecryptString(key, "BqvGk+lyQ+pyhSqwV3MfRg==");
Console.WriteLine($"[+] Original payload: {decryptedString}");
}
The result is:
[+] Original payload: Hello World!
I am using your own method as well:
public static string DecryptString(string key, string cipherText)
{
byte[] iv = new byte[16];
byte[] buffer = Convert.FromBase64String(cipherText);
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(buffer))
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader((Stream)cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
SO I think you need to either provide more of the error message if there is any, or we need more of the code. Cause your key decrypts the AES string just fine with your own provided method.
If I had to guess the issue is 1 of 2 things.
var str = Console.ReadLine();
I don't see you reference str anywhere. also it is going to read the entire console line, which might give you more than the aes string. Also you might just be calling your throw exception method. I am not sure why that is there. Perhaps try getting rid of that and running code. I am referring to this method.
private static object DecryptString(string key)
{
throw new NotImplementedException();
}
Related
I am using AES criptography algorithms to encrypt and decrypt my values in my project. My code works almost everytime but sometimes I get Padding is invalid and cannot be removed error. My project is ASP .NET Core 3.1 project and it's published on IIS Server 8.5.
As said at Padding is invalid and cannot be removed? question asked 9 years ago, my keys and salts are always set 128 bits and padding mode is always set to PKCS#7 like this code: aes.Padding = PaddingMode.PKCS7;.
But sometimes, I got this error. After debugging my code with the same key, salt and decrypted value I didn't get any error and my code works fine for another 10 hours or so. I have no idea why my code behaves like this but I couldn't find any solution.
My Constructor:
public void KriptoAlgoritmasiniAyarla(string password, string salt, SymmetricAlgorithm algorithm)
{
if (password == null) throw new ArgumentNullException(nameof(password));
if (salt == null) throw new ArgumentNullException(nameof(salt));
DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
var rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
var rgbIv = rgb.GetBytes(algorithm.BlockSize >> 3);
_sifreleyici = algorithm.CreateEncryptor(rgbKey, rgbIv);
_desifreleyici = algorithm.CreateDecryptor(rgbKey, rgbIv);
}
My encrption code:
public byte[] ByteDizisineSifrele(string plainText)
{
try
{
byte[] encrypted;
// Create a new AesManaged.
using (AesManaged aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
// 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, _sifreleyici, CryptoStreamMode.Write))
{
// Create StreamWriter and write data to a stream
using (StreamWriter sw = new StreamWriter(cs))
sw.Write(plainText);
encrypted = ms.ToArray();
}
}
}
// Return encrypted data
return encrypted;
}
catch (Exception exp)
{
throw exp;
}
}
My decryption code:
public string ByteDizisiDesifreEt(byte[] cipherText)
{
try
{
string plaintext = null;
// Create AesManaged
using (AesManaged aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
// Create the streams used for decryption.
using (MemoryStream ms = new MemoryStream(cipherText))
{
// Create crypto stream
using (CryptoStream cs = new CryptoStream(ms, _desifreleyici, CryptoStreamMode.Read))
{
// Read crypto stream
using (StreamReader reader = new StreamReader(cs))
plaintext = reader.ReadToEnd();
}
}
}
return plaintext;
}
catch (Exception exp)
{
throw exp;
}
}
Probably because you are reusing the same ICryptoTransform objects (_sifreleyici and _desifreleyici). At some point, the transform object can't be reused anymore and therefore the interface has a property to determine that. The ICryptoTransform.CanReuseTransform property.
Consequently, you need to check this property and recreate the objects when you get false.
Example
private readonly byte[] Key, IV;
public void KriptoAlgoritmasiniAyarla(
string password,
string salt,
SymmetricAlgorithm algorithm)
{
// ...
Key = // Get the key..
IV = // Get the IV..
}
private ICryptoTransform encryptor;
private ICryptoTransform Encryptor
{
get
{
if (encryptor == null || !encryptor.CanReuseTransform)
{
encryptor?.Dispose();
encryptor = Algorithm.CreateEncryptor(Key, IV);
}
return encryptor;
}
}
private ICryptoTransform decryptor;
private ICryptoTransform Decryptor
{
get
{
if (decryptor == null || !decryptor.CanReuseTransform)
{
decryptor?.Dispose();
decryptor = Algorithm.CreateDecryptor(Key, IV);
}
return decryptor;
}
}
Then use these two properties in the related methods to create the CryptoStream.
Alternative
I'd like to propose the code below as an alternative that can be used with the classes that derive from the SymmetricAlgorithm abstract class.
public class SymmetricCrypto<T> : IDisposable where T : SymmetricAlgorithm, new()
{
private readonly T Algorithm = new T();
public SymmetricCrypto()
{
Algorithm.GenerateKey();
Algorithm.GenerateIV();
}
public SymmetricCrypto(byte[] key, byte[] iv)
{
Algorithm.Key = key;
Algorithm.IV = iv;
}
public SymmetricCrypto(string pass)
{
var bytes = Encoding.UTF8.GetBytes(pass);
var rfc = new Rfc2898DeriveBytes(pass,
new SHA256Managed().ComputeHash(bytes), 1000);
Algorithm.Key = rfc.GetBytes(Algorithm.LegalKeySizes[0].MaxSize / 8);
Algorithm.IV = rfc.GetBytes(Algorithm.LegalBlockSizes[0].MinSize / 8);
}
public SymmetricCrypto(byte[] pass)
{
var rfc = new Rfc2898DeriveBytes(pass,
new SHA256Managed().ComputeHash(pass), 1000);
Algorithm.Key = rfc.GetBytes(Algorithm.LegalKeySizes[0].MaxSize / 8);
Algorithm.IV = rfc.GetBytes(Algorithm.LegalBlockSizes[0].MinSize / 8);
}
public byte[] Encrypt(string input) =>
Transform(Encoding.UTF8.GetBytes(input), Algorithm.CreateEncryptor());
public string Decrypt(byte[] input) =>
Encoding.UTF8.GetString(Transform(input, Algorithm.CreateDecryptor()));
private byte[] Transform(byte[] input, ICryptoTransform cryptoTrans)
{
using (var ms = new MemoryStream())
using (var cs = new CryptoStream(ms, cryptoTrans, CryptoStreamMode.Write))
{
cs.Write(input, 0, input.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
}
public void Dispose() => Algorithm.Dispose();
}
Usage:
void SomeCaller()
{
using (var crypt = new SymmetricCrypto<AesManaged>("password"))
{
var bytes = crypt.Encrypt("Plain Text....");
// ...
var plainText = crypt.Decrypt(bytes);
// ...
}
}
how to generate a key and key IV and not write them explicitly?
public sealed class MyCryptoClass
{
protected RijndaelManaged myRijndael;
private static string encryptionKey = "142eb4a7ab52dbfb971e18daed7056488446b4b2167cf61187f4bbc60fc9d96d";
private static string initialisationVector ="26744a68b53dd87bb395584c00f7290a";
I try generate encryptionKey and initialisationVector
protected static readonly MyCryptoClass _instance = new MyCryptoClass();
public static MyCryptoClass Instance
{
get { return _instance; }
}
public string EncryptText(string plainText)
{
using (myRijndael = new RijndaelManaged())
{
myRijndael.Key = HexStringToByte(encryptionKey);
myRijndael.IV = HexStringToByte(initialisationVector);
myRijndael.Mode = CipherMode.CBC;
myRijndael.Padding = PaddingMode.PKCS7;
byte[] encrypted = EncryptStringToBytes(plainText, myRijndael.Key, myRijndael.IV);
string encString = Convert.ToBase64String(encrypted);
return encString;
}
}
Let's do it step by step to keep things simple.
You need two methods to achieve your goal. I'll start with encryption method:
static byte[] Encrypt(string input, byte[] Key, byte[] IV)
{
byte[] encryptedBytes;
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.Key = Key;
rijndael.IV = IV;
ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, rijndael.IV);
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream,
encryptor, CryptoStreamMode.Write))
{
using (var streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(input);
}
encryptedBytes = memoryStream.ToArray();
}
}
}
return encryptedBytes;
}
Then we need a Decrypt method subsequently:
static string Decrypt(byte[] cipher, byte[] Key, byte[] IV)
{
string plaintext = null;
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.Key = Key;
rijndael.IV = IV;
ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);
using (var memoryStream = new MemoryStream(cipher))
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (var streamReader = new StreamReader(cryptoStream))
{
plaintext = streamReader.ReadToEnd();
}
}
}
}
return plaintext;
}
Note: It's better to wrap Encrypt and Decrypt methods in a class and then use them.
You can call the methods like below:
string original = "This is what would be encrypted!";
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
myRijndael.GenerateKey(); // this line generates key
myRijndael.GenerateIV(); // this line generates initialization vektor
// This line returns encrypted text
byte[] encryptedBytes = Encrypt(original, myRijndael.Key, myRijndael.IV);
// You can decrypt the encrypted text like so
string decryptedString = Decrypt(encryptedBytes, myRijndael.Key, myRijndael.IV);
}
Hello Friendly OverFlowers:
I have a line of code in the bigger example that is not working:
plaintext = srDecrypt.ReadToEnd();
It reports an exception:
The input data is not a complete block.
I have:
1) Looked at Encodings
2) Verified Decrypt (args) were correct.
Oh the intention from the simple main was to get back the encrypted value from the decrypted value. The plaintext = line is in the Decryption portion.
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace Encryptor
{
class Program
{
static void Main(string[] args)
{
CryptDecrypt cd = new CryptDecrypt(new Guid());
string s = cd.Encrypt("Password");
Console.WriteLine(s);
string t = cd.Decrypt(s);
Console.WriteLine(t);
Console.ReadKey();
}
}
public class CryptDecrypt
{
private byte[] Key;
private byte[] IV;
public CryptDecrypt(Guid keyBase)
{
string Hash = keyBase.ToString();
Key = Encoding.UTF8.GetBytes(Hash.Take(32).ToArray());
IV = Encoding.UTF8.GetBytes(Hash.Reverse().Take(16).ToArray());
}
public string Encrypt(string plainText)
{
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.IV = IV;
aesAlg.Key = IV;
aesAlg.Padding = PaddingMode.Zeros;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.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.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
public string Decrypt(string inputStr)
{
// Check arguments.
if (inputStr == null || inputStr.Length <= 0)
throw new ArgumentNullException("cipherText");
byte[] cipherText = Encoding.UTF8.GetBytes(inputStr);
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Padding = PaddingMode.Zeros;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.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();
}
}
}
}
return plaintext;
}
}
}
You have two errors. First is that you use IV as the Key in the Encrypt method, and second you forgot to convert back from Base64 before decrypting.
See the code amended to correct these problems.
void Main()
{
CryptDecrypt cd = new CryptDecrypt(new Guid());
string s = cd.Encrypt("Password");
Console.WriteLine(s);
string t = cd.Decrypt(s);
Console.WriteLine(t);
}
public class CryptDecrypt
{
private byte[] Key;
private byte[] IV;
public CryptDecrypt(Guid keyBase)
{
string Hash = keyBase.ToString();
Key = Encoding.UTF8.GetBytes(Hash.Take(32).ToArray());
IV = Encoding.UTF8.GetBytes(Hash.Reverse().Take(16).ToArray());
}
public string Encrypt(string plainText)
{
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.IV = IV;
aesAlg.Key = Key; <- HERE
aesAlg.Padding = PaddingMode.Zeros;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.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.
swEncrypt.Write(plainText);
swEncrypt.Flush();
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
public string Decrypt(string inputStr)
{
// Check arguments.
if (inputStr == null || inputStr.Length <= 0)
throw new ArgumentNullException("cipherText");
byte[] cipherText = Convert.FromBase64String(inputStr); <- HERE
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Padding = PaddingMode.Zeros;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.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();
}
}
}
}
return plaintext;
}
}
I saw that exists another questions about this topic, but I checked every question and I can't solve my problem..
This is my method to decrypt and another method to call decrypt method with required parameters:
public string Decrypt(AesOperationType operationType, byte[] criptotext, byte[] Key, byte[] initVector)
{
string plaintext = null;
using (Aes aesAlg = Aes.Create())
{
aesAlg.KeySize = 128;
aesAlg.Key = Key;
aesAlg.IV = initVector;
if (operationType == AesOperationType.Cbc)
{
aesAlg.Mode = CipherMode.CBC;
}
else if (operationType == AesOperationType.Cfb)
{
aesAlg.Mode = CipherMode.ECB;
}
//apelam functia de decriptare
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(criptotext))
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
Console.WriteLine("Start decrypt for criptotext : " + BitConverter.ToString(criptotext) + "\n");
Console.WriteLine("Plaintext after decrypt : " + plaintext + "\n");
return plaintext;
}
public byte[] Encrypt_Call()
{
var key = "1212121212121212";
var key_byte = Encoding.ASCII.GetBytes(key);
using (Aes aess = Aes.Create())
{
var iv = aess.IV;
cryptdecrypt object = new cryptdecrypt();
var result = object.Encrypt(AesOperationType.Cbc, "plaintext", key_byte, iv);
return result;
}
}
public void Decrypt_Call()
{
var key = "1212121212121212";
var key_byte = Encoding.ASCII.GetBytes(key);
using (Aes aess = Aes.Create())
{
var iv = aess.IV;
cryptdecrypt object = new cryptdecrypt();
var cryptotext = Encrypt_Call();
var result = object.Decrypt(AesOperationType.Cbc, cryptotext , key_byte, iv);
}
}
Encrypt method works fine, but at decryption method call, I face this error:
Padding is invalid and cannot be removed.
I also tried to put csDecrypt.FlushFinalBlock() this line before this line:
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
The error disappears and as result I get an empty string.
Any ideas to solve this?
Typically an invalid padding error means the decryption failed. In this case with CBC mode the IV is not specified so it will be junk (or random).
Either:
Specify an IV of block length (AES 16-bytes).
create a random IV on encryption and prepend it to the encrypted data. On decryption split the IV off and use for decryption. <–– Best option
I've been trying to understand encryption/decryption code of TripleDES for some days. And I have seen many codes in the google, and the code shown below is one of them.
static void Main(string[] args)
{
string original = "Here is some data to encrypt!";
TripleDESCryptoServiceProvider myTripleDES = new TripleDESCryptoServiceProvider();
byte[] encrypted = EncryptStringToBytes(original, myTripleDES.Key, myTripleDES.IV);
string encrypt = Convert.ToBase64String(encrypted);
string roundtrip = DecryptStringFromBytes(encrypted, myTripleDES.Key, myTripleDES.IV);
Console.WriteLine("encryted: {0}", encrypt);
Console.WriteLine("Round Trip: {0}", roundtrip);
Console.ReadLine();
}
static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
byte[] encrypted;
using (TripleDESCryptoServiceProvider tdsAlg = new TripleDESCryptoServiceProvider())
{
tdsAlg.Key = Key;
tdsAlg.IV = IV;
ICryptoTransform encryptor = tdsAlg.CreateEncryptor(tdsAlg.Key, tdsAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
string plaintext = null;
using (TripleDESCryptoServiceProvider tdsAlg = new TripleDESCryptoServiceProvider())
{
tdsAlg.Key = Key;
tdsAlg.IV = IV;
ICryptoTransform decryptor = tdsAlg.CreateDecryptor(tdsAlg.Key, tdsAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
There is no error in the code. I works fine. But strangely I noticed that the plainText is never been encoded. There is no line like Encoding.Unicode.GetBytes(plainText); or Encoding.UTF8.GetBytes(plainText); or similar like that. So, my question is , how does (in the code) the plainText which is a string gets converted to the encrypted byte? Is there any work done inside the streams? If thats so then where and how? As far as I understood there is no such line in between the streams that converts the string to byte. So , How does the overall code is working without this basic transformation?
Update:
Is this code really a valid code?
You are sending the plaintext to the encryption stream in the line swEncrypt.Write(plaintext). This does the byte conversion.
The StreamWriter is doing the encoding. The constructor being used specifies UTF-8 encoding:
This constructor creates a StreamWriter with UTF-8 encoding without a
Byte-Order Mark (BOM)