为什么这三个算法最后输出的值不一样,一个node.js写的,一个python和go写的?

python代码:代码地址

import logging
import io
from hashlib import sha1
from struct import pack, unpack

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())
    @staticmethod
def decrypt(key, ibuf):
    r"""
    Return decrypted data.

    """
    obuf = io.BytesIO()
    totalSize = unpack("<I", ibuf.read(4))[0]
    logger.debug("totalSize: {}".format(totalSize))
    ibuf.seek(8)
    aes = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend())
    decryptor = aes.decryptor()
    x = ibuf.read()
    dec = decryptor.update(x) + decryptor.finalize()
    obuf.write(dec[:totalSize])
    return obuf.getvalue()  # return obuf.getbuffer()

node.js代码:

function decrypt (key, ibuf) {
  console.log(`totalSize: ${key.byteLength}`);
  const obuf = Buffer.alloc(0);
  const totalSize = ibuf.readUInt32LE(0);
  console.log(`totalSize: ${totalSize}`);
  const aesKey = crypto.createDecipheriv('aes-128-ecb', key, Buffer.alloc(0), { authTagLength: 0 });
  //const aesKey = crypto.createCipheriv('aes-128-ecb', key, Buffer.alloc(0), { authTagLength: 0 });
  const x = ibuf.slice(8);
  // const x = ibuf.slice(4, totalSize + 16 - (totalSize % 16));

// aesKey.final() 这里报错, 解密的时候 
// 报Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

  const dec = Buffer.concat([aesKey.update(x), aesKey.final()]);
  const resultBuf = dec.slice(0, totalSize);
  return resultBuf;
}

go 代码:代码地址

// standardDecrypt decrypt the CFB file format with ECMA-376 standard encryption.
func standardDecrypt(encryptionInfoBuf, encryptedPackageBuf []byte, opts *Options) ([]byte, error) {
    encryptionHeaderSize := binary.LittleEndian.Uint32(encryptionInfoBuf[8:12])
    block := encryptionInfoBuf[12 : 12+encryptionHeaderSize]
    header := StandardEncryptionHeader{
        Flags:        binary.LittleEndian.Uint32(block[:4]),
        SizeExtra:    binary.LittleEndian.Uint32(block[4:8]),
        AlgID:        binary.LittleEndian.Uint32(block[8:12]),
        AlgIDHash:    binary.LittleEndian.Uint32(block[12:16]),
        KeySize:      binary.LittleEndian.Uint32(block[16:20]),
        ProviderType: binary.LittleEndian.Uint32(block[20:24]),
        Reserved1:    binary.LittleEndian.Uint32(block[24:28]),
        Reserved2:    binary.LittleEndian.Uint32(block[28:32]),
        CspName:      string(block[32:]),
    }
    block = encryptionInfoBuf[12+encryptionHeaderSize:]
    algIDMap := map[uint32]string{
        0x0000660E: "AES-128",
        0x0000660F: "AES-192",
        0x00006610: "AES-256",
    }
    algorithm := "AES"
    _, ok := algIDMap[header.AlgID]
    if !ok {
        algorithm = "RC4"
    }
    verifier := standardEncryptionVerifier(algorithm, block)
    secretKey, err := standardConvertPasswdToKey(header, verifier, opts)
    if err != nil {
        return nil, err
    }
    // decrypted data
    x := encryptedPackageBuf[8:]
    blob, err := aes.NewCipher(secretKey)
    if err != nil {
        return nil, err
    }
    decrypted := make([]byte, len(x))
    size := 16
    for bs, be := 0, size; bs < len(x); bs, be = bs+size, be+size {
        blob.Decrypt(decrypted[bs:be], x[bs:be])
    }
    return decrypted, err
}

请大佬指教为什么我参考python代码写的node.js代码最后输出的内容是不一样的,py版和go版的可以解密成功,node.js的代码可以运行,但是最后解密出来的是不对的?是因为aes-128-ecb算法需要分块解密吗?

key 是16个字节的Buffer 类似这个 <Buffer 0b 9d 2f ab a2 d8 e6 e7 ac 2e c2 c5 a1 fc c4 a1> ibuf 是加密的密文,也是一个Buffer

阅读 2.1k
1 个回答

解密?为什么是用的 createChipheriv 而不是 createDechipheriv

你看有没有可能是这个地方:

    const x = ibuf.slice(8);
    const dec = Buffer.concat([aesKey.update(x), aesKey.final()]);

这里只取了 8 个字节出来,但总长按理说是 totalSize 个字节。所以如果解密内容不足,可能解密是会出错的。


2023-05-24 补充

我写了个小示例

const algorithm = "aes-128-ecb";

function encrypt(key, content) {
    const aes = crypto.createCipheriv(algorithm, key, null);
    let result = Buffer.concat([
        aes.update(content, "utf8"),
        aes.final()
    ]);
    return result;
}
function decrypt(key, data) {
    const aesKey = crypto.createDecipheriv(algorithm, key, Buffer.alloc(0), { authTagLength: 0 });
    const dec = Buffer.concat([aesKey.update(data), aesKey.final()]);
    return dec;
}

const key = randomBytes(16);
console.log("key", key);
const data = encrypt(key, "hello world, hi world, .....");
console.log(data);
const literal = decrypt(key, data).toString("utf-8");
console.log(literal);

加密解密没有问题。解密的部分试了,后两 Buffer.alloc(0)null 不影响,最后一个参数也没影响。所以如果你那里解密不出来,应该还是处理识别和处理上有问题。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏