web-dev-qa-db-ja.com

pfx / cerからsnkを作成する方法は?

マイクロソフトが認定ジャングルを作成したようですが、それは理解するのが困難です。

  • Microsoft X.509証明書(.cer)
  • 個人情報交換(.pfx)
  • アセンブリ署名キー属性(.snk)

    1. Pfxまたはcerに基づいてsnkファイルを作成することをお勧めしますか? (それが可能かどうか、そして可能であればそれはどのように行われるのかわからない)

    2. アセンブリはパスワードで保護されたpfxで署名できますが、代わりにsnkで署名しない限り、厳密な名前が付けられているようには見えません。ただし、snkにはパスワード保護機能がありません。どちらを使用する方が安全ですか?私はプロジェクトの唯一の開発者なので、マルチ開発者の安全環境の問題はありませんが、それでも最善の方法を知りたいです。

どうもありがとう、

31
Houman

あなたが言及したファイルの種類について少し説明:

  • 。cer-filesはX.509証明書です
  • 。pfx-ファイルは、パスワードベースの対称キーを使用して暗号化されたX.509証明書です。また、 PKCS#12(Wikipedia) も参照してください。
  • 。snk-ファイルにはRSAキーのみが含まれます(公開/非公開または公開のみ)

。pfx-filesまたは。snk-filesを使用してアセンブリに署名するかどうかは関係ありません。どちらの方法でも厳密な名前が付けられます。 RSAキーを暗号化された証明書(。pfx)として保存する方が、暗号化されていないキー(。snk)だけを保存するよりも安全です。

クラス_System.Security.Cryptography.X509Certificates.X509Certificate2_を使用すると、コード内のこれらのファイルからキーを簡単に抽出できます。

。pfxからキーを抽出するには:

_/// <summary>
/// Converts .pfx file to .snk file.
/// </summary>
/// <param name="pfxData">.pfx file data.</param>
/// <param name="pfxPassword">.pfx file password.</param>
/// <returns>.snk file data.</returns>
public static byte[] Pfx2Snk(byte[] pfxData, string pfxPassword)
{
    // load .pfx
    var cert = new X509Certificate2(pfxData, pfxPassword, X509KeyStorageFlags.Exportable);

    // create .snk
    var privateKey = (RSACryptoServiceProvider)cert.PrivateKey;
    return privateKey.ExportCspBlob(true);
}
_

privateKey.ExportCspBlob(false)を使用して、公開鍵のみを抽出してください! (例:アセンブリの遅延署名用)

29
Sir Kill A Lot

Pfxからsnkファイルを生成するには:

sn -p keypair.pfx key.snk

私は常に.pfxファイルよりもsnkファイルを使用するのが好きで、バグが少ないように見えます。

29
punkcoder

@ Sir Kill A Lotanswer で提供しているのと同じ方法ですが、PowerShellスクリプトに変換されます(pfx2snk.ps1)。

Param(
    [Parameter(Mandatory=$True,Position=1)]
    [string] $pfxFilePath,
    [string] $pfxPassword
)

# The path to the snk file we're creating
[string] $snkFilePath = [IO.Path]::GetFileNameWithoutExtension($pfxFilePath) + ".snk";

# Read in the bytes of the pfx file
[byte[]] $pfxBytes = Get-Content $pfxFilePath -Encoding Byte;

# Get a cert object from the pfx bytes with the private key marked as exportable
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(
    $pfxBytes,
    $pfxPassword,
    [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable);

# Export a CSP blob from the cert (which is the same format as an SNK file)
[byte[]] $snkBytes = ([Security.Cryptography.RSACryptoServiceProvider]$cert.PrivateKey).ExportCspBlob($true);

# Write the CSP blob/SNK bytes to the snk file
[IO.File]::WriteAllBytes($snkFilePath, $snkBytes);

Pfxファイルのパスとパスワードを指定してそのスクリプトを実行するだけで、snkファイルがpfxファイルと同じディレクトリに作成されます(拡張子以外は同じ名前)。

powershell.exe -File pfx2snk.ps1 -pfxFilePath cert.pfx -pfxPassword "pfx password"

または、pfxにパスワードがない場合(恥、恥):

powershell.exe -File pfx2snk.ps1 cert.pfx

そして、残念なことに、PowerShellスクリプトの実行を許可しない環境(つまり、対話型のPowerShellセッションのみ)で作業するのであれば、標準のcmd.exeコマンドラインからこの醜い1つのライナーを実行できます(必要に応じてファイルパスとpfxパスワードを置き換えます)。

powershell.exe -Command "[IO.File]::WriteAllBytes('SnkFilePath.snk', ([Security.Cryptography.RSACryptoServiceProvider](New-Object System.Security.Cryptography.X509Certificates.X509Certificate2((Get-Content 'PfxFilePath.pfx' -Encoding Byte), 'PfxPassword', [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)).PrivateKey).ExportCspBlob($true));"

実際には、このワンライナーをVisual Studioの事前構築プロセスの標準部分として使用して、厳密な名前の署名のために、authenticode署名証明書(pfxファイル)から同じキーを使用するプロセスを自動化します。それは要件ではありませんが、同じである必要があることは私には理にかなっているようで、それが私のOCD傾向に影響を与えます。

(厳密な名前の署名にpfxファイルを使用して「バギー」体験をしたので、元のpfxではなくsnkファイルを使用します @ punkcoder 答え)

また、興味がある場合は、Visual Studioでのビルド後のプロセスの一部として、authenticode署名を(とにかく "Release"プロジェクト構成で)プロジェクト出力に追加する次のようなものを用意しています。

powershell.exe -Command "Set-AuthenticodeSignature -FilePath '$(TargetPath)' -Certificate '$(SolutionDir)MyCert.pfx' -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll -HashAlgorithm sha256;"
5
David Woodward