I'm trying to port working code decoding the values read from an NXP NTAG424 NFC tag in a web-based application. I have a working example that uses crypto
in a node.js environment but when I try to port it so crypto.subtle
it fails.
The issue seems to be the decipher.setAutoPadding(false)
, which when removed in the crypto
example below causes an error when calling .final()
. This is strange because the payload being decrypted, ENC
, is 32 bytes (hex) and the encrypted source coming from the NTAG424 IC is 16 bytes according to documentation (4.4.2.1):
Random padding generated by the PICC to make the input 16 bytes long. It is only relevant if SDMReadCtr is not mirrored, as SDMReadCtr adds uniqueness already
Constants shared between both approachs:
const KEY = '00000000000000000000000000000000'
const ENC = 'EF963FF7828658A599F3041510671E88'
const IV = Buffer.alloc(16)
I don't understand why the padding is throwing an error, assuming it's the same issue with both the crypto
and crypto.subtle
approaches, as the source data is exactly 16 bytes, but searches on this have yielded no clear solution.
Thanks for any insights on how to get this to work with SubtleCrypto.
Apparently no padding was used during encryption (this is possible whenever the length of the plaintext already corresponds to an integer multiple of the AES block size, i.e. 16 bytes) or one that differs from PKCS#7 padding. If decryption is then carried out with PKCS#7 padding enabled, the bytes at the end do not match the specified padding, which leads to the error message. For correct decryption, the padding must be disabled in this case.
WebCrypto uses PKCS#7 padding by default and does not allow you to disable padding. Therefore, WebCrypto might not be the best choice for this task.
But if you absolutely have to use WebCrypto, there is a workaround: You have to append the missing block with the encrypted padding before decryption.
In CBC mode, when encrypting a block, the previous block is used as IV, i.e. to determine the required block, you only need to encrypt an empty block and use your ciphertext as IV (as your ciphertext consists of only one block).
The following code does this and can decrypt the ciphertext: