4

私は先週の金曜日にこのすべてにいましたが、まだ困惑しています。

このコマンドを実行すると:

echo -n "Data To Sign" | openssl pkeyutl -sign -inkey path/to/my.pem | openssl base64

opensslを介して出力を取得します。

1c284UkFgC6pqyJ+woSU+DiWB4MabWVDVhhUbBrTtF7CkpG8MjY+KkPFsZm9ZNM8vCjZjf...Kw=

この動作をC#で複製したいと思います。私が最初に試みたのは、opensslを使用して.pemファイルから.p12ファイルを作成することでした。これを行うには、次の2つのopensslコマンドを実行します。

openssl req -new -key path/to/my.pem -x509 -batch > my.crt
openssl pkcs12 -export -in my.crt -inkey path/to/my.pem -out my.p12

次に、X509Certificate2andRSACryptoServiceProviderクラスを使用して.p12とsignをロードします。以下のコード:

var dataToSign = "Data To Sign";
var p12 = new X509Certificate2(@"path\to\my.p12","");
var rsa = (RSACryptoServiceProvider)p12.PrivateKey;
var signedBytes = rsa.SignData(Encoding.UTF8.GetBytes(dataToSign), "SHA1");
var result = Convert.ToBase64String(signedBytes);

これにより、次のようになります。

B2qM6MTjoZFSbnckezzpXrKFq67vFgsCPYBmaAbKOFmzVQLIU4a+GC6LWTMdNO4...Q0=

残念ながら、出力は一致しません。しばらくこれと戦った後、私はここSOでいくつかの答えによって提案されたBouncyCastleルートに行くことにしました。そのライブラリを使用して思いついたコードは次のとおりです。

StreamReader sr = new StreamReader(@"path\to\my.pem");
PemReader pr = new PemReader(sr);
var pemKeyParams = (RsaPrivateCrtKeyParameters)pr.ReadObject();
var cypherParams = new RsaKeyParameters(true, pemKeyParams.Modulus, pemKeyParams.Exponent);
ISigner sig = SignerUtilities.GetSigner("SHA1withRSA");
sig.Init(true, cypherParams);
var bytes = Encoding.UTF8.GetBytes("Data To Sign");
sig.BlockUpdate(bytes, 0, bytes.Length);
byte[] signature = sig.GenerateSignature();
var result = Convert.ToBase64String(signature);

これも次のようになります。

B2qM6MTjoZFSbnckezzpXrKFq67vFgsCPYBmaAbKOFmzVQLIU4a+GC6LWTMdNO4...Q0=

BouncyCastleの出力は、Security名前空間のネイティブライブラリを使用するC#コードによって提供される出力と一致しますが、opensslの出力と一致させたいと思います。私は何が間違っているのですか?

バージョン
-OpenSSL1.0.1c.NET
4.0
BouncyCastle 1.7.0
Windows 7

my.pem-

----- BEGIN PRIVATE KEY ----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOtk3bYdQsjeG1Xy 2KgF8ecWcPudPLEnV32OIbtA + h2hXQ853ZRsxusopm7vmqtI2 / aVfc2vyw9AGY0U cjqPnyEq7et5oQydo5 + aTEW3PenP9DR3MJ273ipPbrYX + I3XzJ + I6 // k6DO / OAIA JLlXc9iT1pblSrHymFNEkIFiUgj3AgMBAAECgYBtP1Lmwo3MS8jECwEieh / a8D9f h4ozbd7dFqnxDicGuW1HM8PyrsljOmqD8hAGjroHpznLzFqhqU4ye9rH8wAWsKUj QST / RjyDU3SNscyU /例えば+ ezuawUXafpPUEUTJ0aofdHn9GIVipiIi / 4uaPP / IYtuC U2smep4C2 + geqfTugQJBAP5MTaRQjoYBGKS / Bgd0JB16MHFV6FPDCX3NZ2CLTyZm o8edQZI4SbWoxkJaGqBOqDbz / dSmTLfRNmpAmC + az5sCQQDs + CyDLbs3URvD7ajx JjsJoPbuVmqPBPGmAy / 4Qt3QVp9AWk + 9uckU90DYMqJp5bdGoeokmA65uuEcvqbs yzfVAkEA018FIlE7RjNfEoEdN9DXvBC2d14a0JTLLOAwz1S8I4UpGWCjAjD7Q53X vYs7mogG1jaUg87 + 8cNaYZLzbI5XhQJANyqbajqGQB2Awj8cum81BUvU0K2LhxoWi5hoXXprmynfTyL3N2r99gSNswcuqkqRPT9KfBRuMSzhZUi5IZ05tQJBAKdQ3mJZ 1Vys2nEAXbQD5 / ldi1 + VF / 0t4Z + JxqFBjqtsAoASBN + kSiPAnRl3r175oZ9

この質問の目的で、新しい.pemを生成しました。上記のキーは重要なものを保護しませんが、上記の手順を再現するために提供します。

これまでに検討したこと:
*エンコーディング(ASCIIとUTF8)
*エンディアン(-opensslへのrevはまだどちらのコード化された結果とも一致しません)
* hashalg(「SHA1」が公式に正しいハッシュであることがどこにも見つかりませんでした使用するアルゴリズムですが、他の人が使用していて他のオプションを試しても役に立たなかったようです)
*改行(echoの-nはライブラリと同等である必要があると思いますが、削除しても役に立ちませんでした)
* SOについて質問する(結果は保留中です:-))

TIA

4

2 に答える 2

3

openssl pkeyutlコマンドは、データのダイジェストに署名するのではなく、実際にはデータに直接署名していると思います。

pkeyutlのopensslドキュメントには、この示唆に富むコメントが含まれています。

「特に明記されていない限り、すべてのアルゴリズムは、sign、verify、verifyrecover操作に使用されるダイジェストを指定するdigest:algオプションをサポートしています。値algは、EVP_get_digestbyname()関数で使用されるダイジェスト名(たとえば、sha1)を表す必要があります。」

コマンドラインにダイジェストオプションが表示されません。さらに、同じドキュメント(RSAのセクション)から:

「PKCS#1パディングでは、メッセージダイジェストが設定されていない場合、提供されたデータはDigestInfo構造を使用する代わりに直接署名または検証されます。ダイジェストが設定されている場合、DigestInfo構造が使用され、その長さはダイジェストに対応している必要がありますタイプ。"

openssldgstのドキュメントも参照してください。

于 2013-01-22T09:22:20.553 に答える
1

RSA署名では、さまざまなパディングモード(PKCS#1、PSSなど)を使用できます。最後のものではランダムなソルトを使用しているため、署名は毎回異なります。したがって、最初に、opensslが毎回同じ値を生成するかどうかを確認し(デフォルトのパディングopensslコードが使用するものが見つかりませんでした。これは、-rsa_padding_modeパラメーターで変更できます)、実際には、両方の署名が反対側で正しく検証できるかどうかを確認します。 。

于 2013-01-21T19:53:54.560 に答える