# C#에서 Verified PDF 서명의 서명자 인증서를 읽는 방법 (X.509, eIDAS, 체인)
감사 파이프라인에 계약서가 도착했습니다. 이 계약서는 디지털 서명이 되어 있으며 서명은 유효합니다. 이제 규정 준수 팀은 누가 서명했는지, 그날 아침 해당 인증서가 유효했는지, 발급 CA가 신뢰 목록과 일치하는지 확인해야 합니다. 원시 서명 바이트를 추출하고, DER을 파싱하며, 인증서 체인을 수동으로 추적할 수도 있습니다. 또는 객체 `VerifiedSignature`에 대해 `SignerCertificate`을 요청하여 속성으로서 답변을 읽을 수 있습니다.
그것이 [`VerifiedSignature`](https://ironpdf.com/object-reference/api/IronPdf.Signing.Inspection.VerifiedSignature.html)에서 `SignerCertificate` 및 `CertificateChain` 속성이 구축된 이유입니다. [`PdfDocument.GetVerifiedSignatures()`](https://ironpdf.com/how-to/signing/)에서 반환되며, 서명자의 전체 X.509 신원, 발행 CA, 유효 기간, SHA-256 엄지 인쇄, 원시 DER 바이트 및 루트까지의 모든 중간 인증서를 노출합니다. 이것이 바로 eIDAS 규정 준수, 인증서 고정, 감사 추적 및 신뢰 체인 검증을 위해 필요한 API 인터페이스입니다.
이 가이드에서는 세 가지 유형의 인증서 검사를 단계별로 설명합니다:
- **표준 X.509 세부사항:** 신원 속성, 전체 식별 명칭, 유효 기간 창 및 `X509Certificate2` 상호 운용성을 위한 원시 DER 바이트.
- **eIDAS 및 규제 분야 항목:** 서명자의 국가 ID를 `SubjectSerialNumber`에서 가져와 numeric OID(예: eIDAS organizationIdentifier를 위한 `2.5.4.97`)를 읽습니다.
- **트러스트 체인 검증:** SHA-256 썸프린트 고정 및 서명자에서 루트 CA까지 전체 체인을 추적하는 과정.
[30일 무료 체험을 시작하여](https://ironpdf.com/#trial-license) 검증 파이프라인에서 인증서 검사를 테스트해 보세요.
!!!--LIBRARY_NUGET_INSTALL_BLOCK--!!!
*as-heading:2(빠른 시작: 서명된 PDF에서 서명자 인증서 읽기)*
로드된 PDF에서 `GetVerifiedSignatures`을 호출하고 결과에서 서명자 인증서 속성을 직접 읽습니다.
```cs
:title=Read certificate details in three lines
var sig = PdfDocument.FromFile("signed.pdf").GetVerifiedSignatures().First();
var cert = sig.SignerCertificate;
Console.WriteLine($"{cert?.CommonName} ({cert?.Organization}) valid until {cert?.NotAfter}");
```
<div class="hsg-featured-snippet">
<h3>최소 워크플로우 (3단계)</h3>
<ol>
<li><a class="js-modal-open" data-modal-id="trial-license-after-download" href="https://www.nuget.org/packages/IronPdf/">NuGet에서 IronPDF를 다운로드하세요.</a></li>
<li>서명된 PDF를 불러온 후 <code>GetVerifiedSignatures()를</code> 호출하여 검증된 서명 객체 목록을 가져옵니다.</li>
<li>신원 및 유효성을 확인하려면 <code>sig.SignerCertificate를</code> 참조하거나, 전체 신뢰 체인을 확인하려면 <code>sig.CertificateChain을</code> 탐색하십시오.</li>
</ol>
</div>
<br class="clear" />
## 서명자의 주민등록번호 또는 개인 식별번호는 어떻게 추출하나요?
`SubjectSerialNumber` 속성은 인증서의 주제 DN에서 SERIALNUMBER OID의 값을 반환합니다. 규제 대상 산업(eIDAS 인증서, 은행, 정부 발급 디지털 ID)에서 이 필드에는 서명자의 주민등록번호, 납세자번호 또는 개인 식별 번호가 입력됩니다. 이는 인증서 자체의 일련번호가 아닙니다; 그것이 `CertificateSerialNumber`입니다.
```csharp
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}");
}
```
[[t:(이 두 가지의 차이를 간단히 상기시키면: `SubjectSerialNumber`는 문서를 *누가* 서명했는지(사람 또는 조직 ID, 주제 DN에 포함된 국가 ID 또는 세금 번호와 같은 것)를 알려줍니다. `CertificateSerialNumber`는 *어떤 인증서*가 사용되었는지를 알려줍니다; (이는 발급 인증 기관이 해지 목록 및 감사 로그를 위해 할당하는 고유한 일련 번호입니다.)]]
## 편의성 식별 속성에 어떻게 접근하나요?
`SignerCertificateInfo`는 가장 일반적으로 필요한 주제 DN 필드를 직접 속성으로 노출하여 사용자가 전체 DN 문자열을 스스로 구문 분석할 필요가 없도록 합니다.
#### 서명자의 이름 및 소속 읽기
`CommonName`, `Organization`, `Country`, 및 `Email` 속성은 대부분의 신원 워크플로우에서 가장 먼저 찾는 것을 다룹니다.
```csharp
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}");
}
```
`Email` 속성은 먼저 `emailAddress` OID를 위한 주제 DN을 확인합니다. 존재하지 않으면, 주제 대체 이름(SAN) `rfc822Name` 확장으로 대체합니다. `Country` 속성은 ISO 3166-1 alpha-2 코드 (예: "DE", "US", "FR") 두 글자를 반환합니다. 해당 필드가 인증서에 존재하지 않으면, 모든 편리 속성은 `null`을 반환합니다.
#### 모든 내용이 필요할 때 전체 DN 읽기
감사 로그, 다운스트림 구문 분석 또는 규정 준수 보고서를 위해 `SubjectDN` 및 `IssuerDN`은 완전한 식별 명칭 문자열을 반환합니다.
```csharp
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}");
}
```
## 임의의 주제 및 발행자 필드는 어떻게 추출하나요?
`GetSubjectField(string)` 및 `GetIssuerField(string)` 메소드는 짧은 이름이나 숫자 OID를 허용합니다. 이들은 대소문자를 구분하지 않으며 필드가 존재하지 않으면 `null`을 반환합니다.
지원되는 짧은 이름: `CN`, `O`, `OU`, `C`, `L`, `ST`, `E`, `SERIALNUMBER`, `SURNAME`, `T`, `GIVENNAME`, `UID`, `ORGANIZATIONIDENTIFIER`.
#### 모든 주제 분야 읽기 (eIDAS OID 포함)
주제 DN에서 필드를 가져오기 위해 `"OU"`와 같은 짧은 이름이나 `"2.5.4.97"`와 같은 숫자 OID(eIDAS organizationIdentifier)를 전달합니다.
```csharp
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"}");
}
```
숫자형 OID 조회는 표준 약칭으로 표기되지 않는 조직 식별자, Professional 자격 또는 관할권별 필드가 포함된 eIDAS 및 규제 산업용 인증서에 필수적입니다.
#### 발행자 필드 읽기
`GetIssuerField`은 발행 CA의 식별 명칭에 대해 같은 방식으로 작동합니다. 이는 신뢰성 검증, CA 보고, 발급 기관별 서명 그룹화에 유용합니다.
```csharp
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})");
}
```
## 인증서 유효성은 어떻게 확인하나요?
`SignerCertificateInfo`은 두 가지 유효성 검사를 제공합니다:
- `IsExpired`는 `DateTime.UtcNow > NotAfter`일 경우 `true`을 반환합니다.
- `IsValidAt(DateTime)`는 주어진 타임스탬프가 `NotAfter` 윈도우 내에 있을 경우 `true`을 반환합니다. 일반적인 용도는 서명 시점에 인증서가 유효했는지 확인하는 것입니다.
```csharp
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
bool validAtSigning = cert.IsValidAt(sig.SigningDate);
Console.WriteLine($"Valid at signing time ({sig.SigningDate}): {validAtSigning}");
}
```
[[t:(`IsExpired`는 인증서에서 유효성 날짜를 추출할 수 없을 때 `false`(not `true`)을 반환합니다. 이 헬퍼는 의도적으로 보수적인 방식을 취하며, 메타데이터가 누락되었다는 이유만으로 유효 기간이 만료되었다고 가정하지 않습니다. 제로 트러스트 워크플로의 경우, 유효 기간이 누락된 경우를 명시적으로 실패 사례로 처리하십시오.)]]
[감사 추적](https://ironpdf.com/how-to/revision-history/)을 위해 현재 유효성을 위한 `IsExpired` 검사와 서명 시점의 유효성을 위한 `IsValidAt(signingDate)` 검사를 모두 기록하세요. 현재 만료된 인증서라도 문서가 서명되었을 당시에는 유효했을 수 있습니다; 두 데이터 포인트 모두 규정 준수에 중요합니다.
## 인증서 고정(Certificate Pinning)에 SHA-256 썸프린트를 어떻게 사용하나요?
`Sha256Thumbprint` 속성은 64자 대문자 16진수 문자열인 DER 인코딩된 인증서의 SHA-256 해시를 반환합니다. 이는 승인된 서명자 인증서 목록과 대조하여 확인하는 값입니다.
```csharp
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}");
}
```
## 원시 인증서 데이터로부터 X509Certificate2를 어떻게 생성합니까?
`RawData` 속성은 DER 인코딩된 인증서를 `byte[]`로 반환합니다. 각 호출은 방어적 복사본을 반환하므로, 내부 데이터가 참조를 통해 노출되는 일은 절대 없습니다. 이를 사용하여 .NET의 네이티브 암호화 API(체인 구축, 정책 검증, CRL 검사)와의 상호 운용성을 위한 `System.Security.Cryptography.X509Certificates.X509Certificate2`을 구성할 수 있습니다.
```csharp
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");
}
```
[[i:(모든 `RawData`에 대한 액세스는 신선한 방어 복사본을 반환합니다. 내부 바이트 배열은 참조로 노출되지 않으므로, 반환된 바이트를 변경하더라도 이후 호출에는 영향을 미치지 않습니다.)]]
이 상호 운용 경로는 IronPDF의 서명 검증을 다음과 같은 기존 .NET 인증서 검증 파이프라인에 플러그할 수 있게 해줍니다. [`X509Chain.Build()`](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509chain.build), CRL/OCSP를 통한 폐기 검사, 또는 커스텀 `X509CertificateValidator` 구현.
## 인증서 체인을 어떻게 추적합니까?
`VerifiedSignature`에 있는 `CertificateChain` 속성은 서명자 → 중간 CA(s) → 루트 CA의 순서로 `IReadOnlyList<SignerCertificateInfo>`을 반환합니다. 인덱스 0은 항상 서명자 인증서(같은 객체는 `SignerCertificate`)입니다. 이 목록은 절대 null이 아닙니다; 체인(chain)을 추출할 수 없는 경우, 해당 체인에는 서명자 인증서만 포함됩니다.
```csharp
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}");
}
}
```
[[i:(체인의 모든 `SignerCertificateInfo`은 동일한 속성을 노출합니다: 신원 필드, 유효성, 엄지 인쇄, `RawData`, `GetSubjectField()`, 및 `GetIssuerField()`. (중간 CA의 만료일을 모두 확인하고, 신뢰할 수 있는 루트 저장소에 있는 루트 인증서의 썸프린트를 대조하며, 규정 준수 감사를 위해 전체 체인을 기록할 수 있습니다.)]]
## 다음 단계
`SignerCertificate` 및 `CertificateChain`은 IronPDF API 표면을 벗어나지 않고 완전한 X.509 검사를 제공합니다. 여기서부터는 이러한 속성이 연결되는 IronPDF의 부분으로 더 깊이 들어가는 자연스러운 다음 단계입니다.
워크플로우의 서명 측면에서는 [디지털 서명 방법](https://ironpdf.com/how-to/signing/)에서 인증서 생성, 메타데이터 및 증분 서명을 다룹니다. 고급 보안 환경에서 HSM 기반 서명을 위해서는 [HSM 서명 안내서](https://ironpdf.com/how-to/signing-pdf-with-hsm/)에서 PKCS#11 통합을 다룹니다. 실행할 준비가 된 스니펫이 필요하십니까? [디지털 서명 코드 예제](https://ironpdf.com/examples/digitally-sign-a-pdf/)가 제공합니다.
자신의 서명된 PDF에서 시도할 준비가 되셨습니까? [30일 무료 체험을 시작](https://ironpdf.com/#trial-license)하거나 [라이선스 옵션을 조회](https://ironpdf.com/licensing/)하세요.
감사 파이프라인에 계약서가 도착했습니다. 이 계약서는 디지털 서명이 되어 있으며 서명은 유효합니다. 이제 규정 준수 팀은 누가 서명했는지, 그날 아침 해당 인증서가 유효했는지, 발급 CA가 신뢰 목록과 일치하는지 확인해야 합니다. 원시 서명 바이트를 추출하고, DER을 파싱하며, 인증서 체인을 수동으로 추적할 수도 있습니다. 또는 객체 VerifiedSignature에 대해 SignerCertificate을 요청하여 속성으로서 답변을 읽을 수 있습니다.
그것이 VerifiedSignature에서 SignerCertificate 및 CertificateChain 속성이 구축된 이유입니다. PdfDocument.GetVerifiedSignatures()에서 반환되며, 서명자의 전체 X.509 신원, 발행 CA, 유효 기간, SHA-256 엄지 인쇄, 원시 DER 바이트 및 루트까지의 모든 중간 인증서를 노출합니다. 이것이 바로 eIDAS 규정 준수, 인증서 고정, 감사 추적 및 신뢰 체인 검증을 위해 필요한 API 인터페이스입니다.
이 가이드에서는 세 가지 유형의 인증서 검사를 단계별로 설명합니다:
표준 X.509 세부사항: 신원 속성, 전체 식별 명칭, 유효 기간 창 및 X509Certificate2 상호 운용성을 위한 원시 DER 바이트.
eIDAS 및 규제 분야 항목: 서명자의 국가 ID를 SubjectSerialNumber에서 가져와 numeric OID(예: eIDAS organizationIdentifier를 위한 2.5.4.97)를 읽습니다.
트러스트 체인 검증: SHA-256 썸프린트 고정 및 서명자에서 루트 CA까지 전체 체인을 추적하는 과정.
Install IronPDF by running the command above in the NuGet Package Manager Console, or search for the package in the NuGet Package Manager.
빠른 시작: 서명된 PDF에서 서명자 인증서 읽기
로드된 PDF에서 GetVerifiedSignatures을 호출하고 결과에서 서명자 인증서 속성을 직접 읽습니다.
1Install IronPDF with NuGet Package Manager
PM > Install-Package IronPdf
Install-Package IronPdf
2다음 코드 조각을 복사하여 실행하세요.
var sig = PdfDocument.FromFile("signed.pdf").GetVerifiedSignatures().First();var cert = sig.SignerCertificate;Console.WriteLine($"{cert?.CommonName} ({cert?.Organization}) valid until {cert?.NotAfter}");
var sig = PdfDocument.FromFile("signed.pdf").GetVerifiedSignatures().First();
var cert = sig.SignerCertificate;
Console.WriteLine($"{cert?.CommonName} ({cert?.Organization}) valid until {cert?.NotAfter}");
서명된 PDF를 불러온 후 GetVerifiedSignatures()를 호출하여 검증된 서명 객체 목록을 가져옵니다.
신원 및 유효성을 확인하려면 sig.SignerCertificate를 참조하거나, 전체 신뢰 체인을 확인하려면 sig.CertificateChain을 탐색하십시오.
서명자의 주민등록번호 또는 개인 식별번호는 어떻게 추출하나요?
SubjectSerialNumber 속성은 인증서의 주제 DN에서 SERIALNUMBER OID의 값을 반환합니다. 규제 대상 산업(eIDAS 인증서, 은행, 정부 발급 디지털 ID)에서 이 필드에는 서명자의 주민등록번호, 납세자번호 또는 개인 식별 번호가 입력됩니다. 이는 인증서 자체의 일련번호가 아닙니다; 그것이 CertificateSerialNumber입니다.
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 CAConsole.WriteLine($"Certificate Serial (CA-issued): {cert.CertificateSerialNumber}");}
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}");
}
ImportsIronPdfImportsIronPdf.Signing.InspectionDim 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 CAConsole.WriteLine($"Certificate Serial (CA-issued): {cert.CertificateSerialNumber}")Next
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, 주제 DN에 포함된 국가 ID 또는 세금 번호와 같은 것)를 알려줍니다. CertificateSerialNumber는 어떤 인증서가 사용되었는지를 알려줍니다; (이는 발급 인증 기관이 해지 목록 및 감사 로그를 위해 할당하는 고유한 일련 번호입니다.
편의성 식별 속성에 어떻게 접근하나요?
SignerCertificateInfo는 가장 일반적으로 필요한 주제 DN 필드를 직접 속성으로 노출하여 사용자가 전체 DN 문자열을 스스로 구문 분석할 필요가 없도록 합니다.
서명자의 이름 및 소속 읽기
CommonName, Organization, Country, 및 Email 속성은 대부분의 신원 워크플로우에서 가장 먼저 찾는 것을 다룹니다.
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 propertiesConsole.WriteLine($"CommonName (CN): {cert.CommonName}");Console.WriteLine($"Organization (O): {cert.Organization}");Console.WriteLine($"Country (C): {cert.Country}");Console.WriteLine($"Email: {cert.Email}");}
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}");
}
ImportsIronPdfImportsIronPdf.Signing.InspectionDim 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 propertiesConsole.WriteLine($"CommonName (CN): {cert.CommonName}")Console.WriteLine($"Organization (O): {cert.Organization}")Console.WriteLine($"Country (C): {cert.Country}")Console.WriteLine($"Email: {cert.Email}")Next
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 속성은 먼저 emailAddress OID를 위한 주제 DN을 확인합니다. 존재하지 않으면, 주제 대체 이름(SAN) rfc822Name 확장으로 대체합니다. Country 속성은 ISO 3166-1 alpha-2 코드 (예: "DE", "US", "FR") 두 글자를 반환합니다. 해당 필드가 인증서에 존재하지 않으면, 모든 편리 속성은 null을 반환합니다.
모든 내용이 필요할 때 전체 DN 읽기
감사 로그, 다운스트림 구문 분석 또는 규정 준수 보고서를 위해 SubjectDN 및 IssuerDN은 완전한 식별 명칭 문자열을 반환합니다.
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 parsingConsole.WriteLine($"Full Subject DN: {cert.SubjectDN}");Console.WriteLine($"Full Issuer DN: {cert.IssuerDN}");}
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}");
}
ImportsIronPdfImportsIronPdf.Signing.InspectionDim 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 parsingConsole.WriteLine($"Full Subject DN: {cert.SubjectDN}")Console.WriteLine($"Full Issuer DN: {cert.IssuerDN}")Next
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을 반환합니다.
지원되는 짧은 이름: CN, O, OU, C, L, ST, E, SERIALNUMBER, SURNAME, T, GIVENNAME, UID, ORGANIZATIONIDENTIFIER.
모든 주제 분야 읽기 (eIDAS OID 포함)
주제 DN에서 필드를 가져오기 위해 "OU"와 같은 짧은 이름이나 "2.5.4.97"와 같은 숫자 OID(eIDAS organizationIdentifier)를 전달합니다.
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"}");}
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"}");
}
ImportsIronPdfImportsIronPdf.Signing.InspectionDim 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 AsString = cert.GetSubjectField("OU") Dim surname AsString = cert.GetSubjectField("SURNAME") Dim givenName AsString = cert.GetSubjectField("GIVENNAME") Dim title AsString = cert.GetSubjectField("T") ' Numeric OID lookup (eIDAS organizationIdentifier) Dim orgId AsString = 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
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 보고, 발급 기관별 서명 그룹화에 유용합니다.
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})");}
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})");
}
ImportsIronPdfImportsIronPdf.Signing.InspectionDim 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 AsString = cert.GetIssuerField("CN") Dim issuerO AsString = cert.GetIssuerField("O") Dim issuerCountry AsString = cert.GetIssuerField("C")Console.WriteLine($"Issued by: {issuerCN} ({issuerO}, {issuerCountry})")Next
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
이 종류의 라이브러리 중 가장 좋아하는 것은 IronPDF입니다. PDF 파일을 빠르고 효율적으로 조작할 수 있습니다. 또한 PDF/A 형식으로 내보내기 및 PDF 문서의 디지털 서명과 같은 많은 유용한 기능을 가지고 있습니다.
IsExpired는 DateTime.UtcNow > NotAfter일 경우 true을 반환합니다.
IsValidAt(DateTime)는 주어진 타임스탬프가 NotAfter 윈도우 내에 있을 경우 true을 반환합니다. 일반적인 용도는 서명 시점에 인증서가 유효했는지 확인하는 것입니다.
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 bool validAtSigning = cert.IsValidAt(sig.SigningDate);Console.WriteLine($"Valid at signing time ({sig.SigningDate}): {validAtSigning}");}
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
bool validAtSigning = cert.IsValidAt(sig.SigningDate);
Console.WriteLine($"Valid at signing time ({sig.SigningDate}): {validAtSigning}");
}
ImportsIronPdfImportsIronPdf.Signing.InspectionDim pdf = PdfDocument.FromFile("archived-contract.pdf")For Each sig In pdf.GetVerifiedSignatures() Dim cert = sig.SignerCertificate If cert Is Nothing Then Continue ForConsole.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 Dim validAtSigning AsBoolean = cert.IsValidAt(sig.SigningDate)Console.WriteLine($"Valid at signing time ({sig.SigningDate}): {validAtSigning}")Next
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
Dim validAtSigning As Boolean = cert.IsValidAt(sig.SigningDate)
Console.WriteLine($"Valid at signing time ({sig.SigningDate}): {validAtSigning}")
Next
팁: IsExpired는 인증서에서 유효성 날짜를 추출할 수 없을 때 false(not true)을 반환합니다. 이 헬퍼는 의도적으로 보수적인 방식을 취하며, 메타데이터가 누락되었다는 이유만으로 유효 기간이 만료되었다고 가정하지 않습니다. 제로 트러스트 워크플로의 경우, 유효 기간이 누락된 경우를 명시적으로 실패 사례로 처리하십시오.
감사 추적을 위해 현재 유효성을 위한 IsExpired 검사와 서명 시점의 유효성을 위한 IsValidAt(signingDate) 검사를 모두 기록하세요. 현재 만료된 인증서라도 문서가 서명되었을 당시에는 유효했을 수 있습니다; 두 데이터 포인트 모두 규정 준수에 중요합니다.
인증서 고정(Certificate Pinning)에 SHA-256 썸프린트를 어떻게 사용하나요?
Sha256Thumbprint 속성은 64자 대문자 16진수 문자열인 DER 인코딩된 인증서의 SHA-256 해시를 반환합니다. 이는 승인된 서명자 인증서 목록과 대조하여 확인하는 값입니다.
using IronPdf;using IronPdf.Signing.Inspection;using System.Collections.Generic;// Known-good signer thumbprints from a compliance databasevar 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}");}
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}");
}
ImportsIronPdfImportsIronPdf.Signing.InspectionImportsSystem.Collections.Generic' Known-good signer thumbprints from a compliance databaseDim pinnedThumbprints As New HashSet(OfString) 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 AsBoolean = pinnedThumbprints.Contains(cert.Sha256Thumbprint)Console.WriteLine($"Signer: {cert.CommonName}, Thumbprint: {cert.Sha256Thumbprint}")Console.WriteLine($"Pinned: {trusted}")Next
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을 구성할 수 있습니다.
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");}
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");
}
ImportsIronPdfImportsIronPdf.Signing.InspectionImportsSystem.Security.Cryptography.X509CertificatesDim 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 AsByte() = 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
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의 서명 검증을 다음과 같은 기존 .NET 인증서 검증 파이프라인에 플러그할 수 있게 해줍니다. X509Chain.Build(), CRL/OCSP를 통한 폐기 검사, 또는 커스텀 X509CertificateValidator 구현.
인증서 체인을 어떻게 추적합니까?
VerifiedSignature에 있는 CertificateChain 속성은 서명자 → 중간 CA(s) → 루트 CA의 순서로 IReadOnlyList<SignerCertificateInfo>을 반환합니다. 인덱스 0은 항상 서명자 인증서(같은 객체는 SignerCertificate)입니다. 이 목록은 절대 null이 아닙니다; 체인(chain)을 추출할 수 없는 경우, 해당 체인에는 서명자 인증서만 포함됩니다.
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}"); }}
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}");
}
}
ImportsIronPdfImportsIronPdf.Signing.InspectionDim 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 AsInteger = 0 To sig.CertificateChain.Count - 1 Dim cert = sig.CertificateChain(i) Dim role AsString = 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}") NextNext
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은 동일한 속성을 노출합니다: 신원 필드, 유효성, 엄지 인쇄, RawData, GetSubjectField(), 및 GetIssuerField(). (중간 CA의 만료일을 모두 확인하고, 신뢰할 수 있는 루트 저장소에 있는 루트 인증서의 썸프린트를 대조하며, 규정 준수 감사를 위해 전체 체인을 기록할 수 있습니다.
다음 단계
SignerCertificate 및 CertificateChain은 IronPDF API 표면을 벗어나지 않고 완전한 X.509 검사를 제공합니다. 여기서부터는 이러한 속성이 연결되는 IronPDF의 부분으로 더 깊이 들어가는 자연스러운 다음 단계입니다.
워크플로우의 서명 측면에서는 디지털 서명 방법에서 인증서 생성, 메타데이터 및 증분 서명을 다룹니다. 고급 보안 환경에서 HSM 기반 서명을 위해서는 HSM 서명 안내서에서 PKCS#11 통합을 다룹니다. 실행할 준비가 된 스니펫이 필요하십니까? 디지털 서명 코드 예제가 제공합니다.
커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.