I have the next code that perfectly works encrypting and decrypting in net framework even with a invalid key for RijndaelManaged, but now in the netCore it doesn’t work because its needs a 16 bytes key, I want to recreate the key that the library in net frameworks makes with a key expansion to decrypt in a net core app, but I don’t now how
I found a similar problem but in PHP here RijndaelManaged.CreateEncryptor key expansion, but it says “just chop off the last 2 bytes” but of what? and how I complete the rest of bytes?
//Code tha works in the framework app
///8 bytes
_key = System.Text.ASCIIEncoding.UTF8.GetBytes("abcdefgh");
//16 bytes
_iv = System.Text.ASCIIEncoding.UTF8.GetBytes("abcdefghijklmnop");
_provider = new RijndaelManaged();
_provider.Mode = CipherMode.CBC;
_provider.KeySize = 128;
_provider.CreateEncryptor(_key, _iv)
Related
We are trying to integrate with a legacy c# application that uses RijndaelManaged for symmetric encryption. However it appears that they have used a 13 byte string as an encryption key!
The code is basically:
var initVectorBytes = Encoding.ASCII.GetBytes("16-char string");
var keyBytes = Encoding.ASCII.GetBytes("13-char string");
var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC };
var decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
var memoryStream = new System.IO.MemoryStream(encryptedbytes);
var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
....
In theory this shouldn't work - the docs clearly say "The key size must be 128, 192, or 256 bits" and when we try this (on a Xamarin/Mono compiler - don't have easy access to .net at the moment) it throws an exception.
But it apparently works on the legacy system, and they have unit tests that also call CreateDecryptor with a 13 byte key; so presumably a real .net system does somehow do something with this code. (I note that the docs for .net version 2.0 don't talk about key length restrictions - the code is compiled using .net 3.5 however)
Is it possible that it uses the Rijndael algorithm with a 104 byte key and block size? Or would it somehow pad the key or something?
I've been working on this for a while and I don't know much about either PHP or C#. We are building an application that is using AES 128 CBC mode encryption to store things in the database. One part is PHP and JS, the other is C# .NET WPF.
The person who wrote the PHP used the Mcrypt library to crypt/decrypt. I'm using the Chilkat library to encrypt/decrypt. Chilkat had a default C# example that is supposed to mimic the PHP Mcrypt.
Currently I can symmetrically encrypt/decrypt things on .Net, and .Net can decrypt anything from PHP. However the PHP side cannot decrypt anything that I encrypt to the database from the .Net side.
I've narrowed at least part of down to encoding issues, but I'm not sure how to fix it. The decryption scheme on PHP side usually decrypts to ASCII, but for things that I send it decrypts to UTF-8. I've tried to decrypt it then encode from UTF-8 to ASCII to no avail.
I'll show you the in/outputs and the functions. The IV is being set to 16 ASCII 0s to help my debugging along even though it shouldn't really matter.
input from .Net to mcrypt_encrypt func: string "1220"
output: 3tRIG7qUxUsU7WoXDybRRcdQRobOfeFGtQ438V7XRD8=
Parameter input into database = 'same as above'
input of PHP side decrypt func = 3tRIG7qUxUsU7WoXDybRRcdQRobOfeFGtQ438V7XRD8= 'same as above'
output of the mcrypt_decrypt function = ��J���{$�Z'?�u 'iconv says utf-8 encoding'
Ask for anything else and I'll get it if it would help. I'm sure this is some stupid easy problem I can't see.
PHP side - if it matters the PHP charset is set to UTF-8
function encrypt($input)
{
$this->iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
/*No longer using random iv :(
$this->iv = mcrypt_create_iv($this->iv_size, MCRYPT_RAND);*/
//use 16 zeros
$this->iv = '0000000000000000';
$encrypted = $this->iv .mcrypt_encrypt(MCRYPT_RIJNDAEL_128, KEY, $input, MODE, $this->iv);
//Finally encode this as base 64, see http://php.net/manual/en/function.base64-encode.php
$encrypted = base64_encode($encrypted);
return $encrypted;
}
function decrypt($input)
{
/*Get our message back!!!
First decode the base 64 string. Note, de/encoding bas 64 != encryption*/
$ciphertext_dec = base64_decode($input);
//Get the iv back out for decryption
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
//$iv_dec = substr($ciphertext_dec, 0, $iv_size);*/
$iv_dec = '0000000000000000';
//Now get the text of encrypted message (all but the iv in front)
$ciphertext_dec = substr($ciphertext_dec, $iv_size);
//Now decrypt the message
$plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, KEY, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
//Test
//test
//$plaintext_dec = iconv("UTF-8", "ASCII", $plaintext_dec);
//echo mb_detect_encoding($plaintext_dec, "auto");
//echo $plaintext_dec;
/*However, we might now have blank space # end of output b/c
remember we de/encrypt via block, so a 10 char long message
could be padded to 16 char long with blank spaces. Get rid of those.*/
$plaintext_dec = trim($plaintext_dec);
//return so we can compare to, i.e., original input
return $plaintext_dec;
}
.NET C#
public string mcrypt_encrypt(string plainText)
{
plainText = Encoding.ASCII.GetString(crypt.IV) + plainText;
byte[] myText = Encoding.ASCII.GetBytes(plainText);
// Do 128-bit AES encryption:
byte[] cipherText = crypt.EncryptBytes(myText);
return Convert.ToBase64String(cipherText);
}
public string mcrypt_decrypt(string cipher_text)
{
byte[] cipher_dec = Convert.FromBase64String(cipher_text);
byte[] plainBytes = crypt.DecryptBytes(cipher_dec);
string decrypted = Encoding.ASCII.GetString(plainBytes);
string plain_text = decrypted.Substring(16, decrypted.Length - 16);
return plain_text.TrimEnd('\0');
}
C# Chilkat init:
// AES is also known as Rijndael.
crypt.CryptAlgorithm = "aes";
// CipherMode may be "ecb" or "cbc"
crypt.CipherMode = "cbc";
// KeyLength may be 128, 192, 256
crypt.KeyLength = 128;
// Pad with NULL bytes (PHP pads with NULL bytes)
crypt.PaddingScheme = 3;
// EncodingMode specifies the encoding of the output for
// encryption, and the input for decryption.
// It may be "hex", "url", "base64", or "quoted-printable".
crypt.EncodingMode = "hex";
// The secret key must equal the size of the key. For
// 256-bit encryption, the binary secret key is 32 bytes.
// For 128-bit encryption, the binary secret key is 16 bytes.
string keyAscii = #"&=*FS6wksG#Zs3qG";
crypt.SecretKey = Encoding.UTF8.GetBytes(keyAscii);
crypt.Charset = "ASCII";
crypt.SetEncodedIV("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", "ascii");
You have a variety of different problems here. The issue causing the problem you seeing in not being able to decrypt in PHP data that was encrypted in .NET is that in the PHP version you're performing a substr on the ciphertext prior to decryption. The comments in the code indicate that you're removing the IV, except that that seems to have only been relevant in a prior version of your code when you were (correctly) using a random IV each time - now you're just discarding the first 16 bytes of ciphertext which due to the mode of operation corrupts the subsequent data block.
The other problem (though masked by the fact that you're discarding the first 16 bytes of the plaintext data when decrypting in .NET) is that the IV you're using in .NET (16 bytes of 0x00) is not the same as the IV you're using in PHP (16 '0' characters = 16 bytes of 0x30).
I would suggest reverting to using a random IV for every encryption and prepending the IV to the ciphertext after encryption When decrypting, read the IV from the first bytes of the ciphertext then decrypt the remainder. This is much more secure than having a static IV, especially when the data being encrypted is likely to often be the same.
It looks like it's a simple character encoding issue. Your C# code is getting the ASCII representation of your string and encrypting that, but your PHP code is decrypting it and expecting it to be UTF-8.
Try swapping your Encoding.ASCII calls for Encoding.UTF8 and make sure your crypt.Charset and crypt.SetEncodedIV are UTF8 as well
I'm using AES on WP8 (Windows Phone 8) in C# on Visual Studio, and System.Security.Cryptography does not contain the attribute 'Mode' for AESManaged.
I've looked up this problem for the past 3 days now, and haven't found any reference or anything to import.
The code I am currently using is:
AesManaged cipher = new AesManaged();
cipher.BlockSize = 8;
/*cipher.Mode = CipherMode.CFB;
cipher.Padding = PaddingMode.None;*/
//cipher.KeySize = 128;
//cipher.FeedbackSize = 8;
cipher.Key = key;
cipher.IV = key;
return cipher;
While the BlockSize throws an exception 'Specified block size is not valid for this algorithm.'
I was originally using RijndaelManaged but that isn't available on WP8 but according to this it should be available.
Silverlight verison of AES have no mode property. Here is MSDN article about that.
"The AES algorithm is essentially the Rijndael symmetric algorithm with a fixed block size and iteration count. This class functions the same way as the .NET Framework RijndaelManaged class but limits blocks to 128 bits and does not allow feedback modes.
The cipher mode is always CBC, and the padding mode is always PKCS7."
You can extract AES from BounceCastle library if you need more modes and flexibility. I did that before.
We encrypt PDFs using AESManaged algorithm implemented in .NET framework. I used the example explained in here to implement C# code to encrypt the file. Now I need to decrypt that file using an iPhone application.(That is the requirement). So I use the this code to do that but decryption failed by returning an error.
'Error Domain=CommonCryptoErrorDomain Code=-4304 "Decode Error"
UserInfo=0x127356c0 {NSLocalizedFailureReason=Input data did not
decode or decrypt correctly, NSLocalizedDescription=Decode Error'
Can some one help me to resolve this issue.
We use 12345678 as encryption key.
Most likely the problem is in the deriving actual key from the password (12345678 cannot be the AES key directly - it is only 8 bytes).
Technically this should work though I've never tested it, both methods uses the same ad-hoc format.
Encrypt using my authenticated encryption example.
//use your secret data you want to encrypt instead.
String secretMessage = "Message";
var rnCryptorHeader = new Byte[]{
2, //RNCryptor Format version 2
0 //RNCryptor Uses password
};
//encryptedString is base64 encoded
var encryptedString = AESThenHMAC.SimpleEncryptWithPassword(secretMessage,
password:"1234567891011",
nonSecretPayload:rnCryptorHeader);
Then Decrypt using RNCryptor and NSData+Base64 for IOS
//This is the encrypted data passed from .net
NSString *encryptedString = #"AgE8C9E7gsfyOAmSotIOgyLQ0O6mdcuMXXjN/iZa3azym4KVWZAkfykIP6mqMt/qkpfftdB3XQhMkoxtQEM+rA0iHxOvZiNlmA2KJtg6BOnmlg==";
NSData *encryptedData = [NSData dataFromBase64String: encryptedString];
NSError *error;
NSData *decryptedData = [RNDecryptor decryptData:encryptedData
withPassword:#"1234567891011"
error:&error];
NSString *secretMessage = [[[NSString alloc] initWithData:decryptedData
encoding:NSUTF8StringEncoding] autorelease];
Since you aren't dealing with strings and are dealing with bytes directly, just remove the Base64 and utf8 encoding/decoding from this objective-c example and the linked c# example, once you are sure this is working.
I am trying to port the following code from C# into Java. I have made multiple attempts to try and decrypt my encrypted data and I get gibberish every time. The code below uses the org.bouncycastle library and unfortunately there doesn't seem to be a 1-1 mapping between the C# code and the Java code.
I basically know three things:
byte[] file - This contains my encrypted file. Usually a pretty large array of bytes.
byte[] padding - It is 32*bytes* every time and it seems that the first 16 bytes of this are used as the IV.
byte[] aesKey - It is 32*bytes* every time and I do not know how exactly the C# code is using this array.
Original C# Code
private byte[] decryptmessage(byte[] cmessage, byte[] iVector, byte[] m_Key)
{
{
//// randomly generated number acts as inetialization vector
m_IV = new byte[16];
Array.Copy(iVector, 0, m_IV, 0, 16);
// GenerateAESKey();
KeyParameter aesKeyParam = ParameterUtilities.CreateKeyParameter("AES", m_Key);
ParametersWithIV aesIVKeyParam = new ParametersWithIV(aesKeyParam, m_IV);
IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CFB/NoPadding");
cipher.Init(false, aesIVKeyParam);
return cipher.DoFinal(cmessage);
}
}
My attempt in Java
private static byte[] decryptMessage(byte[] file, byte[] iVector, byte[] aesKey) throws Exception {
IvParameterSpec spec = new IvParameterSpec(Arrays.copyOfRange(iVector, 0, 16));
SecretKeySpec key = new SecretKeySpec(Arrays.copyOfRange(aesKey, 0, 16), "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, spec);
return cipher.doFinal(file);
}
P.S: This is the final step of decryption. Before all this I had to take out some initial set of bytes from my encrypted file and decrypt them using an RSA private key to get this AES key.
If someone has a link / document I can read that properly explains the whole process of using AES to encrypt a file, then using RSA on the key and iv to the begining of the encrypted file, I will be extremely happy. I have just been staring at the C# code, I'd like to see something with pictures.
EDIT: Bytes not bits.
EDIT2: Renamed padding to iVector for consistency and correctness.
In the C# code, you initialize the key with 256 bits (32 bytes) and thus get AES-256. In the Java code, you only use 128 bit (16 bytes) and get AES-128.
So the fix is probably:
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
You might then find that Java doesn't want to use 256 bit keys (for legal reason). You then have to intall the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6.