C# を使用して Verified PDF 署名から署名者の証明書を読み取る方法 (X.509、eIDAS、チェーン)
監査パイプラインに契約書が送られてきました。それはデジタル署名されており、署名は有効です。コンプライアンスチームは、誰が署名したのか、その朝、署名者の証明書は有効だったのか、発行元のCAは信頼済みリストと一致しているのか、といった回答を求めています。生の署名バイト列を取得し、DERを解析し、手作業で証明書チェーンを辿ることも可能です。 あるいは、VerifiedSignature オブジェクトに SignerCertificate を問い合わせ、その回答をプロパティとして読み取ることもできます。
これこそが、VerifiedSignature の SignerCertificate および CertificateChain プロパティが設計された目的です。 PdfDocument.GetVerifiedSignatures() から返される情報には、署名者の完全な X.509 識別情報、発行 CA、有効期限、SHA-256 サムプリント、生の DER バイトデータ、およびルート証明書に至るまでの中間証明書がすべて含まれます。 これこそが、eIDAS準拠、証明書ピンニング、監査証跡、および信頼の連鎖の検証に必要なAPIインターフェースです。
このガイドでは、3つの種類の証明書検査について解説します:
- 標準的な X.509 の詳細:識別プロパティ、完全な識別名(DN)、有効期間、および
X509Certificate2相互運用性のための生の DER バイト。 - eIDASおよび規制対象業界の分野:
2.5.4.97のような数値OIDを読み取ってeIDASのorganizationIdentifierを特定します。 - トラストチェーンの検証:SHA-256 サムプリントのピンニング、および署名者からルート CA までのチェーン全体を辿る検証。
30日間トライアルを開始し、検証パイプラインでの証明書検査機能を試してみてください。
クイックスタート:署名付きPDFから署名者の証明書を読み取る
読み込まれたPDFに対してGetVerifiedSignaturesを呼び出し、結果から署名者の証明書プロパティを直接読み取ります。
-
IronPDF をNuGetパッケージマネージャでインストール
PM > Install-Package IronPdf -
このコード スニペットをコピーして実行します。
var sig = PdfDocument.FromFile("signed.pdf").GetVerifiedSignatures().First(); var cert = sig.SignerCertificate; Console.WriteLine($"{cert?.CommonName} ({cert?.Organization}) valid until {cert?.NotAfter}"); -
実際の環境でテストするためにデプロイする
今日プロジェクトで IronPDF を使い始めましょう無料トライアル
最小限のワークフロー(3ステップ)
- NuGetからIronPDFをダウンロードする。
- 署名付きPDFを読み込み、
GetVerifiedSignatures()を呼び出して、検証済みの署名オブジェクトのリストを取得します - 身元と有効性については
sig.SignerCertificate を参照するか、完全な信頼チェーンについてはsig.CertificateChainを参照してください
署名者の国民IDまたは個人IDをどのように抽出しますか?
SubjectSerialNumber プロパティは、証明書の Subject DN から SERIALNUMBER OID の値を返します。 規制対象業界(eIDAS認定証明書、銀行、政府発行のデジタルIDなど)において、このフィールドには署名者の国民ID、納税者番号、または個人識別番号が格納されます。 これは証明書自体のシリアル番号ではありません; つまり CertificateSerialNumber です。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-serial-number.cs
using IronPdf;
using IronPdf.Signing.Inspection;
var pdf = PdfDocument.FromFile("eidas-signed-invoice.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
var cert = sig.SignerCertificate;
if (cert is null) continue;
// Subject DN SERIALNUMBER OID (national ID, tax ID, etc.)
Console.WriteLine($"Signer Identity (SERIALNUMBER): {cert.SubjectSerialNumber ?? "not present"}");
// Certificate's own serial from the issuing CA
Console.WriteLine($"Certificate Serial (CA-issued): {cert.CertificateSerialNumber}");
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Dim pdf = PdfDocument.FromFile("eidas-signed-invoice.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Dim cert = sig.SignerCertificate
If cert Is Nothing Then Continue For
' Subject DN SERIALNUMBER OID (national ID, tax ID, etc.)
Console.WriteLine($"Signer Identity (SERIALNUMBER): {If(cert.SubjectSerialNumber, "not present")}")
' Certificate's own serial from the issuing CA
Console.WriteLine($"Certificate Serial (CA-issued): {cert.CertificateSerialNumber}")
Next
SubjectSerialNumberは、ドキュメントに署名した者(個人または組織ID。Subject DNに埋め込まれた国民IDや納税者番号など)を示します。 CertificateSerialNumber は、どの証明書が使用されたかを示します; (これは、発行元の認証局が失効リストおよび監査ログ用に割り当てる一意のシリアル番号です。Convenience Identityのプロパティにはどのようにアクセスしますか?
SignerCertificateInfo は、最も頻繁に必要とされる Subject DN フィールドを直接プロパティとして公開しているため、DN 文字列全体を自分で解析する必要はありません。
署名者の氏名および所属の読み方
Emailプロパティは、ほとんどのIDワークフローが最初に参照する項目を網羅しています。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-identity-common.cs
using IronPdf;
using IronPdf.Signing.Inspection;
var pdf = PdfDocument.FromFile("signed-agreement.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
var cert = sig.SignerCertificate;
if (cert is null) continue;
// Common Subject DN fields exposed directly as properties
Console.WriteLine($"CommonName (CN): {cert.CommonName}");
Console.WriteLine($"Organization (O): {cert.Organization}");
Console.WriteLine($"Country (C): {cert.Country}");
Console.WriteLine($"Email: {cert.Email}");
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Dim pdf = PdfDocument.FromFile("signed-agreement.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Dim cert = sig.SignerCertificate
If cert Is Nothing Then Continue For
' Common Subject DN fields exposed directly as properties
Console.WriteLine($"CommonName (CN): {cert.CommonName}")
Console.WriteLine($"Organization (O): {cert.Organization}")
Console.WriteLine($"Country (C): {cert.Country}")
Console.WriteLine($"Email: {cert.Email}")
Next
Email プロパティは、まず Subject DN に対して emailAddress OID をチェックします。 存在しない場合は、Subject Alternative Name (SAN) rfc822Name 拡張子にフォールバックします。 Country プロパティは、2文字の ISO 3166-1 alpha-2 コード(例: "DE"、"US"、"FR")を返します。 対応するフィールドが証明書に存在しない場合、すべての利便性プロパティは null を返します。
必要な情報をすべて把握したい場合のDN全文の読み方
監査ログ、下流の解析、またはコンプライアンスレポートのために、SubjectDN および IssuerDN は完全な識別名(Distinguished Name)文字列を返します。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-identity-full-dn.cs
using IronPdf;
using IronPdf.Signing.Inspection;
var pdf = PdfDocument.FromFile("signed-agreement.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
var cert = sig.SignerCertificate;
if (cert is null) continue;
// Full DN strings for audit logging or downstream parsing
Console.WriteLine($"Full Subject DN: {cert.SubjectDN}");
Console.WriteLine($"Full Issuer DN: {cert.IssuerDN}");
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Dim pdf = PdfDocument.FromFile("signed-agreement.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Dim cert = sig.SignerCertificate
If cert Is Nothing Then Continue For
' Full DN strings for audit logging or downstream parsing
Console.WriteLine($"Full Subject DN: {cert.SubjectDN}")
Console.WriteLine($"Full Issuer DN: {cert.IssuerDN}")
Next
任意の"件名"および"発行者"フィールドを抽出するにはどうすればよいですか?
GetSubjectField(string) および GetIssuerField(string) メソッドは、短縮名または数値 OID のいずれかを受け付けます。 これらは大文字小文字を区別せず、フィールドが存在しない場合は null を返します。
サポートされている短縮名:ST, E, SERIALNUMBER, SURNAME, T, GIVENNAME, UID, ORGANIZATIONIDENTIFIER.
あらゆる分野の読み取り(eIDAS OID を含む)
"OU" のような短い名前、または "2.5.4.97"(eIDAS 組織識別子)のような数値 OID を渡すことで、サブジェクト DN から任意のフィールドを取得できます。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-field-subject.cs
using IronPdf;
using IronPdf.Signing.Inspection;
var pdf = PdfDocument.FromFile("eidas-contract.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
var cert = sig.SignerCertificate;
if (cert is null) continue;
// Short-name lookups (case-insensitive)
string? orgUnit = cert.GetSubjectField("OU");
string? surname = cert.GetSubjectField("SURNAME");
string? givenName = cert.GetSubjectField("GIVENNAME");
string? title = cert.GetSubjectField("T");
// Numeric OID lookup (eIDAS organizationIdentifier)
string? orgId = cert.GetSubjectField("2.5.4.97");
Console.WriteLine($"Name: {givenName} {surname} ({title}), OU: {orgUnit}");
Console.WriteLine($"eIDAS Org ID (2.5.4.97): {orgId ?? "not present"}");
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Dim pdf = PdfDocument.FromFile("eidas-contract.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Dim cert = sig.SignerCertificate
If cert Is Nothing Then Continue For
' Short-name lookups (case-insensitive)
Dim orgUnit As String = cert.GetSubjectField("OU")
Dim surname As String = cert.GetSubjectField("SURNAME")
Dim givenName As String = cert.GetSubjectField("GIVENNAME")
Dim title As String = cert.GetSubjectField("T")
' Numeric OID lookup (eIDAS organizationIdentifier)
Dim orgId As String = cert.GetSubjectField("2.5.4.97")
Console.WriteLine($"Name: {givenName} {surname} ({title}), OU: {orgUnit}")
Console.WriteLine($"eIDAS Org ID (2.5.4.97): {If(orgId, "not present")}")
Next
数値OIDの検索は、標準的な短縮名ではカバーされない組織識別子、Professional資格、または管轄区域固有のフィールドを埋め込んだeIDASおよび規制対象業界の証明書にとって不可欠です。
発行者のフィールドの読み取り
GetIssuerField は、発行CAの識別名に対しても同様に機能します。 これは、信頼性の検証、CAレポート作成、および発行機関ごとの署名のグループ化に役立ちます。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-field-issuer.cs
using IronPdf;
using IronPdf.Signing.Inspection;
var pdf = PdfDocument.FromFile("eidas-contract.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
var cert = sig.SignerCertificate;
if (cert is null) continue;
// GetIssuerField works the same way as GetSubjectField
string? issuerCN = cert.GetIssuerField("CN");
string? issuerO = cert.GetIssuerField("O");
string? issuerCountry = cert.GetIssuerField("C");
Console.WriteLine($"Issued by: {issuerCN} ({issuerO}, {issuerCountry})");
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Dim pdf = PdfDocument.FromFile("eidas-contract.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Dim cert = sig.SignerCertificate
If cert Is Nothing Then Continue For
' GetIssuerField works the same way as GetSubjectField
Dim issuerCN As String = cert.GetIssuerField("CN")
Dim issuerO As String = cert.GetIssuerField("O")
Dim issuerCountry As String = cert.GetIssuerField("C")
Console.WriteLine($"Issued by: {issuerCN} ({issuerO}, {issuerCountry})")
Next
証明書の有効性を確認するにはどうすればよいですか?
SignerCertificateInfo は、2つの妥当性チェックヘルパーを提供します:
IsExpiredは、DateTime.UtcNow > NotAfterの場合、trueを返します。IsValidAt(DateTime)は、指定されたタイムスタンプがNotAfterの Windows のウィンドウ内に収まる場合、trueを返します。 一般的な用途としては、署名時点での証明書の有効性を確認することです。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-validity.cs
using IronPdf;
using IronPdf.Signing.Inspection;
var pdf = PdfDocument.FromFile("archived-contract.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
var cert = sig.SignerCertificate;
if (cert is null) continue;
Console.WriteLine($"Valid from: {cert.NotBefore}");
Console.WriteLine($"Valid until: {cert.NotAfter}");
Console.WriteLine($"Expired now: {cert.IsExpired}");
// Confirm certificate was valid when the document was signed
if (sig.SigningDate.HasValue)
{
bool validAtSigning = cert.IsValidAt(sig.SigningDate.Value);
Console.WriteLine($"Valid at signing time ({sig.SigningDate.Value}): {validAtSigning}");
}
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Dim pdf = PdfDocument.FromFile("archived-contract.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Dim cert = sig.SignerCertificate
If cert Is Nothing Then Continue For
Console.WriteLine($"Valid from: {cert.NotBefore}")
Console.WriteLine($"Valid until: {cert.NotAfter}")
Console.WriteLine($"Expired now: {cert.IsExpired}")
' Confirm certificate was valid when the document was signed
If sig.SigningDate.HasValue Then
Dim validAtSigning As Boolean = cert.IsValidAt(sig.SigningDate.Value)
Console.WriteLine($"Valid at signing time ({sig.SigningDate.Value}): {validAtSigning}")
End If
Next
IsExpired は、証明書から有効期限を抽出できない場合、false を返します(true ではありません)。 このヘルパーは意図的に保守的な設計となっており、メタデータが欠落しているという理由だけで有効期限が切れたとみなすことはありません。 ゼロトラストワークフローでは、有効期限が欠落している場合を明示的に失敗ケースとして扱うこと。監査証跡については、IsExpired チェック(現在の有効性)と IsValidAt(signingDate) チェック(署名時の有効性)の両方をログに記録してください。 現在では有効期限が切れている証明書であっても、文書に署名された時点では有効であった可能性があります; コンプライアンスの観点からは、両方のデータポイントが重要です。
証明書ピンニングにおいて、SHA-256 サムプリントはどのように使用されますか?
Sha256Thumbprint プロパティは、DER エンコードされた証明書の SHA-256 ハッシュである、64 文字の大文字の 16 進数文字列を返します。 これは、有効性が確認済みの署名者証明書リストに対して照合する値です。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-thumbprint-pinning.cs
using IronPdf;
using IronPdf.Signing.Inspection;
using System.Collections.Generic;
// Known-good signer thumbprints from a compliance database
var pinnedThumbprints = new HashSet<string>
{
"A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2",
"F6E5D4C3B2A1F6E5D4C3B2A1F6E5D4C3B2A1F6E5D4C3B2A1F6E5D4C3B2A1F6E5"
};
var pdf = PdfDocument.FromFile("submitted-form.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
var cert = sig.SignerCertificate;
if (cert is null) continue;
// Pin against trusted thumbprint list
bool trusted = pinnedThumbprints.Contains(cert.Sha256Thumbprint);
Console.WriteLine($"Signer: {cert.CommonName}, Thumbprint: {cert.Sha256Thumbprint}");
Console.WriteLine($"Pinned: {trusted}");
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Imports System.Collections.Generic
' Known-good signer thumbprints from a compliance database
Dim pinnedThumbprints As New HashSet(Of String) From {
"A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2",
"F6E5D4C3B2A1F6E5D4C3B2A1F6E5D4C3B2A1F6E5D4C3B2A1F6E5D4C3B2A1F6E5"
}
Dim pdf = PdfDocument.FromFile("submitted-form.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Dim cert = sig.SignerCertificate
If cert Is Nothing Then Continue For
' Pin against trusted thumbprint list
Dim trusted As Boolean = pinnedThumbprints.Contains(cert.Sha256Thumbprint)
Console.WriteLine($"Signer: {cert.CommonName}, Thumbprint: {cert.Sha256Thumbprint}")
Console.WriteLine($"Pinned: {trusted}")
Next
生の証明書データから X509Certificate2 をどのように構築しますか?
RawData プロパティは、DER エンコードされた証明書を byte[] として返します。 各呼び出しは防御的なコピーを返すため、内部データが参照によって公開されることはありません。 これを使用して、.NETのネイティブ暗号化API(チェーン構築、ポリシー検証、CRLチェック)との相互運用性を実現するためのSystem.Security.Cryptography.X509Certificates.X509Certificate2を構築できます。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-x509-interop.cs
using IronPdf;
using IronPdf.Signing.Inspection;
using System.Security.Cryptography.X509Certificates;
var pdf = PdfDocument.FromFile("signed-report.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
var cert = sig.SignerCertificate;
if (cert is null) continue;
// Construct X509Certificate2 from defensive DER copy
byte[] derBytes = cert.RawData;
var x509 = new X509Certificate2(derBytes);
Console.WriteLine($"X509 Subject: {x509.Subject}");
Console.WriteLine($"X509 Issuer: {x509.Issuer}");
Console.WriteLine($"X509 Serial: {x509.SerialNumber}");
Console.WriteLine($"X509 Algorithm: {x509.SignatureAlgorithm.FriendlyName}");
Console.WriteLine($"X509 Key Size: {x509.PublicKey.Key.KeySize} bits");
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Imports System.Security.Cryptography.X509Certificates
Dim pdf = PdfDocument.FromFile("signed-report.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Dim cert = sig.SignerCertificate
If cert Is Nothing Then Continue For
' Construct X509Certificate2 from defensive DER copy
Dim derBytes As Byte() = cert.RawData
Dim x509 = New X509Certificate2(derBytes)
Console.WriteLine($"X509 Subject: {x509.Subject}")
Console.WriteLine($"X509 Issuer: {x509.Issuer}")
Console.WriteLine($"X509 Serial: {x509.SerialNumber}")
Console.WriteLine($"X509 Algorithm: {x509.SignatureAlgorithm.FriendlyName}")
Console.WriteLine($"X509 Key Size: {x509.PublicKey.Key.KeySize} bits")
Next
RawData への各アクセスは、新しい防御用コピーを返します。 内部のバイト配列は参照によって公開されることは決してないため、返されたバイトを変更しても、その後の呼び出しには影響しません。)}]
この相互運用パスを使用すると、IronPDFの署名検証機能を、X509CertificateValidator実装など、既存 for .NET証明書検証パイプラインに組み込むことができます。
証明書チェーンをどのように辿るのですか?
CertificateChain プロパティは、VerifiedSignature に対して、署名者 → 中間 CA → ルート CA の順に並べられた IReadOnlyList<SignerCertificateInfo> を返します。 インデックス 0 は常に署名者証明書です(SignerCertificate と同じオブジェクト)。 このリストは決してnullになりません; チェーンを抽出できない場合、そのチェーンには署名者の証明書のみが含まれています。
:path=/static-assets/pdf/content-code-examples/how-to/verify-pdf-signatures-chain-walking.cs
using IronPdf;
using IronPdf.Signing.Inspection;
var pdf = PdfDocument.FromFile("enterprise-signed.pdf");
foreach (var sig in pdf.GetVerifiedSignatures())
{
Console.WriteLine($"--- Signature: {sig.SignatureName} ---");
Console.WriteLine($"Chain length: {sig.CertificateChain.Count}");
// Walk from signer (index 0) through intermediates to root CA
for (int i = 0; i < sig.CertificateChain.Count; i++)
{
var cert = sig.CertificateChain[i];
string role = i == 0 ? "Signer"
: i == sig.CertificateChain.Count - 1 ? "Root CA"
: $"Intermediate CA ({i})";
Console.WriteLine($" [{role}]");
Console.WriteLine($" Subject: {cert.SubjectDN}");
Console.WriteLine($" Issuer: {cert.IssuerDN}");
Console.WriteLine($" Serial: {cert.CertificateSerialNumber}");
Console.WriteLine($" Valid: {cert.NotBefore} to {cert.NotAfter}");
Console.WriteLine($" Expired: {cert.IsExpired}");
Console.WriteLine($" Thumbprint: {cert.Sha256Thumbprint}");
}
}
Imports IronPdf
Imports IronPdf.Signing.Inspection
Dim pdf = PdfDocument.FromFile("enterprise-signed.pdf")
For Each sig In pdf.GetVerifiedSignatures()
Console.WriteLine($"--- Signature: {sig.SignatureName} ---")
Console.WriteLine($"Chain length: {sig.CertificateChain.Count}")
' Walk from signer (index 0) through intermediates to root CA
For i As Integer = 0 To sig.CertificateChain.Count - 1
Dim cert = sig.CertificateChain(i)
Dim role As String = If(i = 0, "Signer", If(i = sig.CertificateChain.Count - 1, "Root CA", $"Intermediate CA ({i})"))
Console.WriteLine($" [{role}]")
Console.WriteLine($" Subject: {cert.SubjectDN}")
Console.WriteLine($" Issuer: {cert.IssuerDN}")
Console.WriteLine($" Serial: {cert.CertificateSerialNumber}")
Console.WriteLine($" Valid: {cert.NotBefore} to {cert.NotAfter}")
Console.WriteLine($" Expired: {cert.IsExpired}")
Console.WriteLine($" Thumbprint: {cert.Sha256Thumbprint}")
Next
Next
SignerCertificateInfo は、SignerCertificate と同じプロパティ(識別フィールド、有効性、サムプリント、GetSubjectField()、および GetIssuerField()。 (中間CAの有効期限をすべて検証し、信頼されたルートストアと照合してルートのサムプリントを確認し、コンプライアンス監査のために完全なチェーンをログに記録することができます。)}]
次のステップ
SignerCertificate および CertificateChain を使用すれば、IronPDF API のインターフェースから離れることなく、X.509 証明書の完全な検証を行うことができます。 ここから、これらのプロパティが組み込まれるIronPDFの機能について、さらに詳しく見ていくのが自然な流れです。
ワークフローの署名に関する部分については、デジタル署名のハウツーガイドで、証明書の作成、メタデータ、および増分署名について解説しています。 高セキュリティ環境におけるHSMベースの署名については、HSM署名ガイドでPKCS#11の統合について解説しています。 すぐに使えるスニペットが必要ですか? デジタル署名のコード例がそれらを提供しています。
ご自身の署名済みPDFで試してみませんか? 30日間トライアルを開始するか、ライセンスオプションをご覧ください。

