SSlと.NETを開く-データ署名

はじめに



良い一日! 偶然、私はデータを非常に暗号化するのが好きな1人のオペレーターと仕事をしなければなりませんでした:)タスクは簡単で非常に普通のように見えました-RSAアルゴリズムは誰にでも人気があり、親しみやすく、暗号化の実装は。 :)しかし、私はこれらの行のペアを書き始めるまでしか考えていませんでした...



挑戦する



したがって、私が必要としたのは、私たちの側からのリクエストに署名(署名)し、RSAアルゴリズムを使用してパートナーから送信された署名済みリクエストを復号化することです。



署名に関するいくつかの言葉 :パブリックとプライベートの2つのキーがあります。 サブスクライバーAは、 プライベートキーでメッセージを暗号化し、サブスクライバーBに送信します。このメッセージを受信し、 パブリックキー(サブスクライバーAによって送信された)を持っているサブスクライバーBは、このメッセージがサブスクライバーAによって送信されたことを確認できます。Rsa に関する十分な一般情報があるため、そこで停止します。



暗号化ツール



私の場合、「クライアント」は一般的なOpen SSLプログラムを使用していました。これにより、データの署名など​​、暗号化に関して多くのことができます。 プログラムは次のように機能します。ファイル、キーを入力として受け取り、署名されたメッセージを発行します。 検証は同様の方法で機能します。暗号化されたファイル、公開キーを受け入れ、成功した場合、暗号化されたメッセージを含むファイルを発行します。

.NETでRSA署名を実装するために、暗号化と署名を行うことができる非常に便利なRSACryptoServiceProviderクラスがあります。 これらの実装の署名の概念が非常に異なることが判明するまでは大丈夫でしょう... :(私はインターネット上で検索に1時間費やさなければなりませんでしたが、情報はあまりありませんでした。実装の非互換性に関する人々の苦情をよく見ましたが、主なポイントはまた、OpenSSLは(暗号化として)データを署名に挿入し、.NETのみが署名します(これは論理的です)。OpenSSL実装を含むC#ライブラリ1つしか見つかりませんでしたが、支払われることが判明しました。

OpenSSL rsautlは非常に異なります。 以下がその機能です。

1.入力データはハッシュされません。 パディングおよび署名できるように、十分な量のデータである必要があります。 PKCS v1.5パディングが常に使用されます。 データは、パディング前にASN.1エンコードされていません。

2. PKCS v1.5で埋め込まれたデータはRSA署名され、署名が返されます。

ほぼ絶望的であり、OpenSSLのラッパーを作成することさえありましたが、偶然1つの良いリンクを見つけました: OPEN SSL NETプロジェクト-つまり OpenSSLのラッパー、またはむしろそれが使用するライブラリ-libeay32.dllおよびssleay32.dll 。 しかし、判明したように、すべてがそこに明白であったわけではありませんが、C#クラス間の掘り下げは、Cでソースコードを実装するよりもまだ簡単です:ライブラリの作成者と少し話し合って、OpenSSLに似た署名および検証メソッドを含むラッパークラスを作成しました。



念のため、OpenSSLユーティリティで作業する例を挙げて、関心のある人が-helpで時間を無駄にしないようにしてください:)

署名: openssl rsautl -inkey priv.key -in temp.txt -out temp.bin -sign

検証: openssl rsautl -pubin -inkey pub.key -in temp2.​​bin -out result2.txt -verify

したがって、コード自体:



RsaUtl OpenSSLエミュレータークラス



コード自体に関するコメントは不要だと思います。 このクラスをOpenSSL.NETのアセンブリに含めましたが、同じ成功を収めて、外部で使用できます。 操作を正常に行うには、ライブラリlibeay32.dll、ssleay32.dllが必要です(アセンブリの外部で使用する場合は、ManagedOpenSsl.dll)。 クラスについての簡単な説明:キーをpem形式でダウンロードし、データに署名/チェックします。 キーがファイルへのパスとバイト[]のセットの両方を示すことができるように、オーバーロードしました。



using System;

using System.Collections. Generic ;

using System.Text;

using System.IO;

using System.Security.Cryptography.X509Certificates;

using OpenSSL;



namespace Rsautl

{

/// <summary>

/// Openssl -rsautl

/// </summary>

public static class Rsautl

{

private static RSA ReadPrivateKey( string path)

{

Stream s = File .Open(path, FileMode .Open);

byte [] pk = new byte [s.Length];

s.Read(pk, 0, pk.Length);

s.Close();

BIO b = new BIO(pk);

return RSA.FromPrivateKey(b);



}

private static RSA ReadPrivateKey( byte [] path)

{

BIO b = new BIO(path);

return RSA.FromPrivateKey(b);



}

private static RSA ReadPubKey( string path)

{

Stream s = File .Open(path, FileMode .Open);

byte [] pk = new byte [s.Length];

s.Read(pk, 0, pk.Length);

s.Close();

BIO b = new BIO(pk);

return RSA.FromPublicKey(b);

}

private static RSA ReadPubKey( byte [] path)

{

BIO b = new BIO(path);

return RSA.FromPublicKey(b);

}



#region

public static byte [] RsaUtlSignData( byte [] data, string privatekeypath)

{

RSA key = ReadPrivateKey(privatekeypath);

return key.PrivateEncrypt(data,RSA.Padding.PKCS1);

}

public static byte [] RsaUtlSignData( byte [] data, byte [] privatekey)

{

RSA key = ReadPrivateKey(privatekey);

return key.PrivateEncrypt(data, RSA.Padding.PKCS1);



}

#endregion



#region

public static byte [] RsaUtlVerifyData( byte [] sign, string pathtopublickey)

{

RSA key = ReadPubKey(pathtopublickey);

return key.PublicDecrypt(sign, RSA.Padding.PKCS1);

}

public static byte [] RsaUtlVerifyData( byte [] sign, byte [] publickey)

{

RSA key = ReadPubKey(publickey);

return key.PublicDecrypt(sign, RSA.Padding.PKCS1);

}

#endregion



}

}



* This source code was highlighted with Source Code Highlighter .








おわりに



この記事が誰かにとって有益であり、貴重な時間を節約することを願っています。 1分ですべてができるとは言わないでください-信じられませんが)サードパーティのライブラリなしでNETのデータに署名する方法がまだあるなら、OpenSSL互換性を書くのは素晴らしいことです!!!

PSは、記事の評価を主張してください;)

PS2誰もが興味を持っている場合、OpenPGPで苦労した方法についての記事を書くことができます=)同様の話があります... :)



All Articles