2

我正在使用C_DecryptCKM_AES_CBC_PAD机制。我知道我的 272 字节长的密文实际上应该解密为 256 字节,这意味着添加了一个完整的填充块。

我知道根据标准,在使用 NULL 输出缓冲区调用时C_Decrypt,函数可能会返回比实际所需长度稍长的输出长度,特别是在使用填充时,这是可以理解的,因为函数不知道有多少填充字节位于最终块中,而不执行实际解密。

所以问题是,如果我知道我应该得到准确的 256 字节,例如在我上面解释的场景中CKR_BUFFER_TOO_SMALL,尽管传递了 256 字节的缓冲区,我仍然得到错误是否有意义?(说清楚:我是在相应的输出缓冲区长度参数中表示这是输出缓冲区的长度,看C_Decrypt的参数来观察我的意思)

我在使用 Safenet Luna 设备时遇到了这种行为,但不知道该怎么做。是我的代码没有通过在输出缓冲区中传递 NULL 来首先查询长度的错误,还是 HSM/PKCS11 库端的错误?

我也许应该提到的另一件事是,当我提供 272 (256+16) 字节的输出缓冲区时,调用成功,我注意到我正在取回我预期的明文,还有填充块,这意味着 16 个最终字节值 0x10。但是,输出长度正确更新为 256,而不是272 - 这也证明我没有意外使用 CKM_AES_CBC 而不是 CKM_AES_CBC_PAD,我也怀疑过 :)

4

1 回答 1

1

我过去曾使用C_Decrypt的CKM.AES_CBC_PAD填充机制。您必须对C_Decrypt进行 2 次调用(第一次 ==> 要获得纯文本的大小,第二次 ==> 实际解密)请参阅此处的文档,其中讨论了确定保存纯文本所需的缓冲区长度。

下面是显示解密行为的分步代码:

//Defining the decryption mechanism
CK_MECHANISM mechanism = new CK_MECHANISM(CKM.AES_CBC_PAD);

//Initialize to zero -> variable to hold size of plain text
LongRef lRefDec = new LongRef();

// Get ready to decrypt 
CryptokiEx.C_DecryptInit(session_1, mechanism, key_handleId_in_hsm);

// Get the size of the plain text -> 1st call to decrypt
CryptokiEx.C_Decrypt(session_1, your_cipher, your_cipher.length, null, lRefDec);

// Allocate space to the buffer to store plain text.  
byte[] clearText = new byte[(int)lRefDec.value];

// Actual decryption -> 2nd call to decrypt
CryptokiEx.C_Decrypt(session_1, eFileCipher, eFileCipher.length, eFileInClear,lRefDec);

有时,解密失败是因为您输入的加密数据误导了解密算法(但是,加密成功但相应的解密将失败)解密算法。因此,重要的是不要将原始字节直接发送到加密算法;而是使用 UTF-8/16 模式对输入数据进行编码,以防止数据被误解为网络控制字节。

于 2019-07-10T15:31:32.107 回答