我找不到为什么Foxit PDF阅读器显示我的签名文件无效。首先,我将空白签名容器插入pdf
public class BlankSignatureContainer2: IExternalSignatureContainer
{
private readonly PdfName filter;
private readonly PdfName subFilter;
private byte[] docBytesHash;
private byte[] docDigest;
private const String HASH_ALGORITHM = DigestAlgorithms.SHA256;
private X509Certificate[] chain;
public BlankSignatureContainer2(PdfName filter, PdfName subFilter, X509Certificate[] chain)
{
this.filter = filter;
this.subFilter = subFilter;
this.chain = chain;
}
public virtual byte[] GetDocBytesHash()
{
return docBytesHash;
}
public virtual byte[] GetDocBytesDigest()
{
return docDigest;
}
public virtual byte[] Sign(Stream docBytes)
{
PdfPKCS7 sgn = new PdfPKCS7(null, chain, HASH_ALGORITHM, false);
docDigest = DigestAlgorithms.Digest(docBytes, DigestAlgorithms.GetMessageDigest(HASH_ALGORITHM));
docBytesHash = sgn.GetAuthenticatedAttributeBytes(docDigest, PdfSigner.CryptoStandard.CADES, null, null);
using (SHA256 sha256 = SHA256.Create())
{
docBytesHash = sha256.ComputeHash(docBytesHash);
}
return new byte[0];
}
public virtual void ModifySigningDictionary(PdfDictionary signDic)
{
signDic.Put(PdfName.Filter, filter);
signDic.Put(PdfName.SubFilter, subFilter);
}
}
docbytesshash
我发送到外部Web服务以使用合格的签名进行签名。
using (MemoryStream stream = new MemoryStream())
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(value.pdfFile))) //pdf file to sign
using (PdfReader pdfReader = new PdfReader(ms))
{
//Get signers and CA certificates
X509Certificate[] chain = await _signPdf.GetMidChain(certificate.Cert);
// creating empty signature container, getting file digest and hash
var blankSignature = new BlankSignatureContainer2(PdfName.Adobe_PPKLite, PdfName.ETSI_CAdES_DETACHED, chain);
var stamper = new PdfSigner(pdfReader, stream, new StampingProperties().UseAppendMode());
var appearance = stamper.GetSignatureAppearance();
//Method to add signature appearance
var sigAppearance = new SigAppearance("stamp1.svg", chain[0].SubjectDN.GetValueList(X509Name.CN).Cast<string>().FirstOrDefault() ?? "", DateTime.Now, "Sign", stamper.GetDocument());
appearance.SetPageRect(new iText.Kernel.Geom.Rectangle(sigAppearance.GetPosition()));
stamper.SetFieldName(new GetSignatureToSign(stamper.GetDocument()).GetSignatureName());
new PdfCanvas(appearance.GetLayer2(), stamper.GetDocument()).AddXObjectFittedIntoRectangle(sigAppearance.GetXObject(), sigAppearance.GetRectangle());
stamper.SignExternalContainer(blankSignature, 8192*2+2);
//Call external webservice to sign blankSignature.GetDocBytesHash()
var msrp = await _clientMID.SignAsync(new MidSignReqModel() {
NationalIdentityNumber = value.personalCode,
PhoneNumber = value.phone,
Language = value.language,
DisplayText = value.ShortMessage(),
DisplayTextFormat = "UCS-2",
Hash = Convert.ToBase64String(blankSignature.GetDocBytesHash()),
HashType = "SHA256"
});
接下来,我使用webservice的结果对pdf进行了签名。这是外部签名容器:
public class ExternalSignatureContainer2: IExternalSignatureContainer
{
private X509Certificate[] chain;
private byte[] signature;
private string hashAlgorithm;
public ExternalSignatureContainer2(X509Certificate[] chain, byte[] signature, string hashAlgorithm)
{
this.chain = chain;
this.signature = signature;
this.hashAlgorithm = hashAlgorithm;
}
public void ModifySigningDictionary(PdfDictionary signDic)
{
//throw new NotImplementedException();
}
public byte[] Sign(Stream data)
{
//create TimeStamp Client
ITSAClient tsa = new TSAClientBouncyCastle(@"http://demo.sk.ee/tsa/");
string hashAlgorithm = "SHA256";
PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, false);
byte[] digest = DigestAlgorithms.Digest(data, DigestAlgorithms.GetMessageDigest(hashAlgorithm));
sgn.SetExternalDigest(signature, null, "ECDSA");
return sgn.GetEncodedPKCS7(digest, PdfSigner.CryptoStandard.CADES, tsa, null, null);
}
}
这是签名代码:
public async Task<byte[]> Sign2(string file, byte[] signature, X509Certificate[] chain, string hashAlgorithm)
{
using (var tempStream = new MemoryStream(File.ReadAllBytes(Path.Combine(Directory.GetCurrentDirectory(), @"drafts", file))))
using (var destination = new MemoryStream())
{
var tempReader = new PdfReader(tempStream);
var gsContainer = new ExternalSignatureContainer2(chain, signature, hashAlgorithm);
var signer = new PdfSigner(tempReader, destination, new StampingProperties().UseAppendMode());
signer.SetCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING);
PdfSigner.SignDeferred(signer.GetDocument(), new GetSignatureToSign(signer.GetDocument()).GetSignatureName(), destination, gsContainer);
using (MemoryStream LTV = new MemoryStream())
using (var newSource = new MemoryStream(destination.ToArray()))
{
PdfDocument pdfDoc = new PdfDocument(new PdfReader(newSource), new PdfWriter(LTV), new StampingProperties().UseAppendMode());
LtvVerification v = new LtvVerification(pdfDoc);
SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);
IList<string> names = signatureUtil.GetSignatureNames();
String sigName = names[(names.Count - 1)];
PdfPKCS7 pkcs7 = signatureUtil.ReadSignatureData(sigName);
if (pkcs7.IsTsp())
{
v.AddVerification(sigName, new OcspClientBouncyCastle(null), new CrlClientOnline(), LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.YES);
}
else
{
foreach (String name in names)
{
v.AddVerification(name, new OcspClientBouncyCastle(null), new CrlClientOnline(), LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.YES);
}
}
v.Merge();
pdfDoc.Close();
return await Task.FromResult( LTV.ToArray());
}
}
}
并且有结果:
找不到我做错了什么。
你的问题与这个问题有关,比如在这种情况下,ECDSA签名格式存在问题。因此,要了解更多细节,请阅读这里的答案。
正如在回答上述问题时所解释的,ECDSA签名值有两种主要的编码格式,
整数
值和根据我的经验,Adobe Reader支持这两种格式,而Foxit显然只支持前一种。
嵌入的签名值使用后一种格式。因此,Foxit不接受它。
要使您的签名与Foxit(以及iText自己的验证)兼容,您应该切换到前一种格式。检查您的web服务是否可以以TLV格式返回签名。或者,您必须在代码中从普通格式转换为TLV格式。
实际上,在这里可以看到,对于数字签名,Foxit声称与底层操作系统紧密集成。正如文中所解释的,虽然这确实可能具有使操作系统识别的任何证书能够被Foxit使用的优点,但它的缺点是,由不依赖操作系统的签名软件生成的签名可能存在问题,甚至由Foxit在其他操作系统上生成或成功验证的签名也可能存在问题。。。
旁白:就像上述问题一样,签名容器中还有另一个问题:在签名算法字段中,它有ECDSA公钥的OID,而不是实际签名算法的OID。虽然Adobe Reader和Foxit都接受这一点,但其他不太松散的验证器将拒绝这一点。
使用此错误的OID是当前iText版本中的一个已知问题。目前,您可以使用BouncyCastle或. Net安全API类而不是iText的PdfPKCS7
来创建CMS签名容器。
PDF下载示例:https://drive.google.com/file/d/12wv1Pb7gh4vCKOGhX4cZ3aOrLSiOo4If/view?usp=sharing 因此,当PDF在A.Reader(连续版本)中打开时,它表示证书无效,因为对该文档所做的更改导致签名无效。 但我看不出有什么变化。我们自己的应用程序只添加了一个签名(证书),为数千个其他PDF添加了正确的签名。未执行其
当我使用带电子令牌的IText对PDF进行签名时,签名的PDF在Acrobat Adobe Reader中显示“至少一个签名无效”。我正在使用有效的电子代币。以下是签署Pdf的代码。
我有一个私人钥匙在档案里。“privatekey.pem”并且不知道如何创建谁能帮助我吗?我正在尝试使用IText7签名pdf。
我对iTextSharp有意见。我有一个带有表单字段的文档,并且我已经为签名生成了字段。当第一个人在文件上签字时,它就会正常工作。Adobe Reader显示有效签名。当我让第二个人在文档上签名时,Adobe Reader显示签名1现在是“未知签名”,签名无效。Adobe reader显示: 此签名中包含的格式或信息有错误(支持信息:SigDict/Contents非法数据)
作为我对客户机/服务器pdf签名研究的一部分,我测试了itext pdf延迟签名示例。不幸的是,我得到的合并空签名pdf和哈希值的pdf ie输出显示无效签名。 下面是我的代码片段 我正在使用pkcss11 usb令牌进行签名
我正在将代码从iText5迁移到iText7,目前我正在努力将一个签名添加到已经包含另一个签名的PDF中。这些签名是用我们的国民身份证(公民卡)进行的。 在iText5中,我使用了PdfStamper,但它在Itext7中丢失了... 这是我目前所掌握的: POReID(https://github.com/POReID/POReID)是用于与智能卡交互的库。 当第一次签署文件时,它工作得很好。再