【问题标题】:encrypt using ase256 gives different output in python and nodejs使用 ase256 加密在 python 和 nodejs 中给出不同的输出
【发布时间】:2019-03-18 17:13:27
【问题描述】:

我正在尝试使用 key = "secret_key" 和文本 "11869021012" 加密字符串 "1"。早些时候我在nodejs中写过这个。现在我想把它移植到python。但令人惊讶的是,两者都给出了不同的输出。

var crypto = require('crypto');

function getBytes (str) {
  let bytes = [], char;
  str = encodeURI(str);
  while (str.length) {
    char = str.slice(0, 1);
    str = str.slice(1);

    if ('%' !== char) {
      bytes.push(char.charCodeAt(0));
    } else {
      char = str.slice(0, 2);
      str = str.slice(2);

      bytes.push(parseInt(char, 16));
    }
  }
  return bytes;
};


function getIV (str, bytes){
    iv = getBytes(str);
    if(!bytes) bytes = 16;
    for(let i=iv.length;i<bytes;i++) {
      iv.push(0);
    }
    return Buffer.from(iv);
};

function getKey (pwd){
    pwd = Buffer.from(getBytes(pwd), 'utf-8');
    let hash = crypto.createHash('sha256');
    pwd = hash.update(pwd).digest();
    return pwd;
};

function createCipherIV (algorithm, input_key, iv_input, text){
    let iv = getIV(iv_input);
    let key = getKey(input_key);
    let cipher = crypto.createCipheriv(algorithm, key, iv);
    let encrypted = cipher.update(text)
    encrypted += cipher.final('base64');
    return encrypted;
}

output = createCipherIV('aes256', 'secret_key', '11869021012', '1') 
console.log(output)

这将产生输出: s6LMaE/YRT6y8vr2SehLKw==

python 代码:

# AES 256 encryption/decryption using pycrypto library
import base64
import hashlib

from Crypto.Cipher import AES
from Crypto import Random

BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

password = "secret_key"

def encrypt(raw, password):
    private_key = hashlib.sha256(bytearray(password, "utf-8")).digest()
    raw = pad(raw)
    iv = b'11869021012\x00\x00\x00\x00\x00'
    cleartext = bytearray(raw, 'utf-8')
    cipher = AES.new(private_key, AES.MODE_CBC, iv)

    return base64.b64encode(iv + cipher.encrypt(cleartext))

# First let us encrypt secret message
encrypted = encrypt("1", password)
print(encrypted)

这将产生输出: MTE4NjkwMjEwMTIAAAAAALOizGhP2EU+svL69knoSys=

我在这里使用 aes256 算法来加密消息。 显然它们非常接近,但节点似乎正在用一些额外的字节填充输出。有什么想法可以让两者互操作吗?

【问题讨论】:

  • 你应该匹配操作模式,总之一切。 const algorithm = 'aes-256-cbc'; JS 如果你想使用CBC模式。
  • 即使在使用 'aes-256-cbc' 之后,我也会得到一些输出
  • 因为python中没有加密,只有base64编码。
  • 在我们做 cipher.encrypt(cleartext)) 时就在那里。对吗?
  • Rob 的回答没有解决您的问题吗?

标签: encryption aes cryptojs pycrypto


【解决方案1】:

首先,在一个安全的加密系统中,您应该期望每次加密时输出都不同,即使使用相同的代码也是如此。您的这一事实并不表明它是不安全的密码。通常这是通过添加随机 IV 来完成的。

你的 IV 是“11869021012”,这很糟糕(因为它不是随机的,甚至不是 16 个字节),但看起来你在两者中使用它的方式都是一样的,所以没关系。

您的密码是字符串的 SHA-256,这是一种创建密钥的可怕方式,但在这两种情况下,您似乎仍然使用相同的方式,所以没关系。

您的问题是 Python 代码发出 IV 后跟密文。您的 JS 代码不会发出 IV;它只发出密文。所以你可能在 Python 中是这个意思:

return base64.b64encode(cipher.encrypt(cleartext))

或者您需要重新编写 JavaScript 以在 Base64 编码之前将 IV 和密文粘合在一起。

【讨论】:

  • 谢谢@rob-napier 我的错。我正在额外添加iv。现在得到类似的输出。
猜你喜欢
  • 1970-01-01
  • 2018-09-28
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2021-08-04
  • 2012-11-10
相关资源
最近更新 更多