一言で言えば、これは私の問題です:
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-----
文字列は 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);
最初にbase64は、一部のバイナリデータのエンコードのみです。 RSA公開鍵をバイナリでエンコードする方法は複数あります。ただし、これをOpenSSLから取得した場合は、DERでエンコードされたRSAPublicKey
構造である可能性があります。
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER } -- e
一般に、ASN.1デコーダーが必要です。 Mono.Security.dll は one を提供しますが、このような単純な構造の場合は、それを実行することをお勧めしますASN.1は基本的にタグ、長さおよび値であるため、手動。
パートナーも.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/