【问题标题】:What is the correct behavior of C_Decrypt in pkcs#11?pkcs#11 中 C_Decrypt 的正确行为是什么?
【发布时间】:2019-06-29 14:35:36
【问题描述】:

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

我知道according to the standard 在使用 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,我也怀疑过 :)

【问题讨论】:

  • 我想到的一件事是,也许这实际上是一种防御类型的填充预言攻击,其中攻击者以某种方式控制输出缓冲区的大小,并以这种方式揭示了纯文本。这可能吗?
  • AFAIK 库的内部目的需要额外的缓冲区空间,以确保它可以产生正确的输出(例如内存移动)。我认为这是为了保护目的而这样做的,在您的情况下,仅出于这个原因,它就等于一个额外的填充块大小。尝试加密/解密 255 字节并在第一步检查缓冲区大小。
  • 问题是强制这个保护空间是否是正确的行为。我很确定它是用于您解释的目的。
  • 符合PKCS#11的规范,所以答案是肯定的。在 Microsoft 的 Crypto API 中可以看到相同的行为。
  • 我同意这似乎与标准不矛盾。

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


【解决方案1】:

我过去曾使用 CKM.AES_CBC_PAD 填充机制和 C_Decrypt。您必须对 C_Decrypt 进行 2 次调用 (第一次 ==> 要获取纯文本的大小,第二次 ==> 实际解密)。请参阅文档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 模式对输入数据进行编码,以防止数据被误解为网络控制字节。

【讨论】:

  • 这是(部分)很好的信息,但我不能将其标记为已接受的答案,因为它并不完全准确。如果您知道预期的输出量,标准中的任何内容都不会强制您进行两次调用。此外,关于输入数据格式的部分非常不清楚,似乎与我无关。也许这是您正在考虑的一个特定于平台的问题,它可能特别与 Java 相关,但一般不相关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-01
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多