Использование открытого ключа в кодировке Base64 для проверки подписи RSA - PullRequest
17 голосов
/ 15 февраля 2012

В двух словах, это моя проблема:

private string publicKeyString = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFOGwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWpbY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5yGPhGAAmqYrm8YiupwQIDAQAB";

/* Some transformation required, using publicKeyString to initiate a new RSACryptoServiceProvider object
*/

//for now:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

byte[] selfComputedHash = new byte[]; //left out of the example
byte[] signature = new byte[];

bool result = rsa.VerifyHash(selfComputedHash, CryptoConfig.MapNameToOID("SHA1"), signature);

Как видите, проблема заключается в инициировании нового RSACryptoServiceProvider с заданной строкой открытого ключа в кодировке Base64. Мне удалось создать экземпляр объекта с помощью объекта RSAParameters, загруженного байтами [] для модуля и экспоненты, полученными из этой строки открытого ключа, с помощью команды оболочки OpenSSL. Но так как этот открытый ключ может измениться в будущем, я хочу сохранить его в своем первоначальном виде в базе данных. Должен быть более простой способ справиться с этим.

Множество примеров, которые я до сих пор читал, позволяют избежать этой проблемы, экспортируя и импортируя сгенерированные закрытые и открытые ключи в и из объекта контейнера ключей и используя его в одном и том же фрагменте кода и, таким образом, не «передавая» ключ в некоторой строковой форме не хватает памяти. Некоторые люди выражали ту же проблему, как здесь, в StackOverflow, так и на других сайтах, но я пока не смог найти удовлетворительный ответ.

Любая идея приветствуется.

Справочная информация: Мой коммуникационный партнер вычисляет 20-байтовый хэш SHA1 из входной строки переменной длины, состоящей из информации, содержащейся в нескольких полях сообщения в кодировке ASCII. Затем этот хэш подписывается RSA с помощью закрытого ключа моего партнера и отправляется мне вместе с сообщением ASCII. По прибытии я сам вычисляю хеш SHA1, используя те же поля из сообщения ASCII, а затем пытаюсь проверить, не были ли эти поля изменены, вызывая VerifyHash.

Ключ предоставляется в 2 формах: обычная и noNL. Версия noNL включена в код выше, обычная версия такова:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFO
GwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWp
bY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5y
GPhGAAmqYrm8YiupwQIDAQAB
-----END PUBLIC KEY-----

Ответы [ 3 ]

14 голосов
/ 15 февраля 2012

Ваша строка является кодировкой base64 для SubjectPublicKeyInfo .Вы можете использовать Bouncycastle.net для его декодирования следующим образом:

byte[] publicKeyBytes = Convert.FromBase64String(publicKeyString);
AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(publicKeyBytes);
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters) asymmetricKeyParameter;
RSAParameters rsaParameters = new RSAParameters();
rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);
4 голосов
/ 15 февраля 2012

Первый base64 - это только кодировка некоторых двоичных данных.Существует несколько способов закодировать в двоичном виде открытый ключ RSA.Однако, если вы получили это от OpenSSL, это, скорее всего, структура * 1003. * в кодировке DER.

 RSAPublicKey ::= SEQUENCE {
     modulus            INTEGER,    -- n
     publicExponent     INTEGER  }  -- e

В общем случае вам понадобится декодер ASN.1, Mono.Security.dll one , но для такой простой структуры вы, возможно, захотите сделать это вручную , поскольку ASN.1 в основном представляет собой Tag , Length и Значение .

0 голосов
/ 15 февраля 2012

Если ваш партнер также использует .NET, он может получить производную от Mono makecert https://github.com/mono/mono/blob/bf55818da11240bd108dc51b374fae3d3b5482ce/mcs/tools/security/makecert.cs для генерации файлов сертификатов и отправки вам напрямую.

В этом случае вы можете легко загружать сертификаты вместо необработанных байтов,

http://www.lextm.com/2012/02/simple-publicprivate-key-signing-sample-code/

...