このページには自動翻訳されたテキストを含めることができます。

C# および VB.NET で USB トークンと HSM デバイスを使用して PDF に署名する方法

信頼された証明機関は、ドキュメント署名証明書の秘密鍵のダウンロードを許可しなくなりました。代わりに、秘密鍵はUSBトークン、スマートカード、クラウドベースのHSMなどの安全なハードウェアに保存する必要があります。

Docotic.Pdf ライブラリ を使用すると、HSM デバイスを使用して .NET で PDF ドキュメントに署名できます。この記事では、Azure Key Vault、AWS KMS、PKCS#11 準拠ハードウェアとの統合について説明します。

Docotic.Pdf ライブラリ 9.7.18373 回帰テスト 15,244人が合格 NuGet の合計ダウンロード数 5,976,723

ライブラリと期間限定の無料ライセンスキーは、C# .NET PDF ライブラリをダウンロード ページから入手できます。

外部PDF署名

前提条件

この記事のコードサンプルでは、​​PDFドキュメントへの署名に自己署名証明書を使用しています。デフォルトでは、PDFビューアはこれらの署名を信頼しません。自己署名証明書はテスト目的のみに使用し、実稼働環境では使用しないでください。信頼できるPDF署名を生成するには、サードパーティの認証局が発行したドキュメント署名証明書を使用してください。

適切な証明書を取得する

Adobe Approved Trust List (AATL) に掲載されている企業からの証明書を優先してください。Adobe Acrobat はデフォルトでこれらの企業からの証明書を信頼し、「証明書の有効性が不明です」という警告を表示しません。

EU(eIDAS)準拠のドキュメントを作成するには、欧州連合信頼リスト(EUTL)に掲載されているプロバイダーが発行する適格証明書を使用する必要があります。

.NET で証明書を使用する方法を学びましょう

ドキュメント署名証明書を注文すると、通常、HSMデバイスへのアクセスが提供されます。これは、物理的なUSBトークンまたはクラウドベースのHSMソリューションのいずれかです。

次に、このHSMでデータに署名する方法を学習する必要があります。暗号化プロバイダーはそれぞれ異なるため、これが最も難しい部分です。USBトークンまたはクラウドAPIのドキュメントに従ってください。

理想的には、対応する .NET SDK を見つける必要があります。少なくとも ネイティブ SDK を見つけて、.NET の相互運用性を介して使用してください。

目標は、証明書を使用して任意のバイトに署名できる C# または VB.NET コードを作成することです。

外部署名用 PDF API

HSMデバイスで任意のバイトに署名できるようになったら、Docotic.PdfでPDFドキュメントに署名する準備が整います。そのためには、IPdfSignerインターフェースを実装し、署名に使用します。

IPdfSigner インターフェースを実装します

IPdfSigner は2つのメンバーを宣言します。SignatureAlgorithm プロパティは、署名に使用されるアルゴリズムを返します。通常は、RSA または ECDSA アルゴリズムを使用します。

Sign メソッドは外部署名フローの重要な部分です。Docotic.Pdf は、PDF ドキュメントのバイト列のダイジェストをこのメソッドに渡します。HSM デバイスでこのダイジェストに署名し、デジタル署名のバイト列を返す必要があります。ここで PKCS#7 オブジェクトを返さないでください。暗号署名を生成して返すだけです。

Docotic.Pdf は、署名ごとに Sign メソッドを 2 回呼び出します。最初の呼び出しは署名に必要なスペースを計算します。2 回目の呼び出しは実際にドキュメントに署名します。

外部署名用の PdfSigningOptions を作成します

PdfSigningOptions(IPdfSigner, X509Certificate2[]) コンストラクター を使用して、IPdfSigner 実装で PDF ドキュメントに署名します。証明書チェーンを取得し、2 番目の引数として指定します。少なくとも 1 つの証明書が必要で、署名証明書が先頭になければなりません。

最後のピースは PdfSigningOptions.DigestAlgorithm プロパティです。このプロパティの値は、IPdfSigner.SignatureAlgorithm および IPdfSigner.Sign 実装と一致している必要があります。

一般的なシナリオで外部署名を使用してPDFに署名する方法を確認しましょう。

C# で PKCS#11 ドライバーを使用して PDF ドキュメントに署名する

暗号化USBトークンまたはスマートカードにPKCS#11ドライバーが付属している場合は、.NETのPkcs11Interop.X509StoreまたはPkcs11Interopライブラリを使用できます。Pkcs11Interopは、Atos CardOSスマートカード、YubiKey PIV、SmartCard-HSM、SafeNet ProtectServer HSM、およびその他のHSMと互換性があります。

PKCS#11 ドライバーを使用して PDF ドキュメントに署名する のコードサンプルは、USB トークンまたはスマートカードを使用して PDF ドキュメントに署名する方法を示しています。以下の行をカスタマイズする必要があります。

string pkcsLibraryPath = @"C:\Program Files\SoftHSM2\lib\softhsm2-x64.dll";
ulong slotId = 1743347971;
string alias = "YOUR-ALIAS";
string certLabel = "YOUR-CERTIFICATE";
string pin = "YOUR-PIN";
var digestAlgorithm = PdfDigestAlgorithm.Sha512;

サンプル構成では、USBトークンのエミュレーターとしてSoftHSM2を使用しています。実際のアプリケーションでは、SoftHSM2は必要ありません。代わりに、USBトークンに付属のドライバーを使用してください。

Azure Key Vault を使用して PDF ドキュメントに署名する

Microsoft Azure Key Vault は、証明書とキーを安全に保管します。以下の準備が必要です。

  1. Azure アカウントを作成します。
  2. Azure ユーザーを作成します。
  3. Key Vault を作成します。
  4. 選択した Azure ユーザーに Key Vault へのアクセスを許可します。
  5. Key Vault にドキュメント署名証明書を追加します。統合証明機関から証明書を インポート できます。

次に、.NET で署名するために Azure.Security.KeyVault.Keys NuGet パッケージを使用します。Azure Key Vault のキーを使用して署名するためのサンプル C# コードは次のとおりです。

var vaultUrl = new Uri("https://YOUR-VAULT.vault.azure.net/");
var credential = new DefaultAzureCredential();

var keyClient = new KeyClient(vaultUrl, credential);
KeyVaultKey key = keyClient.GetKey("YOUR-KEY");
var cryptoClient = new CryptographyClient(key.Id, credentials);
byte[] messageToSign = ..;
byte[] signature = cryptoClient.SignData(SignatureAlgorithm.RS512, messageToSign).Signature;

関連する IPdfSigner 実装は次のようになります。

class AzureSigner : IPdfSigner
{
    private readonly CryptographyClient m_client;
    private readonly AzureSignatureAlgorithm m_signingAlgorithm;

    public AzureSigner(CryptographyClient client, AzureSignatureAlgorithm signingAlgorithm)
    {
        m_client = client;
        m_signingAlgorithm = signingAlgorithm;
    }

    public PdfSignatureAlgorithm SignatureAlgorithm
    {
        get
        {
            if (m_signingAlgorithm == AzureSignatureAlgorithm.RS256 ||
                m_signingAlgorithm == AzureSignatureAlgorithm.RS384 ||
                m_signingAlgorithm == AzureSignatureAlgorithm.RS512)
                return PdfSignatureAlgorithm.Rsa;

            throw new NotSupportedException($"Unsupported {nameof(SignatureAlgorithm)} value: {m_signingAlgorithm}");
        }
    }

    public PdfDigestAlgorithm DigestAlgorithm
    {
        get
        {
            if (m_signingAlgorithm == AzureSignatureAlgorithm.RS256)
                return PdfDigestAlgorithm.Sha256;

            if (m_signingAlgorithm == AzureSignatureAlgorithm.RS384)
                return PdfDigestAlgorithm.Sha384;

            if (m_signingAlgorithm == AzureSignatureAlgorithm.RS512)
                return PdfDigestAlgorithm.Sha512;

            throw new NotSupportedException($"Unsupported {nameof(SignatureAlgorithm)} value: {m_signingAlgorithm}");
        }
    }

    public byte[] Sign(byte[] message)
    {
        return m_client.SignData(m_signingAlgorithm, message).Signature;
    }
}

最後に、この AzureSigner クラスを使用して PDF ドキュメントに署名します。

CryptographyClient cryptoClient = ..;
using X509Certificate2 cert = ..
var signer = new AzureSigner(cryptoClient, SignatureAlgorithm.RS512);

using var pdf = new PdfDocument();

PdfPage page = pdf.Pages[0];
PdfSignatureField field = page.AddSignatureField(50, 50, 200, 200);

var options = new PdfSigningOptions(signer, new[] { cert })
{
    DigestAlgorithm = signer.DigestAlgorithm,
    Field = field,
};

pdf.SignAndSave(options, ..);

GitHub で Azure Key Vault を使用して PDF ドキュメントに署名する の完全なコードサンプルをご覧ください。

AWS KMS を使用して PDF ドキュメントに署名する

AWS Key Management Service (KMS) は、暗号化キーを安全に保管するためのもう 1 つの方法です。準備手順は Azure Key Vault と同じです。

  1. AWS アカウントを作成します。
  2. IAM ユーザーを作成します。
  3. 署名キーを追加します。
  4. 選択した IAM ユーザーにキーへのアクセスを許可します。

AWS の場合は、.NET の AWSSDK.KeyManagementService NuGet パッケージを使用する必要があります。PDF 署名のサンプルコードは、Azure のシナリオとほぼ同様です。

using var pdf = new PdfDocument();

PdfPage page = pdf.Pages[0];
PdfSignatureField field = page.AddSignatureField(50, 50, 200, 200);

var signingAlgorithm = SigningAlgorithmSpec.RSASSA_PSS_SHA_512;
var signer = new AwsSigner("arn:aws:kms:YOUR-id", signingAlgorithm)
var options = new PdfSigningOptions(signer, new[] { cert })
{
    DigestAlgorithm = signer.DigestAlgorithm,
    Field = field,
};

pdf.SignAndSave(options, ..);


class AwsSigner : IPdfSigner
{
    private readonly string m_keyId;
    private readonly SigningAlgorithmSpec m_signingAlgorithm;

    public AwsSigner(string keyId, SigningAlgorithmSpec signingAlgorithm)
    {
        m_keyId = keyId;
        m_signingAlgorithm = signingAlgorithm;
    }

    public PdfSignatureAlgorithm SignatureAlgorithm
    {
        get
        {
            if (m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_256 ||
                m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_384 ||
                m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_512)
                return PdfSignatureAlgorithm.Rsa;

            throw new NotSupportedException($"Unsupported {nameof(SigningAlgorithmSpec)} value: {m_signingAlgorithm}");
        }
    }

    public PdfDigestAlgorithm DigestAlgorithm
    {
        get
        {
            string alg = m_signingAlgorithm.Value;
            if (alg.EndsWith("256"))
                return PdfDigestAlgorithm.Sha256;

            if (alg.EndsWith("384"))
                return PdfDigestAlgorithm.Sha384;

            if (alg.EndsWith("512"))
                return PdfDigestAlgorithm.Sha512;

            throw new NotSupportedException($"Unsupported {nameof(SigningAlgorithmSpec)} value: {m_signingAlgorithm}");
        }
    }

    public byte[] Sign(byte[] message)
    {
        using var kmsClient = new AmazonKeyManagementServiceClient();
        using var stream = new MemoryStream(message);
        var signRequest = new SignRequest()
        {
            SigningAlgorithm = m_signingAlgorithm,
            KeyId = m_keyId,
            MessageType = MessageType.RAW,
            Message = stream,
        };
        SignResponse signResponse = kmsClient.SignAsync(signRequest).GetAwaiter().GetResult();
        return signResponse.Signature.ToArray();
    }
}

完全な AWS KMS を使用して PDF ドキュメントに署名する コードサンプルも GitHub で入手できます。

結論

Docotic.Pdf ライブラリ を活用して、USB トークン、スマートカード、またはクラウドベースの HSM を使用して PDF ドキュメントに署名します。これを実現するには、C# または VB.NET コードで IPdfSigner インターフェイスを実装します。

GitHub から PDF のデジタル署名のコードサンプル をダウンロードしてお試しください。追加情報については、関連記事をご覧ください。

よくある質問

USB トークンまたはスマートカードを使用して PDF に署名するにはどうすればよいですか?

Docotic.Pdf および Pkcs11Interop .NET ライブラリを使用して、トークンまたはスマートカードで PDF に署名します。詳細については、C# で PKCS#11 ドライバーを使用して PDF ドキュメントに署名するセクションを参照してください。

USBトークンまたはスマートカードでSoftHSMを使用するにはどうすればよいですか?

SoftHSM は実際の HSM デバイスをシミュレートします。USB トークンまたはスマートカードをお持ちの場合は、SoftHSM は必要ありません。代わりに、HSM デバイスに付属の PKCS#11 ドライバーを使用してください。

外部署名を使用してPDFドキュメントに署名するにはどうすればよいですか?

Azure Key Vault を使用して PDF ドキュメントに署名する および AWS KMS を使用して PDF ドキュメントに署名する のセクションをご確認ください。他のクラウドベースの HSM を使用した外部 PDF 署名も同様のプロセスに従います。

.NET で Azure Key Vault を使用するにはどうすればよいですか?

Azure.Security.KeyVault.Keys NuGet パッケージを使用してください。GitHub の Azure Key Vault を使用して PDF ドキュメントに署名する コードサンプルをお試しください。