秘密鍵と公開鍵 (.key および .cer ファイル) を使用して、.Net で RSAParameters オブジェクトを作成する必要があります。サードパーティのソフトウェアを使用せずに .Net でこれを行うことは可能ですか? もしそうなら、どこを見ればいいですか?
最終的に、cryptoServer のキーブロブを作成するために、このオブジェクトから Exponent、Modulus、D、P、Q、DP、DQ、InverseQ を抽出する必要があります。
ありがとう!
秘密鍵と公開鍵 (.key および .cer ファイル) を使用して、.Net で RSAParameters オブジェクトを作成する必要があります。サードパーティのソフトウェアを使用せずに .Net でこれを行うことは可能ですか? もしそうなら、どこを見ればいいですか?
最終的に、cryptoServer のキーブロブを作成するために、このオブジェクトから Exponent、Modulus、D、P、Q、DP、DQ、InverseQ を抽出する必要があります。
ありがとう!
「.key」および「.cer」ファイル拡張子は、キーのエンコード方法を明確に指定するものではありません。ただし、「。cer」ファイルがX.509証明書であり、(他の多くのものの中でも)公開鍵が含まれている可能性があります。したがって、 (名前空間内の) X509Certificate
andX509Certificate2
クラスを使用しSystem.Security.Cryptography.X509Certificates
て証明書をデコードし、公開鍵を抽出することをお勧めします。
ただし、公開鍵ではなく秘密鍵が必要です。X509Certificate2に関するMSDNドキュメントは、「証明書」という用語を使用して、パブリック部分(「.cer」ファイルにあるもの)またはパブリック部分とプライベート部分の結合を単一のファイル( MSDNが「PKCS7(Authenticode)」と記述している形式)。
エンコードされたRSA秘密鍵は通常、PKCS#1で説明されている形式に従います。これは複雑ではありませんが、 ASN.1に依存しているため、使用には多少の注意が必要です。このようなRSAキーは、キータイプも指定するより大きな構造にラップされる場合があります(つまり、キーはRSA用です)。詳細については、 PKCS#8を参照してください。また、両方の種類のキーエンコーディングは、通常、PEM形式で表示されます。これは、ヘッダー()とフッターを備えたBase64です。-----BEGIN RSA PRIVATE KEY-----
もちろん、秘密鍵はどのような形式でもかまいません( ".key"拡張子は過度に有益ではありません)。オプションで、PKCS#8とPEMの両方を対称的に暗号化できます(パスワードから派生したキーを使用)。PKCS#12もありますformat。これは、証明書と秘密鍵のコレクションのアーカイブ形式と見なすことができ、以前の形式をラップします。PKCS#12には多くの暗号化レイヤーが含まれており、Microsoftの世界では「PFX」(または混乱し続ける「証明書ファイル」)という名前で知られています。
これらすべての形式を少しのコードでデコードすることは可能ですが、その時点で、独自の形式を作成するのではなく、すでにそのような作業を行っているライブラリを使用することをお勧めします。弾力がある城はその仕事の通常の容疑者です。
OpenSSLコマンドラインツールは、いくつかのキー形式と証明書形式の間の変換に役立ちます。
編集:秘密鍵がPKCS#8 DER形式であり、パスワードで保護されていない場合(PKCS#8で保護できます)、比較的簡単なコードでデコードできます。DERは、構造化データを一連のバイトに変換するための一連のルールです。データ要素は、次の3つの連続した部分としてエンコードされます。
したがって、名前は「TLV」(「タグ、長さ、値」として)です。一部の要素は、それ自体がサブ要素を含む構造体です。この場合、値は、それぞれ独自のタグ、長さ、および値を持つサブ要素のエンコーディングの連結で構成されます。
タグは通常1バイトです。PKCS#8およびRSAキーの場合、タグ0x30('SEQUENCE'、つまりサブ要素を持つ要素)、0x02('INTEGER':整数値)、および0x04('OCTET STRING':blob)に関心があります。 。
長さは次のいずれかとしてエンコードされます。
INTEGERの場合、値は符号付きビッグエンディアン規則で解釈されます(最初のバイトが最上位で、最初のバイトの上位ビットが整数符号を指定します。RSAの場合、すべての値が正であるため、最初のバイトは正である必要があります。 0から127の間の値を持ちます)。System.Numerics.BigInteger
.NET 4.0には、大量のバイトをデコードできるコンストラクタがありますが、ビッグエンディアンではなくリトルエンディアンの規則でそれらを想定しているため、バイトの順序を逆にする必要があることに注意してください。
PKCS#8の構造は次のとおりです。
PrivateKeyInfo ::= SEQUENCE {
version Version,
privateKeyAlgorithm AlgorithmIdentifier,
privateKey OCTET STRING,
attributes [0] Attributes OPTIONAL
}
Version ::= INTEGER { v1(0) }
それがASN.1表記です。ここで理解する必要があるのは、オブジェクトがSEQUENCE要素であるということです。オブジェクトはSEQUENCEタグ(0x30)、長さ(n)、値(nバイト)の順にエンコードされます。その場合、値は、それぞれTLV形式の一連のエンコードされた要素で構成されます。最初の要素はINTEGERであり、通常の状態では数値0である必要があります(ゼロは '0x02 0x01 0x00'としてエンコードされます)。2番目の要素はですが、AlgorithmIdentifier
ここでは詳しく説明しません。これは実際にはSEQUENCEであり、キータイプを識別します(ここでは、「これはRSAキーです」と表示されます)。タグ(0x30である必要があります)を読み取り、次に長さを読み取り、値をスキップします。3番目の要素はOCTETSTRINGです。0x04タグ、長さm、値mです。バイト。それが私たちが興味を持っていることです。OCTETSTRINGの内容であるその値を抽出する必要があります。次の段落でデコードします。SEQUENCEの4番目の要素PrivateKeyInfo
はオプションであり(まったく存在しない場合があり、通常は存在しない場合があります)、この形式のさまざまな拡張機能をエンコードするために使用できます。
OCTETSTRINGの内容を抽出したとします。これはバイトのシーケンスであり、実際には構造のDERエンコーディングであり、ASN.1では次のようになります。
RSAPrivateKey ::= SEQUENCE {
version INTEGER,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
-- otherPrimeInfos must be absent if version is two-prime,
-- present if version is multi-prime.
}
したがって、OCTET STRINGの内容は、0x30(SEQUENCEのタグ)で始まり、次に長さ(r)、次にrバイトで始まる必要があります。これらのrバイトは、9つのINTEGERのエンコーディングです。最初のINTEGERは0である必要があります。そうでない場合、RSAキーには3つ以上の素因数があり、運命にあります。後続の8つのINTEGERは、探している整数です。それらをデコードするだけで完了です。最後のフィールド(otherPrimeInfos
)はオプションであり、RSAキーが「通常の」RSAキー(3つ以上ではなく2つの素因数を持つ)の場合は存在しないはずです。