HSM を使用した HLK 署名
はじめに
このトピックでは、サード パーティのネットワーク ベースのハードウェア セキュリティ モジュール (HSM) を使用して Extended Validation (EV) 証明書を格納するときに発生する可能性があるセットアップと構成の問題について説明します。
背景
HLK パッケージ
HLKX パッケージ ファイルは、Open Packaging Conventions を使用します。 この仕様は ISO ワーキング グループの一部であり、HLKX ファイルが Signtool と互換性がないことを示しています。
HLK パッケージの署名
HLK がパッケージに署名すると、署名とリレーションシップが HLK データと共にパッケージに配置されます。 これは、System.IO.Packaging.PackageDigitalSignature
がパッケージ内のデータの署名を検証するために使用するデータです。
Note
現在、HLK パッケージ署名では RSA 証明書と DSA 証明書のみがサポートされています。これは、System.Security.Cryptography.Xml.SignedXml の署名に使用される .NET ライブラリによって決定されます。
暗号化サービス プロバイダー
暗号化 サービス プロバイダー (CSP) には、暗号化標準とアルゴリズムの実装が含まれています。 少なくとも、CSP は CryptoSPI (システム プログラム インターフェイス) の関数を実装する ダイナミック リンク ライブラリ (DLL)で構成されます。 ほとんどの CSP には、独自の全ての関数の実装が含まれています。 ただし、一部の CSP は、主に Windows サービス コントロール マネージャーによって管理される Windows ベースのサービス プログラムに関数を実装します。 スマート カード やセキュアなコプロセッサーなど、ハードウェア に関数を実装する CSP もあります。 CSP が独自の関数を実装していない場合、DLL はパススルー レイヤーとして機能し、オペレーティング システムと実際の CSP 実装間の通信を容易にします。
証明書ストアとレジストリ
証明書ストア内の証明書はすべて、最終的な署名を行う CSP DLL にマップされます。 これは、次のレジストリ エントリで確認できます。
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider\Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider]
"Image Path"="%SystemRoot%\\system32\\dssenh.dll"
"SigInFile"=dword:00000000
"Type"=dword:0000000d
ネットワークベースの HSM によってホストされる証明書を使用した HLKX パッケージ署名
コントローラーの構成
HSM 証明書で署名するよう HLK コントローラーを設定するには、システムに次の情報が存在する必要があります。
- HSM の証明機関 (CA)
- HSM から の CSP ファイル
これらのコンポーネントを使用して HSM クライアントを構成する方法については、HSM プロバイダーが文書化する必要があります。
HLK を使用した署名
コントローラーが正しく構成されている場合は、HLK からローカルにインストールされた証明書と同じように、HSM からの証明書をポイントして、パッケージに署名できます。
HSM 構成のテスト
Signtool の使用
署名可能かを理解する最初の手順は、signtool を使用してファイルに署名することです。 これにより、署名ワークフローが正しく機能していることを確認できます。 まず、PE ファイル (exe または dll) に署名します。 たとえば、名前を使用して署名します。
signtool sign /f HighValue.cer /csp "Hardware Cryptography Module" /kHighValueContainerMyControl.exe
signtool sign /n "My Company Certificate" MyFile.exe
または、インストールされている証明書の SHA1 ハッシュを使用して署名します。
signtool sign /sha1 0cf1d2f7befc7d143678f86963aef5572b710cf2 MyFile.exe
証明書名はサブジェクト情報にあり、SHA1 ハッシュは拇印にあります。 ハッシュを使用する場合は、ハッシュ内のすべてのスペースと特殊文字を削除し、上記の例のような形式にします。 また、Personal Information Exchange (PFX) ファイルを使用して署名することもできます。 PFX ファイルには秘密キーを含めることができ、証明書には公開キーのみが含まれるため、これはおそらくあなたがやりたいことではありません。
signtool sign /f certdata.pfx MyFile.exe
signtool を使用して署名を確認できます
signtool verify /v /pa MyFile.exe
PFX ファイル以外のものを使用してファイルに署名および確認できた場合は、HLK パッケージに署名することができます。 署名できなかった場合は、「トラブルシューティング」セクションを参照してください。
PackageDigitalSignature の使用
このドキュメントの最後にある「コード サンプル」セクションに、PackageDigitalSignature
を使用して署名するコード例があります。 このドキュメントを受け取った時点で、完全な C# ファイルも入手しているはずです。 この例を使用するには、署名されていないパッケージへの完全なパスと、署名に使用する証明書の拇印を指定する必要があります。 署名できなかった場合は、「トラブルシューティング」セクションを参照してください。
トラブルシューティング
最も可能性の高い原因は、HSM から証明書と関連する CSP がシステムにインストールされていないことです。 次を試すことができます。
- HSM ベンダーでサポートされているツールだけを使用して、このシステムにサインオンできますか?
- HSM ベンダーは、このシステムに証明書と CSP をインストールしていますか?
- 証明書のプロパティは何ですか?
- HSM ベンダーは signtool を使用してサポートおよび文書化していますか? HSM で Signtool を使用してファイルに署名できる場合、これはシステムが正しく構成されていることを示し、HLK が HLKX パッケージに署名できることも意味しています。
- サンプル コード (HSM_example.cs) を実行した場合に、CspKeyContainerInfo.ProviderName に出力される内容
- そのプロバイダー名は、ベンダーが提供する正しい CSP DLL にマップされていますか。 その情報は、上記のようにレジストリで確認できます。
コード サンプル
PackageDigitalSignatureManager
public static void Sign(string package, X509Certificate2 certificate)
{
// Open the package to sign it
Package packageToSign = Package.Open(package);
// Specify that the digital signature should exist
// embedded in the signature part
PackageDigitalSignatureManager signatureManager = new PackageDigitalSignatureManager(packageToSign);
signatureManager.CertificateOption = CertificateEmbeddingOption.InCertificatePart;
// We want to sign every part in the package
List<Uri> partsToSign = new List<Uri>();
foreach (PackagePart part in packageToSign.GetParts())
{
partsToSign.Add(part.Uri);
}
// We will sign every relationship by type
// This will mean the signature is invalidated if *anything* is modified in //the package post-signing
List<PackageRelationshipSelector> relationshipSelectors = new List<PackageRelationshipSelector>();
foreach (PackageRelationship relationship in packageToSign.GetRelationships())
{
relationshipSelectors.Add(new PackageRelationshipSelector(relationship.SourceUri, PackageRelationshipSelectorType.Type, relationship.RelationshipType));
}
try
{
signatureManager.Sign(partsToSign, certificate, relationshipSelectors);
}
finally
{
packageToSign.Close();
}
}