У меня есть JavaScript, связанный с кнопкой HTMl, которая выполняет кодировку AES-GCM и записывает полезную информацию в консоль.
function strToArrayBuffer(str) {
let buf = new ArrayBuffer(str.length * 2);
let bufView = new Uint16Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function arrayBufferToString(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function arrayBufferToHex(buf) {
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, "0")).join("");
}
let iv = window.crypto.getRandomValues(new Uint8Array(12));
console.log('nonce/iv: ' + arrayBufferToHex(iv));
let algoEncrypt = {
name: 'AES-GCM',
iv: iv,
tagLength: 128
};
let plainText =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer imperdiet pretium leo, et auctor velit fermentum nec. Mauris eu finibus orci.";
console.log('Input Text: ' + plainText);
let secretKey = null;
window.crypto.subtle.generateKey(
{name: 'AES-GCM', length: 256},
true,
['encrypt', 'decrypt']
).then(function (key) {
secretKey = key;
return window.crypto.subtle.encrypt(algoEncrypt, key, strToArrayBuffer(plainText));
}).then(function (cipherText) {
console.log('Encrypted Hex:\n' + arrayBufferToHex(cipherText));
return window.crypto.subtle.decrypt(algoEncrypt, secretKey, cipherText);
}).then(function (newPlainText) {
if (arrayBufferToString(newPlainText) == plainText) {
console.log("decryption matches");
} else {
console.log("decryption ERROR:" + arrayBufferToHex(newPlainText));
}
return window.crypto.subtle.exportKey("raw", secretKey);
}).then(function (keyData) {
console.log('Password Hex:\n' + arrayBufferToHex(keyData));
}).catch(function (err) {
console.log('Error: ' + err.message);
});
Пример вывода на консоль:
nonce/iv: b17eb886854af06d9d43d4d7
Input Text: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer imperdiet pretium leo, et auctor velit fermentum nec. Mauris eu finibus orci.
Encrypted Hex: facdbb0b024b059d0c78a2634bd6592c04feba0ecb833eee03c7e2c8135854d8ba5bcb80cac1ce8a1c7396fc684e4aa1a44c8b30e9bc800a033ff7ca1a7542a219c42208449232aa671e6443d92c87eca16fb4c06a61d965f455822d8131c26d8bfc6fdfbb5eaae7409516653f33a2c207affdd1539e29e65e236a232b98efc3056e69526115a71837d99f2235d92f6bc64b020e160f44d7281d307ab5cc33791d37bca8423d94f21bf4eccc1717a33891381cb116bbd8dc1f2ae953d94b00f4eef0bc237a7998d99a1a46b9581c34199aeda20cf68158cce43c8492370eccec55dc0f207a495d320aa7d7d8c3bf49c50726046b02ac6e9a9ce6d10d679ff07cff3462bdda051597f0ff5a1f6fb411be3048b72c2d7fe4242783d61d4115a576fcaae05016e6c4648d835b11
decryption matches encrypt
Password Hex:
ce24825df74a15e84597a9446c4821e384661fb790281abec94eab4e5cd95b1b
Затем я пытаюсь расшифровать с помощью Python 2.7:
import sys
import binascii
import datetime
import time
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import (Cipher, algorithms, modes)
from Cryptodome.Cipher import AES
hexdata = "facdbb0b024b059d0c78a2634bd6592c04feba0ecb833eee03c7e2c8135854d8ba5bcb80cac1ce8a1c7396fc684e4aa1a44c8b30e9bc800a033ff7ca1a7542a219c42208449232aa671e6443d92c87eca16fb4c06a61d965f455822d8131c26d8bfc6fdfbb5eaae7409516653f33a2c207affdd1539e29e65e236a232b98efc3056e69526115a71837d99f2235d92f6bc64b020e160f44d7281d307ab5cc33791d37bca8423d94f21bf4eccc1717a33891381cb116bbd8dc1f2ae953d94b00f4eef0bc237a7998d99a1a46b9581c34199aeda20cf68158cce43c8492370eccec55dc0f207a495d320aa7d7d8c3bf49c50726046b02ac6e9a9ce6d10d679ff07cff3462bdda051597f0ff5a1f6fb411be3048b72c2d7fe4242783d61d4115a576fcaae05016e6c4648d835b11"
noncehex = "b17eb886854af06d9d43d4d7"
keyhex = "ce24825df74a15e84597a9446c4821e384661fb790281abec94eab4e5cd95b1b"
nonce = binascii.unhexlify(noncehex)
assert(len(nonce) == 12)
key = binascii.unhexlify(keyhex)
assert(len(key) == 32)
binary = binascii.unhexlify(hexdata)
cipher = Cipher(algorithms.AES(key), None, backend=default_backend())
cipher.mode = modes.GCM(nonce)
text = cipher.decryptor().update(binary)
print(text)
decryptor = AES.new(key=key, mode=AES.MODE_GCM, nonce=nonce)
text = decryptor.decrypt(binary)
print(text)
Результат очень близок, но имеет конечный шум с использованием двух разных расшифровщиков Python:
%> ./pydecrypt.py
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer imperdiet pretium leo, et auctor velit fermentum nec. Mauris eu finibus orci.���7P��&���ջq�
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer imperdiet pretium leo, et auctor velit fermentum nec. Mauris eu finibus orci.���7P��&���ջq�
Что я делаю не так, чтобы вызвать шум в конце? Я что-то упускаю из данных? (Значение iv / nonce составляет 12 символов, но дополнительный шум составляет 14 символов, и значения, похоже, не совпадают, поэтому я не думаю, что это так.)