Как кодировать данные с помощью PKCS #1 v1.5 в .Net

Я пытаюсь выполнить аутентификацию активной карты на смарт-карте, совместимой с PIV. См. Приложение A.2 к этот документ для более подробной информации.

У меня есть открытый ключ из связанного сертификата X.509. Мне нужно отправить карте какие-то случайные данные, которые она подпишет своим закрытым ключом, затем мне нужно проверить подпись с помощью открытого ключа.

Пример в документе, который я разместил, отмечает, что данные, которые они отправляют для подписи, «закодированы в соответствии со схемой заполнения подписи PKCS # 1 v1.5». Как мне так кодировать мои случайные данные? Я думал, что заполнение данных было частью процесса подписи RSA.

// Generate random data
byte[] randomData = new byte[128];
Random random = new Random();
random.NextBytes(randomData);

// Hash the random data
SHA1Managed sha1 = new SHA1Managed();
byte[] hash = sha1.ComputeHash(randomData);

// Send the hash to the Smart Card and get back signed data
byte[] signature = SendToSmartCardForSignature(hash);

// Verify the data and the signature match using the public key
RSACryptoServiceProvider rsa = smartCardCertificate.PublicKey;
bool verified = rsa.VerifyData(randomData, CryptoConfig.MapNameToOID("SHA1"), signature);

// verified is false...why?

person Ben    schedule 14.01.2011    source источник


Ответы (2)


«Правильный» способ сделать это с помощью криптографической функциональности .NET — реализовать собственную реализацию System.Security.Cryptography.RSA. Метод DecryptValue должен вызывать "сырой" метод шифрования с закрытым ключом RSA для смарт-карт. Также не забудьте переопределить свойство KeySize.

Затем вы можете использовать RSAPKCS1SignatureFormatter для заполнения данных и вызовите смарт-карту.

person Rasmus Faber    schedule 14.01.2011
comment
Потрясающий. У меня это работает, но это немного беспорядок. Я постараюсь реализовать это, чтобы очистить его. Спасибо. - person Ben; 14.01.2011

Раздел 9.2 — EMSA-PKCS1-v1_5 этого документа описывает метод кодирования.

Я не смог найти в библиотеке .NET ничего, что могло бы сделать это за меня, поэтому я сделал это вручную, так как это довольно просто.

Хэшируйте ваши данные, как я делал в своем исходном примере кода.

  1. Кодируйте хешированные данные в значение ASN.1 типа DigestInfo — цитируемый документ фактически предоставляет массивы байтов, необходимые для этого, поэтому вам не нужно разбираться в этом. Я использовал SHA1, поэтому мне просто нужно было вставить следующий массив байтов в мой массив байтов хешированных данных с индексом 0: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14

  2. Закодированный массив байтов PKCS #1 v1.5 имеет вид {0x00, 0x01, PS, 0x00, T}, где T — массив байтов DigestInfo из первого шага, а PS — массив байтов 0xFF. Длина массива PS зависит от вас. В моем случае этот массив должен был быть подписан закрытым ключом RSA-2048, поэтому длина массива должна была быть 0x100, поэтому я сделал PS достаточно длинным, чтобы достичь этой цели.

Отправьте закодированный массив байтов на смарт-карту для подписи. Смарт-карта выполнит фактическую операцию RSA с закрытым ключом и вернет результат. Функция .NET VerifyData возвращает значение true.

person Ben    schedule 14.01.2011
comment
Извините, не могли бы вы мне помочь. Вы сказали, что у вас есть 2048-битный ключ rsa, поэтому массив должен иметь длину 0x100. Какого размера он должен быть, если у меня 1024-битный ключ? - person GregorMohorko; 04.02.2017
comment
Я не уверен, но, наверное, половина? 0x100 — это 256, попробуйте 128 или 0x80. - person Ben; 05.02.2017