public void Security(string PDF, string userPassword, PasswordValidity userPasswordValidity, string ownerPassword, PasswordValidity ownerPasswordValidity) { string errorMsg = string.Empty; string filePath = Path.Combine(TestHelper.DataFolder, PDF); Assert.IsTrue(File.Exists(filePath)); PdfFile pdfFile = new PdfFile(filePath); pdfFile.Open(ref errorMsg); Assert.IsTrue(string.IsNullOrEmpty(errorMsg)); IDecryptor pdfDecryptor = DecryptorFactory.Get(pdfFile.EncryptionRecordInfo); PasswordValidity passwordValidity = pdfDecryptor.ValidatePassword(userPassword, ValidationMode.ValidateUserPassword); Assert.AreEqual(passwordValidity, userPasswordValidity); passwordValidity = pdfDecryptor.ValidatePassword(ownerPassword, ValidationMode.ValidateOwnerPassword); Assert.AreEqual(passwordValidity, ownerPasswordValidity); }
private void DecryptWorkerDoWork(object sender, DoWorkEventArgs e) { TimeSpan ts; const int timeSlice = 50; const int nrOfSpeedMeasurements = 50; ulong passwordCount = 0, prevPasswordCount = 0; object[] args = (object[])e.Argument; IDecryptor decryptor = DecryptorFactory.Get((EncryptionRecord)args[0]); IPasswordIterator passwordIterator = (IPasswordIterator)args[1]; ValidationMode validationMode = (ValidationMode)args[2]; IMovingAverage avg = new SimpleMovingAverage(nrOfSpeedMeasurements); PasswordValidity passwordValidity = PasswordValidity.Invalid; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string currentPassword = passwordIterator.GetNextPassword(); while (!string.IsNullOrEmpty(currentPassword) && validationMode != ValidationMode.None && !decryptBackgroundWorker.CancellationPending) { passwordValidity = decryptor.ValidatePassword(currentPassword, validationMode); passwordCount++; ts = stopWatch.Elapsed; if (ts.Milliseconds > timeSlice || passwordValidity != PasswordValidity.Invalid) { avg.AddSample((60000 * (passwordCount - prevPasswordCount)) / ((ulong)ts.Milliseconds + 1)); //Avoid div by zero decryptBackgroundWorker.ReportProgress(0, new object[] { passwordValidity, currentPassword, (ulong)avg.Average, passwordCount }); prevPasswordCount = passwordCount; stopWatch.Restart(); if ((passwordValidity & PasswordValidity.OwnerPasswordIsValid) == PasswordValidity.OwnerPasswordIsValid) { validationMode &= ~ValidationMode.ValidateOwnerPassword; } if ((passwordValidity & PasswordValidity.UserPasswordIsValid) == PasswordValidity.UserPasswordIsValid) { validationMode &= ~ValidationMode.ValidateUserPassword; } } currentPassword = passwordIterator.GetNextPassword(); } if (decryptBackgroundWorker.CancellationPending) { e.Cancel = true; } else { e.Result = passwordCount; } }
public void SetPassword(string password, PasswordValidity passwordValidity) { if ((passwordValidity & PasswordValidity.OwnerPasswordIsValid) == PasswordValidity.OwnerPasswordIsValid) { RecoveredOwnerPassword = password; } if ((passwordValidity & PasswordValidity.UserPasswordIsValid) == PasswordValidity.UserPasswordIsValid) { RecoveredUserPassword = password; } }
private void DecryptWorkerProgressChanged(object sender, ProgressChangedEventArgs e) { if (e.UserState != null) { object[] args = (object[])e.UserState; PasswordValidity passwordValidity = (PasswordValidity)args[0]; CurrentPassword = args[1].ToString(); Speed = (ulong)args[2]; PasswordCount = (ulong)args[3]; if (passwordValidity != PasswordValidity.Invalid) { SelectedFile.SetPassword(CurrentPassword, passwordValidity); WriteToFile(passwordValidity, CurrentPassword); Status = string.Format("{0}: {1}", passwordValidity.ToString(), CurrentPassword); } } }
public PasswordValidity ValidatePassword(string password, ValidationMode mode) { PasswordValidity isValid = PasswordValidity.Invalid; if ((mode & ValidationMode.ValidateUserPassword) == ValidationMode.ValidateUserPassword && ValidateUserPassword(password) != PasswordValidity.Invalid) { isValid |= PasswordValidity.UserPasswordIsValid; } if ((mode & ValidationMode.ValidateOwnerPassword) == ValidationMode.ValidateOwnerPassword && ValidateOwnerPassword(password) != PasswordValidity.Invalid) { isValid |= PasswordValidity.OwnerPasswordIsValid; } return(isValid); }
private Task WriteToFile(PasswordValidity passwordValidity, string CurrentPassword) { string destinationFilePath = string.Empty; string summaryMsg = string.Format("{0},{1},{2}={3}{4}", DateTime.Now.ToString(CultureInfo.CurrentCulture), SelectedFile.Info.FullName, passwordValidity.ToString(), CurrentPassword, Environment.NewLine); FileMode fileMode = OverwritePasswordFile ? FileMode.Create : FileMode.Append; if (SaveOptionsPasswordFile == SaveOptions.UseSourceFolder) { destinationFilePath = string.Format("{0}\\{1}", SelectedFile.Info.DirectoryName, PasswordStorageFilename); } else if (SaveOptionsPasswordFile == SaveOptions.UseCustomFolder) { destinationFilePath = string.Format("{0}\\{1}", SelectedSavePath, PasswordStorageFilename); } return(FileHelpers.WriteToFileAsync(destinationFilePath, fileMode, summaryMsg)); }
private void OnOkCmdExecute() { PasswordValidity validity = PdfDecryptor.ValidatePassword(Password, ValidationMode.ValidateUserPassword | ValidationMode.ValidateOwnerPassword); if (validity == PasswordValidity.Invalid) { ErrorContent = "Failed to unlock PDF, please try again [" + Password + "]"; ForegroundColor = Brushes.Red; HasError = true; } else { ForegroundColor = Brushes.Green; HasError = false; if ((validity & PasswordValidity.UserPasswordIsValid) == PasswordValidity.UserPasswordIsValid && (validity & PasswordValidity.OwnerPasswordIsValid) == PasswordValidity.OwnerPasswordIsValid) { RecoveredUserPassword = Password; RecoveredOwnerPassword = Password; ErrorContent = string.Format("PDF unlocked with User and Owner password: [{0}].", Password); } else { if ((validity & PasswordValidity.UserPasswordIsValid) == PasswordValidity.UserPasswordIsValid) { RecoveredUserPassword = Password; ErrorContent = string.Format("PDF unlocked with User password: [{0}].", Password); } if ((validity & PasswordValidity.OwnerPasswordIsValid) == PasswordValidity.OwnerPasswordIsValid) { RecoveredOwnerPassword = Password; ErrorContent = string.Format("PDF unlocked with Owner password: [{0}].", Password); } } } Password = string.Empty; }
/// <summary> /// Opens an existing PDF document asynchronously. /// </summary> public static async Task <PdfDocument> OpenAsync( Stream stream, string password = null, PdfDocumentOpenMode openmode = PdfDocumentOpenMode.Modify, PdfPasswordProvider passwordProvider = null) { PdfDocument document; #if !DEBUG try #endif { Lexer lexer = new Lexer(stream); document = new PdfDocument(lexer); document._state |= DocumentState.Imported; document._openMode = openmode; document._fileSize = stream.Length; // Get file version. byte[] header = new byte[1024]; stream.Position = 0; stream.Read(header, 0, 1024); document._version = GetPdfFileVersion(header); if (document._version == 0) { throw new InvalidOperationException(PSSR.InvalidPdf); } document._irefTable.IsUnderConstruction = true; Parser parser = new Parser(document); // Read all trailers or cross-reference streams, but no objects. document._trailer = await parser.ReadTrailerAsync(); if (document._trailer == null) { ParserDiagnostics.ThrowParserException("Invalid PDF file: no trailer found."); // TODO L10N using PSSR. } Debug.Assert(document._irefTable.IsUnderConstruction); document._irefTable.IsUnderConstruction = false; // Is document encrypted? PdfReference xrefEncrypt = document._trailer.Elements[PdfTrailer.Keys.Encrypt] as PdfReference; if (xrefEncrypt != null) { PdfObject encrypt = await parser.ReadObjectAsync(null, xrefEncrypt.ObjectID, false, false); encrypt.Reference = xrefEncrypt; xrefEncrypt.Value = encrypt; PdfStandardSecurityHandler securityHandler = document.SecurityHandler; TryAgain: PasswordValidity validity = securityHandler.ValidatePassword(password); if (validity == PasswordValidity.Invalid) { if (passwordProvider != null) { PdfPasswordProviderArgs args = new PdfPasswordProviderArgs(); passwordProvider(args); if (args.Abort) { return(null); } password = args.Password; goto TryAgain; } else { if (password == null) { throw new PdfReaderException(PSSR.PasswordRequired); } else { throw new PdfReaderException(PSSR.InvalidPassword); } } } else if (validity == PasswordValidity.UserPassword && openmode == PdfDocumentOpenMode.Modify) { if (passwordProvider != null) { PdfPasswordProviderArgs args = new PdfPasswordProviderArgs(); passwordProvider(args); if (args.Abort) { return(null); } password = args.Password; goto TryAgain; } else { throw new PdfReaderException(PSSR.OwnerPasswordRequired); } } } else { if (password != null) { // Password specified but document is not encrypted. // ignore } } PdfReference[] irefs2 = document._irefTable.AllReferences; int count2 = irefs2.Length; // 3rd: Create iRefs for all compressed objects. Dictionary <int, object> objectStreams = new Dictionary <int, object>(); for (int idx = 0; idx < count2; idx++) { PdfReference iref = irefs2[idx]; if (iref.Value is PdfCrossReferenceStream xrefStream) { for (int idx2 = 0; idx2 < xrefStream.Entries.Count; idx2++) { PdfCrossReferenceStream.CrossReferenceStreamEntry item = xrefStream.Entries[idx2]; // Is type xref to compressed object? if (item.Type == 2) { //PdfReference irefNew = parser.ReadCompressedObject(new PdfObjectID((int)item.Field2), (int)item.Field3); //document._irefTable.Add(irefNew); int objectNumber = (int)item.Field2; if (!objectStreams.ContainsKey(objectNumber)) { objectStreams.Add(objectNumber, null); PdfObjectID objectID = new PdfObjectID((int)item.Field2); parser.ReadIRefsFromCompressedObject(objectID); } } } } } // 4th: Read compressed objects. for (int idx = 0; idx < count2; idx++) { PdfReference iref = irefs2[idx]; if (iref.Value is PdfCrossReferenceStream xrefStream) { for (int idx2 = 0; idx2 < xrefStream.Entries.Count; idx2++) { PdfCrossReferenceStream.CrossReferenceStreamEntry item = xrefStream.Entries[idx2]; // Is type xref to compressed object? if (item.Type == 2) { PdfReference irefNew = parser.ReadCompressedObject(new PdfObjectID((int)item.Field2), (int)item.Field3); Debug.Assert(document._irefTable.Contains(iref.ObjectID)); //document._irefTable.Add(irefNew); } } } } PdfReference[] irefs = document._irefTable.AllReferences; int count = irefs.Length; // Read all indirect objects. for (int idx = 0; idx < count; idx++) { PdfReference iref = irefs[idx]; if (iref.Value == null) { #if DEBUG_ if (iref.ObjectNumber == 1074) { iref.GetType(); } #endif try { Debug.Assert(document._irefTable.Contains(iref.ObjectID)); PdfObject pdfObject = await parser.ReadObjectAsync(null, iref.ObjectID, false, false); Debug.Assert(pdfObject.Reference == iref); pdfObject.Reference = iref; Debug.Assert(pdfObject.Reference.Value != null, "Something went wrong."); } catch (Exception ex) { Debug.WriteLine(ex.Message); // 4STLA rethrow exception to notify caller. throw; } } else { Debug.Assert(document._irefTable.Contains(iref.ObjectID)); //iref.GetType(); } // Set maximum object number. document._irefTable._maxObjectNumber = Math.Max(document._irefTable._maxObjectNumber, iref.ObjectNumber); } // Decrypt all objects. if (xrefEncrypt != null) { document.SecurityHandler.DecryptDocument(); } // Fix references of trailer values and then objects and irefs are consistent. document._trailer.Finish(); #if DEBUG_ // Some tests... PdfReference[] reachables = document.xrefTable.TransitiveClosure(document.trailer); reachables.GetType(); reachables = document.xrefTable.AllXRefs; document.xrefTable.CheckConsistence(); #endif if (openmode == PdfDocumentOpenMode.Modify) { // Create new or change existing document IDs. if (document.Internals.SecondDocumentID == "") { document._trailer.CreateNewDocumentIDs(); } else { byte[] agTemp = Guid.NewGuid().ToByteArray(); document.Internals.SecondDocumentID = PdfEncoders.RawEncoding.GetString(agTemp, 0, agTemp.Length); } // Change modification date document.Info.ModificationDate = DateTime.Now; // Remove all unreachable objects int removed = document._irefTable.Compact(); if (removed != 0) { Debug.WriteLine("Number of deleted unreachable objects: " + removed); } // Force flattening of page tree PdfPages pages = document.Pages; Debug.Assert(pages != null); //bool b = document.irefTable.Contains(new PdfObjectID(1108)); //b.GetType(); document._irefTable.CheckConsistence(); document._irefTable.Renumber(); document._irefTable.CheckConsistence(); } } #if !DEBUG catch (Exception ex) { Debug.WriteLine(ex.Message); throw; } #endif return(document); }
/// <summary> /// Opens an existing PDF document. /// </summary> public static PdfDocument Open(Stream stream, string password, PdfDocumentOpenMode openmode, PdfPasswordProvider passwordProvider) { PdfDocument document = null; try { Lexer lexer = new Lexer(stream); document = new PdfDocument(lexer); document.state |= DocumentState.Imported; document.openMode = openmode; document.fileSize = stream.Length; // Get file version byte[] header = new byte[1024]; stream.Position = 0; stream.Read(header, 0, 1024); document.version = GetPdfFileVersion(header); if (document.version == 0) { throw new InvalidOperationException(PSSR.InvalidPdf); } // Read all trailers document.irefTable.IsUnderConstruction = true; Parser parser = new Parser(document); document.trailer = parser.ReadTrailer(); document.irefTable.IsUnderConstruction = false; // Is document encrypted? PdfReference xrefEncrypt = document.trailer.Elements[PdfTrailer.Keys.Encrypt] as PdfReference; if (xrefEncrypt != null) { //xrefEncrypt.Value = parser.ReadObject(null, xrefEncrypt.ObjectID, false); PdfObject encrypt = parser.ReadObject(null, xrefEncrypt.ObjectID, false); encrypt.Reference = xrefEncrypt; xrefEncrypt.Value = encrypt; PdfStandardSecurityHandler securityHandler = document.SecurityHandler; TryAgain: PasswordValidity validity = securityHandler.ValidatePassword(password); if (validity == PasswordValidity.Invalid) { if (passwordProvider != null) { PdfPasswordProviderArgs args = new PdfPasswordProviderArgs(); passwordProvider(args); if (args.Abort) { return(null); } password = args.Password; goto TryAgain; } else { if (password == null) { throw new PdfReaderException(PSSR.PasswordRequired); } else { throw new PdfReaderException(PSSR.InvalidPassword); } } } else if (validity == PasswordValidity.UserPassword && openmode == PdfDocumentOpenMode.Modify) { if (passwordProvider != null) { PdfPasswordProviderArgs args = new PdfPasswordProviderArgs(); passwordProvider(args); if (args.Abort) { return(null); } password = args.Password; goto TryAgain; } else { throw new PdfReaderException(PSSR.OwnerPasswordRequired); } } } else { if (password != null) { // Password specified but document is not encrypted. // ignore } } PdfReference[] irefs = document.irefTable.AllReferences; int count = irefs.Length; // Read all indirect objects for (int idx = 0; idx < count; idx++) { PdfReference iref = irefs[idx]; if (iref.Value == null) { try { Debug.Assert(document.irefTable.Contains(iref.ObjectID)); PdfObject pdfObject = parser.ReadObject(null, iref.ObjectID, false); Debug.Assert(pdfObject.Reference == iref); pdfObject.Reference = iref; Debug.Assert(pdfObject.Reference.Value != null, "something got wrong"); } catch (Exception ex) { Debug.WriteLine(ex.Message); } } else { Debug.Assert(document.irefTable.Contains(iref.ObjectID)); iref.GetType(); } // Set maximum object number document.irefTable.maxObjectNumber = Math.Max(document.irefTable.maxObjectNumber, iref.ObjectNumber); } // Encrypt all objects if (xrefEncrypt != null) { document.SecurityHandler.EncryptDocument(); } // Fix references of trailer values and then objects and irefs are consistent. document.trailer.Finish(); #if DEBUG_ // Some tests... PdfReference[] reachables = document.xrefTable.TransitiveClosure(document.trailer); reachables.GetType(); reachables = document.xrefTable.AllXRefs; document.xrefTable.CheckConsistence(); #endif if (openmode == PdfDocumentOpenMode.Modify) { // Create new or change existing document IDs if (document.Internals.SecondDocumentID == "") { document.trailer.CreateNewDocumentIDs(); } else { byte[] agTemp = Guid.NewGuid().ToByteArray(); document.Internals.SecondDocumentID = PdfEncoders.RawEncoding.GetString(agTemp, 0, agTemp.Length); } // Change modification date document.Info.ModificationDate = DateTime.Now; // Remove all unreachable objects int removed = document.irefTable.Compact(); if (removed != 0) { Debug.WriteLine("Number of deleted unreachable objects: " + removed.ToString()); } // Force flattening of page tree PdfPages pages = document.Pages; //bool b = document.irefTable.Contains(new PdfObjectID(1108)); //b.GetType(); document.irefTable.CheckConsistence(); document.irefTable.Renumber(); document.irefTable.CheckConsistence(); } } finally { //if (filestream != null) // filestream.Close(); } return(document); }
public int Open(ref string errorMsg) { int result = Constants.Failure; int cryptoMode = 0; try { PdfReader pdfReader = new PdfReader(Info.FullName, out encryptionRecordInfo.pdfVersion, out encryptionRecordInfo.documentID, out encryptionRecordInfo.uValue, out encryptionRecordInfo.oValue, out encryptionRecordInfo.pValue, out encryptionRecordInfo.rValue, out cryptoMode, out encryptionRecordInfo.isEncrypted, out encryptionRecordInfo.keyLength); if (encryptionRecordInfo.isEncrypted && (encryptionRecordInfo.uValue == null || encryptionRecordInfo.oValue == null)) { errorMsg = "PDF encryption type not supported."; } else if (encryptionRecordInfo.isEncrypted) { //When using AES encryption, the option is available to refrain from encrypting the metadata. encryptionRecordInfo.metadataIsEncrypted = (cryptoMode & PdfWriter.DO_NOT_ENCRYPT_METADATA) != PdfWriter.DO_NOT_ENCRYPT_METADATA; if ((cryptoMode & PdfWriter.ENCRYPTION_MASK) == PdfWriter.STANDARD_ENCRYPTION_40) { encryptionRecordInfo.encryptionType = PdfEncryptionType.StandardEncryption40Bit; encryptionRecordInfo.metadataIsEncrypted = true; } else if ((cryptoMode & PdfWriter.ENCRYPTION_MASK) == PdfWriter.STANDARD_ENCRYPTION_128) { encryptionRecordInfo.encryptionType = PdfEncryptionType.StandardEncryption128Bit; encryptionRecordInfo.metadataIsEncrypted = true; } else if ((cryptoMode & PdfWriter.ENCRYPTION_MASK) == PdfWriter.ENCRYPTION_AES_128) { encryptionRecordInfo.encryptionType = PdfEncryptionType.AesEncryption128Bit; } else if ((cryptoMode & PdfWriter.ENCRYPTION_MASK) == PdfWriter.ENCRYPTION_AES_256) { encryptionRecordInfo.encryptionType = PdfEncryptionType.AesEncryption256Bit; encryptionRecordInfo.MaxPasswordSize = Constants.MaxPasswordSizeV2; encryptionRecordInfo.PasswordCharset = CharsetEncoding.Unicode; } else if ((cryptoMode & PdfWriter.ENCRYPTION_MASK) == PdfWriter.ENCRYPTION_AES_256_ISO) { encryptionRecordInfo.encryptionType = PdfEncryptionType.AesIsoEncryption256Bit; encryptionRecordInfo.MaxPasswordSize = Constants.MaxPasswordSizeV2; encryptionRecordInfo.PasswordCharset = CharsetEncoding.Unicode; } IDecryptor pdfDecryptor = DecryptorFactory.Get(EncryptionRecordInfo); PasswordValidity passwordValidity = pdfDecryptor.ValidatePassword(string.Empty, ValidationMode.ValidateUserPassword | ValidationMode.ValidateOwnerPassword); UserPasswordIsSet = (passwordValidity & PasswordValidity.UserPasswordIsValid) != PasswordValidity.UserPasswordIsValid; OwnerPasswordIsSet = (passwordValidity & PasswordValidity.OwnerPasswordIsValid) != PasswordValidity.OwnerPasswordIsValid; } result = Constants.Success; } catch (Exception ex) { errorMsg = ex.Message; } return(result); }