RSA_sign и RSACryptoProvider.VerifySignature - PullRequest
2 голосов
/ 11 мая 2010

Я пытаюсь узнать, как получить некоторый код, использующий OpenSSL для криптографии, чтобы хорошо играть с другой программой, которую я пишу на C #, с использованием поставщиков криптографии Microsoft, доступных в .NET.

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

// Code in C, using the OpenSSL RSA implementation

char msgToSign[] = "Hello World";     // the message to be signed
char signature[RSA_size(rsa)];        // buffer that will hold signature
int slen = 0;                         // will contain signature size

// rsa is an OpenSSL RSA context, that's loaded with the public/private key pair

memset(signature, 0, sizeof(signature));

RSA_sign(NID_sha1
      , (unsigned char*)msgToSign
      , strlen(msgToSign)
      , signature
      , &slen
      , rsa);

// now signature contains the message signature
//  and can be verified using the RSA_verify counterpart
// .. I would like to verify the signature in C#

В C # я бы сделал следующее:

  • импортирует открытый ключ другой стороны в RSACryptoServiceProvider объект
  • получить сообщение и его подпись
  • попытаться проверить подпись

У меня работают первые две части (я проверил, что открытый ключ загружается правильно, потому что мне удалось отправить зашифрованный RSA-текст из кода C # в код OpenSSL в C и успешно расшифровать его)

Чтобы проверить подпись в C #, я попытался использовать метод: VerifySignature для RSACryptoServiceProvider, но это не сработало. И, копаясь в Интернете, я смог найти лишь некоторую расплывчатую информацию, указывающую на то, что .NET использует другой метод для генерации подписи, чем OpenSSL. Итак, кто-нибудь знает, как этого добиться?

EDIT

Так как был запрос, вот сторона C # вещей.

byte[] receivedSignature;
// ....
// receivedSignature is set to the byte array generated by the OpenSSL side
//   I've verified this much is working correctly

// I use my utility to parse a PEM file and extract the other side's public key
//   also, verified to be working correctly - the public key is good.
RSACryptoServiceProvider rsa = MyPEMLoader.LoadFromFile("publicKey.pem");

string msgToVerify = "Hello World";
byte[] msgBytes = Encoding.ASCII.GetBytes(msg);  // other side uses ASCII, so do the same
bool verified = rsa.VerifyHash(msgBytes, "SHA1", receivedSignature);

// verfied is false.. verfification failed!

Ответы [ 2 ]

1 голос
/ 11 мая 2010

Это может помочь, если вы показали свой код C #. Я думаю, что это должно быть что-то вроде:

    string msg = ...;
    byte[] localData = Encoding.UTF8.GetBytes(msg);
    bool ok = rsa.VerifyHash(localData, "SHA1", receivedhash);

И, конечно, я просто угадываю часть UTF-8. Может быть и ASCII.

Редактировать: Вот страница MSDN . Кажется, что пример делает это по-другому, localData хэшируется первым.

hashedData = hash.ComputeHash(signedData);
return rsaCSP.VerifyHash(hashedData, CryptoConfig.MapNameToOID("SHA1"), signature);
0 голосов
/ 05 июня 2011

Вы должны удалить вашу утилиту pem, это не обязательно и используйте

 var cert = new X509Certificate2(HttpContext.Current.Request.MapPath("~/App_Data/PublicKey.pem"), "");
var rsaCryptoIPT = (RSACryptoServiceProvider)cert.PublicKey.Key;
var sha1 = new SHA1CryptoServiceProvider();
if (!rsaCryptoIPT.VerifyData(data, sha1, signature))
                throw new InvalidOperationException("Invalid signature from bank ");

Если это не поможет, вы можете опубликовать код для чтения файлов pem.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...