I have a Security class that Encode and Decode string, but when I try do decode - something going wrong.
Here is my Security class:
class Security
{
public static String encrypt(String imput, String key)
{
String cipherText;
var rijndael = new RijndaelManaged()
{
Key = Encoding.Unicode.GetBytes(key),
Mode = CipherMode.ECB,
BlockSize = 128,
Padding = PaddingMode.Zeros,
};
ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, null);
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
using (var streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(imput);
streamWriter.Flush();
}
cipherText = Convert.ToBase64String(memoryStream.ToArray());
}
}
return cipherText;
}
public static String decrypt(String imput, String key)
{
byte[] data = Convert.FromBase64String(imput);
String decrypted;
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Encoding.UTF8.GetBytes(key);
rijAlg.Mode = CipherMode.ECB;
rijAlg.BlockSize = 128;
rijAlg.Padding = PaddingMode.Zeros;
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, null);
using (MemoryStream msDecrypt = new MemoryStream(data))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
decrypted = srDecrypt.ReadToEnd();
}
}
}
}
return decrypted;
}
}
In program.cs:
String A = Security.encrypt("text", "1234567891234567");
A = Security.decrypt(A, "1234567891234567");
Finaly it return something like that: �%����;\0�\a��f6 , but I need original string. Where I made a mistake?
Use the same encoding in both methods, either Encoding.Unicode or Encoding.UTF8
Related
Sonarlint is warning me a bout a critical security risk on my encrypt routines
I don't understand why it triggers the first aes.CreateEncryptor(aes.Key, aes.IV); but not the second
Sonar gives me an example on how to fix it, but if the IV is generated randomly, how do I get it back in the decrypt part ?
and why is the sonar example called Encrypt() and not generateRandomIV() ?
I found these on SO I believe
Can someone help me out?
public static string EncryptString(string plainText, string key)
{
byte[] iv = new byte[16];
byte[] array;
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream))
{
streamWriter.Write(plainText);
}
array = memoryStream.ToArray();
}
}
}
return Convert.ToBase64String(array);
}
public static string DecryptString(string cipherText, string key)
{
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();
}
}
}
}
}
sonar example:
public byte[] Encrypt(byte[] key, byte[] data, MemoryStream target)
{
using var aes = new AesCryptoServiceProvider();
var encryptor = aes.CreateEncryptor(key, aes.IV); // aes.IV is automatically generated to random secure value
using var cryptoStream = new CryptoStream(target, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(data);
return aes.IV;
}
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);
}
I am building a application that can encrypt and decrypt files, in c#. The encryption seems like its working (I think its working) however the decryption gives me the exception "The input data is not a complete block." I have tried almost everything I could find online so I thought I should come here. Here is the decryption code:
static void decryptAES (/*byte[] buffer,*/string filePath,byte[] key, byte[] IV)
{
Console.WriteLine("1");
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.Padding = PaddingMode.PKCS7;
AES.Key = key;
AES.BlockSize = 128;
AES.KeySize = 128;
AES.IV = IV;
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
using (ICryptoTransform crypt = AES.CreateDecryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(crStream))
{
//breaks here
string data = reader.ReadToEnd();
File.WriteAllText(filePath, data);
File.Move(filePath, filePath.Replace(".encrypted", ""));
}
}
}
}
}
}
It breaks on the line with the comment //breaks here by the way.
Thanks.
Here is the encrypt function
static void encryptAES(byte[] filesBytes,string
filePath,AesCryptoServiceProvider aes)
{
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
using (ICryptoTransform crypt = aes.CreateEncryptor(aes.Key, aes.IV))
{
using (CryptoStream csStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Write))
{
csStream.Write(filesBytes, 0, filesBytes.Length);
}
try { File.Move(filePath, filePath + ".encrypted"); }
catch (UnauthorizedAccessException)
{
}
}
}
}
And here is the key generation:
static AesCryptoServiceProvider generateAES()
{
AesCryptoServiceProvider a = new AesCryptoServiceProvider();
a.Padding = PaddingMode.PKCS7;
a.BlockSize =128;
a.KeySize = 128;
a.GenerateIV();
a.GenerateKey();
return a;
}
Here is how I stored the IV and AES Key:
private static void dumpKeys(AesCryptoServiceProvider aes)
{
foreach (byte b in aes.Key)
{
Console.Write(b);
}
Console.WriteLine();
foreach (byte b in aes.IV)
{
Console.Write(b);
}
byte[] encryptedKey = encryptRSA(aes.Key);
byte[] encryptedIV = encryptRSA(aes.IV);
Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys");
File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys\0000000000000.Key", encryptedKey);
File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys\1111111111111.IV", encryptedIV);
}
And here is how I retrieve the key and iv data:
byte[] AESKey = decrypt(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys\0000000000000.Key");
byte[] AESIV = decrypt(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Keys\1111111111111.IV");
static byte[] decrypt(string path)
{
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
RSA.FromXmlString(Properties.Resources.privateKey);
byte[] unencrypted = RSA.Decrypt(File.ReadAllBytes(path), true);
foreach (byte b in unencrypted)
{
Console.Write(b);
}
Console.WriteLine();
return unencrypted;
}
}
Btw I store a public RSA key in my resources file and I use that to decrypt the key.
Thanks
So far, so good. Do you extract the generated Key and IV? I modified your decryption function to an encryption function...
public static void Main()
{
var f = #"q:\test.txt";
AesCryptoServiceProvider AES = new AesCryptoServiceProvider();
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.BlockSize = 128;
AES.KeySize = 128;
AES.GenerateKey();
AES.GenerateIV();
var key = AES.Key;
var iv = AES.IV;
encryptAES(AES, f, key, iv);
decryptAES(AES, f + ".encrypted", key, iv);
}
static void encryptAES(SymmetricAlgorithm algo, string filePath, byte[] key, byte[] IV)
{
using (FileStream fin = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (FileStream fout = new FileStream(filePath + ".encrypted", FileMode.OpenOrCreate, FileAccess.Write))
{
using (ICryptoTransform crypt = algo.CreateEncryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fout, crypt, CryptoStreamMode.Write))
{
fin.CopyTo(crStream);
}
}
}
}
}
static void decryptAES(SymmetricAlgorithm algo, string filePath, byte[] key, byte[] IV)
{
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (ICryptoTransform crypt = algo.CreateDecryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(crStream))
{
string data = reader.ReadToEnd();
File.WriteAllText(filePath.Replace(".encrypted", ".restored"), data);
}
}
}
}
}
Tested it with your code, slightly modified (changed FileMode.Open to FileMode.OpenOrCreate, Added File.Delete before File.Move and merged File.WriteAllText with File.Move) and it works. So a) please review your code. b) If it still fails, provide more details, a single codeblock with every function and a Main-method that calls your functions to reproduce your failure...
static AesCryptoServiceProvider generateAES()
{
AesCryptoServiceProvider a = new AesCryptoServiceProvider();
a.Padding = PaddingMode.PKCS7;
a.BlockSize = 128;
a.KeySize = 128;
a.GenerateIV();
a.GenerateKey();
return a;
}
static void encryptAES(byte[] filesBytes, string filePath, AesCryptoServiceProvider aes)
{
using (FileStream fStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (ICryptoTransform crypt = aes.CreateEncryptor(aes.Key, aes.IV))
{
using (CryptoStream csStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Write))
{
csStream.Write(filesBytes, 0, filesBytes.Length);
}
try {
File.Delete(filePath + ".encrypted");
File.Move(filePath, filePath + ".encrypted");
}
catch (UnauthorizedAccessException)
{
}
}
}
}
static void decryptAES(/*byte[] buffer,*/string filePath, byte[] key, byte[] IV)
{
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.Padding = PaddingMode.PKCS7;
AES.Key = key;
AES.BlockSize = 128;
AES.KeySize = 128;
AES.IV = IV;
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
using (ICryptoTransform crypt = AES.CreateDecryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(crStream))
{
//breaks here
string data = reader.ReadToEnd();
File.WriteAllText(filePath.Replace(".encrypted", ""), data);
}
}
}
}
}
}
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;
}
}
Please help me modify this code to encrypt/decrypt in blocks instead of huge byte arrays! the code that converts the file and calls the encryption class is:
Console.Write("Enter File Path: ");
docPath = Console.ReadLine();
extension = docPath.Substring(docPath.IndexOf(".")).Trim();
byte[] binarydata = File.ReadAllBytes(docPath);
text = System.Convert.ToBase64String(binarydata, 0, binarydata.Length);
var Encrypted = AESCryptography.Encrypt(text, m.ToString(), extension);
using (FileStream fs = File.Create(docPath.Substring(0,docPath.IndexOf(".")) + ".aent"))
{
Byte[] info = new UTF8Encoding(true).GetBytes(Encrypted);
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
And the class that does the actual encryption is this:
public static class AESCryptography
{
private const int keysize = 256;
public static string Encrypt(string plainText, string passPhrase, string extention)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
{
byte[] keyBytes = password.GetBytes(keysize / 8);
using (RijndaelManaged symmetricKey = new RijndaelManaged())
{
symmetricKey.GenerateIV();
symmetricKey.Mode = CipherMode.CBC;
using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, symmetricKey.IV))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
return Convert.ToBase64String(cipherTextBytes) + "\n" + Convert.ToBase64String(symmetricKey.IV) + "\n" + extention;
}
}
}
}
}
}
public static string Decrypt(string cipherText, string passPhrase, string initVector)
{
byte[] initVectorBytes = Convert.FromBase64String(initVector);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
{
byte[] keyBytes = password.GetBytes(keysize / 8);
using (RijndaelManaged symmetricKey = new RijndaelManaged())
{
symmetricKey.Mode = CipherMode.CBC;
using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
}
}
}
I need the encryption class to be able to encrypt files as big as ~2.5GB.
I have tried multiple times, most didn't work others didn't even encrypt!
Please Help! I need to present this tomorrow!
You can 'chain' streams to encrypt large files, so you don't need to hold them in memory.
See answer from anton-gogolev https://stackoverflow.com/a/38629596/1776231 for question AES-Encrypt-then-MAC a large file with .NET
using(var encryptedFileStream = File.OpenWrite("..."))
using(var macCryptoStream = new CryptoStream(encryptedFileStream, mac, CryptoStreamMode.Write))
using(var encryptCryptoStream = new CryptoStream(macCryptoStream, encryptor, CryptoStreamMode.Write))
using(var inputFileStream = File.OpenRead("..."))
inputFileStream.CopyTo(encryptCryptoStream);