在 itextsharp 中 Pades LTV 验证抛出 The Uri Prefix is not Recognized
Pades LTV verification in itextsharp throws The Uri Prefix is not Recognized
我已成功签署一份支持 LTV 的 pdf。我可以通过 Adobe Acrobat Reader 以及外部验证器检查 pdf 和 LTV 签名是否有效。
我正在尝试使用 iTextSharp 5.5.10 进行相同的验证。
我正在关注 iText 示例代码 C5_06
但是当我调用 ltvVerifier.Verify
时,我收到 System.NotSupportedException, The Uri Prefix is not Recognized
。我正在加载用于签署 pdf en cert 参数的证书。
验证码:
public static bool Validate(byte[] pdfIn, X509Certificate2 cert)
{
using (var reader = new PdfReader(pdfIn))
{
var fields = reader.AcroFields;
var signames = fields.GetSignatureNames();
if (!signames.Any(n => fields.SignatureCoversWholeDocument(n)))
throw new Exception("None signature covers all document");
var verifications = signames.Select(n => fields.VerifySignature(n));
var invalidSignature = verifications.Where(v => !v.Verify());
var invalidTimeStamp = verifications.Where(v => !v.VerifyTimestampImprint());
if (invalidSignature.Any())
throw new Exception("Invalid signature found");
}
using (var reader = new PdfReader(pdfIn))
{
var ltvVerifier = new LtvVerifier(reader)
{
OnlineCheckingAllowed = false,
CertificateOption = LtvVerification.CertificateOption.WHOLE_CHAIN,
Certificates = GetChain(cert).ToList(),
VerifyRootCertificate = false,
Verifier = new MyVerifier(null)
};
var ltvResult = new List<VerificationOK> { };
ltvVerifier.Verify(ltvResult);
if (!ltvResult.Any())
throw new Exception("Ltv verification failed");
}
return true;
}
从证书链构建 X509 证书列表的辅助函数:
private static X509.X509Certificate[] GetChain(X509Certificate2 myCert)
{
var x509Chain = new X509Chain();
x509Chain.Build(myCert);
var chain = new List<X509.X509Certificate>();
foreach(var cert in x509Chain.ChainElements)
{
chain.Add(
DotNetUtilities.FromX509Certificate(cert.Certificate)
);
}
return chain.ToArray();
}
自定义验证器,刚从示例中复制:
class MyVerifier : CertificateVerifier
{
public MyVerifier(CertificateVerifier verifier) : base(verifier) { }
override public List<VerificationOK> Verify(
X509.X509Certificate signCert, X509.X509Certificate issuerCert, DateTime signDate)
{
Console.WriteLine(signCert.SubjectDN + ": ALL VERIFICATIONS DONE");
return new List<VerificationOK>();
}
}
这是相关的堆栈跟踪:
in System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
in System.Net.WebRequest.Create(String requestUriString)
in iTextSharp.text.pdf.security.CrlVerifier.GetCrl(X509Certificate signCert, X509Certificate issuerCert)
in iTextSharp.text.pdf.security.CrlVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate)
in iTextSharp.text.pdf.security.OcspVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate)
in iTextSharp.text.pdf.security.LtvVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime sigDate)
in iTextSharp.text.pdf.security.LtvVerifier.VerifySignature()
in iTextSharp.text.pdf.security.LtvVerifier.Verify(List`1 result)
谢谢。
问题是签名者证书链中的证书提供了两个用于 CRL 下载的 URI,第一个是 ldap URI,然后是一个 http URI,请参见。 @Egl 对您的问题的评论,但 iText 假定它可以简单地获取第一个给定的 URI 并使用 System.Net.WebRequest
来请求其内容。
遗憾的是 WebRequest
开箱即用仅支持 http:、https:、ftp: 和文件:(参见 this msdn page)。因此,它失败了 iText 尝试通过 ldap 请求 CRL,其中 Exception
iText 没有捕获。
您可以通过
完成这项工作
要么注册 ldap WebRequest
处理程序(参见 this msdn page)。
警告:虽然 msdn 页面表明可以执行类似的操作,但我还没有这样做。此外,OP 无法轻易遵循这条道路。因此,可能存在超出 msdn 文档描述范围的限制。可能只能使用 web-ish 协议 (ftp:, file:, http:, https:)?
或更改 iText 验证器(实际更改 iText 类 或 copying/deriving 自己的 CrlVerifier
和 LtvVerifier
变体)以使用 http -URI.
这可以通过捕获此类异常然后继续下一个 CRL 请求 URI 或(如 OP 所做的那样)通过完全忽略 ldap URI(在 CertificateUtil.GetCRLURL
中过滤)来实现。
我已成功签署一份支持 LTV 的 pdf。我可以通过 Adobe Acrobat Reader 以及外部验证器检查 pdf 和 LTV 签名是否有效。
我正在尝试使用 iTextSharp 5.5.10 进行相同的验证。
我正在关注 iText 示例代码 C5_06
但是当我调用 ltvVerifier.Verify
时,我收到 System.NotSupportedException, The Uri Prefix is not Recognized
。我正在加载用于签署 pdf en cert 参数的证书。
验证码:
public static bool Validate(byte[] pdfIn, X509Certificate2 cert)
{
using (var reader = new PdfReader(pdfIn))
{
var fields = reader.AcroFields;
var signames = fields.GetSignatureNames();
if (!signames.Any(n => fields.SignatureCoversWholeDocument(n)))
throw new Exception("None signature covers all document");
var verifications = signames.Select(n => fields.VerifySignature(n));
var invalidSignature = verifications.Where(v => !v.Verify());
var invalidTimeStamp = verifications.Where(v => !v.VerifyTimestampImprint());
if (invalidSignature.Any())
throw new Exception("Invalid signature found");
}
using (var reader = new PdfReader(pdfIn))
{
var ltvVerifier = new LtvVerifier(reader)
{
OnlineCheckingAllowed = false,
CertificateOption = LtvVerification.CertificateOption.WHOLE_CHAIN,
Certificates = GetChain(cert).ToList(),
VerifyRootCertificate = false,
Verifier = new MyVerifier(null)
};
var ltvResult = new List<VerificationOK> { };
ltvVerifier.Verify(ltvResult);
if (!ltvResult.Any())
throw new Exception("Ltv verification failed");
}
return true;
}
从证书链构建 X509 证书列表的辅助函数:
private static X509.X509Certificate[] GetChain(X509Certificate2 myCert)
{
var x509Chain = new X509Chain();
x509Chain.Build(myCert);
var chain = new List<X509.X509Certificate>();
foreach(var cert in x509Chain.ChainElements)
{
chain.Add(
DotNetUtilities.FromX509Certificate(cert.Certificate)
);
}
return chain.ToArray();
}
自定义验证器,刚从示例中复制:
class MyVerifier : CertificateVerifier
{
public MyVerifier(CertificateVerifier verifier) : base(verifier) { }
override public List<VerificationOK> Verify(
X509.X509Certificate signCert, X509.X509Certificate issuerCert, DateTime signDate)
{
Console.WriteLine(signCert.SubjectDN + ": ALL VERIFICATIONS DONE");
return new List<VerificationOK>();
}
}
这是相关的堆栈跟踪:
in System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
in System.Net.WebRequest.Create(String requestUriString)
in iTextSharp.text.pdf.security.CrlVerifier.GetCrl(X509Certificate signCert, X509Certificate issuerCert)
in iTextSharp.text.pdf.security.CrlVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate)
in iTextSharp.text.pdf.security.OcspVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate)
in iTextSharp.text.pdf.security.LtvVerifier.Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime sigDate)
in iTextSharp.text.pdf.security.LtvVerifier.VerifySignature()
in iTextSharp.text.pdf.security.LtvVerifier.Verify(List`1 result)
谢谢。
问题是签名者证书链中的证书提供了两个用于 CRL 下载的 URI,第一个是 ldap URI,然后是一个 http URI,请参见。 @Egl 对您的问题的评论,但 iText 假定它可以简单地获取第一个给定的 URI 并使用 System.Net.WebRequest
来请求其内容。
遗憾的是 WebRequest
开箱即用仅支持 http:、https:、ftp: 和文件:(参见 this msdn page)。因此,它失败了 iText 尝试通过 ldap 请求 CRL,其中 Exception
iText 没有捕获。
您可以通过
完成这项工作要么注册 ldap
WebRequest
处理程序(参见 this msdn page)。警告:虽然 msdn 页面表明可以执行类似的操作,但我还没有这样做。此外,OP 无法轻易遵循这条道路。因此,可能存在超出 msdn 文档描述范围的限制。可能只能使用 web-ish 协议 (ftp:, file:, http:, https:)?
或更改 iText 验证器(实际更改 iText 类 或 copying/deriving 自己的
CrlVerifier
和LtvVerifier
变体)以使用 http -URI.这可以通过捕获此类异常然后继续下一个 CRL 请求 URI 或(如 OP 所做的那样)通过完全忽略 ldap URI(在
CertificateUtil.GetCRLURL
中过滤)来实现。