I use this example from stackoverflow :
C# Encryption to PHP Decryption
GENERATE FUNCTION :
public static void GenerateKeyIV(out string key, out string IV)
{
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
key = Convert.ToBase64String(rj.Key);
IV = Convert.ToBase64String(rj.IV);
}
Encrypt 2 FUNCTION :
public static string Encrypt2(string prm_text_to_encrypt, string prm_key, string prm_iv)
{
var sToEncrypt = prm_text_to_encrypt;
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
var key = Encoding.ASCII.GetBytes(prm_key);
var IV = Encoding.ASCII.GetBytes(prm_iv);
//var key = Convert.FromBase64String(prm_key);
//var IV = Convert.FromBase64String(prm_iv);
var encryptor = rj.CreateEncryptor(key, IV);
var msEncrypt = new MemoryStream();
var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
var toEncrypt = Encoding.ASCII.GetBytes(sToEncrypt);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
var encrypted = msEncrypt.ToArray();
return (Convert.ToBase64String(encrypted));
}
MAIN PROGRAM :
Enc2.GenerateKeyIV(out key, out iv);
string encrypted_url = Enc2.Encrypt2("test tekst todo",key,iv);
Console.WriteLine(encrypted_url);
==> iv = cCJNWmwOtIBg6zM7Mz/JQV/lcauNMWf50nQk1ZiEKZ4=
==> key = gNDiEqWk7aGhj1+A2EURW5CPurxHPcfy3F2FTa4peC0=
==> System.Security.Cryptography.CryptographicException: Specified initialization vector (IV) does not match the block size for this algorithm.
==> the key and iv seem to be properly generated, I dont understand why I receive this error.
Check your encryption method Enc2.Encrypt2(). It may be using a different block size from what you specified in your IV generation method.
UPDATE:
Do this:
public static string Encrypt2(string prm_text_to_encrypt, string prm_key, string prm_iv)
{
var sToEncrypt = prm_text_to_encrypt;
var rj = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 256,
BlockSize = 256,
//FeedbackSize = 256
};
var key = Convert.FromBase64String(prm_key);
var IV = Convert.FromBase64String(prm_iv);
var encryptor = rj.CreateEncryptor(key, IV);
var msEncrypt = new MemoryStream();
var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
var toEncrypt = Encoding.ASCII.GetBytes(sToEncrypt);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
var encrypted = msEncrypt.ToArray();
return (Convert.ToBase64String(encrypted));
}
Related
I am rewriting some code to have a random IV that is prepended to my encrypted string. The encryption I think is correct (can't decrypt so I'm not 100% sure), but the problem is when I run the decrypt function, I get an exception
System.Security.Cryptography.CryptographicException: 'The input data is not a complete block.'
Below is the source code. Does anyone know where I'm going wrong? I think the error is in the binaryWritr.Write call, but after several iterations, I'm not making progress. Any help would be greatly appreciated!
public static string EncryptString(string inputText)
{
using(var aes = new AesCryptoServiceProvider() {
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
}) {
var input = Encoding.UTF8.GetBytes(inputText);
aes.GenerateIV();
var iv = aes.IV;
using(var encrypter = aes.CreateEncryptor(aes.Key, iv))
using(var cipherStream = new MemoryStream()) {
using(var tCryptoStream = new CryptoStream(cipherStream, encrypter, CryptoStreamMode.Write))
using(var tBinaryWriter = new BinaryWriter(tCryptoStream)) {
//Prepend IV to data
cipherStream.Write(iv, 0, iv.Length);
tBinaryWriter.Write(input);
tCryptoStream.FlushFinalBlock();
}
return Convert.ToBase64String(cipherStream.ToArray());
}
}
}
public static string DecryptString(string inputText)
{
var aes = new AesCryptoServiceProvider() {
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
};
//get first 16 bytes of IV and use it to decrypt
var iv = new byte[16];
Array.Copy(Encoding.ASCII.GetBytes(inputText), 0, iv, 0, iv.Length);
using(var ms = new MemoryStream()) {
using(var cs = new CryptoStream(ms, aes.CreateDecryptor(aes.Key, iv), CryptoStreamMode.Write))
using(var binaryWriter = new BinaryWriter(cs)) {
//Decrypt Cipher Text from Message
binaryWriter.Write(
Encoding.ASCII.GetBytes(inputText),
iv.Length,
inputText.Length - iv.Length
);
}
return Encoding.Default.GetString(ms.ToArray());
}
}
I have the following lines in a PHP 7 program encrypting/decrypting data:
$key = base64_decode("mykey===");
$iv = substr(hash('sha256', "myiv======"), 0, 16);
printf(base64_encode(openssl_encrypt("hello", "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv)));
printf("<br>");
printf(openssl_decrypt(base64_decode("2XJxQXSbPuJ9LMsZ/FESGw=="), "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv));
This is working, PHP decrypts "hello" to "2XJxQXSbPuJ9LMsZ/FESGw==" and vice versa. However I'm trying to decrypt and encrypt the same data (from a Database) with C# but can't seem to figure it out. I used the following method for decryption (C#):
private string aes_decrypt(string cipherText, string key, string iv)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
aes.Key = Convert.FromBase64String(key);
aes.IV = Encoding.UTF8.GetBytes(iv);
if (aes.Key.Length < 32)
{
var paddedkey = new byte[32];
Buffer.BlockCopy(aes.Key, 0, paddedkey, 0, aes.Key.Length);
aes.Key = paddedkey;
}
var decrypt = aes.CreateDecryptor();
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
byte[] xXml = Convert.FromBase64String(cipherText);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = ms.ToArray();
}
String Output = Encoding.UTF8.GetString(xBuff);
return Output;
}
But a call to this method:
string encryptionkey = "mykey===";
string encryptioniv = GenerateSHA256String("myiv======").Substring(0, 16);
string str = aes_decrypt("2XJxQXSbPuJ9LMsZ/FESGw==", encryptionkey, encryptioniv);
Console.WriteLine(#str);
returns: HellO++++??????+
The encryption method doesnt seem to work either (referenced online and modified):
private static String EncryptIt(String s, string akey, string aIV)
{
String result;
byte[] key = Convert.FromBase64String(akey);
byte[] IV = Encoding.UTF8.GetBytes(aIV);
RijndaelManaged rijn = new RijndaelManaged();
rijn.Mode = CipherMode.CBC;
rijn.Padding = PaddingMode.PKCS7;
rijn.KeySize = 256;
rijn.BlockSize = 128;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (ICryptoTransform encryptor = rijn.CreateEncryptor(key, IV))
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(s);
}
}
}
result = Convert.ToBase64String(msEncrypt.ToArray());
}
rijn.Clear();
return result;
}
A call to this method: EncryptIt("hello", encryptionkey, encryptioniv); returns ul0axDR0WWGcpeijPRNusg== and not 2XJxQXSbPuJ9LMsZ/FESGw== which was generated by PHP. Anyone knows what's wrong here?
For reference, I used these methods with the IV, they are working without errors:
private string GenerateSHA256String(string inputString)
{
SHA256 sha256 = SHA256Managed.Create();
byte[] bytes = Encoding.UTF8.GetBytes(inputString);
byte[] hash = sha256.ComputeHash(bytes);
return GetStringFromHash(hash);
}
private string GetStringFromHash(byte[] hash)
{
StringBuilder result = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
result.Append(hash[i].ToString("X2"));
}
return result.ToString();
}
Old question, but I ran into this again recently.
When using PHP 7.2 openssl_decrypt/openssl_encrypt padding as OPENSSL_RAW_DATA, it only worked for me when the chsarp AES padding was set to PaddingMode.PKCS7.
The original post has PaddingMode.None for decrypt and PaddingMode.PKCS7 for encrypt.
I had andriod code and I tried to convert it to c#. It's a simple Encryption class. But when I try to decrypt data with it I catch: Wrong algorithm: AES or Rijndael required.
Here is my converted code:
public static string decrypt(string data)
{
byte[] dataBytes = Convert.FromBase64String(data);
SecretKey secretKey = getSecretKey(hashTheKey("ABCD"));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(2, secretKey, new IvParameterSpec(new byte[16]),
SecureRandom.getInstance("SHA1PRNG"));
var x = cipher.doFinal(dataBytes);
return System.Text.Encoding.UTF8.GetString(x);
}
public static SecretKey getSecretKey(char[] key)
{
var secretKeyType = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
var secretkey = secretKeyType.generateSecret(new PBEKeySpec(key,
System.Text.Encoding.UTF8
.GetBytes("ABCD"),
100, 128)).getEncoded();
return new SecretKeySpec(secretkey, "AES/CBC/PKCS5Padding");
}
public static char[] hashTheKey(string key)
{
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(System.Text.Encoding.UTF8.GetBytes(key));
return Convert.ToBase64String(messageDigest.digest()).ToCharArray();
}
Here is my original android code:
private char[] hashTheKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(key.getBytes());
return Base64.encodeToString(messageDigest.digest(),
Base64.NO_PADDING).toCharArray();
}
private SecretKey getSecretKey(char[] key) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException {
return new SecretKeySpec(
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
.generateSecret(new PBEKeySpec(key,
"ABCD".getBytes("UTF8"),
100, 128)).getEncoded(), "AES");
}
public String decrypt(String data) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, InvalidKeySpecException {
byte[] dataBytes = Base64.decode(data, Base64.DEFAULT);
SecretKey secretKey = getSecretKey(hashTheKey("ABCD"));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(2, secretKey, new IvParameterSpec(new byte[16]),
SecureRandom.getInstance("SHA1PRNG"));
return new String(cipher.doFinal(dataBytes));
}
c# and java are using the same well-estabilished cryptography algorithms, but differs in approach how to invoke them. It is still possible to convert the code though.
One key point is difference in base64 encoding - C# always use padding.
Converted code goes like:
const int KeySize = 128;
static string HashTheKey(string key) {
String hashKey;
using (var sha = new SHA1Managed()) {
hashKey = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(key)));
}
// beware - you're on C# now so remove the padding and add the newline to match java
return hashKey.Replace("=", "") + "\n";
}
static byte[] GetSecretKey(string password) {
var salt = Encoding.UTF8.GetBytes("JVAaVhAiddKAaghraikhmaini");
using (var pass = new Rfc2898DeriveBytes(password, salt, 65536)) {
return pass.GetBytes(KeySize / 8);
}
}
static void Main(string[] args) {
string encrypted = "vtlkQHTz7/oz2weuAAkLz2Q5c2yj2LGukF7SHJjT+TA8oRLixTQSXQ7dG1O736hyT1HJxcz0P4DzzVaO5chWKKSJQ2uPEpDQJu/fZGguqDw=";
byte[] encryptedBytes = Convert.FromBase64String(encrypted);
using (var aes = new AesManaged()) {
aes.KeySize = KeySize;
aes.Padding = PaddingMode.PKCS7;
aes.Key = GetSecretKey(HashTheKey("Android"));
// you're using the same init vector in your android code
aes.IV = new byte[16];
using (var decryptor = aes.CreateDecryptor()) {
// dumps {"barcode":"12345678","token":"cad603fc-1e53-4a95-9150-f1694baa07f9"}
Console.Out.WriteLine(Encoding.UTF8.GetString(decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length)));
}
}
}
C# does not handle the encryption algorithms as Android or java do you have to use either AES or Rijndael algorithm as you can see the error to covert to the simple text into Encrypted Base64 and vice versa you can use the following class in C#
public static class Stringcipher
{
// This constant is used to determine the keysize of the encryption algorithm in bits.
// We divide this by 8 within the code below to get the equivalent number of bytes.
private const int Keysize = 256;
// This constant determines the number of iterations for the password bytes generation function.
private const int DerivationIterations = 1000;
public static string Encrypt(string plainText, string passPhrase)
{
// Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
// so that the same Salt and IV values can be used when decrypting.
var saltStringBytes = Generate256BitsOfRandomEntropy();
var ivStringBytes = Generate256BitsOfRandomEntropy();
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
{
var keyBytes = password.GetBytes(Keysize / 8);
using (var symmetricKey = new RijndaelManaged())
{
symmetricKey.BlockSize = 256;
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.PKCS7;
using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
{
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
// Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
var cipherTextBytes = saltStringBytes;
cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
memoryStream.Close();
cryptoStream.Close();
return Convert.ToBase64String(cipherTextBytes);
}
}
}
}
}
}
public static string Decrypt(string cipherText, string passPhrase)
{
// Get the complete stream of bytes that represent:
// [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
// Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
// Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
// Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
{
var keyBytes = password.GetBytes(Keysize / 8);
using (var symmetricKey = new RijndaelManaged())
{
symmetricKey.BlockSize = 256;
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.PKCS7;
using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
{
using (var memoryStream = new MemoryStream(cipherTextBytes))
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
var plainTextBytes = new byte[cipherTextBytes.Length];
var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
}
}
private static byte[] Generate256BitsOfRandomEntropy()
{
var randomBytes = new byte[32]; // 32 Bytes will give us 256 bits.
using (var rngCsp = new RNGCryptoServiceProvider())
{
// Fill the array with cryptographically secure random bytes.
rngCsp.GetBytes(randomBytes);
}
return randomBytes;
}
}
I have been looking everywhere for some sample code on how to encrypt a simple string with the encryption in the title using the Bouncy Castle Framework.
This code will run on a Windows Universal project.
My previous attempts to encrypt using the build in API's failed to decrypt on the server.
I tried this: which gives me a string like:
4pQUfomwVVsl68oQqWoWYNRmRM+Cp+vNFXBNdkN6dZPQ34VZ35vsKn9Q7QGTDVOj+w5mqVYHnGuAOFOgdgl8kA==
s = String.Format("{0}_{1}", s, DateTime.Now.ToString("ddMMyyyyHmmss"));
SymmetricKeyAlgorithmProvider algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
IBuffer keymaterial = CryptographicBuffer.ConvertStringToBinary("[Key]", BinaryStringEncoding.Utf8);
CryptographicKey KEY = algorithm.CreateSymmetricKey(keymaterial);
IBuffer IV = CryptographicBuffer.ConvertStringToBinary("[IV]", BinaryStringEncoding.Utf8);
IBuffer data = CryptographicBuffer.ConvertStringToBinary(s, BinaryStringEncoding.Utf8);
IBuffer output = CryptographicEngine.Encrypt(KEY, data, IV);
return CryptographicBuffer.EncodeToBase64String(output);
The server does encryption/decryption with
public static string Encrypt(string text, byte[] key, byte[] iv, int keysize = 128, int blocksize = 128, CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = blocksize;
aes.KeySize = keysize;
aes.Mode = cipher;
aes.Padding = padding;
byte[] src = Encoding.UTF8.GetBytes(text);
using (ICryptoTransform encrypt = aes.CreateEncryptor(key, iv))
{
byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
encrypt.Dispose();
return Convert.ToBase64String(dest);
}
}
public static string Decrypt(string text, byte[] key, byte[] iv, int keysize = 128, int blocksize = 128, CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = blocksize;
aes.KeySize = keysize;
aes.Mode = cipher;
aes.Padding = padding;
byte[] src = Convert.FromBase64String(text);
using (ICryptoTransform decrypt = aes.CreateDecryptor(key, iv))
{
byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
decrypt.Dispose();
return Encoding.UTF8.GetString(dest); //Padding is invalid and cannot be removed.
}
}
But it fails becasue:
Padding is invalid and cannot be removed.
That's why I want to try Bouncy Castle, but I can't find any suitable example code.
EDIT
I tried using Bouncy Castle with the code provided in the answer.
Now I'm getting the error:
initialisation vector must be the same length as block size
byte[] inputBytes = Encoding.UTF8.GetBytes(s);
byte[] IV = Encoding.UTF8.GetBytes("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
byte[] key = Encoding.UTF8.GetBytes("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
Debug.WriteLine(IV.Length); //32
Debug.WriteLine(cipher.GetBlockSize()); //16
KeyParameter keyParam = new KeyParameter(key);
ParametersWithIV keyParamWithIv = new ParametersWithIV(keyParam, IV);
cipher.Init(true, keyParamWithIv); //Error Message thrown
byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)]; //cip
int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
cipher.DoFinal(outputBytes, length); //Do the final block
string encryptedInput = Convert.ToBase64String(outputBytes);
The length on the server is 128. How can I force it to be equal and same length?
Here are snippets I use. It uses the default built-in System.Security.Cryptography. It doesn't need to be BC
/// <summary>
/// Encrypt a byte array using AES 128
/// </summary>
/// <param name="key">128 bit key</param>
/// <param name="secret">byte array that need to be encrypted</param>
/// <returns>Encrypted array</returns>
public static byte[] EncryptByteArray(byte[] key, byte[] secret)
{
using (MemoryStream ms = new MemoryStream())
{
using (AesManaged cryptor = new AesManaged())
{
cryptor.Mode = CipherMode.CBC;
cryptor.Padding = PaddingMode.PKCS7;
cryptor.KeySize = 128;
cryptor.BlockSize = 128;
//We use the random generated iv created by AesManaged
byte[] iv = cryptor.IV;
using (CryptoStream cs = new CryptoStream(ms, cryptor.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
cs.Write(secret, 0, secret.Length);
}
byte[] encryptedContent = ms.ToArray();
//Create new byte array that should contain both unencrypted iv and encrypted data
byte[] result = new byte[iv.Length + encryptedContent.Length];
//copy our 2 array into one
System.Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
System.Buffer.BlockCopy(encryptedContent, 0, result, iv.Length, encryptedContent.Length);
return result;
}
}
}
/// <summary>
/// Decrypt a byte array using AES 128
/// </summary>
/// <param name="key">key in bytes</param>
/// <param name="secret">the encrypted bytes</param>
/// <returns>decrypted bytes</returns>
public static byte[] DecryptByteArray(byte[] key, byte[] secret)
{
byte[] iv = new byte[16]; //initial vector is 16 bytes
byte[] encryptedContent = new byte[secret.Length - 16]; //the rest should be encryptedcontent
//Copy data to byte array
System.Buffer.BlockCopy(secret, 0, iv, 0, iv.Length);
System.Buffer.BlockCopy(secret, iv.Length, encryptedContent, 0, encryptedContent.Length);
using (MemoryStream ms = new MemoryStream())
{
using (AesManaged cryptor = new AesManaged())
{
cryptor.Mode = CipherMode.CBC;
cryptor.Padding = PaddingMode.PKCS7;
cryptor.KeySize = 128;
cryptor.BlockSize = 128;
using (CryptoStream cs = new CryptoStream(ms, cryptor.CreateDecryptor(key, iv), CryptoStreamMode.Write))
{
cs.Write(encryptedContent, 0, encryptedContent.Length);
}
return ms.ToArray();
}
}
}
If you really need BC, here is a quick test I manage to write based on the test suit from https://github.com/bcgit/bc-csharp/blob/master/crypto/test/src/crypto/test/AESFastTest.cs
You can tailor it for your need
private static void TestBC()
{
//Demo params
string keyString = "jDxESdRrcYKmSZi7IOW4lw==";
string input = "abc";
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] iv = new byte[16]; //for the sake of demo
//Set up
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7
KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyString));
ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16);
// Encrypt
cipher.Init(true, keyParamWithIV);
byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
cipher.DoFinal(outputBytes, length); //Do the final block
string encryptedInput = Convert.ToBase64String(outputBytes);
Console.WriteLine("Encrypted string: {0}", encryptedInput);
//Decrypt
cipher.Init(false, keyParamWithIV);
byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)];
length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0);
cipher.DoFinal(comparisonBytes, length); //Do the final block
Console.WriteLine("Decrypted string: {0}",Encoding.UTF8.GetString(comparisonBytes)); //Should be abc
}
enter link description here
byte[] k; //32 byte
string para; // plaintext
string msgRefNo; // 16byte
byte[] inputBytes = Encoding.UTF8.GetBytes(para);
byte[] IV = Encoding.UTF8.GetBytes(msgRefNo);
byte[] key = k;
AesEngine engine = new AesEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
PaddedBufferedBlockCipher cipher1 = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
KeyParameter keyParam = new KeyParameter(key);
ParametersWithIV keyParamWithIv = new ParametersWithIV(keyParam, IV);
cipher1.Init(true, keyParamWithIv); //Error Message thrown
byte[] outputBytes = new byte[cipher1.GetOutputSize(inputBytes.Length)]; //cip
int length = cipher1.ProcessBytes(inputBytes, outputBytes, 0);
cipher1.DoFinal(outputBytes, length); //Do the final block
string encryptedInput = Convert.ToBase64String(outputBytes);
return encryptedInput;
I use RJ256 to login, since the return string is fairly small, it works (PHP gives encrypted string and C# needs to decrypt).
The data gets decrypted and fully works. Although, now I am transferring a 79KB string from PHP (Encrypted) to C# (Needs to Decrypt) and I get this error:
http://i.imgur.com/M4sgEct.png
This error only happens when the string is a bit larger than normally.
Here is my PHP code to encrypt:
private function _encrypt($data)
{
$iv = "sfhfskfsusfdsfd79fd8s79sdf789f79";
$key = "da4b9237bacccdf1";
// to append string with trailing characters as for PKCS7 padding scheme
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$padding = $block - (strlen($data) % $block);
$data .= str_repeat(chr($padding), $padding);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);
// this is not needed here
//$crypttext = urlencode($crypttext);
return base64_encode($crypttext);
}
Here is my C# Code to decrypt:
public static dynamic DecryptRJ256(string cypher, bool isJson = true, bool getBytes = false)
{
string sRet;
var encoding = new UTF8Encoding();
var key = encoding.GetBytes("da4b9237bacccdf1");
var iv = encoding.GetBytes("sfhfskfsusfdsfd79fd8s79sdf789f79");
using (var rj = new RijndaelManaged())
{
try
{
rj.Padding = PaddingMode.PKCS7;
rj.Mode = CipherMode.CBC;
rj.KeySize = 256;
rj.BlockSize = 256;
rj.Key = key;
rj.IV = iv;
var ms = new MemoryStream(Decode(cypher));
using (var cs = new CryptoStream(ms, rj.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
using (var sr = new StreamReader(cs))
{
sRet = sr.ReadLine();
}
}
}
finally
{
rj.Clear();
}
}
// ReSharper disable once AssignNullToNotNullAttribute
return (isJson ? JsonConvert.DeserializeObject<dynamic>(sRet) : (getBytes ? Encoding.UTF8.GetBytes(sRet) : (dynamic)sRet));
}
How can I make it work?
How about this:
public static byte[] DecryptRJ256(string prm_key, string prm_iv, string prm_text_to_decrypt)
{
var sEncryptedString = prm_text_to_decrypt;
var myRijndael = new RijndaelManaged();
myRijndael.Padding = PaddingMode.Zeros;
myRijndael.Mode = CipherMode.CBC;
myRijndael.KeySize = 256;
myRijndael.BlockSize = 256;
byte[] key;
byte[] IV;
key = Encoding.ASCII.GetBytes(prm_key);
IV = Encoding.ASCII.GetBytes(prm_iv);
var decryptor = myRijndael.CreateDecryptor(key, IV);
var sEncrypted = Convert.FromBase64String(sEncryptedString);
var fromEncrypt = new byte[sEncrypted.Length];
var msDecrypt = new MemoryStream(sEncrypted);
var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
//Return (System.Text.Encoding.ASCII.GetString(fromEncrypt))
return fromEncrypt;
}