Вот версия с CryptoJS 3.1.2. Всегда остерегайтесь следующих вещей (используйте одно и то же на обоих языках):
- Режим работы (в данном случае CBC)
- Заполнение (в данном случае нулевое заполнение; лучше использовать заполнение PKCS#7)
- Ключ (та же функция вывода или ключ очистки)
- Кодировка (одинаковая кодировка для ключа, открытого текста, зашифрованного текста и т. д.)
- IV (генерируется при шифровании, передается на расшифровку)
Если строка передается в качестве аргумента key
функции CryptoJS encrypt()
, эта строка используется для получения фактического ключа, который будет использоваться для шифрования. Если вы хотите использовать ключ (допустимые размеры: 16, 24 и 32 байта), вам нужно передать его как WordArray.
Результатом шифрования CryptoJS является строка зашифрованного текста в формате OpenSSL. Чтобы получить из него фактический зашифрованный текст, вам нужно получить доступ к его свойству ciphertext
.
IV должен быть случайным для каждого шифрования, чтобы он был семантически безопасным. Таким образом, взглянув только на зашифрованный текст, злоумышленники не могут сказать, является ли один и тот же открытый текст, который был зашифрован несколько раз, на самом деле одним и тем же открытым текстом.
Ниже приведен пример, который я сделал.
JavaScript:
var key = CryptoJS.enc.Utf8.parse('1234567890123456'); // TODO change to something with more entropy
function encrypt(msgString, key) {
// msgString is expected to be Utf8 encoded
var iv = CryptoJS.lib.WordArray.random(16);
var encrypted = CryptoJS.AES.encrypt(msgString, key, {
iv: iv
});
return iv.concat(encrypted.ciphertext).toString(CryptoJS.enc.Base64);
}
function decrypt(ciphertextStr, key) {
var ciphertext = CryptoJS.enc.Base64.parse(ciphertextStr);
// split IV and ciphertext
var iv = ciphertext.clone();
iv.sigBytes = 16;
iv.clamp();
ciphertext.words.splice(0, 4); // delete 4 words = 16 bytes
ciphertext.sigBytes -= 16;
// decryption
var decrypted = CryptoJS.AES.decrypt({ciphertext: ciphertext}, key, {
iv: iv
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
Код Python 2 с pycrypto:
BLOCK_SIZE = 16
key = b"1234567890123456" # TODO change to something with more entropy
def pad(data):
length = BLOCK_SIZE - (len(data) % BLOCK_SIZE)
return data + chr(length)*length
def unpad(data):
return data[:-ord(data[-1])]
def encrypt(message, key):
IV = Random.new().read(BLOCK_SIZE)
aes = AES.new(key, AES.MODE_CBC, IV)
return base64.b64encode(IV + aes.encrypt(pad(message)))
def decrypt(encrypted, key):
encrypted = base64.b64decode(encrypted)
IV = encrypted[:BLOCK_SIZE]
aes = AES.new(key, AES.MODE_CBC, IV)
return unpad(aes.decrypt(encrypted[BLOCK_SIZE:]))
Предупреждение. Имейте в виду, что и python2, и pycrypto устарели, поэтому код необходимо скорректировать, чтобы он соответствовал python3 и pycryptodome.
Другие соображения:
Похоже, вы хотите использовать парольную фразу в качестве ключа. Парольные фразы обычно читаются человеком, а ключи — нет. Вы можете получить ключ из фразы-пароля с помощью таких функций, как PBKDF2, bcrypt или scrypt.
Приведенный выше код не является полностью безопасным, поскольку в нем отсутствует аутентификация. Зашифрованные тексты, не прошедшие проверку подлинности, могут привести к жизнеспособным атакам и незамеченным манипуляциям с данными. Обычно схема «зашифровать-затем-MAC» используется с хорошей функцией MAC, такой как HMAC-SHA256.
person
Artjom B.
schedule
23.06.2015