web-dev-qa-db-ja.com

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);

ご覧のとおり、問題は、指定されたBase64でエンコードされた公開鍵文字列を使用して新しいRSACryptoServiceProviderを開始することです。 OpenSSL Shellコマンドを使用して、この公開鍵文字列から派生したModulusとExponentのbyte []がロードされたオブジェクトRSAParametersを使用してインスタンス化を行うことができました。ただし、この公開鍵は将来変更される可能性があるため、元の形式でデータベースに保存できるようにしたいと思います。これに対処するためのより簡単な方法が必要です。

これまでに読んだ多くの例では、生成された秘密鍵と公開鍵をキーコンテナオブジェクトとの間でエクスポートおよびインポートし、同じコードで使用して、キーを「転送」しないことで、この問題を回避しています。一部の文字列がメモリから不足しています。 StackOverflowと他のサイトの両方で同じ問題を表明している人もいますが、私はまだ満足のいく答えを見つけることができていません。

どんなアイデアでも大歓迎です。

背景情報:私の通信パートナーは、ASCIIでエンコードされたメッセージのいくつかのフィールドに含まれる情報で構成される可変長の入力文字列から20バイトのSHA1ハッシュを計算します。次に、このハッシュはパートナーの秘密鍵を使用してRSA署名され、ASCIIメッセージとともに送信されます。到着時に、ASCIIメッセージの同じフィールドを使用してSHA1ハッシュを自分で計算し、VerifyHashを呼び出してこれらのフィールドが変更されていないかどうかを確認しようとします。

キーは、通常と「noNL」の2つの形式で提供されます。 noNLバージョンは上記のコードに含まれています。通常のバージョンは次のとおりです。

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

文字列は SubjectPublicKeyInfo のbase64エンコーディングです。 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);
14
Rasmus Faber

最初にbase64は、一部のバイナリデータのエンコードのみです。 RSA公開鍵をバイナリでエンコードする方法は複数あります。ただし、これをOpenSSLから取得した場合は、DERでエンコードされたRSAPublicKey構造である可能性があります。

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

一般に、ASN.1デコーダーが必要です。 Mono.Security.dllone を提供しますが、このような単純な構造の場合は、それを実行することをお勧めしますASN.1は基本的にタグ長さおよびであるため、手動

4
poupou

パートナーも.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/

0
Lex Li