/// <summary>Switches to the previous revision.</summary> /// <exception cref="System.IO.IOException"/> /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/> public virtual void SwitchToPreviousRevision() { LOGGER.Info("Switching to previous revision."); latestRevision = false; dss = document.GetCatalog().GetPdfObject().GetAsDictionary(PdfName.DSS); DateTime cal = pkcs7.GetTimeStampDate(); if (cal == SignUtils.UNDEFINED_TIMESTAMP_DATE) { cal = pkcs7.GetSignDate(); } // TODO: get date from signature signDate = cal.ToUniversalTime(); IList <String> names = sgnUtil.GetSignatureNames(); if (names.Count > 1) { signatureName = names[names.Count - 2]; document = new PdfDocument(new PdfReader(sgnUtil.ExtractRevision(signatureName)), new DocumentProperties() .SetEventCountingMetaInfo(metaInfo)); this.acroForm = PdfAcroForm.GetAcroForm(document, true); this.sgnUtil = new SignatureUtil(document); names = sgnUtil.GetSignatureNames(); signatureName = names[names.Count - 1]; pkcs7 = CoversWholeDocument(); LOGGER.Info(MessageFormatUtil.Format("Checking {0}signature {1}", pkcs7.IsTsp() ? "document-level timestamp " : "", signatureName)); } else { LOGGER.Info("No signatures in revision"); pkcs7 = null; } }
public virtual void LastBytesNotCoveredTest01() { String inPdf = sourceFolder + "lastBytesNotCoveredTest01.pdf"; PdfDocument pdfDocument = new PdfDocument(new PdfReader(inPdf)); SignatureUtil signatureUtil = new SignatureUtil(pdfDocument); NUnit.Framework.Assert.IsFalse(signatureUtil.SignatureCoversWholeDocument("Signature1")); }
public virtual void NotIndirectSigDictionaryTest() { String inPdf = sourceFolder + "notIndirectSigDictionaryTest.pdf"; PdfDocument pdfDocument = new PdfDocument(new PdfReader(inPdf)); SignatureUtil signatureUtil = new SignatureUtil(pdfDocument); NUnit.Framework.Assert.IsTrue(signatureUtil.SignatureCoversWholeDocument("Signature1")); }
public virtual void SpacesBeforeContentsTest02() { String inPdf = sourceFolder + "spacesBeforeContentsTest02.pdf"; PdfDocument pdfDocument = new PdfDocument(new PdfReader(inPdf)); SignatureUtil signatureUtil = new SignatureUtil(pdfDocument); NUnit.Framework.Assert.IsTrue(signatureUtil.SignatureCoversWholeDocument("Signature1")); }
public virtual void BytesAreCoveredTest02() { String inPdf = sourceFolder + "bytesAreCoveredTest02.pdf"; PdfDocument pdfDocument = new PdfDocument(new PdfReader(inPdf)); SignatureUtil signatureUtil = new SignatureUtil(pdfDocument); NUnit.Framework.Assert.IsTrue(signatureUtil.SignatureCoversWholeDocument("sig")); }
public virtual void GetSignaturesTest02() { String inPdf = sourceFolder + "simpleDocument.pdf"; PdfDocument pdfDocument = new PdfDocument(new PdfReader(inPdf)); SignatureUtil signatureUtil = new SignatureUtil(pdfDocument); IList <String> signatureNames = signatureUtil.GetSignatureNames(); NUnit.Framework.Assert.AreEqual(0, signatureNames.Count); }
/// <summary>Signs a PDF where space was already reserved.</summary> /// <param name="document">the original PDF</param> /// <param name="fieldName">the field to sign. It must be the last field</param> /// <param name="outs">the output PDF</param> /// <param name="externalSignatureContainer"> /// the signature container doing the actual signing. Only the /// method ExternalSignatureContainer.sign is used /// </param> /// <exception cref="System.IO.IOException"/> /// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/> public static void SignDeferred(PdfDocument document, String fieldName, Stream outs, IExternalSignatureContainer externalSignatureContainer) { SignatureUtil signatureUtil = new SignatureUtil(document); PdfDictionary v = signatureUtil.GetSignatureDictionary(fieldName); if (v == null) { throw new PdfException(PdfException.ThereIsNoFieldInTheDocumentWithSuchName1).SetMessageParams(fieldName); } if (!signatureUtil.SignatureCoversWholeDocument(fieldName)) { new PdfException(PdfException.SignatureWithName1IsNotTheLastItDoesntCoverWholeDocument).SetMessageParams(fieldName ); } PdfArray b = v.GetAsArray(PdfName.ByteRange); long[] gaps = SignatureUtil.AsLongArray(b); // TODO: refactor if (b.Size() != 4 || gaps[0] != 0) { throw new ArgumentException("Single exclusion space supported"); } IRandomAccessSource readerSource = document.GetReader().GetSafeFile().CreateSourceView(); Stream rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(readerSource, gaps)); byte[] signedContent = externalSignatureContainer.Sign(rg); int spaceAvailable = (int)(gaps[2] - gaps[1]) - 2; if ((spaceAvailable & 1) != 0) { throw new ArgumentException("Gap is not a multiple of 2"); } spaceAvailable /= 2; if (spaceAvailable < signedContent.Length) { throw new PdfException(PdfException.AvailableSpaceIsNotEnoughForSignature); } StreamUtil.CopyBytes(readerSource, 0, gaps[1] + 1, outs); ByteBuffer bb = new ByteBuffer(spaceAvailable * 2); foreach (byte bi in signedContent) { bb.AppendHex(bi); } int remain = (spaceAvailable - signedContent.Length) * 2; for (int k = 0; k < remain; ++k) { bb.Append((byte)48); } byte[] bbArr = bb.ToByteArray(); outs.Write(bbArr); StreamUtil.CopyBytes(readerSource, gaps[2] - 1, gaps[3] + 1, outs); }
/// <exception cref="Org.BouncyCastle.Security.GeneralSecurityException"/> protected internal virtual void InitLtvVerifier(PdfDocument document) { this.document = document; this.acroForm = PdfAcroForm.GetAcroForm(document, true); this.sgnUtil = new SignatureUtil(document); IList <String> names = sgnUtil.GetSignatureNames(); signatureName = names[names.Count - 1]; this.signDate = DateTimeUtil.GetCurrentUtcTime(); pkcs7 = CoversWholeDocument(); LOGGER.Info(MessageFormatUtil.Format("Checking {0}signature {1}", pkcs7.IsTsp() ? "document-level timestamp " : "", signatureName)); }
/// <summary>This is the first method to be called when using external signatures.</summary> /// <remarks> /// This is the first method to be called when using external signatures. The general sequence is: /// preClose(), getDocumentBytes() and close(). /// <p> /// <CODE>exclusionSizes</CODE> must contain at least /// the <CODE>PdfName.CONTENTS</CODE> key with the size that it will take in the /// document. Note that due to the hex string coding this size should be byte_size*2+2. /// </remarks> /// <param name="exclusionSizes"> /// Map with names and sizes to be excluded in the signature /// calculation. The key is a PdfName and the value an Integer. At least the /Contents must be present /// </param> /// <exception cref="System.IO.IOException">on error</exception> protected internal virtual void PreClose(IDictionary <PdfName, int?> exclusionSizes) { if (preClosed) { throw new PdfException(PdfException.DocumentAlreadyPreClosed); } // TODO: add mergeVerification functionality preClosed = true; PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(document, true); SignatureUtil sgnUtil = new SignatureUtil(document); String name = GetFieldName(); bool fieldExist = sgnUtil.DoesSignatureFieldExist(name); acroForm.SetSignatureFlags(PdfAcroForm.SIGNATURE_EXIST | PdfAcroForm.APPEND_ONLY); PdfSigFieldLockDictionary fieldLock = null; if (cryptoDictionary == null) { throw new PdfException(PdfException.NoCryptoDictionaryDefined); } cryptoDictionary.GetPdfObject().MakeIndirect(document); if (fieldExist) { PdfSignatureFormField sigField = (PdfSignatureFormField)acroForm.GetField(fieldName); sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject()); fieldLock = sigField.GetSigFieldLockDictionary(); if (fieldLock == null && this.fieldLock != null) { this.fieldLock.GetPdfObject().MakeIndirect(document); sigField.Put(PdfName.Lock, this.fieldLock.GetPdfObject()); fieldLock = this.fieldLock; } sigField.Put(PdfName.P, document.GetPage(appearance.GetPageNumber()).GetPdfObject()); sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject()); PdfObject obj = sigField.GetPdfObject().Get(PdfName.F); int flags = 0; if (obj != null && obj.IsNumber()) { flags = ((PdfNumber)obj).IntValue(); } flags |= PdfAnnotation.LOCKED; sigField.Put(PdfName.F, new PdfNumber(flags)); PdfDictionary ap = new PdfDictionary(); ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject()); sigField.Put(PdfName.AP, ap); sigField.SetModified(); } else { PdfWidgetAnnotation widget = new PdfWidgetAnnotation(appearance.GetPageRect()); widget.SetFlags(PdfAnnotation.PRINT | PdfAnnotation.LOCKED); PdfSignatureFormField sigField = PdfFormField.CreateSignature(document); sigField.SetFieldName(name); sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject()); sigField.AddKid(widget); if (this.fieldLock != null) { this.fieldLock.GetPdfObject().MakeIndirect(document); sigField.Put(PdfName.Lock, this.fieldLock.GetPdfObject()); fieldLock = this.fieldLock; } int pagen = appearance.GetPageNumber(); widget.SetPage(document.GetPage(pagen)); PdfDictionary ap = widget.GetAppearanceDictionary(); if (ap == null) { ap = new PdfDictionary(); widget.Put(PdfName.AP, ap); } ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject()); acroForm.AddField(sigField, document.GetPage(pagen)); if (acroForm.GetPdfObject().IsIndirect()) { acroForm.SetModified(); } else { //Acroform dictionary is a Direct dictionary, //for proper flushing, catalog needs to be marked as modified document.GetCatalog().SetModified(); } } exclusionLocations = new Dictionary <PdfName, PdfLiteral>(); PdfLiteral lit = new PdfLiteral(80); exclusionLocations[PdfName.ByteRange] = lit; cryptoDictionary.Put(PdfName.ByteRange, lit); foreach (KeyValuePair <PdfName, int?> entry in exclusionSizes) { PdfName key = entry.Key; lit = new PdfLiteral((int)entry.Value); exclusionLocations[key] = lit; cryptoDictionary.Put(key, lit); } if (certificationLevel > 0) { AddDocMDP(cryptoDictionary); } if (fieldLock != null) { AddFieldMDP(cryptoDictionary, fieldLock); } if (signatureEvent != null) { signatureEvent.GetSignatureDictionary(cryptoDictionary); } if (certificationLevel > 0) { // add DocMDP entry to root PdfDictionary docmdp = new PdfDictionary(); docmdp.Put(PdfName.DocMDP, cryptoDictionary.GetPdfObject()); document.GetCatalog().Put(PdfName.Perms, docmdp); document.GetCatalog().SetModified(); } cryptoDictionary.GetPdfObject().Flush(false); document.Close(); range = new long[exclusionLocations.Count * 2]; long byteRangePosition = exclusionLocations.Get(PdfName.ByteRange).GetPosition(); exclusionLocations.JRemove(PdfName.ByteRange); int idx = 1; foreach (PdfLiteral lit1 in exclusionLocations.Values) { long n = lit1.GetPosition(); range[idx++] = n; range[idx++] = lit1.GetBytesCount() + n; } iText.IO.Util.JavaUtil.Sort(range, 1, range.Length - 1); for (int k = 3; k < range.Length - 2; k += 2) { range[k] -= range[k - 1]; } if (tempFile == null) { bout = temporaryOS.ToArray(); range[range.Length - 1] = bout.Length - range[range.Length - 2]; MemoryStream bos = new MemoryStream(); PdfOutputStream os = new PdfOutputStream(bos); os.Write('['); for (int k_1 = 0; k_1 < range.Length; ++k_1) { os.WriteLong(range[k_1]).Write(' '); } os.Write(']'); System.Array.Copy(bos.ToArray(), 0, bout, (int)byteRangePosition, bos.Length); } else { try { raf = FileUtil.GetRandomAccessFile(tempFile); long len = raf.Length; range[range.Length - 1] = len - range[range.Length - 2]; MemoryStream bos = new MemoryStream(); PdfOutputStream os = new PdfOutputStream(bos); os.Write('['); for (int k_1 = 0; k_1 < range.Length; ++k_1) { os.WriteLong(range[k_1]).Write(' '); } os.Write(']'); raf.Seek(byteRangePosition); raf.Write(bos.ToArray(), 0, (int)bos.Length); } catch (System.IO.IOException e) { try { raf.Close(); } catch (Exception) { } try { tempFile.Delete(); } catch (Exception) { } throw; } } }
/// <summary>The verification constructor.</summary> /// <remarks> /// The verification constructor. This class should only be created with /// PdfStamper.getLtvVerification() otherwise the information will not be /// added to the Pdf. /// </remarks> /// <param name="document"> /// The /// <see cref="iText.Kernel.Pdf.PdfDocument"/> /// to apply the validation to. /// </param> public LtvVerification(PdfDocument document) { this.document = document; this.acroForm = PdfAcroForm.GetAcroForm(document, true); this.sgnUtil = new SignatureUtil(document); }