将 Java (BouncyCastle) 移植到 NodeJs (CryptoJS)

Porting Java (BouncyCastle) to NodeJs (CryptoJS)

我目前正在尝试使用 BouncyCastle 将以下代码从 Java 移植到使用 CryptoJS 的 NodeJs(但我愿意为 NodeJS 使用不同的库)。

唯一重要的是,代码的结果是一样的。

Java:

import java.security.Security;
import javax.xml.bind.DatatypeConverter;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.macs.CMac;
import org.bouncycastle.crypto.params.KeyParameter;

public class MainIntel {

    public static void main(String args[]) {
        Security.addProvider(new BouncyCastleProvider());

        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            System.out.println("Bouncy Castle provider is NOT available");
        } else {
            byte[] kSdm = toByteArray("00000000000000000000000000000000");
            System.out.println(toHexString(kSdm));

            byte[] sv2 = toByteArray("3CC30001008004DE5F1EACC0403D0000");
            System.out.println(toHexString(sv2));

            byte[] kSes = calculateMFCMAC(kSdm, sv2);
            System.out.println(toHexString(kSes));
        }
    }

    public static String toHexString(byte[] array) {
        return DatatypeConverter.printHexBinary(array);
    }

    public static byte[] toByteArray(String s) {
        return DatatypeConverter.parseHexBinary(s);
    }

    public static byte[] calculateMFCMAC(byte[] key, byte[]
            valueToMAC) {

        try {

            int cmacSize = 16;
            BlockCipher cipher = new AESFastEngine();
            Mac cmac = new CMac(cipher, cmacSize * 8);
            KeyParameter keyParameter = new KeyParameter(key);
            cmac.init(keyParameter);
            cmac.update(valueToMAC, 0, valueToMAC.length);
            byte[] CMAC = new byte[cmacSize];
            cmac.doFinal(CMAC, 0);
            
            return CMAC;
 
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

}

此代码给出以下输出:

00000000000000000000000000000000
3CC30001008004DE5F1EACC0403D0000
3FB5F6E3A807A03D5E3570ACE393776F

节点:

const CryptoJS = require('crypto-js');

const kSdm = '00000000000000000000000000000000';
console.log(kSdm);
const sv2 = '3CC30001008004DE5F1EACC0403D0000';
console.log(sv2);
const kSes = encrypt(kSdm, sv2);
console.log(kSes);

function encrypt(key, data) {
    const ciphertext = CryptoJS.AES.encrypt(
        CryptoJS.enc.Hex.parse(data),
        CryptoJS.enc.Hex.parse(key),
        {
            padding: CryptoJS.pad.NoPadding,
            mode: CryptoJS.mode.CBC,
            iv: CryptoJS.enc.Hex.parse(key)
        },
    ).toString();
    return Buffer.from(ciphertext, 'base64').toString('hex');
}

但是这段代码给了我:

00000000000000000000000000000000
3CC30001008004DE5F1EACC0403D0000
42808a1bc75ba899a50471b1c6c1bbe3

NodeJs - 选项 2:

var key = new Buffer('00000000000000000000000000000000', 'hex');
var src = new Buffer('3CC30001008004DE5F1EACC0403D0000', 'hex');
cipher = crypto.createCipheriv('aes-128-cbc', key, Buffer.alloc(0));
cipher.setAutoPadding(false);
result = cipher.update(src).toString('hex');
result += cipher.final().toString('hex');
console.log(result);

还给我:

42808a1bc75ba899a50471b1c6c1bbe3

所以结果输出

不同。

有人知道我该如何解决吗?就像我说的,我愿意使用任何其他 NodeJS 加密库,如 jsrsasign 等。

感谢您的帮助:)

crypto-js 没有实现 AES-CMAC 算法,所以你会得到不同的结果。 我发现了一个 node-aes-cmac。使用它,我得到了预期的输出。

参考代码:

var aesCmac = require('node-aes-cmac').aesCmac;
 
 
// Example with buffers.
var bufferKey = Buffer.from('00000000000000000000000000000000', 'hex');
var bufferMessage = Buffer.from('3CC30001008004DE5F1EACC0403D0000','hex');
var options = {returnAsBuffer: true};
cmac = aesCmac(bufferKey, bufferMessage, options);

console.log("cmac "+ Buffer.from(cmac, 'base64').toString('hex')) ;

**Output** 

cmac 3fb5f6e3a807a03d5e3570ace393776f