pkcs#11中C_Decrypt的正确行为是什么?

时间:2019-06-29 14:35:36

标签: pkcs#11 pkcs#7 hsm cbc-mode cryptoki

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

我知道according to the standard在使用空输出缓冲区调用C_Decrypt时,该函数可能会返回比实际所需长度稍长的输出长度,尤其是在使用填充时,这是可以理解的,因为该函数在不执行实际解密的情况下无法知道最终块中有多少个填充字节。

所以问题是,是否知道我应该准确返回256个字节,例如在上面我解释的场景中,尽管我仍然仍然收到CKR_BUFFER_TOO_SMALL错误,这是否有意义通过一个256字节的缓冲区? (为清楚起见:我在适当的输出缓冲区长度参数中指示这是输出缓冲区的长度,请参见C_Decrypt的参数以了解我的意思)

我在使用Safenet Luna设备时遇到此问题,不确定如何处理。是我的代码错误是没有通过在输出缓冲区中传递NULL首先不查询长度,还是在HSM / PKCS11库方面的错误?

我应该提到的另一件事是,当我提供一个272(256 + 16)字节的输出缓冲区时,调用成功,并且我注意到我正在取回预期的纯文本,但也取回了padding块。 表示16个最后的字节,其值为0x10。但是,输出长度正确更新为256,不是 272-这也证明我不是偶然使用了CKM_AES_CBC而不是CKM_AES_CBC_PAD,我也怀疑了一会儿:)

1 个答案:

答案 0 :(得分:1)

我以前在 C_Decrypt 中使用 CKM.AES_CBC_PAD 填充机制。您必须进行两次调用 C_Decrypt (第一个==>以获得纯文本的大小,第二个==>实际解密)。请参阅文档here,该文档讨论确定保留纯文本所需的缓冲区的长度。

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

//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模式对输入数据进行编码,也可以避免误解数据作为网络控制字节。