Whenever I decrypt a file I end up with \0 in between each character (this is a text file) The original is fine, and the decryption is successful without errors.
When I do open the file ; "hello" would become "h\0e\0l\0..."
Here is my decryption function: (I came up with a fix of converting the byte array to utf8 then manually removing the nulls, this is obviously not a solution. )
public static void DecryptFileToFile(String fromFile, String toFile, byte[] Key)
{
byte[] encryptedFile = IO.convertFileToByte(fromFile);
using (Aes aesAlg = Aes.Create())
{
byte[] dataIV = encryptedFile.Take(16).ToArray(); //first 16 bytes is iv
byte[] encryptedData = encryptedFile.Skip(16).Take(encryptedFile.Length-16).ToArray();
aesAlg.Key = Key;
using (var decryptor = aesAlg.CreateDecryptor(Key, dataIV))
{
byte[] final = PerformCryptography(decryptor, encryptedData);
string result = System.Text.Encoding.UTF8.GetString(final);
result = result.Replace("\0", string.Empty);
IO.writeStringToFile(result,toFile);
}
}
}
private static byte[] PerformCryptography(ICryptoTransform cryptoTransform, byte[] data)
{
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
return memoryStream.ToArray();
}
}
}
to encrypt:
public static void EncryptFileToFile(String fromFile, String toFile, byte[] Key){
byte[] original = IO.convertFileToByte(fromFile);
using (Aes aesAlg = Aes.Create())
{
aesAlg.GenerateIV();
aesAlg.Key = Key;
using (var encryptor = aesAlg.CreateEncryptor(Key, aesAlg.IV))
{
byte[] encryptedData = PerformCryptography(encryptor, original);
byte[] final = Combine(aesAlg.IV,encryptedData);
IO.writeByteToFile(final, toFile);
}
}
}
Related
I created public and private keys (pem) with openSsl tool. I used commands:
openssl genrsa -out privatekey.pem 2048
openssl req -new -key privatekey.pem -x509 -days 3650 -out publiccert.pem
Then I generate aesKey:
byte[] GenerateAesKey()
{
var rnd = new RNGCryptoServiceProvider();
var b = new byte[16];
rnd.GetNonZeroBytes(b);
return b;
}
My method for encrypt data:
string CreateSecurePayload(byte[] aesKey)
{
object obj = new
{
contact = new
{
email = "myName#email.com",
firstName = "John",
lastName = "Doe"
}
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
var res = "";
using (Aes myRijndael = Aes.Create())
{
byte[] encrypted = EncryptStringToBytes(json, aesKey, myRijndael.IV);
res = Convert.ToBase64String(encrypted);
}
return res;
}
byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
byte[] encrypted;
using (Aes rijAlg = Aes.Create())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
And then I encrypt my aesKey with private key:
string SecureKey(byte[] aesKey)
{
byte[] plainTextBytes = aesKey;
AsymmetricCipherKeyPair keys;
FileStream fileStream = new FileStream("path/to/privatekey.pem", FileMode.Open);
using (var reader = new StreamReader(fileStream))
{
var pr = new PemReader(reader);
keys = (AsymmetricCipherKeyPair)pr.ReadObject();
}
var eng = new OaepEncoding(new RsaEngine());
eng.Init(true, keys.Private);
int length = plainTextBytes.Length;
int blockSize = eng.GetInputBlockSize();
var cipherTextBytes = new List<byte>();
for (int chunkPosition = 0;
chunkPosition < length;
chunkPosition += blockSize)
{
int chunkSize = Math.Min(blockSize, length - chunkPosition);
cipherTextBytes.AddRange(eng.ProcessBlock(
plainTextBytes, chunkPosition, chunkSize
));
}
return Convert.ToBase64String(cipherTextBytes.ToArray());
}
Call methods:
void Main()
{
var aesKey = GenerateAesKey();
var encryptData = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
securePayload = CreateSecurePayload(aesKey),
secureKey = SecureKey(aesKey)
});
}
I have a problem. Service does not decrypt my data with public key. I upload public key earlier in service.
Could you help me? Thanks
And I have examples of how I can encrypt data but in other languages:
I got the example, but on JS. I think I have a problem with IV, because I don`t send it
Here is the class that help you to perform Encryption/Decryption:
public static class DecryptionHelper
{
private static string EncryptionDecryptionKey = "your_key";
public static string Encrypt(string Text)
{
//var key = GenerateKey();
var key = Encoding.UTF8.GetBytes(EncryptionDecryptionKey);
var plainText = Text;
var encryptedData = EncryptStringToBytes(key, plainText);
return Convert.ToBase64String(encryptedData);
}
public static string Decrypt(string Text)
{
//var key = GenerateKey();
var key = Encoding.UTF8.GetBytes(EncryptionDecryptionKey);
byte[] encryptedData = Convert.FromBase64String(Text);
var decryptedData = DecryptBytesToString(key, encryptedData);
return decryptedData;
}
private static string DecryptBytesToString(byte[] key, byte[] data)
{
// IV was prepended to the encrypted bytes so peel that off
Tuple<byte[], byte[]> splitResult = SplitByteArray(data);
byte[] iv = splitResult.Item1;
byte[] cipherText = splitResult.Item2;
// Declare the string used to hold the decrypted text.
string plaintext;
// Create an RijndaelManaged object
// with the specified key and IV.
using (var aes = CreateAes256Algorithm())
{
aes.Key = key;
aes.IV = iv;
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
// Create the streams used for decryption.
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
private static Tuple<byte[], byte[]> SplitByteArray(byte[] data)
{
byte[] first = new byte[16];
Buffer.BlockCopy(data, 0, first, 0, first.Length);
byte[] second = new byte[data.Length - first.Length];
Buffer.BlockCopy(data, first.Length, second, 0, second.Length);
return Tuple.Create(first, second);
}
private static byte[] GenerateKey()
{
using (var aes = CreateAes256Algorithm())
{
aes.GenerateKey();
return aes.Key;
}
}
private static RijndaelManaged CreateAes256Algorithm()
{
return new RijndaelManaged { KeySize = 256, BlockSize = 128 };
}
private static byte[] EncryptStringToBytes(byte[] key, string plainText)
{
byte[] encrypted;
byte[] iv;
// Create an RijndaelManaged object with the specified key and IV.
using (var aes = CreateAes256Algorithm())
{
aes.Key = key;
aes.GenerateIV();
iv = aes.IV;
// Create a encrytor to perform the stream transform.
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
// Create the streams used for encryption.
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
// convert stream to bytes
encrypted = msEncrypt.ToArray();
}
}
}
// Prepend the iV to the encrypted bytes
return CombineByteArrays(iv, encrypted);
}
private static byte[] CombineByteArrays(byte[] first, byte[] second)
{
byte[] ret = new byte[first.Length + second.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
return ret;
}
}
Then to use it like:
Keys.FacebookClientId = DecryptionHelper.Decrypt(FacebookClientId);
using System;
using System.Text;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Encodings;
using System.Security.Cryptography;
using System.IO;
public static string CreateSecureLoad(string unencryptedPayload, ref byte[] generatedAesKey)
{
// This method generates and returns a secure payload
RijndaelManaged cryptoAlgo = new RijndaelManaged
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.ECB,
KeySize = 128,
BlockSize = 128
};
generatedAesKey = cryptoAlgo.Key;
var clearTextArray = Encoding.UTF8.GetBytes(unencryptedPayload);
var encryptor = cryptoAlgo.CreateEncryptor();
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(
msEncrypt,
encryptor,
CryptoStreamMode.Write))
{
csEncrypt.Write(clearTextArray);
csEncrypt.FlushFinalBlock();
var cipher = msEncrypt.ToArray();
return Convert.ToBase64String(cipher);
}
}
}
public static string CreateSecureKey(byte[] aesKey, string privateKeyPEM)
{
// This method generates and returns a secure key
// Accepts the string contents of the private key PEM file as input
var encryptEngine = new Pkcs1Encoding(new RsaEngine());
using (var textReader = new StringReader(privateKeyPEM))
{
var pemReader = new PemReader(textReader);
var keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
encryptEngine.Init(true, keyPair.Private);
}
var encrypted = Convert.ToBase64String(
encryptEngine.ProcessBlock(
aesKey,
0,
aesKey.Length));
return encrypted;
}
static void Main(string[] args)
{
String payload = "some json";
byte[] generatedAesKey = new byte[16];
var privateKeyPEM = File.ReadAllText("privatekey.pem");
var securePayload = CreateSecureLoad(payload, ref generatedAesKey);
var secureKey = CreateSecureKey(generatedAesKey, privateKeyPEM);
// Return encrypted key
Console.WriteLine("secureKey: " + secureKey);
// Return encrypted payload
Console.WriteLine("securePayload: " + securePayload);
Console.ReadLine();
}
}
encryption in this way works fine but when i try to use Decrypt it gives me padding Error i don't know why ?? Here is main Method and used Key & IV Value.
& BaseEncryptor Class Where i Use Encryption & Decryption Method
I tried uesing every type in padding but it also doesn't work.I tried to change block size and key size it also doesn't work.
static void Main(string[] args)
{
string key = "ldm_encrypt_code1234567891234567";
string IV = "9876897123651785";
string encstr = BaseEncryptor.EncryptUsingAes(Encoding.UTF8.GetBytes(#"Hello Code"), Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(IV)); //Encryption
string xc=BaseEncryptor.Decrypt(Encoding.UTF8.GetBytes(encstr), Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(IV)); //Decryption way
}
public class BaseEncryptor
{
public static string EncryptUsingAes(byte[] inputTextByte, byte[] privateKeyByte, byte[] sharedIVKeyByte)
{
using (var aesEncryption = AesEncryptionType(privateKeyByte, sharedIVKeyByte))
{
// Convert string to byte array
byte[] dest = new byte[inputTextByte.Length];
// encryption
using (ICryptoTransform encrypt = aesEncryption.CreateEncryptor(aesEncryption.Key, aesEncryption.IV))
{
dest = encrypt.TransformFinalBlock(inputTextByte, 0, inputTextByte.Length);
encrypt.Dispose();
}
return BitConverter.ToString(dest).Replace("-", "");
}
}
public static AesCryptoServiceProvider AesEncryptionType(byte[] privateKeyByte, byte[] sharedIVKeyByte)
{
//used in both encryption & Decryption
var aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = sharedIVKeyByte;
aes.Key = privateKeyByte;
aes.Mode = CipherMode.CBC; //Mode
aes.Padding = PaddingMode.PKCS7; //Padding not working in case of none or Zeros
return aes;
}
public static string DecryptUsingAes(byte[] inputTextByte, byte[] privateKeyByte, byte[] sharedIVKeyByte)
{
using (var aesDecryption = AesEncryptionType(privateKeyByte, sharedIVKeyByte))
{
// Convert string to byte array
byte[] dest = new byte[inputTextByte.Length];
// encryption
using (ICryptoTransform decrypt = aesDecryption.CreateDecryptor(aesDecryption.Key, aesDecryption.IV))
{
dest = decrypt.TransformFinalBlock(inputTextByte, 0, inputTextByte.Length);
decrypt.Dispose();
}
// Convert byte array to UTF8 string
return Encoding.UTF8.GetString(dest); ;
}
}
public static string Decrypt(byte[] cipherText, byte[] Key, byte[] IV)
{
string plaintext = null;
// Create AesManaged
using (var aesDecryption = AesEncryptionType(Key, IV))
{
// Create a decryptor
// Create the streams used for decryption.
using (ICryptoTransform decryptor = aesDecryption.CreateDecryptor(Key, IV))
{
string result;
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
result = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}
}
I try to build simple AES encryption helper to encrypt/decrypt some strings
Fist, I have an issue with Padding mode wherein decryption it only accepts if Zero otherwise an error about padding occurs!
The second issue is when I try to encrypt simple string "Hello World," it got encrypted, and I have the base64 string, but when trying to decrypt, there's no error, but a weird unknown character is shown! like 㡲啁䎰廾ử靱㡲啁䎰廾ử靱
My code:
private static int keySizes = 256;
private static int blockSize = 128;
private static PaddingMode pMode = PaddingMode.Zeros;
private static CipherMode cMode = CipherMode.ECB;
private static byte[] key = GenEncryptionKey();
private const string passphrase = #"StartYourMorningWithASmile";
private static byte[] GenEncryptionKey()
{
HashAlgorithm hash = MD5.Create();
return hash.ComputeHash(Encoding.Unicode.GetBytes(passphrase));
}
private static AesManaged CreateCryptor()
{
AesManaged cryptor = new AesManaged();
cryptor.KeySize = keySizes;
cryptor.BlockSize = blockSize;
cryptor.Padding = pMode;
cryptor.Key = key;
cryptor.Mode = cMode;
cryptor.GenerateIV();
return cryptor;
}
public static string EncryptParams(string reqVal)
{
string cipherText = "";
if (string.IsNullOrEmpty(reqVal) || reqVal.Length < 1)
throw new ArgumentNullException();
byte[] plainBytes = Encoding.Unicode.GetBytes(reqVal);
using (var cryptor = CreateCryptor())
{
ICryptoTransform encryptor = cryptor.CreateEncryptor();
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(plainBytes, 0, plainBytes.Length);
}
byte[] cipherBytes = ms.ToArray();
cipherText = Convert.ToBase64String(cipherBytes);
}
cryptor.Clear();
}
return cipherText;
}
public static string DecryptParams(string resVal)
{
var data = Convert.FromBase64String(resVal);
byte[] cipherBytes = new byte[data.Length];
string plainText = "";
using (var crypto = CreateCryptor())
{
ICryptoTransform Dec = crypto.CreateDecryptor();
using (MemoryStream ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
plainText = Encoding.Unicode.GetString(ms.ToArray());
}
}
crypto.Clear();
}
return plainText;
}
UPDATE 1:
Please set also the IV yourself to achieve successful decryption, as #maarten-bodewes pointed out. I missed that part and the decryption somehow worked (?) with your existing code, but you always should provide the same key and IV to a symmetric encryption algorithm to have it work both ways.
ORIGINAL ANSWER:
Your decryption fails (produces incorrect results) because you implemented the decryption part incorrectly (by using CryptoStreamMode.Write instead of CryptoStreamMode.Read) and besides feeding the decryption stream all zero bytes
At the point of execution of
cs.Write(cipherBytes, 0, cipherBytes.Length);
the variable cipherBytes is all zero. The real encrypted buffer is in the data variable which you only use to set the length of cipherBytes
So change your decryption method to this.
BONUS: After correcting the decryption part, you can specify the padding as you wish! I tested with PKCS7 and it is ok.
public static string DecryptParams(string resVal)
{
var cipherBytes = Convert.FromBase64String(resVal);
string plainText = "";
using (var crypto = CreateCryptor())
{
ICryptoTransform Dec = crypto.CreateDecryptor();
using (MemoryStream ms = new MemoryStream(cipherBytes))
{
using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Read))
{
byte[] decryptBlock = new byte[4096];
MemoryStream decryptStream = new MemoryStream();
int readBytes;
while ((readBytes = cs.Read(decryptBlock, 0, 4096)) > 0)
{
decryptStream.Write(decryptBlock, 0, readBytes);
}
plainText = Encoding.Unicode.GetString(decryptStream.ToArray());
}
}
crypto.Clear();
}
return plainText;
}
Hope this helps.
Thanks to Oguz
Below is my description method after edit
public static string DecryptParams(string resVal)
{
var data = Convert.FromBase64String(resVal);
byte[] cipherBytes = new byte[data.Length];
string plainText = "";
using (var crypto = CreateCryptor())
{
ICryptoTransform Dec = crypto.CreateDecryptor();
using (MemoryStream ms = new MemoryStream(data))
{
using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Read))
{
cs.Read(cipherBytes, 0, cipherBytes.Length);
plainText = Encoding.Unicode.GetString(cipherBytes.ToArray());
}
}
crypto.Clear();
}
return plainText;
}
one more thing about the return result after the decryption I got the original string plus \0\0\0\0 so I use myString.TrimEnd('\0') to solve that.
I am trying to implement image steganography with LSB and everything works except decrypting.
There is my class responsible for encryption and decryption of strings below. Encrypting works fine but Decrypt method always returns null:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApp1
{
class Encryptor {
//text to encrypt or already decrypted
private String decryptedText = "";
//text to decrypt or already encrypted
private String encryptedText = "";
private String key = "";
public Encryptor setDecryptedText(String text)
{
decryptedText = text;
return this;
}
public Encryptor setEncryptedText(String text)
{
encryptedText = text;
return this;
}
public Encryptor setKey(String text)
{
key = text;
return this;
}
Byte[] getHash(Byte[] hash)
{
Byte[] newHash = new Byte[32];
for (int i = 0; i < 32; i++)
{
newHash[i] = hash[i];
}
return newHash;
}
Byte[] getIV(Byte[] hash)
{
Byte[] newHash = new Byte[16];
int j = 0;
for (int i = 32; i < 48; i++)
{
newHash[j++] = hash[i];
}
return newHash;
}
String EncryptAesManaged()
{
SHA512 shaM = new SHA512Managed();
Byte[] data = Encoding.UTF8.GetBytes(key);
Byte[] hash = shaM.ComputeHash(data);
try
{
return Encrypt(decryptedText, getHash(hash), getIV(hash));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
String DecryptAesManaged()
{
SHA512 shaM = new SHA512Managed();
var data = Encoding.UTF8.GetBytes(key);
Byte[] hash = shaM.ComputeHash(data);
try
{
return Decrypt(Convert.FromBase64String(encryptedText), getHash(hash), getIV(hash));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return "";
}
String Encrypt(string plainText, byte[] Key, byte[] IV)
{
Byte[] encrypted;
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs)) {
sw.Write(Encoding.UTF8.GetBytes(plainText));
cs.FlushFinalBlock();
encrypted = ms.ToArray();
}
}
}
aes.Clear();
}
return Convert.ToBase64String(encrypted);
}
string Decrypt(byte[] cipherText, byte[] Key, byte[] IV)
{
string plaintext = null;
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform decryptor = aes.CreateDecryptor(Key, IV);
try
{
using (MemoryStream ms = new MemoryStream(cipherText))
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (StreamReader reader = new StreamReader(cs))
{
plaintext = reader.ReadToEnd(); //Here get null
}
aes.Clear();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return plaintext;
}
public String getEncrypted()
{
return EncryptAesManaged();
}
public String getDecrypted()
{
return DecryptAesManaged();
}
}
}
Why is Decrypt() returning null rather than the originally encrypted string?
You don't show how you use your Encryptor class, so your question doesn't quite include a Minimal, Complete, and Verifiable example. I was able to reproduce the problem with the following test harness:
public static void Test()
{
var key = "my key";
var plainText = "hello";
var encryptor = new Encryptor();
encryptor.setDecryptedText(plainText);
encryptor.setKey(key);
var encrypted = encryptor.getEncrypted();
Console.WriteLine(encrypted);
var deecryptor = new Encryptor();
deecryptor.setEncryptedText(encrypted);
deecryptor.setKey(key);
var decrypted = deecryptor.getDecrypted();
Console.WriteLine(decrypted);
Assert.IsTrue(plainText == decrypted);
}
Demo fiddle #1 here.
Given that, your code has 2 problems, both of which are actually in encryption rather than decryption.
Firstly, in Encrypt(string plainText, byte[] Key, byte[] IV), you are writing to the StreamWriter sw, then flushing the CryptoStream and returning the MemoryStream contents -- but you never flush or dispose sw, so its buffered contents are never forwarded to the underlying stream(s).
To fix this, your code should looks something like:
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(Encoding.UTF8.GetBytes(plainText));
}
}
encrypted = ms.ToArray();
}
Now getDecrypted() no longer returns a null result -- but instead returns a wrong result of "System.Byte[]", as shown in demo fiddle #2 here.
Secondly, again in Encrypt(...), you are effectively encoding your plainText twice at this line:
sw.Write(Encoding.UTF8.GetBytes(plainText));
Encoding.UTF8.GetBytes(plainText) converts the plain text to a byte array, but the StreamWriter is also intended to do this job, converting strings to bytes and passing them to the underlying stream. So, since you are not passing a string to Write(), the overload that gets called is StreamWriter.Write(Object):
Writes the text representation of an object to the text string or stream by calling the ToString() method on that object.
Thus what actually gets encrypted is the ToString() value of a byte array, which is "System.Byte[]".
To fix this, simply remove the call to Encoding.UTF8.GetBytes(plainText) and write the string directly. Thus your Encrypt() method should now look like:
static String Encrypt(string plainText, byte[] Key, byte[] IV)
{
string encrypted;
using (var aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write, true))
{
using (var sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
}
// Calling GetBuffer() avoids the extra allocation of ToArray().
encrypted = Convert.ToBase64String(ms.GetBuffer(), 0, checked((int)ms.Length));
}
aes.Clear();
}
return encrypted;
}
Demo fiddle #3 here that now passes successfully.
Disclaimer: this answer does not attempt to to review your code for security best practices such as secure setup of salt and IV.
So, I am having an issue with decrypting the decoded base64 aes string. Is this possible? I wrote a small console program to work this out but no luck. Here is my example:
As depicted, I have successfully converted the base64 back the aes encrypted string, but when I try to decrypt it I get more junk. If a code snippet is need let me. Thank you all for your help :)
UPDATE: Code snippet for decrypting method
static void Main(string[] args)
{
string plainText;
string decrypted;
string decryptedFromB64EncodedDecoded;
string fromBase64ToEncryptedText;
string encryptedText;
string encryptedTextBase64;
byte[] encryptedBytes;
byte[] encryptedBytes2;
byte[] encryptedBytesBase64;
RijndaelManaged crypto = new RijndaelManaged();
UTF8Encoding UTF = new UTF8Encoding();
Console.WriteLine("Please put in the text to be encrypted.");
plainText = Console.ReadLine();
try
{
encryptedBytes = encrypt(plainText, crypto.Key, crypto.IV);
encryptedText = Encoding.ASCII.GetString(encryptedBytes);
//encryptedBytes2 = Encoding.ASCII.GetBytes(encryptedText);
encryptedTextBase64 = toBase64String(encryptedText);
encryptedBytesBase64 = fromBase64String(encryptedTextBase64);
fromBase64ToEncryptedText = Encoding.ASCII.GetString(encryptedBytesBase64);
encryptedBytes2 = Encoding.ASCII.GetBytes(fromBase64ToEncryptedText);
decrypted = decrypt(encryptedBytes, crypto.Key, crypto.IV);
decryptedFromB64EncodedDecoded = decrypt(encryptedBytes2, crypto.Key, crypto.IV);
Console.WriteLine("Start: {0}", plainText);
Console.WriteLine("Encrypted: {0}", encryptedText);
Console.WriteLine("Encrypted Base64: {0}", encryptedTextBase64);
Console.WriteLine("From Base64 To AES Encypted Text: {0}", fromBase64ToEncryptedText);
Console.WriteLine("Decrypted: {0}", decrypted);
Console.WriteLine("Decrypted From Encode and then Decode Base64 Text: {0}", decryptedFromB64EncodedDecoded);
}
catch (Exception ex)
{
Console.WriteLine("Exception: {0}", ex.Message);
}
Console.ReadLine();
}
public static string decrypt (byte[] textToDecrypt, byte[] key, byte[] IV)
{
RijndaelManaged crypto = new RijndaelManaged();
MemoryStream stream = new MemoryStream(textToDecrypt) ;
ICryptoTransform decryptor = null;
CryptoStream cryptoStream = null;
StreamReader readStream = null;
string text = string.Empty;
try
{
crypto.Key = key;
crypto.IV = IV;
crypto.Padding = PaddingMode.None;
decryptor = crypto.CreateDecryptor(crypto.Key, crypto.IV);
cryptoStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Read);
//cryptoStream.Read(textToDecrypt, 0, textToDecrypt.Length);
readStream = new StreamReader(cryptoStream);
text = readStream.ReadToEnd();
cryptoStream.Close();
byte[] decodedValue = stream.ToArray();
return text;
}
catch (Exception)
{
throw;
}
finally
{
if (crypto != null)
{
crypto.Clear();
}
stream.Flush();
stream.Close();
}
}
public static byte[] encrypt(string text, byte[] key, byte[] IV)
{
RijndaelManaged crypto = null;
MemoryStream stream = null;
//ICryptoTransform is used to perform the actual decryption vs encryption, hash function are a version crypto transforms
ICryptoTransform encryptor = null;
//CryptoStream allows for encrption in memory
CryptoStream cryptoStream = null;
UTF8Encoding byteTransform = new UTF8Encoding();
byte[] bytes = byteTransform.GetBytes(text);
try
{
crypto = new RijndaelManaged();
crypto.Key = key;
crypto.IV = IV;
stream = new MemoryStream();
encryptor = crypto.CreateEncryptor(crypto.Key, crypto.IV);
cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(bytes, 0, bytes.Length);
}
catch (Exception)
{
throw;
}
finally
{
if (crypto != null)
{
crypto.Clear();
}
cryptoStream.Close();
}
return stream.ToArray();
}
public static string toBase64String(string value)
{
UTF8Encoding UTF = new UTF8Encoding();
byte[] myarray = UTF.GetBytes(value);
return Convert.ToBase64String(myarray);
}
public static byte[] fromBase64String(string mystring)
{
//UTF8Encoding UTF = new UTF8Encoding();
//byte[] myarray = UTF.GetBytes(value);
return Convert.FromBase64String(mystring);
}
I don't know how you're decrypting but before you decrypt, you should convert the base 64 string to a byte array before sending it into the decryption.
byte[] encryptedStringAsBytes = Convert.FromBase64String(base64EncodedEncryptedValue);
Then with the byte array you can pass to the CryptoStream via a MemoryStream.
UPDATE
I believe the issue is how you're setting up your streams
using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
{
rijndaelManaged.Padding = paddingMode;
rijndaelManaged.Key = key;
rijndaelManaged.IV = initVector;
MemoryStream memoryStream = null;
try
{
memoryStream = new MemoryStream(valueToDecrypt);
using (ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader(cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
finally
{
if (memoryStream != null)
memoryStream.Dispose();
}
}
UPDATE 2
This is how you should basically perform the steps.
To encrypt
Encode your plain text string using the Encoding.GetBytes(stringToEncrypt)
pass the byte[] into the crypto API (via memory stream, etc.)
get the bytes from the encrypted stream and encode the results as Base64
To Decrypt (do the reverse)
Convert the base64 encoded string to bytes using Convert.FromBase64String(base64EncodedEncryptedValue)
pass that byte array into your decryption function above
Try:
encryptedBytes2 = Encoding.ASCII.GetBytes(encryptedText);
Based on your comment. The bytes are just that bytes, so in order to decrypt the ciphertext you need to undo any encoding or series of encodings you have done.
If you really want to go from Encrypted Bytes -> Base64String -> ASCII string -> then decrypt that ASCII string? you would need to base64 decode the ascii string then convert that string to bytes using
Encoding.ASCII.GetBytes(yourdecodedstring);
Note that base 64 decoding is not the same as using Convert.FromBase84String.