public void Setup() { _ftpConnectionWrap = Substitute.For <IFtpConnection>(); _pathUtil = Substitute.For <IPathUtil>(); _pathUtil.MAX_PATH.Returns(259); var factory = Substitute.For <IFtpConnectionFactory>(); factory.BuilConnection(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>()).Returns(_ftpConnectionWrap).AndDoes(delegate(CallInfo info) { _host = info.ArgAt <string>(0); _userName = info.ArgAt <string>(1); _password = info.ArgAt <string>(2); }); _ftpAction = new FtpAction(factory, _pathUtil, Substitute.For <IFtpPasswordProvider>()); _profile = new ConversionProfile(); _profile.Ftp.Enabled = true; _profile.Ftp.Server = ProfileServer; _profile.Ftp.UserName = ProfileUserName; _profile.Ftp.Password = "******"; var jobPws = new JobPasswords(); jobPws.FtpPassword = JobFtpPassword; _job = new Job(new JobInfo(), _profile, new JobTranslations(), new Accounts()); _job.Passwords = jobPws; _job.TokenReplacer = new TokenReplacer(); }
/// <summary> /// Process PDF with updating metadata (for PDF/A), Encryption, adding background and signing according to profile. /// </summary> /// <param name="pdfFile"></param> /// <param name="profile"></param> /// <param name="jobPasswords"></param> public static void ProcessPDF(string pdfFile, ConversionProfile profile, JobPasswords jobPasswords) { if (!ProcessingRequired(profile)) { Logger.Debug("No processing required."); return; } Logger.Debug("Start processing of " + pdfFile); if (!File.Exists(pdfFile)) { throw new ProcessingException("File in PdfProcessor does not exist: " + pdfFile, 26100); } try { DoProcessPDF(pdfFile, profile, jobPasswords); } catch (ProcessingException) { throw; } catch (Exception ex) { Logger.Error(ex.GetType() + " while processing file:" + pdfFile + Environment.NewLine + ex.Message); throw new ProcessingException(ex.GetType() + " while processing file:" + pdfFile + Environment.NewLine + ex.Message, 26999); } }
private static void DoProcessPDF(string pdfFile, ConversionProfile profile, JobPasswords jobPasswords) { string preProcessFile = null; try { preProcessFile = MoveFileToPreProcessFile(pdfFile); using (var stamper = StamperCreator.CreateStamperAccordingToEncryptionAndSignature(preProcessFile, pdfFile, profile)) { Encrypter.SetEncryption(stamper, profile, jobPasswords); //Encryption before adding Background and Signing! XmpMetadataUpdater.UpdateXmpMetadata(stamper, profile); BackgroundAdder.AddBackground(stamper, profile); Signer.SignPdfFile(stamper, profile, jobPasswords); //Signing after adding background and update metadata stamper.Close(); } } finally { //delete copy of original file if (!string.IsNullOrEmpty(preProcessFile)) { if (File.Exists(preProcessFile)) { File.Delete(preProcessFile); } } } }
public void SetUp() { _th = new TestHelper("PDFProcessing encryption test"); _testFile = _th.GenerateTestFile(TestFile.PDFCreatorTestpagePDF); _passwords = new JobPasswords(); _passwords.PdfOwnerPassword = "******"; _passwords.PdfUserPassword = "******"; }
/// <summary> /// Add a signature (set in profile) to a document, that is opened in the stamper. /// The function does nothing, if signature settings are disabled. /// </summary> /// <param name="stamper">Stamper with document</param> /// <param name="profile">Profile with signature settings</param> /// <param name="jobPasswords">Passwords with PdfSignaturePassword</param> /// <param name="accounts">List of accounts</param> /// <exception cref="ProcessingException">In case of any error.</exception> public void SignPdfFile(PdfStamper stamper, ConversionProfile profile, JobPasswords jobPasswords, Accounts accounts) { var signing = profile.PdfSettings.Signature; if (!profile.PdfSettings.Signature.Enabled) //Leave without signing { return; } _logger.Debug("Start signing file."); signing.CertificateFile = Path.GetFullPath(signing.CertificateFile); if (string.IsNullOrEmpty(jobPasswords.PdfSignaturePassword)) { _logger.Error("Launched signing without certification password."); throw new ProcessingException("Launched signing without certification password.", ErrorCode.Signature_LaunchedSigningWithoutPassword); } if (IsValidCertificatePassword(signing.CertificateFile, jobPasswords.PdfSignaturePassword) == false) { _logger.Error("Canceled signing. The password for certificate '" + signing.CertificateFile + "' is wrong."); throw new ProcessingException("Canceled signing. The password for certificate '" + signing.CertificateFile + "' is wrong.", ErrorCode.Signature_WrongCertificatePassword); } if (CertificateHasPrivateKey(signing.CertificateFile, jobPasswords.PdfSignaturePassword) == false) { _logger.Error("Canceled signing. The certificate '" + signing.CertificateFile + "' has no private key."); throw new ProcessingException( "Canceled signing. The certificate '" + signing.CertificateFile + "' has no private key.", ErrorCode.Signature_NoPrivateKey); } var timeServerAccount = accounts.GetTimeServerAccount(profile); if (timeServerAccount == null) { _logger.Error("Launched signing without available timeserver account."); throw new ProcessingException("Launched signing without available timeserver account.", ErrorCode.Signature_NoTimeServerAccount); } try { DoSignPdfFile(stamper, signing, jobPasswords, timeServerAccount); } catch (ProcessingException) { throw; } catch (WebException ex) { throw new ProcessingException(ex.GetType() + " while signing:" + Environment.NewLine + ex.Message, ErrorCode.Signature_NoTimeServerConnection, ex); } catch (Exception ex) { throw new ProcessingException(ex.GetType() + " while signing:" + Environment.NewLine + ex.Message, ErrorCode.Signature_GenericError, ex); } }
public static JobPasswords GetJobPasswords(ConversionProfile profile, Accounts accounts) { var passwords = new JobPasswords(); passwords.PdfOwnerPassword = profile.PdfSettings.Security.OwnerPassword; passwords.PdfUserPassword = profile.PdfSettings.Security.UserPassword; passwords.PdfSignaturePassword = profile.PdfSettings.Signature.SignaturePassword; passwords.FtpPassword = accounts.GetFtpAccount(profile)?.Password ?? ""; passwords.SmtpPassword = accounts.GetSmtpAccount(profile)?.Password ?? ""; passwords.HttpPassword = accounts.GetHttpAccount(profile)?.Password ?? ""; return(passwords); }
/// <summary> /// Add a signature (set in profile) to a document, that is opened in the stamper. /// The function does nothing, if signature settings are disabled. /// </summary> /// <param name="stamper">Stamper with document</param> /// <param name="profile">Profile with signature settings</param> /// <param name="jobPasswords">Passwords with PdfSignaturePassword</param> /// <exception cref="ProcessingException">In case of any error.</exception> public void SignPdfFile(PdfStamper stamper, ConversionProfile profile, JobPasswords jobPasswords) { try { DoSignPdfFile(stamper, profile, jobPasswords); } catch (ProcessingException) { throw; } catch (Exception ex) { throw new ProcessingException(ex.GetType() + " while signing:" + Environment.NewLine + ex.Message, ErrorCode.Signature_GenericError); } }
public void SetUp() { var bootstrapper = new IntegrationTestBootstrapper(); var container = bootstrapper.ConfigureContainer(); _th = container.GetInstance <TestHelper>(); _th.InitTempFolder("PDFProcessing encryption test"); _testFile = _th.GenerateTestFile(TestFile.PDFCreatorTestpagePDF); _passwords = new JobPasswords(); _passwords.PdfOwnerPassword = "******"; _passwords.PdfUserPassword = "******"; PdfProcessor = new ITextPdfProcessor(new FileWrap(), new DefaultProcessingPasswordsProvider()); }
internal void SetEncryption(PdfStamper stamper, ConversionProfile profile, JobPasswords jobPasswords) { if (!profile.PdfSettings.Security.Enabled) { return; } var encryption = CalculatePermissionValue(profile); _logger.Debug("Calculated Permission Value: " + encryption); if (string.IsNullOrEmpty(jobPasswords.PdfOwnerPassword)) { _logger.Error("Launched encryption without owner password."); throw new ProcessingException("Launched encryption without owner password.", ErrorCode.Encryption_NoOwnerPassword); } var ownerPassword = Encoding.Default.GetBytes(jobPasswords.PdfOwnerPassword); byte[] userPassword = null; if (profile.PdfSettings.Security.RequireUserPassword) { if (string.IsNullOrEmpty(jobPasswords.PdfUserPassword)) { _logger.Error("Launched encryption without user password."); throw new ProcessingException("Launched encryption without user password.", ErrorCode.Encryption_NoUserPassword); } userPassword = Encoding.Default.GetBytes(jobPasswords.PdfUserPassword); } switch (profile.PdfSettings.Security.EncryptionLevel) { case EncryptionLevel.Rc40Bit: stamper.SetEncryption(userPassword, ownerPassword, encryption, PdfWriter.STRENGTH40BITS); break; case EncryptionLevel.Rc128Bit: stamper.SetEncryption(userPassword, ownerPassword, encryption, PdfWriter.STRENGTH128BITS); break; case EncryptionLevel.Aes128Bit: stamper.SetEncryption(userPassword, ownerPassword, encryption, PdfWriter.ENCRYPTION_AES_128); break; //default: // break; } }
private void DoSignPdfFile(PdfStamper stamper, Signature signing, JobPasswords jobPasswords, TimeServerAccount timeServerAccount) { Pkcs12Store store = GetCertificateStore(signing.CertificateFile, jobPasswords.PdfSignaturePassword); var certificateAlias = GetCertificateAlias(store); var pk = GetPrivateKey(store, certificateAlias); var appearance = BuildSignatureAppearance(stamper, signing); // Creating the signature IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA512); var chain = GetCertificateChain(store, certificateAlias); var ocspClient = BuildOcspClient(); var tsaClient = BuildTimeServerClient(timeServerAccount); var cryptoStandard = CryptoStandard.CADES; MakeSignature.SignDetached(appearance, pks, chain, null, ocspClient, tsaClient, 0, cryptoStandard); }
internal bool SaveEncryptedFileAs(Secure pdf, ConversionProfile profile, JobPasswords jobPasswords, string outputFilename) { var encryptionFilter = GetEncryptionFilter(profile); var keyLength = GetEncryptionStrength(profile); var permissions = GetPdfPermissions(profile); var userPassword = ""; var ownerPassword = ""; if (IsEncryptionEnabled(profile)) { userPassword = profile.PdfSettings.Security.RequireUserPassword ? jobPasswords.PdfUserPassword : ""; ownerPassword = jobPasswords.PdfOwnerPassword; } return(pdf.SaveAs(outputFilename, userPassword, ownerPassword, permissions, keyLength, encryptionFilter, encryptionFilter)); }
protected AbstractJob(IJobInfo jobInfo, ConversionProfile profile, JobTranslations jobTranslations, IFile fileWrap, IDirectory directoryWrap) { FileWrap = fileWrap; DirectoryWrap = directoryWrap; TempOutputFiles = new List <string>(); OutputFiles = new List <string>(); JobActions = new List <IAction>(); Passwords = new JobPasswords(); JobTranslations = jobTranslations; AutoCleanUp = true; JobInfo = jobInfo; Profile = profile; TokenReplacer = GetTokenReplacer(); //important for testing without workflow }
public void CheckIfFileExistsAndTempFilesAreDeleted_AllPdfPropertiesDisabled() { var pdfFile = _th.GenerateTestFile(TestFile.PDFCreatorTestpagePDF); var profile = new ConversionProfile(); profile.OutputFormat = OutputFormat.Pdf; //UpdateXMPMetadata enabled if format is not PDF/A profile.PdfSettings.Security.Enabled = false; profile.PdfSettings.Signature.Enabled = false; profile.BackgroundPage.Enabled = false; var jobPasswords = new JobPasswords(); PDFProcessor.ProcessPDF(pdfFile, profile, jobPasswords); Assert.IsTrue(File.Exists(pdfFile), "Processed file does not exist."); File.Delete(pdfFile); var files = Directory.GetFiles(_th.TmpTestFolder); Assert.IsEmpty(files, "TmpTestFolder should be empty, after deleting processed file, but contained: " + Environment.NewLine + files); }
internal bool SignPdfFile(Secure secure, ConversionProfile profile, JobPasswords jobPasswords, Accounts accounts) { if (!profile.PdfSettings.Signature.Enabled) { return(true); } if (string.IsNullOrEmpty(jobPasswords.PdfSignaturePassword)) { _logger.Error("Launched signing without certificate password."); throw new ProcessingException("Launched signing without certificate password.", ErrorCode.Signature_LaunchedSigningWithoutPassword); } var certificate = _certificateManager.GetOrRegisterCertificate(profile.PdfSettings.Signature.CertificateFile, jobPasswords.PdfSignaturePassword); var timeServerAccount = accounts.GetTimeServerAccount(profile); if (timeServerAccount == null) { _logger.Error("Launched signing without available timeserver account."); throw new ProcessingException("Launched signing without available timeserver account.", ErrorCode.Signature_NoTimeServerAccount); } try { return(DoSignPdfFile(secure, profile, certificate, timeServerAccount)); } catch (ProcessingException) { throw; } catch (Exception ex) { throw new ProcessingException(ex.GetType() + " while signing:" + Environment.NewLine + ex.Message, ErrorCode.Signature_GenericError, ex); } }
private static void DoSignPdfFile(PdfStamper stamper, ConversionProfile profile, JobPasswords jobPasswords) { var signing = profile.PdfSettings.Signature; if (!signing.Enabled) //Leave without signing { return; } Logger.Debug("Start signing file."); signing.CertificateFile = Path.GetFullPath(signing.CertificateFile); if (string.IsNullOrEmpty(jobPasswords.PdfSignaturePassword)) { Logger.Error("Launched signing without certification password."); throw new ProcessingException("Launched signing without certification password.", 12204); } if (IsValidCertificatePassword(signing.CertificateFile, jobPasswords.PdfSignaturePassword) == false) { Logger.Error("Canceled signing. The password for certificate '" + signing.CertificateFile + "' is wrong."); throw new ProcessingException( "Canceled signing. The password for certificate '" + signing.CertificateFile + "' is wrong.", 12200); } if (CertificateHasPrivateKey(signing.CertificateFile, jobPasswords.PdfSignaturePassword) == false) { Logger.Error("Canceled signing. The certificate '" + signing.CertificateFile + "' has no private key."); throw new ProcessingException( "Canceled signing. The certificate '" + signing.CertificateFile + "' has no private key.", 12201); } var fsCert = new FileStream(signing.CertificateFile, FileMode.Open); var ks = new Pkcs12Store(fsCert, jobPasswords.PdfSignaturePassword.ToCharArray()); string alias = null; foreach (string al in ks.Aliases) { if (ks.IsKeyEntry(al) && ks.GetKey(al).Key.IsPrivate) { alias = al; break; } } fsCert.Close(); ICipherParameters pk = ks.GetKey(alias).Key; var x = ks.GetCertificateChain(alias); var chain = new X509Certificate[x.Length]; for (var k = 0; k < x.Length; ++k) { chain[k] = x[k].Certificate; } ITSAClient tsc = null; if (!string.IsNullOrEmpty(signing.TimeServerUrl.Trim())) { if (!signing.TimeServerIsSecured) { tsc = new TSAClientBouncyCastle(signing.TimeServerUrl); } else { tsc = new TSAClientBouncyCastle(signing.TimeServerUrl, signing.TimeServerLoginName, signing.TimeServerPassword); } } var psa = stamper.SignatureAppearance; if (tsc == null) { psa.SetCrypto(pk, chain, null, PdfSignatureAppearance.WINCER_SIGNED); } else { psa.SetCrypto(null, chain, null, PdfSignatureAppearance.SELF_SIGNED); } if (!profile.PdfSettings.Signature.AllowMultiSigning) { //Lock PDF, except for annotations and form filling (irrelevant for clawPDF) psa.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS; } psa.Reason = signing.SignReason; psa.Contact = signing.SignContact; psa.Location = signing.SignLocation; if (signing.DisplaySignatureInDocument) { var signPage = SignPageNr(stamper, signing); psa.SetVisibleSignature(new Rectangle(signing.LeftX, signing.LeftY, signing.RightX, signing.RightY), signPage, null); } var dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached")); dic.Reason = psa.Reason; dic.Location = psa.Location; dic.Contact = psa.Contact; dic.Date = new PdfDate(psa.SignDate); psa.CryptoDictionary = dic; const int contentEstimated = 15000; // Preallocate excluded byte-range for the signature content (hex encoded) var exc = new Dictionary <PdfName, int>(); exc[PdfName.CONTENTS] = contentEstimated * 2 + 2; psa.PreClose(exc); const string hashAlgorithm = "SHA1"; //Always use HashAlgorithm "SHA1" var sgn = new PdfPKCS7(pk, chain, null, hashAlgorithm, false); var messageDigest = DigestUtilities.GetDigest(hashAlgorithm); var data = psa.GetRangeStream(); var buf = new byte[8192]; int n; while ((n = data.Read(buf, 0, buf.Length)) > 0) { messageDigest.BlockUpdate(buf, 0, n); } var hash = new byte[messageDigest.GetDigestSize()]; messageDigest.DoFinal(hash, 0); byte[] ocsp = null; if (chain.Length >= 2) { var url = PdfPKCS7.GetOCSPURL(chain[0]); if (!string.IsNullOrEmpty(url)) { ocsp = new OcspClientBouncyCastle().GetEncoded(chain[0], chain[1], url); } } var cal = psa.SignDate; var sh = sgn.GetAuthenticatedAttributeBytes(hash, cal, ocsp); sgn.Update(sh, 0, sh.Length); var paddedSig = new byte[contentEstimated]; if (tsc != null) { byte[] encodedSigTsa = null; try { encodedSigTsa = sgn.GetEncodedPKCS7(hash, cal, tsc, ocsp); Array.Copy(encodedSigTsa, 0, paddedSig, 0, encodedSigTsa.Length); } catch (Exception ex) { throw new ProcessingException( ex.GetType() + " while connecting to timeserver (can't connect to timeserver): " + ex.Message, 12205); } if (contentEstimated + 2 < encodedSigTsa.Length) { throw new ProcessingException( "Not enough space for signature", 12202); } } else { var encodedSig = sgn.GetEncodedPKCS7(hash, cal); Array.Copy(encodedSig, 0, paddedSig, 0, encodedSig.Length); if (contentEstimated + 2 < encodedSig.Length) { throw new ProcessingException("Not enough space for signature", 12203); } } var dic2 = new PdfDictionary(); dic2.Put(PdfName.CONTENTS, new PdfString(paddedSig).SetHexWriting(true)); psa.Close(dic2); }
/// <summary> /// Test if the testfile can be opened and/or edited according to the security settings in the profile. /// Test is done with the given passwords, without password and with a bad password. /// </summary> /// <param name="testFile">PDF testfile</param> /// <param name="profile">Profile used for processing</param> /// <param name="passwords">Passwords used for processing</param> public static void MakePasswordTest(string testFile, ConversionProfile profile, JobPasswords passwords) { bool askUserPw = (profile.PdfSettings.Security.Enabled && profile.PdfSettings.Security.RequireUserPassword); //Owner password //File can always be opened and edited with owner password. PasswordTest(testFile, true, true, passwords.PdfOwnerPassword); //User password //File can only be opened with user password is user pw is required. //Note: If encryption is disabled, the files can be opened with PdfReader using any password. // If encryption is enabled, it is not possible, although no password is required. //File can be edited with user password if no owner password is requested (respectively security is disabled). PasswordTest(testFile, askUserPw || !profile.PdfSettings.Security.Enabled, !profile.PdfSettings.Security.Enabled, passwords.PdfUserPassword); //Without password //File can be opened without password if no user password is requested (or security is disabled (of course...)). //File can only be opened with a bad password is user pw is required. //Note: If encryption is disabled, the files can be opened with PdfReader using any password. // If encryption is enabled, it is not possible, although no password is required. //File can be edited without (or bad) password if no owner password is requested (respectively security is disabled). PasswordTest(testFile, !askUserPw, !profile.PdfSettings.Security.Enabled); PasswordTest(testFile, !profile.PdfSettings.Security.Enabled, !profile.PdfSettings.Security.Enabled, "BadPassword" + DateTime.Now.Millisecond); }
/// <summary> /// /// </summary> /// <param name="testFile"></param> /// <param name="profile"></param> /// <param name="passwords"></param> /// <param name="numberOfSignatures"></param> /// <param name="allowMultisigning"></param> public static void TestSignature(string testFile, ConversionProfile profile, JobPasswords passwords, int numberOfSignatures, bool allowMultisigning) { PdfReader pdfReader; if (profile.PdfSettings.Security.Enabled) { if (profile.PdfSettings.Security.RequireUserPassword) { pdfReader = new PdfReader(testFile, Encoding.Default.GetBytes(passwords.PdfUserPassword)); } else { pdfReader = new PdfReader(testFile, Encoding.Default.GetBytes(passwords.PdfOwnerPassword)); } } else { pdfReader = new PdfReader(testFile); } AcroFields af = pdfReader.AcroFields; //Stop here if no Signing was requested if (!profile.PdfSettings.Signature.Enabled) { Assert.AreEqual(0, af.GetSignatureNames().Count, "SignatureName(s) in unsigned file." + Environment.NewLine + "(" + testFile + ")"); return; } //Proceed with checking the number of signatures Assert.AreEqual(numberOfSignatures, af.GetSignatureNames().Count, "Number of SignatureNames must be " + numberOfSignatures + Environment.NewLine + "(" + testFile + ")"); #region Verify the last or single signature in document, which must be always valid String signatureName = af.GetSignatureNames()[numberOfSignatures - 1]; PdfPKCS7 pk = af.VerifySignature(signatureName); Assert.IsTrue(pk.Verify(), "(Last) Signature in document, is not valid."); Assert.IsTrue(af.SignatureCoversWholeDocument(signatureName), "(Last) signature in document, does not cover whole document."); TimeSpan ts = DateTime.Now.ToUniversalTime() - pk.TimeStampDate; Assert.IsTrue(Math.Abs(ts.TotalHours) < 1, "Time stamp has a difference bigger than 1h from now." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.SignLocation, pk.Location, "Wrong SignLocation." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.SignReason, pk.Reason, "Wrong SignReason." + Environment.NewLine + "(" + testFile + ")"); if (profile.PdfSettings.Signature.DisplaySignatureInDocument) { switch (profile.PdfSettings.Signature.SignaturePage) { case SignaturePage.FirstPage: Assert.AreEqual(1, af.GetFieldPositions(signatureName)[0].page, "Signature is not on the first page." + Environment.NewLine + "(" + testFile + ")"); break; case SignaturePage.CustomPage: if (profile.PdfSettings.Signature.SignatureCustomPage > pdfReader.NumberOfPages) { Assert.AreEqual(pdfReader.NumberOfPages, af.GetFieldPositions(signatureName)[0].page, "Signature is not on the requested page." + Environment.NewLine + "(" + testFile + ")"); } else { Assert.AreEqual(profile.PdfSettings.Signature.SignatureCustomPage, af.GetFieldPositions(signatureName)[0].page, "Signature is not on the requested page." + Environment.NewLine + "(" + testFile + ")"); } break; case SignaturePage.LastPage: Assert.AreEqual(pdfReader.NumberOfPages, af.GetFieldPositions(signatureName)[0].page, "Signature is not on the last Page." + Environment.NewLine + "(" + testFile + ")"); break; } Assert.AreEqual(profile.PdfSettings.Signature.LeftX, (int)af.GetFieldPositions(signatureName)[0].position.GetLeft(0), "Wrong position for LeftX." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.LeftY, (int)af.GetFieldPositions(signatureName)[0].position.GetBottom(0), "Wrong position for LeftY." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.RightX, (int)af.GetFieldPositions(signatureName)[0].position.GetRight(0), "Wrong position for RightX." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.RightY, (int)af.GetFieldPositions(signatureName)[0].position.GetTop(0), "Wrong position for RightY." + Environment.NewLine + "(" + testFile + ")"); } else { Assert.AreEqual(1, af.GetFieldPositions(signatureName)[0].page, "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(0, (int)af.GetFieldPositions(signatureName)[0].position.GetLeft(0), "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(0, (int)af.GetFieldPositions(signatureName)[0].position.GetBottom(0), "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(0, (int)af.GetFieldPositions(signatureName)[0].position.GetRight(0), "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(0, (int)af.GetFieldPositions(signatureName)[0].position.GetTop(0), "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); } #endregion /* * var stamper = new PdfStamper(pdfReader, ); * * if (profile.PdfSettings.Signature.AllowMultiSigning) * Assert.AreEqual(0, stamper.SignatureAppearance); * else * Assert.AreEqual(1, stamper.SignatureAppearance); * * stamper.Close(); */ /* * //Check validity of previous signatures. They must be valid if multi signing is allowed, otherwise they must be invalid. * for (int i = 1; i < numberOfSignatures; i++) * { * String previousSignName = af.GetSignatureNames()[i-1]; * //PdfPKCS7 previousPk = af.VerifySignature(previousSignName); * * if (allowMultisigning) * { * var sig = af.VerifySignature(previousSignName); * Assert.IsTrue(sig.Verify(), ""); * Assert.IsTrue(af.SignatureCoversWholeDocument(previousSignName), * "Last or single signature in document, does not cover whole document , although multi signing was enabled."); * } * else * { * var sig = af.VerifySignature(previousSignName); * Assert.IsFalse(sig.Verify(), ""); * Assert.IsFalse(af.SignatureCoversWholeDocument(previousSignName), * "Last or single signature in document, covers whole document , although multi signing was disabled."); * } * } */ }
private static void CheckPDFVersion(string testFile, ConversionProfile profile, JobPasswords passwords, IPdfProcessor pdfProcessor) { PdfReader pdfReader; if (profile.PdfSettings.Security.Enabled) { if (profile.PdfSettings.Security.RequireUserPassword) { pdfReader = new PdfReader(testFile, Encoding.Default.GetBytes(passwords.PdfUserPassword)); } else { pdfReader = new PdfReader(testFile, Encoding.Default.GetBytes(passwords.PdfOwnerPassword)); } } else { pdfReader = new PdfReader(testFile); } using (pdfReader) { CheckPDFVersion(pdfReader, profile, pdfProcessor); } }
public static string TestMultipleSigning(string testFile, ConversionProfile profile, JobPasswords passwords, IPdfProcessor pdfProcessor, Accounts accounts) { using (var pdfReader = BuildPdfReader(testFile, profile, passwords)) { var doubleSignedFile = testFile.Replace(".pdf", "_doubleSignedFile.pdf"); var fileStream = new FileStream(doubleSignedFile, FileMode.Create, FileAccess.Write); var tempFile = testFile.Replace(".pdf", "_tempFile.pdf"); var intendedPdfVersion = pdfProcessor.DeterminePdfVersion(profile); var pdfVersion = PdfWriter.VERSION_1_4; if (intendedPdfVersion == "1.5") { pdfVersion = PdfWriter.VERSION_1_5; } else if (intendedPdfVersion == "1.6") { pdfVersion = PdfWriter.VERSION_1_6; } else if (intendedPdfVersion == "1.7") { pdfVersion = PdfWriter.VERSION_1_7; } //Create Stamper in append mode var stamper = PdfStamper.CreateSignature(pdfReader, fileStream, pdfVersion, tempFile, true); profile.PdfSettings.Signature.SignaturePage = SignaturePage.LastPage; var signer = new ITextSigner(); signer.SignPdfFile(stamper, profile, passwords, accounts); stamper.Close(); using (var doubleSignedPdfReader = BuildPdfReader(doubleSignedFile, profile, passwords)) { var af = doubleSignedPdfReader.AcroFields; Assert.AreEqual(2, af.GetSignatureNames().Count, "Number of SignatureNames must be 2" + Environment.NewLine + "(" + testFile + ")"); //There is currently no way for testing multisigning. //-> af.SignatureCoversWholeDocument(firstSignatureName) is always false, since a singature can't cover future signing //-> firstSignature.Verify() returns always true. /* * var firstSignatureName = af.GetSignatureNames()[0]; * var firstSignature = af.VerifySignature(firstSignatureName); * * if (profile.PdfSettings.Signature.AllowMultiSigning) * { * Assert.IsTrue(firstSignature.Verify(), "First signature is invalid altough multi signing was enabled"); * } * else * { * Assert.IsFalse(firstSignature.Verify(), "First signature is valid altough multi signing was disabled"); * } * //*/ return(doubleSignedFile); } } }
private static PdfReader BuildPdfReader(string testFile, ConversionProfile profile, JobPasswords passwords) { PdfReader pdfReader; if (profile.PdfSettings.Security.Enabled) { if (profile.PdfSettings.Security.RequireUserPassword) { pdfReader = new PdfReader(testFile, Encoding.Default.GetBytes(passwords.PdfUserPassword)); } else { pdfReader = new PdfReader(testFile, Encoding.Default.GetBytes(passwords.PdfOwnerPassword)); } } else { pdfReader = new PdfReader(testFile); } return(pdfReader); }
public static void TestSignature(string testFile, ConversionProfile profile, JobPasswords passwords) { using (var pdfReader = BuildPdfReader(testFile, profile, passwords)) { var af = pdfReader.AcroFields; //Stop here if no Signing was requested if (!profile.PdfSettings.Signature.Enabled) { Assert.AreEqual(0, af.GetSignatureNames().Count, "SignatureName(s) in unsigned file." + Environment.NewLine + "(" + testFile + ")"); return; } //Proceed with checking the number of signatures Assert.AreEqual(1, af.GetSignatureNames().Count, "Number of SignatureNames must be 1" + Environment.NewLine + "(" + testFile + ")"); var signatureName = af.GetSignatureNames()[0]; var pk = af.VerifySignature(signatureName); Assert.IsTrue(pk.Verify(), "(Last) Signature is not valid."); Assert.IsTrue(af.SignatureCoversWholeDocument(signatureName), "(Last) signature does not cover whole document."); var ts = DateTime.Now.ToUniversalTime() - pk.TimeStampDate; Assert.IsTrue(Math.Abs(ts.TotalHours) < 1, "Time stamp has a difference bigger than 1h from now." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.SignLocation, pk.Location ?? "", "Wrong SignLocation." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.SignReason, pk.Reason ?? "", "Wrong SignReason." + Environment.NewLine + "(" + testFile + ")"); if (profile.PdfSettings.Signature.DisplaySignatureInDocument) { switch (profile.PdfSettings.Signature.SignaturePage) { case SignaturePage.FirstPage: Assert.AreEqual(1, af.GetFieldPositions(signatureName)[0].page, "Signature is not on the first page." + Environment.NewLine + "(" + testFile + ")"); break; case SignaturePage.CustomPage: if (profile.PdfSettings.Signature.SignatureCustomPage > pdfReader.NumberOfPages) { Assert.AreEqual(pdfReader.NumberOfPages, af.GetFieldPositions(signatureName)[0].page, "Signature is not on the requested page." + Environment.NewLine + "(" + testFile + ")"); } else { Assert.AreEqual(profile.PdfSettings.Signature.SignatureCustomPage, af.GetFieldPositions(signatureName)[0].page, "Signature is not on the requested page." + Environment.NewLine + "(" + testFile + ")"); } break; case SignaturePage.LastPage: Assert.AreEqual(pdfReader.NumberOfPages, af.GetFieldPositions(signatureName)[0].page, "Signature is not on the last Page." + Environment.NewLine + "(" + testFile + ")"); break; } Assert.AreEqual(profile.PdfSettings.Signature.LeftX, (int)af.GetFieldPositions(signatureName)[0].position.GetLeft(0), "Wrong position for LeftX." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.LeftY, (int)af.GetFieldPositions(signatureName)[0].position.GetBottom(0), "Wrong position for LeftY." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.RightX, (int)af.GetFieldPositions(signatureName)[0].position.GetRight(0), "Wrong position for RightX." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(profile.PdfSettings.Signature.RightY, (int)af.GetFieldPositions(signatureName)[0].position.GetTop(0), "Wrong position for RightY." + Environment.NewLine + "(" + testFile + ")"); } else { Assert.AreEqual(0, (int)af.GetFieldPositions(signatureName)[0].position.GetLeft(0), "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(0, (int)af.GetFieldPositions(signatureName)[0].position.GetBottom(0), "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(0, (int)af.GetFieldPositions(signatureName)[0].position.GetRight(0), "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); Assert.AreEqual(0, (int)af.GetFieldPositions(signatureName)[0].position.GetTop(0), "Wrong position for \"invisible\" signature." + Environment.NewLine + "(" + testFile + ")"); } } }