javascript中的aes-cmac没有给出与python中相同的结果

问题描述

我正在编写代码来读取/写入 NTAG424 DNA NFC 标签。我完全用 javascript 来做这件事,因为我希望能够在 React Native 应用程序中使用它。

NTAG 424 DNA and NTAG 424 DNA TagTamper features and hints 中,它们显示了您每一步应该获得的结果。但他们使用的是 python 解决方案。

输入消息是A55A0001008013C56268A548D8FBBF237CCCAA20EC7E6E48C3DEF9A4C675360F输出(根据手册)是1309C877509E5A215007FF0ED19CA564。而我得到 7CCEF6FEB32F34CA48CB685ECAA0F32C

因为我需要能够在商业上使用这个代码,所以我不能只使用任何库。

function generateSubkeys(key) {
  const cipher = crypto.createCipheriv("aes-128-ecb",key,"");

  const cryptedKey = cipher.update(iv);

  let subkey1 = bt.bitShiftLeft(cryptedKey);
  if (msb(cryptedKey[0]) & 0x80) {
    subkey1 = xor(subkey1,0x87);
  }

  let subkey2 = bt.bitShiftLeft(subkey1);
  if (msb(subkey1[0]) & 0x80) {
    subkey2 = xor(subkey2,0x87);
  }
  return { subkey1: subkey1,subkey2: subkey2 };
}

function msb(bytes) {
  return bytes >>> 31;
}
function aes(key,message) {
  const cipher = crypto.createCipheriv(
    "aes-" + key.length * 8 + "-cbc",iv
  );

  var result = cipher.update(message);
  cipher.final();

  return result;
}

function aesCmac(key,message) {
  const { subkey1,subkey2 } = generateSubkeys(Buffer.from(key,"hex"));
  let numBlocks = Math.ceil(message.length / blockSize);
  var lastBlockRemainder = message.length % blockSize;

  if (numBlocks === 0) {
    numBlocks = 1;
  }

  var messageArray = getMessageArray(message,numBlocks,lastBlockRemainder);
  if (lastBlockRemainder === 0) {
    messageArray[numBlocks - 1] = xor(messageArray[numBlocks - 1],subkey1);
  } else {
    messageArray[numBlocks - 1] = xor(messageArray[numBlocks - 1],subkey2);
  }

  var c = aes(
    key,Buffer.concat(messageArray.slice(0,messageArray.length - 1))
  );
  let c_xor_m = xor(c,messageArray[messageArray.length - 1]);
  c = aes(key,c_xor_m);

  return c;
}

function getMessageArray(message,lastBlockRemainder) {
  var index = 0;
  var messageArray = [];
  if (lastBlockRemainder !== 0) {
    let padding = "80" + "00".repeat(16 - lastBlockRemainder - 1);
    let appendToMessage = Buffer.from(padding,"hex");
    message = Buffer.concat([message,appendToMessage]);
  }
  for (index = 0; index < numBlocks; index++) {
    let messageBlock = message.slice(
      index * blockSize,(index + 1) * blockSize
    );
    messageArray.push(messageBlock);
  }

  return messageArray;
}

我已经尝试了此处提到的 AES-CMAC module for Node.js? 并将代码完全重写为我自己的 AES-CMAC 算法版本。在我尝试过的和我制作的(在 NIST Special Publication 800-38B 的帮助下)中,我得到了相同的结果。

现在我陷入了两难,要么是我的代码错误的,要么是 python crypto library(我不完全理解代码)是错误的。

谁能帮我弄清楚这两个中哪一个是真的?如果我的代码有误,请帮我修复。

解决方法

我找到了答案:javascript 中的 Crypto 库有一个 aes-cbc 密码,它说(并且确实)接受缓冲区和数组。但两者的结果是不同的。

当我使用 UInt8Array 时,我得到了正确的结果。我完全重写了一个 aes-cmac 算法,只是为了弄清楚这是我所需要的。