简体   繁体   中英

Converting C# Cryptography.Rijndael encryption to Javascript (pref. crypto-js)

I have two system which are sharing a user database, so authentication needs to be the same.

The passwords are currently encrypted using C#'s Cryptography.Rijndael (NB not RijndaelManaged). Using a custom key and iv (initialisation vector). (CBC mode and Pkcs7 padding)

The C# encryption is as follows:

Rijndael alg = Rijndael.Create();
alg.Key = key;
alg.IV = IV;
CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(clearData, 0, clearData.Length);
cs.Close();
byte[] encryptedData = ms.ToArray();

key is 256 bits (32 bytes) and iv (initialisation vector) is 128 bits (16 bytes). The block size is 128 bits (16 bytes).

key and iv are a byte arrays from a base64 strings via:

byte[] key = Convert.FromBase64String(base64Key);
byte[] iv = Convert.FromBase64String(base64IV);

NB I have no control on the C# code (legacy system).

On the javascript based system I have to encrypt the passwords exactly the same way. I've tried using node crypto-js to no avail. my code looks something like this:

var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(password), keyCodeWords, {
    iv: ivCodeWords,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
});

keyCodeWords and ivCodeWords are CryptoJS code words from the same base64 key and iv as follows:

var keyCodeWords = CryptoJS.enc.Base64.parse(base64Key);
var ivCodeWords = CryptoJS.enc.Base64.parse(base64IV);

The encryption does work (in the sense that I can encrypt and then decrypt to get the same value). However, the issue is that the encrypted value ( encrypted.ciphertext ) is not the same as the C# one, so I'm unable to authenticate.

The comparison is done base comparing the base64 encrypted output strings.

How do I make crypto-js (or any other javascript encryption library) consistent with C# Rijndael?

The code works correctly... Your problem is probably in the handling of the password/IV in C# or in Javascript... In C#: https://ideone.com/APC4MM and in Javascript: https://jsfiddle.net/jjwy5472/

I've used in both cases the same password:

byte[] key = new byte[] 
{ 
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
};

byte[] iv = new byte[] 
{ 
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
};

the plaintext is

"Hello world! This is a wonderful day! àèéìòù"

and in both cases the resulting encrypted text is

aa429aa5c1c928b86d81b43ff3fb6cc46f24cc73957bc7c00829357bf441eb3be9cf8aef2ff6f819f9b95c69886b169b6959c4f7ece0620c6a28f849516adee9

But note that the encrypted variable in Javascript is a complex object, containing various properties with various versions of your encrypted data. encrypted.toString() returns the base64 version of the encrypted data, encrypted.ciphertext is a WordArray (the equivalent of CryptoJS of byte[] ), and encrypted.ciphertext.toString() is the hex version of it (equivalent to doing BitConverter.ToString(encryptedData).Replace("-", "").ToLowerInvariant() in C#).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM