Цифровая подпись, сделанная в C #, не проверяется в переполнении стека

У меня есть приложение на C #, которое подписывает данные с помощью RSA. Код выглядит следующим образом:

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportCspBlob(privateKeyBlob);

SHA1 sha1 = new SHA1CryptoServiceProvider();
sha1.ComputeHash(myData);

byte[] signature = rsa.SignHash(sha1.Hash, CryptoConfig.MapNameToOID("SHA1"));

Я не могу проверить подпись в C ++. Код выглядит следующим образом:

HCRYPTPROV cryptProvider;
CryptAcquireContext(&cryptProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
// PROV_RSA_SIG does not work

HCRYPTKEY publicKey;
CryptImportKey(cryptProvider, publicKeyBlob, publicKeyBlobLength, 0, 0, &publicKey);

HCRYPTHASH hash;
CryptCreateHash(cryptProvider, CALG_SHA1, 0, 0, &hash);
CryptHashData(hash, myData, myDataLength, 0);

BOOL isSigOk = CryptVerifySignature(hash, signature, signatureLength, publicKey, NULL, CRYPT_NOHASHOID);

Подтверждение возвращает 0, GetLastError() возвращает 2148073478 «Неверная подпись». Хеши одинаковые. Я попробовал это с и без CRYPT_NOHASHOID флаг.

Я попытался подписать данные в C ++ (просто для сравнения результатов). Я удалил CRYPT_VERIFYCONTEXT флаг. Но импорт закрытого ключа BLOB завершается с ошибкой 1008 «Была сделана попытка сослаться на несуществующий токен». Генерация нового ключа завершается с той же ошибкой.

3

Решение

После исчерпывающего байтового осмотра я получил его на работу. В приложении C # было две проблемы.

1) я использовал new RSACryptoServiceProvider(RsaKeySize) генерировать пару ключей. Проблема в том, что это генерирует пару ключей для обмена ключами, а не для подписи. C # не возражает, но это вызвало проблемы в программе C ++. Правильный способ генерации пары ключей:

CspParameters parameters = new CspParameters();
parameters.KeyNumber = (int)KeyNumber.Signature;

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(RsaKeySize, parameters);

2) RSACryptoServiceProvider инвертирует свой вывод (подписи, зашифрованные данные). Это упоминается в документация. Так что вам нужно Array.Reverse() вычисленная подпись перед сохранением.

3

Другие решения

Других решений пока нет …