C# の PDF デジタル署名のガイド
.NET で C# を使用してPDF署名に署名する
.NETでC#を使用してPDFファイルにデジタル署名を行うことは非常に複雑です。ここでは、ABCpdf.NETを使用してPDFドキュメントにデジタル署名を行う方法について説明します。
ABCpdf .NETは、2007年からデジタルPDFドキュメントの署名と署名の検証をサポートしをサポートしています。
署名されたPDF文書は多くの政府が多くの公的にデジタル署名されたPDFを受け入れるようになりました。
EU加盟国では、電子識別、認証および信頼サービス(eIDAS)規制により、電子識別を受け入れるための標準化された法的枠組みが提供されています。
これに加えて、PAdES仕様は、PDFドキュメントに署名を挿入および検証するための一連の技術標準を提供します。
PAdES標準のサポートはバージョン11.3のリリースでABCpdfに導入されました。
デジタル署名について
最も単純なデジタル署名は、手書きの署名と同じです。 ペンでドキュメントに署名したのと同じ方法で、ドキュメントに電子的に署名したことを示します。
デジタル署名には、ドキュメントがデジタル署名されると、署名されてからドキュメントが変更されていないことを証明できるという追加の利点があります。
より具体的には、デジタル署名は、PDFドキュメントなどのファイルの信頼性を確保するために使用されるスキームです。 この場合の信頼性とは、次のことを指します。
- ドキュメントが署名されてから変更されていないことの証明(改ざんされていない) li>
- ドキュメントが個人または団体によってデジタル署名されたことの証明(署名者の証明) li>
- ドキュメントに署名した個人またはエンティティは、ドキュメントに署名したことを否定できません(否認なし) li>
デジタル署名は、Public Key Infrastructure(PKI)やシステムと一連の役割、ポリシーとインターネット上のデジタル証明書を管理するためのプロセスに依存しています。
デジタル署名のワークフロー
ドキュメントドキュメントは、さまざまな理由で何度も署名できます。
例えば、ある人が注文書を作成し、別の人がレビューし、さらに別の人が承認する場合があります。
ワークフローにおいて、それぞれの人がドキュメントに署名する場合があります。 この場合、それぞれの署名はPDFの新しいバージョンになります。
各署名はドキュメントの特定のバージョンに固有であるため、g>各署名は署名されたバージョンに対してのみ有効です。
ほとんどのPDFリーダーでは、特定の署名が有効なバージョンを表示できます。
署名、キー、証明書
署名の背後にある数学、キーと証明書の概念、証明書の信頼性、署名の有効期間、および署名の有効期間を無期限に延長する方法について説明します。
署名の作成
署名の作成は、基本的に、特定の数学的関係を持つ2つの非常に大きな数値を使用した計算です。
この関係により、「署名」した場合に確実になります。 1つの番号を持つ一部のデータでは、他の番号を使用してその署名を検証できます。
データに署名することは、1つの数値で計算を実行するだけです。 署名を検証するには、他の番号で同様の計算を実行します。
ファイル内のすべてのデータを含む署名は必要ありません。 そのファイルに固有の番号のみが必要です。 この指紋のような番号はハッシュと呼ばれます。
この番号またはハッシュは、SHA-256などの一方向メッセージダイジェストアルゴリズムを使用して作成します。
キーと証明書
署名する番号は、秘密鍵と呼ばれます。 他の人が検証する番号は、公開キーと呼ばれます。
秘密鍵は署名者だけが知っている必要があります。 公開鍵は、署名を検証したい人なら誰でも知っている必要があります。
公開鍵は証明書と呼ばれるファイルに保持されます。 証明書に関連付けられている秘密鍵は、通常、別のファイルに保持されています。 各証明書には、次のようなその他の情報が含まれています。
- 証明書の所有者(名前、組織など) li>
- この証明書に署名した証明書(発行者) li>
- 証明書が発行された日付(つまり、発行者が署名した日付) li>
- 証明書の有効期限が切れる日付
- シリアル番号
- 証明書の用途(キーの使用法) li>
信頼の連鎖
証明書は、Certificate Authority(CA)によって発行されます。 CAは、提供された情報が正しいことを確認します。証明書を発行するとき、CAは、CA証明書の秘密鍵を使用してその中のデータに署名します。
では、CAを信頼できることをどうやって知るのでしょうか。 それらの証明書は、別の上位レベルのCAから発行され、さらに上位レベルのCAによって発行および署名される場合があります。 等々。
これにより、階層(信頼のチェーン)が形成されます。証明書は下部にあり、中間CAが上部にあり、最終的には最終的なアービターであるルートCAが上部にあります。
この最上位の証明書は、別の証明書からの秘密鍵ではなく、独自の秘密鍵によって署名されています。 これはルートCAと呼ばれ、証明書のチェーン全体のトラストアンカー(TA)です。 コンピューターのどこかに、信頼できる最上位の証明書を示すファイルがあります。
証明書は、Trusted Service Providers(TSP)または再販業者によって提供されます。 彼らは、信頼の連鎖を完了するために、信頼されているルートCA証明書に依存しています。 これらは、Comodo、GeoTrust、DigiCert、GlobalSignなどの企業です。
証明書の有効期間と失効
証明書は期間限定で有効です。 各証明書には、発行日と有効期限が含まれています。 署名を有効にするには、署名の作成時に証明書が有効である必要があります。
たとえば、秘密鍵が他の誰かに知られるようになった場合、たとえばインターネット上で公開された場合、証明書機関は対応する証明書を取り消すことができます。
署名を検証するソフトウェアプログラムは、証明書が作成されたときに証明書が取り消されたかどうかを確認するために、証明書機関にオンラインで確認する場合があります。
証明書が使用するテクノロジーが危険にさらされた場合にも、証明書が取り消される可能性があります。
秘密鍵を安全に保つ
多くのCAは、秘密鍵が安全に保管されている場合にのみ証明書を発行します。 これは、ハードウェアセキュリティモジュール(HSM)と呼ばれるハードウェアデバイス上にある可能性があります.
最も単純な場合、これはThales SafeNet eToken 5110などの小さなUSBキーです。より複雑なデバイスには、多くの証明書と秘密キーを保持するラックマウント型サーバーユニットが含まれる場合があります。
HSMは秘密鍵を保持します。これにより、オペレーティングシステム上のどのプログラムも秘密鍵を実質的に読み取ることができなくなります。 代わりに、ダイジェストは、この目的のためのプロセッサとファームウェアを備えたHSMで署名されます。 HSMは、セキュリティをさらに強化するためにパスワードで保護される可能性があります。
署名のタイムスタンプ
基本的な署名では、コンピューターの時間を使用して署名時間を指定できます。 ただし、コンピューターの時刻は変更される可能性があるため、これが正確であるかどうかを確認することはできません。
署名時間を示すより確実な方法には、タイムスタンプ権限を使用することが含まれます。 これは、タイムスタンプを追加して署名自体に署名するように要求できる信頼できるサーバーです。
タイムスタンプ要求に署名するタイムスタンプ証明書は、通常、タイムスタンプ応答で返されます。
ほとんどの証明書には、CAによって信頼できると見なされたタイムスタンプサーバーのURLが含まれています。
長期アーカイブのための署名の保持
署名の寿命
証明書が限られた期間有効である場合、有効期限が切れた後、または実際に署名が取り消されているかどうかを確認するにはどうすればよいですか?
ほとんどのCAは検証機関(VA)としても機能し、証明書の失効をチェックできるように証明書内に情報を含めます。 せいぜい基本的に、それらは埋め込まれた証明書失効リスト(CRL)を提供するかもしれません。
ただし、CRLは非常に長くなる可能性があるため、証明書には、取り消された証明書のリストを取得するためのオンライン証明書ステータスプロトコル(OCSP)サーバーのURLが含まれている場合もあります。 各応答は、それ自体が署名されたデータオブジェクトです。
署名に使用された証明書が特定の時点(通常は署名時間)で有効であったという証拠をPDFドキュメントに追加することもできます。 この情報は、ドキュメントセキュリティストア(DSS)と呼ばれるドキュメントカタログのオプションの辞書に入れることができます。
- OCSP-一連のOCSP応答。
- CRL-CRLの配列。
- 証明書?証明書の配列。 理想的には、これには、署名、タイムスタンプ、およびOCSPとCRLの応答を検証するために必要なすべての証明書が含まれている必要があります。 li>
- VRI ?検証関連情報。 これには、上記と同じ情報が含まれていますが、署名ごとに行われます。 また、エントリが作成されたときの時間またはタイムスタンプストリームへの間接参照がある場合もあります。 li>
この情報は、長期検証(LTV)または長期アーカイブ(LTA)と呼ばれます。
将来性のある署名
時間の経過とともにテクノロジーは向上し、コンピューターはより高速になります。 そのため、証明書の生成、署名の署名、および署名のタイムスタンプに使用したアルゴリズムが壊れたり、侵害されたりする可能性があります。
これを防ぐために、ドキュメントタイムスタンプと呼ばれる特別な署名をドキュメントに適用できます。 この署名は、信頼できる時点でのドキュメントの状態を確認します。 当時、署名および関連する長期検証情報が改ざんされておらず、有効であると見なされていたことを証明しています。
新しい署名テクノロジーを使用してドキュメントに繰り返しタイムスタンプを付け、時間の経過とともに改ざんが発生していないことを証明できます。 その時点で有効なアルゴリズムを使用してドキュメントに繰り返しタイムスタンプを付けると、元の署名の整合性が証明されます。
ただし、LTV標準にはさまざまなものがあることに注意してください。 たとえば、PAdES LTVでは、署名にESSCertificateV2属性などの特定の要素が必要です。 ただし、Acrobatは、これらの要素なしでLTVタイムスタンプを受け入れることができます。
PAdESとは何ですか?
PAdES(PDF Advanced Electronic Signatures)は、PDFドキュメントのCAdES標準に特化したものです。
CAdES(CMS Advanced Electronic Signatures)は、EU全体で安全なペーパーレストランザクションを促進するためにEuropean Telecommunications Standard Institute(ETSI)によって開発された標準です。
PAdESには4つのベースラインプロファイルがあり、次のように非常に簡単に表すことができます。
- PAdES Bレベル(基本署名) li>
- PAdES T-Level(PAdES B-信頼できるタイムスタンプ付き) li>
- PAdES LTレベル(長期検証情報が追加されたPAdES T-) li>
- PAdES LTA-レベル(PAdES LT-信頼できるドキュメントのタイムスタンプ署名が追加されています) li>
これらのレベルの違いに関する最も簡単なリファレンスは、ETSIサイトにあります。 。 これにより、長いテキストが、より深く読むための相互参照を含む管理可能な要約にまとめられます。
署名の実装の内部
十分な基本と背景-手を汚す時間。 ボンネットを立てて、署名されたドキュメントの実際の実装の内部を見てみましょう。 関連するファイルの種類と、実際にドキュメントに署名するメカニズムについて説明します。
証明書には何が含まれていますか?
署名は、暗号化メッセージ構文(CMS)に基づいています。 インターネットエンジニアリングタスクフォース(IETF)は、あらゆる形式のデジタルデータのダイジェストを作成、署名、認証、または暗号化するためのCMS標準(RFC 5652)を作成しました。 これはPKCS#7の構文に基づいています。
CMSは、一連のPublic Key Cryptography Standards(PKCS)に依存しています。これらは、数字だけでは役に立たないほど識別されます。
- PKCS#1は、公開鍵と秘密鍵の数学的側面と、それらの暗号化での使用を定義します。 li>
- PKCS#7は、署名、暗号化、および復号化の観点から、技術レベルで暗号化メッセージ構文標準を定義しています。 li>
- PKCS#12は、PKCSオブジェクトのアーカイブファイル形式を定義します。 li>
PKCS#12は、「。p12」または「.pfx」の拡張子を持つファイルの形式で、最も頻繁に遭遇するものです。 この形式は、証明書、秘密鍵、およびその他のデータ項目を格納できる大きなバッグのようなものです。 これらのファイルは通常、パスワードで保護されています。
ほとんどのPKCS定義オブジェクトは、Distinguished Encoding Rules(DER)でエンコードされたAbstract Syntax Notation One(ASN.1)で定義されています。 ASN.1は、クロスプラットフォームインターフェイス記述言語です。 整数、ブール値、文字列、オクテット文字列などのいくつかの基本的なタイプを定義します。 リスト(シーケンス)や選択肢などの構造も同様です。
ASN.1は、証明書、秘密鍵、オンライン証明書ステータスプロトコル(OCSP)応答、証明書失効リスト(CRL)、証明書署名要求(CSR)、さらには証明書自体を含む、ほぼすべてのオブジェクトを定義するために使用されます。 ASN.1で指定されたさまざまなオブジェクトをカバーするRFCは多数あります。
X.509は、公開鍵証明書をASN.1形式でエンコードするための標準です。 これは、それ自体がファイル形式ではありません。証明書に何が表示され、何が表示されるかについてのレシピです。 最も重要なことは、署名の検証に使用する必要のあるアルゴリズムの詳細を義務付けることです。
PDFはどのように署名されますか?
PDFドキュメントに署名するとき、PDFに署名領域を作成します。 署名するバイト範囲と実際のCMS署名を配置するために、その領域にスペースを予約します。 署名を取得するには、最初に署名するデータのダイジェストを取得します。ただし、CMSを挿入するデータの「穴」は除きます。
ドキュメントを一意に識別する指紋を取得できるように、CMSに多数の一方向ダイジェストアルゴリズムを使用する場合があります。
次に、秘密鍵を使用して、このダイジェスト文字列を、CMSに配置する追加の署名付き属性とともに暗号化します。 さらに、署名タイムスタンプなど、署名されていない属性をCMSに追加する場合があります。 CMSには、CMSの署名に使用される公開鍵を含む証明書が含まれている必要があります。
タイムスタンプには、Timestamp Service Authority(TSA)証明書も含める必要があります。 このようにして、検証ソフトウェアアプリケーションは、実際の証明書の信憑性ではないにしても、署名の整合性を即座に判断できます。
署名検証ソフトウェアが証明書の信頼チェーンを構築できるように、証明書階層を含めることもできます。
どのような種類の証明書を使用できますか?
証明書の許可された使用法は、証明書のASN.1でエンコードされた拡張属性にリストされています。 関連する2つの拡張機能があり、どちらもRFC3280で定義されています。
Key Usage拡張機能は、キーの基本的な目的を定義するビットフィールドです。たとえば、デジタル署名、否認なし、キー暗号化などです。
拡張キー使用法(EKU)拡張機能は、これをさらに改良し、公開キーを使用できる追加の目的を定義します。 これらは、コード署名、電子メール保護、タイムスタンプ、認証などを表すために使用される点線の番号シーケンス(1.3.6.1.4.1.343など)であるオブジェクト識別子(OID)の観点から指定されます。 Microsoft などのサードパーティが追加のEKUを定義する場合があります。
理論的には、任意の証明書を使用できます。 署名の技術的側面はすべて同じです。 PDF検証ソフトウェアは、許可された特定の用途の証明書のみを受け入れることができるということです。
PDFの場合、デジタル署名の主な使用法は、最低限必要な使用法です。 それが署名の理由である場合は、否認しないことも必要になる場合があります。
拡張キーの使用法については、Acrobatは、電子メール保護、コード署名、Microsoftのドキュメントの署名。
さらに、PDFドキュメントをデフォルトでAcrobatで検証する場合、つまり、署名者を信頼するようにAcrobatを明示的に設定しない場合は、証明書がAdobe Approved Trust List(AATL)のベンダーによって発行されていることを確認する必要があります。
ABCpdfを使用したドキュメントへの署名
ABCpdf .NETでドキュメントに署名する方法について。
まず、署名証明書が必要です…
使用するCAと必要な証明書の種類は、署名を検証する方法によって異なります。
青い「信頼できる」バーをAdobeAcrobatに表示したいだけの場合は、Adobe によって信頼されている CA によって発行された証明書が必要です。 Adobe Approved Trust List(AATL)には、そのようなCAのリストがあります。
政府との取引には、政府が承認したベンダーが必要になる場合があります。 たとえば、欧州委員会には信頼できるデジタル ID プロバイダーのリストがあります。 あなたはあなたがあなたが言っている人であることをCAに証明する必要があり、これには個人的なインタビューが含まれる場合があります。
信頼できるパートナーの製品をテストし、技術サポート関係を結ぶ際には、信頼できるパートナーの証明書を使用することをお勧めします。 現在の信頼できるリストには、保証付きなどのベンダーが含まれています。
ほとんどのベンダーは、秘密鍵を保護するために、ハードウェアセキュリティモジュール(HSM)で署名証明書を発行することを主張しています。 だから、出荷のための時間を取ってください!
もちろん、受信者が使用するWindowsまたはPDFアプリケーションで手動で信頼できる場合は、自己生成された証明書も含め、任意の証明書を使用できます。
どのような種類の証明書が必要ですか?
繰り返しますが、これは署名を検証している人と署名の目的に大きく依存します。 p>
理論的には、実際に必要なのは2つのキーだけなので、どの証明書でもドキュメントに署名できます。ただし、証明書は通常、証明書で指定された特定の用途で発行されます。 詳細については、上記の「UndertheHood」を参照してください。
Adobe Acrobatの場合、CAがAATLを介して信頼されていれば、電子メール署名用に発行された証明書で署名が有効になります。
ただし、デジタルIDには、実際には否認しない属性も含まれている必要があります。 これは通常、HSMなどの安全な方法で秘密鍵が発行されたことを意味します。
認証機関は、署名証明書を発行する際の主要な使用法が異なる場合があります。 PDF検証ソフトウェアは、キーの使用法についてさまざまな考えを持っている場合があります。
年が進むにつれて、Adobe Acrobatはより厳密になり、受け入れられていた一部の証明書は現在受け入れられなくなりました。 そのため、証明書を購入するときは、ベンダーがAcrobatでの使用を保証していることを確認する必要があります。 p>
コード
「Signature1」という名前の署名フィールドがあるとします。 MyDoc.pdfというファイルにあります。
JohnDoe.p12と呼ばれるPKCS#12ファイルからの証明書を使用して署名に署名し、出力PDFがPAdES Baseline Long Term Archival(PADES_B_LTA)標準に準拠するようにします。
このためには、次の形式のコードを記述します。
Doc doc = new Doc();
doc.Read("MyDoc.pdf");
Signature sig = (Signature)doc.Form.Fields["Signature1"];
sig.Reason = "Final Version";
sig.Location = "London";
sig.TimestampServiceUrl = new Uri("http://timestamp.digicert.com");
sig.Compliance = Signature.ComplianceLevel.PAdES_B_LTA;
X509Certificate2 cert = new X509Certificate2("JoeBlogs.p12", "password",
X509KeyStorageFlags.Exportable);
sig.Sign(cert, true, new OID(CryptoConfig.MapNameToOID("SHA256")));
doc.Save("SignedDoc.pdf");
...
JohnDoe.p12ファイルが秘密鍵とそれに対応する証明書、およびその証明書の発行証明書を保持しているとすると、このコードは次のようになります。
- 証明書(PAdES B_B)を使用してドキュメントデータに署名します li>
- DigiCertのTimestampServiceAuthority(PAdES B-T)を使用して、署名にタイムスタンプを追加します li>
-
次のもので構成されるDocumentSecureStorageエントリを追加します。
-署名証明書のチェーン内の証明書
-証明書ごとに取得されたOCSP応答またはCRL
-オプションで、この情報が追加されたときのタイムスタンプ
-ドキュメントがPAdES_LTに準拠するようになりました
li> - 最後に、ドキュメントにドキュメントタイムスタンプ署名を追加して、ドキュメント全体をPAdESB_LTAに準拠させます
この方法で証明書を渡す場合は、X509Certificate2をX509KeyStorageFlags.Exportableストレージ修飾子で初期化する必要があることに注意してください。
キーを含むGemalto eTokenUSBキーなどのハードウェアセキュリティモジュール(HSM)を使用する場合は、次の署名方法を使用できます。
sig.Sign(X509Certificate2 cert, SecureString password,
new OID(CryptoConfig.MapNameToOID("SHA256")));
...
これを認証クライアントとして使用するには、トークンの証明書をWindows証明書ストアに自動的にインポートするようにソフトウェアを設定する必要があります。
HSMの場合、秘密鍵をエクスポートすることはできません。 代わりに、USBキーのファームウェアが署名を行います。 passwordパラメータを介してUSBキーの正しいパスワードを渡すと、署名時にプロンプトは表示されません。 nullパスワードを渡すと、認証クライアントからのパスワードプロンプトが表示されます。
一部のクラウドベースのHSMでは、使用可能な署名プロンプトがありません。 むしろ署名を行うAPI。 これにより、秘密鍵を非常に安全に保つことができます-それを必要とするコードから十分に離れています。 この場合、HSMがABCpdf .NETによって提供されるデータに署名できるように、署名コールバックを設定する必要があります。
この例では、.NETを使用してコールバックのデータに署名しますが、もちろん、代わりにHSMAPIを使用するようにこのコードを適合させる必要があります。
public void SignDoc() {
// Just use public certificate from file - i.e. do not obtain from registry
using (Doc doc = new Doc()) {
doc.Read(@"C:\DocToSign.pdf");
Signature sig = (Signature)doc.Form.Fields["Signature1"];
sig.CustomSigner = ExternalSigner;
sig.Reason = "Test External Signing";
X509Certificate2 cert = new X509Certificate2(@"C:\GlobalSign.cer");
sig.Sign(cert, true, new Oid(CryptoConfig.MapNameToOID("SHA512")),
X509IncludeOption.EndCertOnly);
doc.Save(@"C:\SignedDoc.pdf");
}
}
byte[] ExternalSigner(byte[] data) {
string serial = "10 20 30 10 40 10 40 50 60 10 20 30"; // needs value
SecureString password = new SecureString(); // needs value
X509Certificate2 cert = null;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try {
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly | OpenFlags.MaxAllowed);
cert = store.Certificates.Find(X509FindType.FindBySerialNumber, serial, false)[0];
}
finally {
store.Close();
}
if (cert.PrivateKey is RSACryptoServiceProvider == false)
throw new Exception("Unsupported key type.");
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey;
CspParameters cspParams = new CspParameters(1, rsa.CspKeyContainerInfo.ProviderName,
rsa.CspKeyContainerInfo.UniqueKeyContainerName) {
KeyPassword = password,
Flags = CspProviderFlags.NoPrompt
};
RSACryptoServiceProvider service = new RSACryptoServiceProvider(cspParams);
return service.SignData(data, "2.16.840.1.101.3.4.2.3"); // SHA512
}
...
したがって、Azure KeyVaultを使用している場合は、次の形式の署名機能を使用できます。
byte[] ExternalSigner(byte[] data) {
var hash = (new SHA512CryptoServiceProvider()).ComputeHash(data);
return GetKeyVaultClient().SignAsync(KeyIdentifier, JsonWebKeySignatureAlgorithm.RS512,
hash).Result.Result;
}
技術的に十分ではありませんか?
独自の証明書を生成してみませんか? X-Certificate and Key Management を使用すると、これを行うことができます。 既存の証明書と同様の証明書を生成できる機能があり、HSMと対話することもできます。
証明書の中に入ってみませんか? 生の証明書やCMS署名などのASN.1でエンコードされたオブジェクトを調べるために、 lapo Webサイトは、完全にJavaScriptで記述された優れたデコーダーを提供します。
なぜ OID ではないのですか? ASN.1をデコードすると、いくつかのオブジェクト識別子(OID)が発生する可能性があります。 ディレクトリはたくさんありますが、Oid-Info.com が気に入っています。