nodejs中的AES-256-ECB加密与php MCrypt模块不匹配

时间:2017-09-14 17:34:48

标签: php node.js encryption mcrypt

我正在接收来自外部方的加密消息。他们使用php和mcrypt进行加密,具有以下配置

  • algo:rijndael-256
  • 模式:ecb
  • 示例加密邮件:"a364cb3bb55c2788b25f04ef6867d770771a7d0fdd44462b40233ea76a8bd00d"。其原始邮件为"thank you"

以下图像显示了配置 Alt text

从我这边,我正在使用nodejs来解密。我有node-mcrypt binding的工作版本。但我想避免本机模块,所以我正在寻找一个纯粹的JavaScript解决方案。

我尝试了节点crypto,但其aes-256-ecb生成了不同(不可读)的输出

在nodejs中使用MCrypt绑定的工作代码:

const decryptAES256 = (encrypted: string, password: string): string => {
  try {
    const desEcb = new MCrypt('rijndael-256', 'ecb');
    desEcb.open(md5(password));
    const ciphertext = desEcb.decrypt(new Buffer(encrypted, 'hex'));
    const plain = ciphertext.toString();

    const isUTF8 = plain.split('').every(c => c.charCodeAt(0) <= 256);

    if (!isUTF8) {
      throw new Error('Invalid Input');
    }

    const unpadding = plain
      .split('')
      .filter(c => c.charCodeAt(0))
      .join('');

    return unpadding;
  } catch (ex) {
    console.error('Invalid token');
  }
};

2 个答案:

答案 0 :(得分:1)

当您声明可能指定不是AES的256位块大小的“rijndael-256”时。 AES有一个块大小:128位。

这似乎是由32位二进制字节的加密输出产生的,对于“谢谢”的输入,输出应该是一个块,因此块大小似乎是32字节(256位)。

  1. 不要使用mcrypt,它只会导致互操作性问题。
  2. 确保使用的是AES,它可以是128位块大小的rijndael。
  3. 请勿将密钥大小与块大小混淆。
  4. 如果输入数据不总是块大小的倍数,则必须将填充添加到输入数据中,指定填充,PKCS#7(néePKCS#5)填充,这可能是默认值。 mcrypt不支持标准填充。如果必须与mcrypt进行互操作,则需要指定无填充并自行执行填充。

答案 1 :(得分:0)

在意识到rijndael 256不等同于aes 256(128版本)之后,我选择在纯javascript中找到一个rijndael特定的lib,这是一个有效的代码:

const Rijndael = require('rijndael-js');

describe('cipher', () => {
  it('should work', () => {
    const text = 'thank you';
    //  + String.fromCharCode(0).repeat(5)
    const key = '94a08da1fecbb6e8b46990538c7b50b2';
    const cipher = new Rijndael(key, 'ecb');
    const ciphertext = cipher.encrypt(text, 256);

    expect(ciphertext.toString('hex')).toBe(
      'a364cb3bb55c2788b25f04ef6867d770771a7d0fdd44462b40233ea76a8bd00d'
    );

    const plaintext = cipher.decrypt(ciphertext, 256);
    const unpadded = plaintext.toString().replace(/\u0000*$/g, '');
    expect(unpadded).toBe(text);
  });
});