I`m porting some crypto code from Python to NodeJS. I have Python example that works perfectly:
from Cryptodome.Cipher import AES
key = bytes.fromhex("befe6acee59a8d3d3c97eeea8cdb9e99");
nonce = bytes.fromhex("5830b603313800002298c44124");
cipherpayload = bytes.fromhex("9f3f2d8dd339");
cipher = AES.new(key, AES.MODE_CCM, nonce=nonce, mac_len=4) # mac_len 4 or 8 or 16 keeps code working
cipher.update(bytes.fromhex("11")) # commenting this line keeps code working
print("result:" + "\"" + cipher.decrypt(cipherpayload).hex() + "\""); # prints result: "011003000104" as intended
But NodeJS version is not working:
const crypto = require('crypto');
let key = Buffer.from('befe6acee59a8d3d3c97eeea8cdb9e99', 'hex');
let nonce = Buffer.from('5830b603313800002298c44124', 'hex');
let cipherpayload = Buffer.from('9f3f2d8dd339', 'hex');
let cipher = crypto.createDecipheriv('aes-128-ccm', key, nonce, { authTagLength: 4 });
cipher.setAAD(Buffer.from('11', 'hex'), { plaintextLength: cipherpayload.length });
console.log('result: ' + '"' + cipher.update(cipherpayload).toString('hex') + '"'); // prints result: ""
All found examples about aes-128-ccm and NodeJS uses cipher.setAuthTag() with tag, but I have no authTag and Python version works correctly. I there any way to decrypt this in NodeJS?
Node version: v17.3.0
Python 3.9.2
Platform: 2021-10-30-raspios-bullseye-armhf-lite
Also tested on 64bit Debian, same result.
Edited:
Full raw network data for this question that I received from device is '95fe5830b603312298c44124f89f3f2d8dd3393800001a'
brute forced tag (4 bytes let me to do this) and found tag value '07860841'
.
I believe, the tag should be in the network data, but I can`t figure out where.
Edited 2:
Brute forced another packet, looked to many packets and found that tag is definitely not transmitting from the device. It is device developer bug.
Really there is no way to correctly decrypt data wit integrity check.
This answer DANGEROUS, you SHOULD check authTag, but if you need to skip this check, jscrypto (https://github.com/Hinaser/jscrypto) helps to do this.
const JsCrypto = require('jscrypto');
var key = JsCrypto.Hex.parse("befe6acee59a8d3d3c97eeea8cdb9e99");
var nonce = JsCrypto.Hex.parse("5830b603313800002298c44124");
var cipherpayload = JsCrypto.Hex.parse("9f3f2d8dd339");
var cp = new JsCrypto.CipherParams({ cipherText: cipherpayload });
var decrypted = JsCrypto.AES.decrypt(cp, key, { iv: nonce, mode: JsCrypto.mode.CCM, padding: JsCrypto.pad.NoPadding });
console.log('result: ' + '"' + decrypted.toString() + '"');