/// <summary>Verifies a certificate against a single OCSP response</summary> /// <param name="ocspResp">the OCSP response</param> /// <param name="signCert">the certificate that needs to be checked</param> /// <param name="issuerCert">the certificate of CA</param> /// <param name="signDate">sign date</param> /// <returns> /// /// <see langword="true"/> /// , in case successful check, otherwise false. /// </returns> /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/> /// <exception cref="System.IO.IOException"/> public virtual bool Verify(BasicOcspResp ocspResp, X509Certificate signCert, X509Certificate issuerCert, DateTime signDate) { if (ocspResp == null) { return(false); } // Getting the responses SingleResp[] resp = ocspResp.Responses; for (int i = 0; i < resp.Length; i++) { // check if the serial number corresponds if (!signCert.SerialNumber.Equals(resp[i].GetCertID().SerialNumber)) { continue; } // check if the issuer matches try { if (issuerCert == null) { issuerCert = signCert; } if (!SignUtils.CheckIfIssuersMatch(resp[i].GetCertID(), issuerCert)) { LOGGER.Info("OCSP: Issuers doesn't match."); continue; } } catch (OcspException) { continue; } // check if the OCSP response was valid at the time of signing if (resp[i].NextUpdate == null) { DateTime nextUpdate = SignUtils.Add180Sec(resp[i].ThisUpdate); LOGGER.Info(MessageFormatUtil.Format("No 'next update' for OCSP Response; assuming {0}", nextUpdate)); if (signDate.After(nextUpdate)) { LOGGER.Info(MessageFormatUtil.Format("OCSP no longer valid: {0} after {1}", signDate, nextUpdate)); continue; } } else { if (signDate.After(resp[i].NextUpdate)) { LOGGER.Info(MessageFormatUtil.Format("OCSP no longer valid: {0} after {1}", signDate, resp[i].NextUpdate)); continue; } } // check the status of the certificate Object status = resp[i].GetCertStatus(); if (status == CertificateStatus.Good) { // check if the OCSP response was genuine IsValidResponse(ocspResp, issuerCert); return(true); } } return(false); }
/// <summary> /// Verifies if an OCSP response is genuine /// If it doesn't verify against the issuer certificate and response's certificates, it may verify /// using a trusted anchor or cert. /// </summary> /// <param name="ocspResp">the OCSP response</param> /// <param name="issuerCert">the issuer certificate</param> /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/> /// <exception cref="System.IO.IOException"/> public virtual void IsValidResponse(BasicOcspResp ocspResp, X509Certificate issuerCert) { //OCSP response might be signed by the issuer certificate or //the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension X509Certificate responderCert = null; //first check if the issuer certificate signed the response //since it is expected to be the most common case if (IsSignatureValid(ocspResp, issuerCert)) { responderCert = issuerCert; } //if the issuer certificate didn't sign the ocsp response, look for authorized ocsp responses // from properties or from certificate chain received with response if (responderCert == null) { if (ocspResp.GetCerts() != null) { //look for existence of Authorized OCSP responder inside the cert chain in ocsp response IEnumerable <X509Certificate> certs = SignUtils.GetCertsFromOcspResponse(ocspResp); foreach (X509Certificate cert in certs) { IList keyPurposes = null; try { keyPurposes = cert.GetExtendedKeyUsage(); if ((keyPurposes != null) && keyPurposes.Contains(id_kp_OCSPSigning) && IsSignatureValid(ocspResp, cert)) { responderCert = cert; break; } } catch (CertificateParsingException) { } } // Certificate signing the ocsp response is not found in ocsp response's certificate chain received // and is not signed by the issuer certificate. if (responderCert == null) { throw new VerificationException(issuerCert, "OCSP response could not be verified"); } } else { //certificate chain is not present in response received //try to verify using rootStore if (rootStore != null) { try { foreach (X509Certificate anchor in SignUtils.GetCertificates(rootStore)) { if (IsSignatureValid(ocspResp, anchor)) { responderCert = anchor; break; } } } catch (Exception) { responderCert = (X509Certificate)null; } } // OCSP Response does not contain certificate chain, and response is not signed by any // of the rootStore or the issuer certificate. if (responderCert == null) { throw new VerificationException(issuerCert, "OCSP response could not be verified"); } } } //check "This certificate MUST be issued directly by the CA that issued the certificate in question". responderCert.Verify(issuerCert.GetPublicKey()); // validating ocsp signers certificate // Check if responders certificate has id-pkix-ocsp-nocheck extension, // in which case we do not validate (perform revocation check on) ocsp certs for lifetime of certificate if (responderCert.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNocheck.Id) == null) { X509Crl crl; try { crl = CertificateUtil.GetCRL(responderCert); } catch (Exception) { crl = (X509Crl)null; } if (crl != null && crl is X509Crl) { CRLVerifier crlVerifier = new CRLVerifier(null, null); crlVerifier.SetRootStore(rootStore); crlVerifier.SetOnlineCheckingAllowed(onlineCheckingAllowed); crlVerifier.Verify((X509Crl)crl, responderCert, issuerCert, DateTimeUtil.GetCurrentUtcTime()); return; } } //check if lifetime of certificate is ok responderCert.CheckValidity(); }
/// <summary>Creates a MessageDigest object that can be used to create a hash.</summary> /// <param name="hashAlgorithm">the algorithm you want to use to create a hash</param> /// <param name="provider">the provider you want to use to create the hash</param> /// <returns>a MessageDigest object</returns> /// <exception cref="Org.BouncyCastle.Security.SecurityUtilityException"/> /// <exception cref="Java.Security.NoSuchProviderException"/> public static IDigest GetMessageDigest(String hashAlgorithm) { return(SignUtils.GetMessageDigest(hashAlgorithm)); }
public void CertificateIsNullTest() { NUnit.Framework.Assert.That(() => { SignUtils.HasUnsupportedCriticalExtension(null); }, NUnit.Framework.Throws.TypeOf <ArgumentException>());; }
/// <summary>Gets the MessageDigest to digest the data imprint</summary> /// <returns>the digest algorithm name</returns> /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/> public virtual IDigest GetMessageDigest() { return(SignUtils.GetMessageDigest(digestAlgorithm)); }
/// <summary> /// Creates a /// <see cref="PrivateKeySignature"/> /// instance. /// </summary> /// <param name="pk"> /// A /// <see cref="Org.BouncyCastle.Crypto.ICipherParameters"/> /// object. /// </param> /// <param name="hashAlgorithm">A hash algorithm (e.g. "SHA-1", "SHA-256",...).</param> /// <param name="provider">A security provider (e.g. "BC").</param> public PrivateKeySignature(ICipherParameters pk, String hashAlgorithm) { this.pk = pk; this.hashAlgorithm = DigestAlgorithms.GetDigest(DigestAlgorithms.GetAllowedDigest(hashAlgorithm)); this.encryptionAlgorithm = SignUtils.GetPrivateKeyAlgorithm(pk); }
internal virtual SignaturePolicyIdentifier ToSignaturePolicyIdentifier() { String algId = DigestAlgorithms.GetAllowedDigest(this.policyDigestAlgorithm); if (algId == null || algId.Length == 0) { throw new ArgumentException("Invalid policy hash algorithm"); } SignaturePolicyIdentifier signaturePolicyIdentifier = null; SigPolicyQualifierInfo spqi = null; if (this.policyUri != null && this.policyUri.Length > 0) { spqi = new SigPolicyQualifierInfo(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.IdSpqEtsUri, new DerIA5String (this.policyUri)); } signaturePolicyIdentifier = new SignaturePolicyIdentifier(new SignaturePolicyId(DerObjectIdentifier.GetInstance (new DerObjectIdentifier(this.policyIdentifier.Replace("urn:oid:", ""))), new OtherHashAlgAndValue(new AlgorithmIdentifier(new DerObjectIdentifier(algId)), new DerOctetString(this.policyHash)), SignUtils.CreateSigPolicyQualifiers (spqi))); return(signaturePolicyIdentifier); }
/// <summary>Constructs appearance (top-level) for a signature.</summary> /// <remarks> /// Constructs appearance (top-level) for a signature. /// <p> /// Consult <A HREF="http://partners.adobe.com/asn/developer/pdfs/tn/PPKAppearances.pdf">PPKAppearances.pdf</A> /// for further details. /// </remarks> /// <returns>a top-level signature appearance</returns> /// <exception cref="System.IO.IOException"/> protected internal virtual PdfFormXObject GetAppearance() { PdfCanvas canvas; if (IsInvisible()) { PdfFormXObject appearance = new PdfFormXObject(new Rectangle(0, 0)); appearance.MakeIndirect(document); return(appearance); } if (n0 == null && !reuseAppearance) { CreateBlankN0(); } if (n2 == null) { n2 = new PdfFormXObject(rect); n2.MakeIndirect(document); String text; if (layer2Text == null) { StringBuilder buf = new StringBuilder(); buf.Append("Digitally signed by "); String name = null; CertificateInfo.X500Name x500name = CertificateInfo.GetSubjectFields((X509Certificate)signCertificate); if (x500name != null) { name = x500name.GetField("CN"); if (name == null) { name = x500name.GetField("E"); } } if (name == null) { name = ""; } buf.Append(name).Append('\n'); buf.Append("Date: ").Append(SignUtils.DateToString(signDate)); if (reason != null) { buf.Append('\n').Append(reasonCaption).Append(reason); } if (location != null) { buf.Append('\n').Append(locationCaption).Append(location); } text = buf.ToString(); } else { text = layer2Text; } if (image != null) { if (imageScale == 0) { canvas = new PdfCanvas(n2, document); canvas.AddImage(image, rect.GetWidth(), 0, 0, rect.GetHeight(), 0, 0); } else { float usableScale = imageScale; if (imageScale < 0) { usableScale = Math.Min(rect.GetWidth() / image.GetWidth(), rect.GetHeight() / image.GetHeight()); } float w = image.GetWidth() * usableScale; float h = image.GetHeight() * usableScale; float x = (rect.GetWidth() - w) / 2; float y = (rect.GetHeight() - h) / 2; canvas = new PdfCanvas(n2, document); canvas.AddImage(image, w, 0, 0, h, x, y); } } PdfFont font; if (layer2Font == null) { font = PdfFontFactory.CreateFont(); } else { font = layer2Font; } Rectangle dataRect = null; Rectangle signatureRect = null; if (renderingMode == PdfSignatureAppearance.RenderingMode.NAME_AND_DESCRIPTION || renderingMode == PdfSignatureAppearance.RenderingMode .GRAPHIC_AND_DESCRIPTION && this.signatureGraphic != null) { if (rect.GetHeight() > rect.GetWidth()) { signatureRect = new Rectangle(MARGIN, rect.GetHeight() / 2, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2); dataRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() / 2 - 2 * MARGIN); } else { // origin is the bottom-left signatureRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() / 2 - 2 * MARGIN, rect.GetHeight() - 2 * MARGIN ); dataRect = new Rectangle(rect.GetWidth() / 2 + MARGIN / 2, MARGIN, rect.GetWidth() / 2 - MARGIN, rect.GetHeight () - 2 * MARGIN); } } else { if (renderingMode == PdfSignatureAppearance.RenderingMode.GRAPHIC) { if (signatureGraphic == null) { throw new InvalidOperationException("A signature image must be present when rendering mode is graphic. Use setSignatureGraphic()" ); } signatureRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() - 2 * MARGIN); } else { // take all space available dataRect = new Rectangle(MARGIN, MARGIN, rect.GetWidth() - 2 * MARGIN, rect.GetHeight() * (1 - TOP_SECTION ) - 2 * MARGIN); } } switch (renderingMode) { case PdfSignatureAppearance.RenderingMode.NAME_AND_DESCRIPTION: { String signedBy = CertificateInfo.GetSubjectFields((X509Certificate)signCertificate).GetField("CN"); if (signedBy == null) { signedBy = CertificateInfo.GetSubjectFields((X509Certificate)signCertificate).GetField("E"); } if (signedBy == null) { signedBy = ""; } AddTextToCanvas(signedBy, font, signatureRect); break; } case PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION: { if (signatureGraphic == null) { throw new InvalidOperationException("A signature image must be present when rendering mode is graphic and description. Use setSignatureGraphic()" ); } float imgWidth = signatureGraphic.GetWidth(); if (imgWidth == 0) { imgWidth = signatureRect.GetWidth(); } float imgHeight = signatureGraphic.GetHeight(); if (imgHeight == 0) { imgHeight = signatureRect.GetHeight(); } float multiplierH = signatureRect.GetWidth() / signatureGraphic.GetWidth(); float multiplierW = signatureRect.GetHeight() / signatureGraphic.GetHeight(); float multiplier = Math.Min(multiplierH, multiplierW); imgWidth *= multiplier; imgHeight *= multiplier; float x = signatureRect.GetRight() - imgWidth; float y = signatureRect.GetBottom() + (signatureRect.GetHeight() - imgHeight) / 2; canvas = new PdfCanvas(n2, document); canvas.AddImage(signatureGraphic, imgWidth, 0, 0, imgHeight, x, y); break; } case PdfSignatureAppearance.RenderingMode.GRAPHIC: { float imgWidth_1 = signatureGraphic.GetWidth(); if (imgWidth_1 == 0) { imgWidth_1 = signatureRect.GetWidth(); } float imgHeight_1 = signatureGraphic.GetHeight(); if (imgHeight_1 == 0) { imgHeight_1 = signatureRect.GetHeight(); } float multiplierH_1 = signatureRect.GetWidth() / signatureGraphic.GetWidth(); float multiplierW_1 = signatureRect.GetHeight() / signatureGraphic.GetHeight(); float multiplier_1 = Math.Min(multiplierH_1, multiplierW_1); imgWidth_1 *= multiplier_1; imgHeight_1 *= multiplier_1; float x_1 = signatureRect.GetLeft() + (signatureRect.GetWidth() - imgWidth_1) / 2; float y_1 = signatureRect.GetBottom() + (signatureRect.GetHeight() - imgHeight_1) / 2; canvas = new PdfCanvas(n2, document); canvas.AddImage(signatureGraphic, imgWidth_1, 0, 0, imgHeight_1, x_1, y_1); break; } } if (renderingMode != PdfSignatureAppearance.RenderingMode.GRAPHIC) { AddTextToCanvas(text, font, dataRect); } } int rotation = document.GetPage(page).GetRotation(); Rectangle rotated = new Rectangle(rect); if (topLayer == null) { topLayer = new PdfFormXObject(rotated); topLayer.MakeIndirect(document); canvas = new PdfCanvas(topLayer, document); if (rotation == 90) { canvas.ConcatMatrix(0, 1, -1, 0, rect.GetHeight(), 0); } else { if (rotation == 180) { canvas.ConcatMatrix(-1, 0, 0, -1, rect.GetWidth(), rect.GetHeight()); } else { if (rotation == 270) { canvas.ConcatMatrix(0, -1, 1, 0, 0, rect.GetWidth()); } } } if (reuseAppearance) { PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(document, true); PdfFormField field = acroForm.GetField(fieldName); PdfStream stream = field.GetWidgets()[0].GetAppearanceDictionary().GetAsStream(PdfName.N); PdfFormXObject xobj = new PdfFormXObject(stream); if (stream != null) { topLayer.GetResources().AddForm(xobj, new PdfName("n0")); PdfCanvas canvas1 = new PdfCanvas(topLayer, document); canvas1.AddXObject(xobj, 1, 0, 0, 1, 0, 0); } else { reuseAppearance = false; if (n0 == null) { CreateBlankN0(); } } } if (!reuseAppearance) { topLayer.GetResources().AddForm(n0, new PdfName("n0")); PdfCanvas canvas1 = new PdfCanvas(topLayer, document); canvas1.AddXObject(n0, 1, 0, 0, 1, 0, 0); } topLayer.GetResources().AddForm(n2, new PdfName("n2")); PdfCanvas canvas1_1 = new PdfCanvas(topLayer, document); canvas1_1.AddXObject(n2, 1, 0, 0, 1, 0, 0); } PdfFormXObject napp = new PdfFormXObject(rotated); napp.MakeIndirect(document); napp.GetResources().AddForm(topLayer, new PdfName("FRM")); canvas = new PdfCanvas(napp, document); canvas.AddXObject(topLayer, 0, 0); return(napp); }
/// <summary> /// Verifies if an OCSP response is genuine /// If it doesn't verify against the issuer certificate and response's certificates, it may verify /// using a trusted anchor or cert. /// </summary> /// <param name="ocspResp">the OCSP response</param> /// <param name="issuerCert">the issuer certificate. This certificate is considered trusted and valid by this method. /// </param> /// <param name="signDate">sign date</param> public virtual void IsValidResponse(BasicOcspResp ocspResp, X509Certificate issuerCert, DateTime signDate) { // OCSP response might be signed by the issuer certificate or // the Authorized OCSP responder certificate containing the id-kp-OCSPSigning extended key usage extension X509Certificate responderCert = null; // first check if the issuer certificate signed the response // since it is expected to be the most common case if (IsSignatureValid(ocspResp, issuerCert)) { responderCert = issuerCert; } // if the issuer certificate didn't sign the ocsp response, look for authorized ocsp responses // from properties or from certificate chain received with response if (responderCert == null) { if (ocspResp.GetCerts() != null) { //look for existence of Authorized OCSP responder inside the cert chain in ocsp response IEnumerable <X509Certificate> certs = SignUtils.GetCertsFromOcspResponse(ocspResp); foreach (X509Certificate cert in certs) { IList keyPurposes = null; try { keyPurposes = cert.GetExtendedKeyUsage(); if ((keyPurposes != null) && keyPurposes.Contains(id_kp_OCSPSigning) && IsSignatureValid(ocspResp, cert)) { responderCert = cert; break; } } catch (CertificateParsingException) { } } // Certificate signing the ocsp response is not found in ocsp response's certificate chain received // and is not signed by the issuer certificate. if (responderCert == null) { throw new VerificationException(issuerCert, "OCSP response could not be verified"); } // RFC 6960 4.2.2.2. Authorized Responders: // "Systems relying on OCSP responses MUST recognize a delegation certificate as being issued // by the CA that issued the certificate in question only if the delegation certificate and the // certificate being checked for revocation were signed by the same key." // and // "This certificate MUST be issued directly by the CA that is identified in the request" responderCert.Verify(issuerCert.GetPublicKey()); // check if lifetime of certificate is ok responderCert.CheckValidity(signDate); // validating ocsp signers certificate // Check if responders certificate has id-pkix-ocsp-nocheck extension, // in which case we do not validate (perform revocation check on) ocsp certs for lifetime of certificate if (responderCert.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNocheck.Id) == null) { X509Crl crl; try { // TODO should also check for Authority Information Access according to RFC6960 4.2.2.2.1. "Revocation Checking of an Authorized Responder" // TODO should also respect onlineCheckingAllowed property? crl = CertificateUtil.GetCRL(responderCert); } catch (Exception) { crl = (X509Crl)null; } if (crl != null && crl is X509Crl) { CRLVerifier crlVerifier = new CRLVerifier(null, null); crlVerifier.SetRootStore(rootStore); crlVerifier.SetOnlineCheckingAllowed(onlineCheckingAllowed); if (!crlVerifier.Verify((X509Crl)crl, responderCert, issuerCert, signDate)) { throw new VerificationException(issuerCert, "Authorized OCSP responder certificate was revoked."); } } else { ILog logger = LogManager.GetLogger(typeof(iText.Signatures.OCSPVerifier)); logger.Error("Authorized OCSP responder certificate revocation status cannot be checked"); } } } else { // TODO throw exception starting from iText version 7.2, but only after OCSPVerifier would allow explicit setting revocation check end points/provide revocation data // throw new VerificationException(issuerCert, "Authorized OCSP responder certificate revocation status cannot be checked."); // certificate chain is not present in response received // try to verify using rootStore according to RFC 6960 2.2. Response: // "The key used to sign the response MUST belong to one of the following: // - ... // - a Trusted Responder whose public key is trusted by the requestor; // - ..." if (rootStore != null) { try { foreach (X509Certificate anchor in SignUtils.GetCertificates(rootStore)) { if (IsSignatureValid(ocspResp, anchor)) { // certificate from the root store is considered trusted and valid by this method responderCert = anchor; break; } } } catch (Exception) { responderCert = (X509Certificate)null; } } if (responderCert == null) { throw new VerificationException(issuerCert, "OCSP response could not be verified: it does not contain certificate chain and response is not signed by issuer certificate or any from the root store." ); } } } }
/// <summary>Verifies a certificate chain against a KeyStore.</summary> /// <param name="certs">the certificate chain</param> /// <param name="keystore">the <c>KeyStore</c></param> /// <param name="crls">the certificate revocation list or <c>null</c></param> /// <param name="calendar">the date, shall not be null</param> /// <returns> /// empty list if the certificate chain could be validated or a /// <c>Object[]{cert,error}</c> where <c>cert</c> is the /// failed certificate and <c>error</c> is the error message /// </returns> public static IList <VerificationException> VerifyCertificates(X509Certificate[] certs, List <X509Certificate> keystore, ICollection <X509Crl> crls, DateTime calendar) { IList <VerificationException> result = new List <VerificationException>(); for (int k = 0; k < certs.Length; ++k) { X509Certificate cert = (X509Certificate)certs[k]; String err = VerifyCertificate(cert, crls, calendar); if (err != null) { result.Add(new VerificationException(cert, err)); } try { foreach (X509Certificate certStoreX509 in SignUtils.GetCertificates(keystore)) { try { if (VerifyCertificate(certStoreX509, crls, calendar) != null) { continue; } try { cert.Verify(certStoreX509.GetPublicKey()); return(result); } catch (Exception) { continue; } } catch (Exception) { } } } catch (Exception) { } int j; for (j = 0; j < certs.Length; ++j) { if (j == k) { continue; } X509Certificate certNext = (X509Certificate)certs[j]; try { cert.Verify(certNext.GetPublicKey()); break; } catch (Exception) { } } if (j == certs.Length) { result.Add(new VerificationException(cert, "Cannot be verified against the KeyStore or the certificate chain" )); } } if (result.Count == 0) { result.Add(new VerificationException((X509Certificate)null, "Invalid state. Possible circular certificate chain" )); } return(result); }
/// <summary>Signs the document using the detached mode, CMS or CAdES equivalent.</summary> /// <remarks> /// Signs the document using the detached mode, CMS or CAdES equivalent. /// <br /><br /> /// NOTE: This method closes the underlying pdf document. This means, that current instance /// of PdfSigner cannot be used after this method call. /// </remarks> /// <param name="externalSignature">the interface providing the actual signing</param> /// <param name="chain">the certificate chain</param> /// <param name="crlList">the CRL list</param> /// <param name="ocspClient">the OCSP client</param> /// <param name="tsaClient">the Timestamp client</param> /// <param name="externalDigest">an implementation that provides the digest</param> /// <param name="estimatedSize">the reserved size for the signature. It will be estimated if 0</param> /// <param name="sigtype">Either Signature.CMS or Signature.CADES</param> /// <exception cref="System.IO.IOException"/> /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/> public virtual void SignDetached(IExternalSignature externalSignature, X509Certificate[] chain, ICollection <ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize, PdfSigner.CryptoStandard sigtype) { if (closed) { throw new PdfException(PdfException.ThisInstanceOfPdfSignerIsAlreadyClosed); } ICollection <byte[]> crlBytes = null; int i = 0; while (crlBytes == null && i < chain.Length) { crlBytes = ProcessCrl(chain[i++], crlList); } if (estimatedSize == 0) { estimatedSize = 8192; if (crlBytes != null) { foreach (byte[] element in crlBytes) { estimatedSize += element.Length + 10; } } if (ocspClient != null) { estimatedSize += 4192; } if (tsaClient != null) { estimatedSize += 4192; } } PdfSignatureAppearance appearance = GetSignatureAppearance(); appearance.SetCertificate(chain[0]); if (sigtype == PdfSigner.CryptoStandard.CADES) { AddDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL2); } PdfSignature dic = new PdfSignature(PdfName.Adobe_PPKLite, sigtype == PdfSigner.CryptoStandard.CADES ? PdfName .ETSI_CAdES_DETACHED : PdfName.Adbe_pkcs7_detached); dic.SetReason(appearance.GetReason()); dic.SetLocation(appearance.GetLocation()); dic.SetSignatureCreator(appearance.GetSignatureCreator()); dic.SetContact(appearance.GetContact()); dic.SetDate(new PdfDate(GetSignDate())); // time-stamp will over-rule this cryptoDictionary = dic; IDictionary <PdfName, int?> exc = new Dictionary <PdfName, int?>(); exc[PdfName.Contents] = estimatedSize * 2 + 2; PreClose(exc); String hashAlgorithm = externalSignature.GetHashAlgorithm(); PdfPKCS7 sgn = new PdfPKCS7((ICipherParameters)null, chain, hashAlgorithm, false); Stream data = GetRangeStream(); byte[] hash = DigestAlgorithms.Digest(data, SignUtils.GetMessageDigest(hashAlgorithm)); byte[] ocsp = null; if (chain.Length >= 2 && ocspClient != null) { ocsp = ocspClient.GetEncoded((X509Certificate)chain[0], (X509Certificate)chain[1], null); } byte[] sh = sgn.GetAuthenticatedAttributeBytes(hash, ocsp, crlBytes, sigtype); byte[] extSignature = externalSignature.Sign(sh); sgn.SetExternalDigest(extSignature, null, externalSignature.GetEncryptionAlgorithm()); byte[] encodedSig = sgn.GetEncodedPKCS7(hash, tsaClient, ocsp, crlBytes, sigtype); if (estimatedSize < encodedSig.Length) { throw new System.IO.IOException("Not enough space"); } byte[] paddedSig = new byte[estimatedSize]; System.Array.Copy(encodedSig, 0, paddedSig, 0, encodedSig.Length); PdfDictionary dic2 = new PdfDictionary(); dic2.Put(PdfName.Contents, new PdfString(paddedSig).SetHexWriting(true)); Close(dic2); closed = true; }