Как правильно C_Decrypt в pkcs#11?

Я использую C_Decrypt с CKM_AES_CBC_PAD механизм. Я знаю, что мой зашифрованный текст длиной 272 байта должен расшифровываться до 256 байтов, что означает добавление полного блока заполнения.

Я знаю, что в соответствии со стандартом при вызове C_Decrypt с NULL выходным буфером функция может вернуть выходную длину, которая несколько больше, чем фактическая требуемая длина, в частности, когда используется заполнение, это понятно, так как функция не может знать, сколько байтов заполнения находится в последнем блоке без переноса из фактического дешифрования.

Таким образом, вопрос заключается в том, имеет ли смысл, если я знаю, что я должен получить ровно 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 случайно, что я тоже подозревал на мгновение:)

1 ответ

В прошлом я использовал механизм заполнения CKM.AES_CBC_PAD с C_Decrypt. Вы должны сделать 2 вызова C_Decrypt (1-й ==> Чтобы получить размер простого текста, 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 сохраняет данные от неверного понимания как байты управления сетью.

Другие вопросы по тегам