NodeJS AES шифрует Python расшифровывает - PullRequest
1 голос
/ 21 июня 2019

У меня есть служба nodejs, которая использует шифрование AES для некоторых данных, которые необходимо расшифровать в Python. Что бы я ни делал, я не могу заставить это работать. Код NodeJS:

const algorithm = 'aes-128-ctr';

function encryptScript(data, key) {
    const cipher = crypto.createCipher(algorithm, key);

    let crypted = cipher.update(data, 'utf8', 'hex');
    crypted += cipher.final('hex');

    return crypted;
}

Я пробовал в Python:

counter = Counter.new(128)
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
print cipher.decrypt(enc.decode("hex"))

Но это не работает.

Моя первая проблема заключается в том, что код Python не принимает ключи, длина которых превышает 32 байта (а код Nodejs делает).

Если я использую криптомодуль NodeJS, расшифровка работает:

function decryptScript(data, key) {
    const decipher = crypto.createDecipher(algorithm, key);
    let dec = decipher.update(data, 'hex', 'utf8');
    dec += decipher.final('utf8');
    return dec;
}

Я не знаю, что делает узел, но это, вероятно, связано с некоторым заполнением данных.

Как я могу заставить это работать?

(Я предпочту решение, которое не потребует изменений в коде NodeJS, а только в скрипте Python).

1 Ответ

1 голос
/ 22 июня 2019
  • CreateCipher использует EVP_BytesToKey для создания ключа и IV из пароля (так называемый ключ в NodeJS-коде это на самом деле пароль ). Здесь - это реализация EVP_BytesToKey в Python.Используемые параметры описаны в документации CreateCipher: MD5, без соли, одна итерация.В CTR-режиме IV обычно увеличивается с каждым блоком, начиная со значения, которое должно быть определено.CreateCipher использует в качестве начального значения IV, определяемое с помощью EVP_BytesToKey.Поэтому функциональность CreateCipher может быть реализована в Python следующим образом:

    import hashlib
    from Crypto.Cipher import AES
    from Crypto.Util import Counter
    
    ...
    
    encrypted = '5e99b5190f12143c057f6bdd8625f958682e737c11e138a2f571c050313dbe1008347604c7c7e8bf506a0a'   # Example
    
    # Generate key and iv
    keySize = 16
    ivSize = 16
    digest = hashlib.md5
    salt = b''
    password = b'123456'                                                                                   # Example
    iteration = 1
    keyiv = EVP_BytesToKey(keySize, ivSize, digest, salt, password, iteration)
    key = keyiv[0]
    iv = keyiv[1]
    
    # Define counter
    nbits = 128
    initial_value = int.from_bytes(iv, byteorder = 'big');
    counter = Counter.new(nbits, initial_value = initial_value)
    
    # Decrypt
    cipher = AES.new(key, AES.MODE_CTR, counter = counter)
    decrypted = cipher.decrypt(bytes.fromhex(encrypted))
    print("Decrypted: " + decrypted.decode('utf8'))
    

    Зашифрованный текст был сгенерирован с помощью кода NodeJS с использованием следующего ввода:

    key = '123456';
    data = 'The quick brown fox jumps over the lazy dog';
    
  • Обратите внимание, что CreateCipher устарело и больше не должно использоваться, особенно в сочетании с режимом CTR.Вместо этого можно использовать CreateCipheriv.В режиме CTR важно, чтобы пара ключ / IV использовалась только один раз.В противном случае безопасность будет потеряна, см. здесь .CreateCipher не обеспечивает рандомизацию, т. Е. Один и тот же пароль всегда генерирует один и тот же ключ и IV и, следовательно, всегда один и тот же поток ключей.Следовательно, безопасность теряется, если один и тот же пароль используется несколько раз.CreateCipheriv, с другой стороны, ожидает ключ и случайный IV.Здесь ключ может использоваться несколько раз, пока рандомизация IV гарантирует, что пары ключ / значение не повторяются, см. здесь .

...