admin管理员组

文章数量:1391977

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(N.B. 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);

N.B. 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 parison is done base paring the base64 encrypted output strings.

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

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(N.B. 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);

N.B. 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 parison is done base paring the base64 encrypted output strings.

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

Share Improve this question edited Mar 24, 2016 at 9:56 Kholofelo asked Mar 24, 2016 at 9:03 KholofeloKholofelo 7249 silver badges16 bronze badges 7
  • There are a million options for Rijndael in C#. Which were yours? Can you show us the code? Have you checked that the encoding fits? Remember that AES is only a subset of Rijndael. If you're using a block size other than 128 bit in C#, then you can't use CryptoJS. – Artjom B. Commented Mar 24, 2016 at 9:06
  • 1 You should never encrypt your user's passwords. You need to use hashing instead with some strong ones being PBKDF2, bcrypt, scrypt and Argon2. Since hash functions are one-way function, you won't be able to "decrypt" the hashes. In order to authenticate your user, you can run the password through the hash function again in order to pare with the hash that is stored in the database. See more: How to securely hash passwords? – Artjom B. Commented Mar 24, 2016 at 9:06
  • @ArtjomB. , C# encryption: 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(); The key is 256 bits, the `iv' is 128 bits. Block size is 128. Unfortunately, I have no control on the C# implementation (legacy system) - I also would have just used hashing. – Kholofelo Commented Mar 24, 2016 at 9:19
  • @ArtjomB., sorry about that I edited my question. Please check it. Thanks. – Kholofelo Commented Mar 24, 2016 at 9:29
  • 1 Ok, it looks fine. So it must be an encoding problem. How are you encoding the password string into bytes on both sides? How are you providing the key and IV from C# in CryptoJS? Can you provide the corresponding code? How are you paring the results? – Artjom B. Commented Mar 24, 2016 at 9:40
 |  Show 2 more ments

1 Answer 1

Reset to default 6

The code works correctly... Your problem is probably in the handling of the password/IV in C# or in Javascript... In C#: https://ideone./APC4MM and in Javascript: https://jsfiddle/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 plex 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#).

本文标签: Converting C CryptographyRijndael encryption to Javascript (pref cryptojs)Stack Overflow