I have recently been experimenting with the "CryptoStream", and ran into the idea of encrypting & decrypting a text via. the Aes class. 'Namespace: System.Security.Cryptography'
After making a function that succesfully encrypted a text using two input parameters: Text, Password
static byte[] Salt = { 18,39,27,48,82,32,12,92 };
public static string EncryptAES(string txt, string Password) {
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(Password, Salt);
RijndaelManaged RJM = new RijndaelManaged();
RJM.Key = rfc.GetBytes(RJM.KeySize / 8);
ICryptoTransform ICT = Aes.Create().CreateEncryptor(RJM.Key, RJM.IV);
using (MemoryStream MS = new MemoryStream()) {
using (CryptoStream CS = new CryptoStream(MS, ICT, CryptoStreamMode.Write)) {
using (StreamWriter SW = new StreamWriter(CS)) {
SW.Write(txt);
}
}
return Convert.ToBase64String(MS.ToArray());
}
}
The issue of decrypting the text took place.
My attempt of decrypt the text was the following:
public static string DecryptAES(string EncryptedTxt, string Password) {
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(EncryptedTxt, Salt);
RijndaelManaged RJM = new RijndaelManaged();
RJM.Key = rfc.GetBytes(RJM.KeySize / 8);
ICryptoTransform ICT = Aes.Create().CreateDecryptor(RJM.Key, RJM.IV);
using (MemoryStream MS = new MemoryStream(Convert.FromBase64String(EncryptedTxt))) {
using (CryptoStream CS = new CryptoStream(MS, ICT, CryptoStreamMode.Read)) {
using (StreamReader SR = new StreamReader(CS)) {
return SR.ReadToEnd();
}
}
}
However; it appears that my way of converting the memorystream to string and then back was invaild, as I get the following error: Error: Value cannot be null\nParameter name: inputBuffer
The error occurs at using (MemoryStream MS = new MemoryStream(Convert.FromBase64String(EncryptedTxt)))
How can I converter the MemoryStream into string and back?
Thanks in advance :-)
Related
I have an encryption algorithm and decryption algorithm used for a login page. When encrypting, everything seems fine and seems to encrypt everything as expected, but when the encrypted password is put back through my decryption algorithm, only the first character is returned.
Example
Here is the code:
public string encrypt(string key, string data)
{
byte[] clearBytes = Encoding.Unicode.GetBytes(data);
byte[] iv = new byte[16];
using (Aes encryptor = Aes.Create())
{
encryptor.Key = Encoding.UTF8.GetBytes(key);
encryptor.IV = iv;
encryptor.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
data = Convert.ToBase64String(ms.ToArray());
}
}
return data;
}
public static string decryptData(string key, string data)
{
byte[] iv = new byte[16];
byte[] clearBytes = Convert.FromBase64String(data);
using (Aes decrpytor = Aes.Create())
{
decrpytor.Key = Encoding.UTF8.GetBytes(key);
decrpytor.IV = iv;
ICryptoTransform decryptor = decrpytor.CreateDecryptor(decrpytor.Key, decrpytor.IV);
decrpytor.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream(clearBytes))
{
using (CryptoStream cs = new CryptoStream((Stream)ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader((Stream)cs))
{
return sr.ReadToEnd();
}
}
}
}
}
public void button1_Click(object sender, EventArgs e)
{
var key = "b14ca5898a4e4133bbce2ea2315a1916";
var str = passWord.Text;
var encryptedPassword = encrypt(key, str);
var decrpted = decryptData(key, encryptedPassword);
passwordTest.Text = encryptedPassword;
decryptedtest.Text = decrpted;
}
the last 2 lines are purely for testing to see what they output.
Any help is appreciated.
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.
i am trying to create a web service which needs to return data in AES 128 encryption format. Someone please help me, how can i achieve this.
thanks in advance.
public class EncryptionAES128
{
static public string EncryptString(string inputString, string key)
{
string output = "";
Rijndael encryption = new RijndaelManaged();
try
{
encryption.IV = GenerateIV();
encryption.Key = StringToByte(key);
ICryptoTransform encryptor = encryption.CreateEncryptor(encryption.Key, encryption.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(inputString);
}
byte[] cipherText = msEncrypt.ToArray();
byte[] encrypted = new byte[cipherText.Length + encryption.IV.Length];
encryption.IV.CopyTo(encrypted, 0);
cipherText.CopyTo(encrypted, IV_LENGTH);
output = ByteToString(encrypted);
}
}
}
catch (Exception ex)
{
throw ex;
}
return output;
Scenario - I have multiple files on my server and as per policy we can keep only encrypted files. We are doing some data migration, for this we have to move these files on to cloud and as per documentations Base64 is the best way to transfer encrypted data over network. I am new in encryption and stuck between this. Let me know if this help you.
How to save file in base64 format?
================================================================
I am new in Encryption and got below code from net and trying to encrypting files using RijndaelManaged and the following code is working fine
public static void EncryptFile(string inputFile, string outputFile)
{
try
{
string password = #"myKey123"; // Your Key Here
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
catch
{
}
}
When I try to decrypt using Convert.FromBase64String, it returns an error
public static string DecryptFile(string inputFile)
{
var myRijndael = new RijndaelManaged { Key = _key, IV = _key, Padding = PaddingMode.PKCS7 };
_decryptor = myRijndael.CreateDecryptor(myRijndael.Key, myRijndael.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(inputFile)))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, _decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
return srDecrypt.ReadToEnd();
}
}
}
}
Please help me to solve this issue
I'm trying to encrypt and decrypt a file using AES. The problem that I have is that when the file gets decrypted, it is broken and you can't open it. The original file has a length of 81.970 bytes and the decrypted file has a length of 81.984 bytes...so there are 14 bytes added for some reason. The problem could be in the way the file gets encrypted but I don't know what I'm doing wrong.
What am I missing here? Could it be the way I'm processing the password, the iv and the padding?
Thanks for your time!
This is the code I use to encrypt:
private AesManaged aesManaged;
private string filePathToEncrypt;
public Encrypt(AesManaged aesManaged, string filePathToEncrypt)
{
this.aesManaged = aesManaged;
this.filePathToEncrypt = filePathToEncrypt;
}
public void DoEncryption()
{
byte[] cipherTextBytes;
byte[] textBytes = File.ReadAllBytes(this.filePathToEncrypt);
using(ICryptoTransform encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(textBytes, 0, textBytes.Length);
cs.FlushFinalBlock();
cipherTextBytes = ms.ToArray();
}
File.WriteAllBytes("EncryptedFile.aes", cipherTextBytes);
}
This is the code I use to decrypt:
private AesManaged aesManaged;
private string filePathToDecrypt;
public Decrypt(AesManaged aesManaged, string filePathToDecrypt)
{
this.aesManaged = aesManaged;
this.filePathToDecrypt = filePathToDecrypt;
}
public void DoDecrypt()
{
byte[] cypherBytes = File.ReadAllBytes(this.filePathToDecrypt);
byte[] clearBytes = new byte[cypherBytes.Length];
ICryptoTransform encryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV);
using (MemoryStream ms = new MemoryStream(cypherBytes))
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Read))
{
cs.Read(clearBytes, 0, clearBytes.Length);
clearBytes = ms.ToArray();
}
File.WriteAllBytes("DecryptedFile.gif", clearBytes);
}
And here is how I call the functions:
string filePathToEncrypt = "dilbert.gif";
string filePathToDecrypt = "EncryptedFile.aes";
string password = "Password";
string passwordSalt = "PasswordSalt";
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(passwordSalt));
var aesManaged = new AesManaged
{
Key = deriveBytes.GetBytes(128 / 8),
IV = deriveBytes.GetBytes(16),
Padding = PaddingMode.PKCS7
};
Console.WriteLine("Encrypting File...");
var encryptor = new Encrypt(aesManaged, filePathToEncrypt);
encryptor.DoEncryption();
Thread.Sleep(300);
Console.WriteLine("Decrypting File...");
var decryptor = new Decrypt(aesManaged, filePathToDecrypt);
decryptor.DoDecrypt();
Thread.Sleep(300);
Try with:
public void DoEncryption()
{
byte[] cipherBytes;
byte[] textBytes = File.ReadAllBytes(this.filePathToEncrypt);
using (ICryptoTransform encryptor = aesManaged.CreateEncryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream input = new MemoryStream(textBytes))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
{
input.CopyTo(cs);
cs.FlushFinalBlock();
cipherBytes = output.ToArray();
}
File.WriteAllBytes("EncryptedFile.aes", cipherBytes);
}
and
public void DoDecrypt()
{
byte[] cypherBytes = File.ReadAllBytes(this.filePathToDecrypt);
byte[] textBytes;
using (ICryptoTransform decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV))
using (MemoryStream input = new MemoryStream(cypherBytes))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
{
cs.CopyTo(output);
textBytes = output.ToArray();
}
File.WriteAllBytes("DecryptedFile.gif", textBytes);
}
Note that the code could be modified to not use temporary byte[] and read/write directly to input/output streams.
In general you can't desume the length of the plaintext from the length of the cyphertext, so this line:
new byte[cypherBytes.Length]
was totally wrong.
And please, don't use Encoding.ASCII in 2016. It is so like previous century. Use Encoding.UTF8 to support non-english characters.
The answer may be very simple. I don't see where do u try to choose a cipher mode, so by default it probably takes CBC, as IV was inited. Then, 81.970 are padded by 14 bytes, to be divisible by 32. So when it happens, the memory you allocated was just 81.970, so the padding bytes doesn't write correctly, cause of some sort of memory leak, and when decrypt is started, unpadding doesn't work correctly.