Мне нужно зашифровать строку, используя шифрование AES.Это шифрование происходило в C # ранее, но его необходимо преобразовать в JavaScript (будет выполняться в браузере).
Текущий код в C # для шифрования выглядит следующим образом -
public static string EncryptString(string plainText, string encryptionKey)
{
byte[] clearBytes = Encoding.Unicode.GetBytes(plainText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
plainText = Convert.ToBase64String(ms.ToArray());
}
}
return plainText;
}
Я пытался использовать CryptoJS для репликации той же функциональности, но он не дает мне эквивалентную зашифрованную строку base64.Вот мой код CryptoJS -
function encryptString(encryptString, secretKey) {
var iv = CryptoJS.enc.Hex.parse('Ivan Medvedev');
var key = CryptoJS.PBKDF2(secretKey, iv, { keySize: 256 / 32, iterations: 500 });
var encrypted = CryptoJS.AES.encrypt(encryptString, key,{iv:iv);
return encrypted;
}
Зашифрованная строка должна быть отправлена на сервер, который сможет ее расшифровать.Сервер может дешифровать зашифрованную строку, сгенерированную из кода C #, но не зашифрованную строку, сгенерированную из кода JS.Я попытался сравнить зашифрованные строки, сгенерированные как кодом, так и обнаружил, что код C # генерирует более длинные зашифрованные строки.Например, сохраняя «Пример строки» в качестве обычного текста и «Пример ключа» в качестве ключа, я получаю следующий результат -
C# - eAQO+odxOdGlNRB81SHR2XzJhyWtz6XmQDko9HyDe0w=
JS - 9ex5i2g+8iUCwdwN92SF+A==
Длина зашифрованной строки JS всегда короче, чем в C #.Есть ли что-то, что я делаю не так?Мне просто нужно скопировать код C # в код JS.
Обновление:
Мой текущий код после Ответ Зергата это -
function encryptString(encryptString, secretKey) {
var keyBytes = CryptoJS.PBKDF2(secretKey, 'Ivan Medvedev', { keySize: 48 / 4, iterations: 1000 });
console.log(keyBytes.toString());
// take first 32 bytes as key (like in C# code)
var key = new CryptoJS.lib.WordArray.init(keyBytes.words, 32);
// skip first 32 bytes and take next 16 bytes as IV
var iv = new CryptoJS.lib.WordArray.init(keyBytes.words.splice(32 / 4), 16);
console.log(key.toString());
console.log(iv.toString());
var encrypted = CryptoJS.AES.encrypt(encryptString, key, { iv: iv });
return encrypted;
}
Как показано в его / ее ответе, что если код C # преобразует обычный текст в байты с использованием ASCII вместо Unicode, то и код C #, и JS будут давать точные результаты.Но так как я не могу изменить код расшифровки, я должен преобразовать код в эквивалент исходного кода C #, который использовал Unicode.
Итак, я попытался понять, в чем разница междубайтовый массив между ASCII и Unicode байтовым преобразованием в C #.Вот что я нашел -
ASCII Byte Array: [69,120,97,109,112,108,101,32,83,116, 114, 105, 110, 103]
Unicode Byte Array: [69,0,120,0,97,0,109,0,112,0,108,0,101,0,32,0,83,0,116,0, 114,0, 105,0, 110,0, 103,0]
Таким образом, некоторые дополнительные байты доступны для каждого символа в C # (поэтому Unicode выделяет в два раза больше байтов каждому символу, чем ASCII).
Вот разница междуи преобразование Unicode и ASCII соответственно -
ASCII
clearBytes: [69,120,97,109,112,108,101,32,83,116,114,105,110,103,]
encryptor.Key: [123,213,18,82,141,249,182,218,247,31,246,83,80,77,195,134,230,92,0,125,232,210,135,115,145,193,140,239,228,225,183,13,]
encryptor.IV: [101,74,46,177,46,233,68,252,83,169,211,13,249,61,118,167,]
Result: eQus9GLPKULh9vhRWOJjog==
Unicode:
clearBytes: [69,0,120,0,97,0,109,0,112,0,108,0,101,0,32,0,83,0,116,0,114,0,105,0,110,0,103,0,]
encryptor.Key: [123,213,18,82,141,249,182,218,247,31,246,83,80,77,195,134,230,92,0,125,232,210,135,115,145,193,140,239,228,225,183,13,]
encryptor.IV: [101,74,46,177,46,233,68,252,83,169,211,13,249,61,118,167,]
Result: eAQO+odxOdGlNRB81SHR2XzJhyWtz6XmQDko9HyDe0w=
Таким образом, поскольку генерируемый ключ и iv имеют одинаковый байтовый массив в подходах Unicode и ASCII, он не должен был генерировать разные выходные данные, но каким-то образом это происходит,Я думаю, что это из-за длины clearBytes, поскольку он использует свою длину для записи в CryptoStream.
Я попытался посмотреть, каков вывод сгенерированных байтов в коде JS, и обнаружил, что он использует слова, которые необходимы длябыть преобразованы в строки, используя метод toString()
.
keyBytes: 7bd512528df9b6daf71ff653504dc386e65c007de8d2877391c18cefe4e1b70d654a2eb12ee944fc53a9d30df93d76a7
key: 7bd512528df9b6daf71ff653504dc386e65c007de8d2877391c18cefe4e1b70d
iv: 654a2eb12ee944fc53a9d30df93d76a7
Поскольку я не могу влиять на длину сгенерированной зашифрованной строки в коде JS (нет прямого доступа к потоку записи), поэтому все еще застрял здесь.