Occasionally getting 'System.Security.Cryptography.CryptographicException: Bad Data' Exception while decrypting string - c#

I have implemented a class as shown below which is responsible for encrypting/decrypting the text data to a utility class called TextEncryptionData.
It works fine for %99.99 of the time. But sometime (very rare) it fails to decrypt the text and I don't know why it happens. Is there any problem in the way I implemented it?
public class SubscriptionStateEncryptionLogic : IEncryptionLogic
{
private static byte[] KEY = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 71 };
private static byte[] IV = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8};
public EncryptionData Encrypt(EncryptionData source)
{
if (source == null)
{
return null;
}
try
{
TextEncryptionData data = source as TextEncryptionData;
using (TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider())
{
cryptoProvider.KeySize = 128;
cryptoProvider.Key = KEY;
cryptoProvider.IV = IV;
cryptoProvider.Mode = CipherMode.CBC;
cryptoProvider.Padding = PaddingMode.PKCS7;
ICryptoTransform transform = cryptoProvider.CreateEncryptor();
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
{
using (StreamWriter writer = new StreamWriter(cryptoStream))
{
writer.Write(data.Data);
writer.Flush();
cryptoStream.FlushFinalBlock();
writer.Flush();
return new TextEncryptionData() { Data = Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length) };
}
}
}
}
}
catch (Exception ex)
{
throw new SubscriptionStateEncryptionException("Error in encrypting the subscription status.", ex);
}
}
public EncryptionData Decrypt(EncryptionData source)
{
if (source == null)
{
return null;
}
try
{
TextEncryptionData data = source as TextEncryptionData;
using (TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider())
{
cryptoProvider.KeySize = 128;
cryptoProvider.Key = KEY;
cryptoProvider.IV = IV;
cryptoProvider.Mode = CipherMode.CBC;
cryptoProvider.Padding = PaddingMode.PKCS7;
ICryptoTransform transform = cryptoProvider.CreateDecryptor();
using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(data.Data)))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(cryptoStream))
{
return new TextEncryptionData() { Data = reader.ReadToEnd() };
}
}
}
}
}
catch (Exception ex)
{
throw new SubscriptionStateEncryptionException("Error in decrypting the subscription status.", ex);
}
}
}

Related

S3 multipart upload with encryption

I am trying to implement multiple upload request with an encryption. First of all I send InitiateMultipartUploadRequest. It get me an upload id. Then I split my file by chunks and send UploadPartRequest.
Function of creating s3 client:
public IAmazonS3 CreateAmazonS3Client()
{
byte[] IV = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
var s3Config = new AmazonS3CryptoConfigurationV2(SecurityProfile.V2)
{
ServiceURL = "_URL_",
ForcePathStyle = true
};
var aes = Aes.Create();
aes.Mode = CipherMode.ECB;
aes.IV = IV;
using (var hashSha256 = new SHA256Managed())
{
aes.Key = hashSha256.ComputeHash(Encoding.Unicode.GetBytes("_PASSWORD_"));
}
return new AmazonS3EncryptionClientV2("_ACCESS_KEY_", "_SECRET_KEY_", s3Config, new EncryptionMaterialsV2(aes, SymmetricAlgorithmType.AesGcm));
}
Function of uploading chunks:
private async Task<UploadPartResponse> UploadFileChunkAsync(string key, string uploadId, byte[] buffer, int partNumber, SemaphoreSlim semaphoreSlim)
{
using var s3Client = CreateAmazonS3Client();
using var stream = new MemoryStream();
var bufferSize = partNumber < buffer.Length / _chunkSize ? _chunkSize : buffer.Length % _chunkSize;
lock (_syncObj)
{
stream.Write(buffer, partNumber * _chunkSize, bufferSize);
stream.Position = 0;
}
var uploadRequest = new UploadPartRequest
{
Key = key,
BucketName = "_BACKET_NAME_",
UploadId = uploadId,
PartNumber = partNumber + 1,
InputStream = stream,
PartSize = bufferSize,
};
return await s3Client.UploadPartAsync(uploadRequest);
}
UploadFileChunkAsync function throw an exception on the last return line (UploadPartAsync). The exception message is: "The given key 'UPLOAD_ID' was not present in the dictionary"
What does it mean, where the key must be placed?

Why do I get a System.Security.Cryptography.CryptographicException during decrypting this byte array

I just started with Cryptography in C# an tried to first encrypt and then decrypt a file. But during the decryption, in the function
private static byte[] Decrypt(byte[] inputBuffer)
, at
byte[] outputBuffer = transform.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
I am getting the following Exception:
System.Security.Cryptography.CryptographicException: "Invalid data".
But why is that?
This is the function to read the file:
private static void DecryptFile()
{
byte[] buffer = new byte[4096];
byte[] decryptionBuffer = new byte[4096];
int bytesRead = 0;
using (FileStream inputStream = File.OpenRead(Environment.CurrentDirectory + "\\Encrypted.txt"))
{
using (FileStream outputStream = File.Create(Environment.CurrentDirectory + "\\Decrypt.mp3"))
{
while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
decryptionBuffer = Decrypt(buffer);
outputStream .Write(decryptionBuffer, 0, decryptionBuffer.Length);
}
}
Console.WriteLine("Done.");
}
}
This is the function to decrypt the file, the key and the initialization vector:
private static byte[] key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
private static byte[] iv = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
private static byte[] Decrypt(byte[] inputBuffer)
{
SymmetricAlgorithm algorithm = DES.Create();
ICryptoTransform transform = algorithm.CreateDecryptor(key, iv);
//here the exception is triggered
byte[] outputBuffer = transform.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
return outputBuffer;
}
this is how the file was encrypted:
private static void EncryptFile()
{
byte[] buffer = new byte[4096];
byte[] enryptionBuffer = new byte[4096];
int bytesRead = 0;
using (FileStream inputStream = File.OpenRead(Environment.CurrentDirectory + "\\Test.txt"))
{
using (FileStream outputStream = File.Create(Environment.CurrentDirectory + "\\Encrypted.txt"))
{
while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
encryptionBuffer = Encrypt(buffer);
outputStream .Write(encryptionBuffer, 0, encryptionBuffer.Length);
}
}
Console.WriteLine("Done.");
}
}
//Key and initialization vector are the same
private static byte[] key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
private static byte[] iv = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
private static byte[] Encrypt(byte[] inputBuffer)
{
SymmetricAlgorithm algorithm = DES.Create();
ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
byte[] outputBuffer = transform.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
return outputBuffer;
}
Your encryption code produces larger output buffers than your input buffers. If you independently encrypt 4096 bytes at a time, it produces 4104 bytes of output1. If you wish to continue to independently encrypt each block of your file, you need to change your decryption code to use 4104 byte buffers when it's working in chunks.
Ideally though, this "encrypt each block separately" isn't a requirement. If that's the case, create your transform object once, not once each time through your loop. And use Transform rather than TransformFinalBlock up until you know you've reached the end of the file (pay attention that they return very different things however).
You're also ignoring bytesRead which tells you how much of your buffer is filled with useful data. You need to use that as well and don't make your final encryption round be x many bytes which are the last bytes of the file and bufferSize - x bytes of the previous block of data from the file.
I would probably look to instead create a CryptoStream that wraps one of your FileStream objects and then use Stream.CopyTo or moral equivalents to do this work. Let libraries worry about managing buffers, loops, etc.
And finally, ideally, you recognize that it's 2019 and so very far from appropriate to be writing new code that uses DES for encryption2
1This program, if you set a breakpoint on the Console.ReadLine line, has c containing 4104 bytes:
using System;
using System.Security.Cryptography;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var b = new byte[4096];
var c = Encrypt(b);
Console.ReadLine();
}
private static byte[] key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
private static byte[] iv = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
private static byte[] Encrypt(byte[] inputBuffer)
{
SymmetricAlgorithm algorithm = DES.Create();
ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
byte[] outputBuffer = transform.TransformFinalBlock(
inputBuffer,
0,
inputBuffer.Length);
return outputBuffer;
}
}
2So my EnryptFile in its entirety would be:
private static void EncryptFile()
{
using (var inputStream = File.OpenRead(Environment.CurrentDirectory + "\\Test.txt"))
using (var outputStream = File.Create(Environment.CurrentDirectory + "\\Encrypted.txt"))
using (var aes = Aes.Create())
using (var cStream = new CryptoStream(
inputStream,
aes.CreateEncryptor(key, iv),
CryptoStreamMode.Read))
{
cStream.CopyTo(outputStream);
}
}
Or an async variant which which uses await cStream.CopyToAsync(outputStream); as it's innermost statement. DecryptFile would be similarly simplified.
I was facing the same problem then I created a customized function for encryption/decryption and using this function also supports large files because we are reading and writing a file chunk by chunk. there is an EncryptMode that is what do you want by this method like if you want to encryption then send _mode as _mode.ENCRYPT and if you want decryption then send _mode as _mode.DECRYPT.
private enum EncryptMode { ENCRYPT, DECRYPT };
public void encryptDecryptChunkByChunk(string _inputPath, string _outputPath, string _encryptionKey, EncryptMode _mode, string _initVector)
{
string _out = "";// output string
//_encryptionKey = MD5Hash (_encryptionKey);
_pwd = Encoding.UTF8.GetBytes(_encryptionKey);
_ivBytes = Encoding.UTF8.GetBytes(_initVector);
int len = _pwd.Length;
if (len > _key.Length)
{
len = _key.Length;
}
int ivLenth = _ivBytes.Length;
if (ivLenth > _iv.Length)
{
ivLenth = _iv.Length;
}
Array.Copy(_pwd, _key, len);
Array.Copy(_ivBytes, _iv, ivLenth);
_rcipher.Key = _key;
_rcipher.IV = _iv;
if (_mode.Equals(EncryptMode.ENCRYPT))
{
//encrypt
using (FileStream fs = new FileStream(_inputPath, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()))
{
System.IO.StreamWriter file = new System.IO.StreamWriter(_outputPath);
try
{
byte[] chunk;
chunk = br.ReadBytes(CHUNK_SIZE);
while (chunk.Length > 0)
{
var base641 = Convert.ToBase64String(chunk);
//DumpBytes(chunk, chunk.Length);
chunk = br.ReadBytes(CHUNK_SIZE);
var base64 = Convert.ToBase64String(chunk);
byte[] plainText = _rcipher.CreateEncryptor().TransformFinalBlock(_enc.GetBytes(base641), 0, base641.Length);
var bas64Encrypted = Convert.ToBase64String(plainText);
//fsCrypt.Write(bas64Encrypted);
file.WriteLine(bas64Encrypted);
}
file.Close();
}
catch (Exception ex)
{
file.Close();
}
}
}
}
if (_mode.Equals(EncryptMode.DECRYPT))
{
FileStream fsOut = new FileStream(_outputPath, FileMode.OpenOrCreate, FileAccess.Write);
try
{
foreach (string line in File.ReadLines(_inputPath))
{
// Process your line here....
var p = line;
var x2 = Convert.FromBase64String(p);
byte[] plainText = _rcipher.CreateDecryptor().TransformFinalBlock(x2, 0, x2.Length);
var y1 = _enc.GetString(plainText);
var y2 = Convert.FromBase64String(y1);
fsOut.Write(y2, 0, y2.Length);
}
fsOut.Close();
}
catch (Exception ex)
{
fsOut.Close();
}
}
_rcipher.Dispose();
}

Specified padding mode is not valid for this algorithm - c# - System.Security.Cryptography

pretty new to c# and currently having a problem decrypting long passwords with an error of
Specified key is not a valid size for this algorithm
I know this has something to do with the encrypted password bits length not being supported but unsure how to go about suggested ways to allow for these longer passwords.
Here's my encrypt and decrypt
"cipherKey": "0123456789abcdef", "cipherVector":
"somereallycooliv"
using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;
namespace DataApi
{
public class Encryption
{
private readonly IConfigurationService _configService;
private const string _vector = "cipherVector";
private const string _key = "cipherKey";
public Encryption(IConfigurationService configService)
{
_configService = configService;
}
public string EncryptString(string text)
{
if(string.IsNullOrEmpty(text))
{
return "";
}
try
{
var key = Encoding.UTF8.GetBytes(_configService.Get(_key));
byte[] IV = Encoding.ASCII.GetBytes(_configService.Get(_vector));
using (var aesAlg = Aes.Create())
{
using (var encryptor = aesAlg.CreateEncryptor(key, IV))
{
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(text);
}
var decryptedContent = msEncrypt.ToArray();
var result = new byte[IV.Length + decryptedContent.Length];
Buffer.BlockCopy(IV, 0, result, 0, IV.Length);
Buffer.BlockCopy(decryptedContent, 0, result, IV.Length, decryptedContent.Length);
return Convert.ToBase64String(result);
}
}
}
}
catch(Exception e) {
Loggifer.Error("Unable to encrypt string: "+text , e );
throw e;
}
}
public string DecryptString(string cipherText)
{
if(string.IsNullOrEmpty(cipherText))
{
return "";
}
try
{
var fullCipher = Convert.FromBase64String(cipherText);
byte[] IV = Encoding.ASCII.GetBytes(_configService.Get(_vector));
var cipher = new byte[16];
Buffer.BlockCopy(fullCipher, 0, IV, 0, IV.Length);
Buffer.BlockCopy(fullCipher, IV.Length, cipher, 0, IV.Length);
var key = Encoding.UTF8.GetBytes(_configService.Get(_key));
using (var aesAlg = Aes.Create())
{
using (var decryptor = aesAlg.CreateDecryptor(key, IV))
{
string result;
using (var msDecrypt = new MemoryStream(cipher))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
result = srDecrypt.ReadToEnd();
}
}
}
return result;
}
}
}
catch (Exception e)
{
Loggifer.Error("Unable to decrypt string: "+cipherText , e );
throw e;
}
}
}
}
Two changes are required in the function public string DecryptString(string cipherText)
var cipher = new byte[fullCipher.Length - IV.Length];
and
Buffer.BlockCopy(fullCipher, IV.Length, cipher, 0, fullCipher.Length - IV.Length);

How to Encrypt a Data Entered from Textbox?

I don't know how to encrypt a data entered from Textbox. The data entered will appear on the next form inside a DataGridView. My problem is I want to encrypt the data when it appears on the DataGridView. I am using C# in Microsoft Visual Studio 2010. Thanks!
frmUsers f2 = new frmUsers();
private void button1_Click(object sender, EventArgs e)
{
setGrid();
}
public void setGrid() {
f2.dataGridView1.Columns.Add("COL1", "Firstname");
f2.dataGridView1.Columns.Add("COL1", "Lastname");
f2.dataGridView1.Columns.Add("COL1", "Email");
f2.dataGridView1.Columns.Add("COL1", "Password");
f2.Show();
f2.dataGridView1.Rows.Add(textBox1.Text, textBox2.Text, textBox3.Text, textBox4.Text, textBox5.Text);
}
Here is a code to encrypt and decrypt a string with specified secret phrase. Keep in mind you should decrypt your cipher with the exact secret you have encrypted it.
public static class Crypto
{
public static string Encrypt(string text, string secret)
{
if (string.IsNullOrEmpty(text))
throw new ArgumentNullException("text");
if (string.IsNullOrEmpty(secret))
throw new ArgumentNullException("secret");
var salt = Encoding.UTF8.GetBytes(secret);
using (var aes = new RijndaelManaged())
{
var key = new Rfc2898DeriveBytes(secret, salt);
aes.Key = key.GetBytes(aes.KeySize / 8);
var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (var ms = new MemoryStream())
{
ms.Write(BitConverter.GetBytes(aes.IV.Length), 0, sizeof(int));
ms.Write(aes.IV, 0, aes.IV.Length);
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
using (var sw = new StreamWriter(cs))
{
sw.Write(text);
}
return Convert.ToBase64String(ms.ToArray());
}
}
}
public static string Decrypt(string cipher, string secret)
{
if (string.IsNullOrEmpty(cipher))
throw new ArgumentNullException("cipher");
if (string.IsNullOrEmpty(secret))
throw new ArgumentNullException("secret");
var salt = Encoding.UTF8.GetBytes(secret);
using (var aes = new RijndaelManaged())
{
var key = new Rfc2898DeriveBytes(secret, salt);
var bytes = Convert.FromBase64String(cipher);
using (var ms = new MemoryStream(bytes))
{
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = ReadByteArray(ms);
var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (var sr = new StreamReader(cs))
{
return sr.ReadToEnd();
}
}
}
}
private static byte[] ReadByteArray(Stream s)
{
var rawLength = new byte[sizeof(int)];
if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length)
{
throw new SystemException("Stream did not contain properly formatted byte array");
}
var buffer = new byte[BitConverter.ToInt32(rawLength, 0)];
if (s.Read(buffer, 0, buffer.Length) != buffer.Length)
{
throw new SystemException("Did not read byte array properly");
}
return buffer;
}
}

AES Encryption getting incorrect result

I'm try to use AES encryption for some text, but the decrypted text is not identical to original one.
Original text: abcd
Decrypted text: ?9T?o??G???x;*
Here is my code:
public static void Main(string[] args)
{
byte[] original = { 97, 98, 99, 100 }; //"abcd"
byte[] key = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] encrypt = Encrypt(original, key, iv);
byte[] decrypt = Decrypt(encrypt, key, iv);
Console.WriteLine(Encoding.UTF8.GetString(original));
Console.WriteLine(Encoding.UTF8.GetString(decrypt));
Console.ReadKey();
}
public static byte[] Encrypt(byte[] original, byte[] key, byte[] iv)
{
using (var memoryStream = new MemoryStream())
{
using (var aes = new AesManaged { Key = key, IV = iv, Padding = PaddingMode.PKCS7, Mode = CipherMode.CBC })
{
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptoStream.Write(original, 0, original.Length);
}
}
return memoryStream.ToArray();
}
}
public static byte[] Decrypt(byte[] encrypt, byte[] key, byte[] iv)
{
using (var memoryStream = new MemoryStream(encrypt))
{
using (var aes = new AesManaged { Key = key, IV = iv, Padding = PaddingMode.PKCS7, Mode = CipherMode.CBC })
{
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Read))
{
byte[] decrypt = new byte[encrypt.Length];
cryptoStream.Read(decrypt, 0, decrypt.Length);
return decrypt;
}
}
}
}
What's wrong? Thanks in advance.
You've got this in your decryption code:
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(),
CryptoStreamMode.Read))
Change it to call aes.CreateDecryptor() and it works fine.
There's something wrong with your decrypt method, use something like this :
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);
}

Categories