Использование открытого ключа с открытым кодом Base64 для проверки RSA-подписи
Вкратце, это моя проблема:
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. Я смог выполнить создание экземпляра с использованием RSAP-параметров объекта, загруженного байтом [] для модуля и Exponent, полученных из этой строки открытого ключа, используя команду оболочки OpenSSL. Но поскольку этот открытый ключ может измениться в будущем, я хочу сохранить его в своей первоначальной форме в базе данных. Должен быть более простой способ справиться с этим.
Множество примеров, которые я прочитал до сих пор, избегают этой проблемы, экспортируя и импортируя сгенерированные закрытые и открытые ключи в объект-ключ-контейнер и из него, и использовать его в одном и том же фрагменте кода и, таким образом, не "переносить", ключ в какой-то строковой форме из памяти. Некоторые люди выразили ту же проблему, как здесь, на StackOverflow, так и на других сайтах, но я еще не смог найти удовлетворительный ответ.
Любая идея более чем приветствуется.
Фоновая информация:
Мой партнер по связям вычисляет 20-байтовый SHA1-хэш из входной строки переменной длины, состоящей из информации, содержащейся в нескольких полях ASCII-кодированного сообщения. Этот хэш затем RSA-подписан с моим закрытым ключом партнера и отправлен вместе со мной ASCII-сообщением. По прибытии я сам вычисляю хэш SHA1, используя те же поля из сообщения ASCII, а затем попытаюсь проверить, не изменились ли эти поля, вызвав VerifyHash.
Ключ предоставляется в двух формах: обычный и "noNL". Версия noNL включена в код выше, обычная версия такова:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFO
GwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWp
bY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5y
GPhGAAmqYrm8YiupwQIDAQAB
-----END PUBLIC KEY-----
Ответы
Ответ 1
Ваша строка является кодировкой 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);
Ответ 2
Первый base64 - это только кодировка некоторых двоичных данных. Существует более одного способа кодирования в двоичном виде открытого ключа RSA. Однако, если вы получили это от OpenSSL, это, вероятно, структура RSAPublicKey
, закодированная DER.
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER } -- e
В общем вам понадобится декодер ASN.1, Mono.Security.dll предоставляет один, но для такой простой структуры вы можете сделать это вручную, так как ASN.1 в основном является тегом, длиной и Значение.
Ответ 3
Если ваш партнер также использует .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/