Open encrypted PDF file by trying passwords from a word list












6












$begingroup$


As an exercise, I wrote a program to decrypt a PDF file. The only thing that is known about the encryption password is that it is a single English word (all capital or lowercase).



The program uses a dictionary file containing over 45000 words to unlock the file. It looks like this:



dictionary.txt



AARHUS
AARON
ABABA
ABACK
ABAFT
ABANDON
ABANDONED
ABANDONING
ABANDONMENT
ABANDONS
ABASE
ABASED
ABASEMENT
ABASEMENTS
ABASES
ABASH
ABASHED
ABASHES

ZEROTH
ZEST
ZEUS
ZIEGFELD
ZIEGFELDS
ZIEGLER
ZIGGY
ZIGZAG
ZILLIONS
ZIMMERMAN
ZINC
ZION
ZIONISM
ZIONIST
ZIONISTS
ZIONS
ZODIAC
ZOE
ZOMBA
ZONAL
ZONALLY
ZONE
ZONED
ZONES
ZONING
ZOO
ZOOLOGICAL
ZOOLOGICALLY
ZOOM
ZOOMS
ZOOS
ZORN
ZOROASTER
ZOROASTRIAN
ZULU
ZULUS
ZURICH


pdf_password_breaker



"""
Brute force password breaker using a dictionary containing
English words.
"""

import sys
import PyPDF2
from pathlib import Path

def get_filename_from_user() -> Path:
"""Asks for a path from the User"""
while True:
filename: str = input("Enter filename in folder of script:")
path: Path = Path(sys.path[0], filename)

if path.is_file():
return path.as_posix()
print("File doesn't existn")


def decrypt(pdf_filename: Path, password: str) -> bool:
"""
Try to decrypt a file. If not successful a false is returned.
If the file passed is not encrypted also a false is passed
"""
with open(pdf_filename, 'rb') as pdf_file:
pdf_reader = PyPDF2.PdfFileReader(pdf_file)
pdf_reader.decrypt(password)
pdf_writer = PyPDF2.PdfFileWriter()

try:
for page_number in range(pdf_reader.numPages):
pdf_writer.addPage(pdf_reader.getPage(page_number))
except PyPDF2.utils.PdfReadError:
return False

new_name: str = pdf_filename.stem + "_decrypted.pdf"
filename_decrypted = pdf_filename.parent / new_name

with open(filename_decrypted, 'wb') as pdf_file_decrypted:
pdf_writer.write(pdf_file_decrypted)
return True


def break_encryption(pdf_filename: Path, dictionary_filename: str) -> bool:
"""Try's out words from a dictionary to break encryption"""
with open(dictionary_filename, 'r') as dictionary_file:
keyword: str = dictionary_file.readline().strip()

if decrypt(pdf_filename, keyword):
return keyword
if decrypt(pdf_filename, keyword.lower()):
return keyword.lower()

while keyword:
keyword = dictionary_file.readline().strip()

if decrypt(pdf_filename, keyword):
return keyword
if decrypt(pdf_filename, keyword.lower()):
return keyword.lower()
return None


def pdf_password_breaker():
"""main loop"""
filename: Path = get_filename_from_user()
password: str = break_encryption(filename, "dictionary.txt")

if password:
print("File unlocked. Password was:" + password)
return
print("File could not be unlocked")

if __name__ == "__main__":
pdf_password_breaker()


I tried a file with a simple password like "hello". It works but it takes a lot of time until it reaches the "hello" in the file.



I wonder if theres a way to improve the speed, or any other aspect of the code.










share|improve this question











$endgroup$

















    6












    $begingroup$


    As an exercise, I wrote a program to decrypt a PDF file. The only thing that is known about the encryption password is that it is a single English word (all capital or lowercase).



    The program uses a dictionary file containing over 45000 words to unlock the file. It looks like this:



    dictionary.txt



    AARHUS
    AARON
    ABABA
    ABACK
    ABAFT
    ABANDON
    ABANDONED
    ABANDONING
    ABANDONMENT
    ABANDONS
    ABASE
    ABASED
    ABASEMENT
    ABASEMENTS
    ABASES
    ABASH
    ABASHED
    ABASHES

    ZEROTH
    ZEST
    ZEUS
    ZIEGFELD
    ZIEGFELDS
    ZIEGLER
    ZIGGY
    ZIGZAG
    ZILLIONS
    ZIMMERMAN
    ZINC
    ZION
    ZIONISM
    ZIONIST
    ZIONISTS
    ZIONS
    ZODIAC
    ZOE
    ZOMBA
    ZONAL
    ZONALLY
    ZONE
    ZONED
    ZONES
    ZONING
    ZOO
    ZOOLOGICAL
    ZOOLOGICALLY
    ZOOM
    ZOOMS
    ZOOS
    ZORN
    ZOROASTER
    ZOROASTRIAN
    ZULU
    ZULUS
    ZURICH


    pdf_password_breaker



    """
    Brute force password breaker using a dictionary containing
    English words.
    """

    import sys
    import PyPDF2
    from pathlib import Path

    def get_filename_from_user() -> Path:
    """Asks for a path from the User"""
    while True:
    filename: str = input("Enter filename in folder of script:")
    path: Path = Path(sys.path[0], filename)

    if path.is_file():
    return path.as_posix()
    print("File doesn't existn")


    def decrypt(pdf_filename: Path, password: str) -> bool:
    """
    Try to decrypt a file. If not successful a false is returned.
    If the file passed is not encrypted also a false is passed
    """
    with open(pdf_filename, 'rb') as pdf_file:
    pdf_reader = PyPDF2.PdfFileReader(pdf_file)
    pdf_reader.decrypt(password)
    pdf_writer = PyPDF2.PdfFileWriter()

    try:
    for page_number in range(pdf_reader.numPages):
    pdf_writer.addPage(pdf_reader.getPage(page_number))
    except PyPDF2.utils.PdfReadError:
    return False

    new_name: str = pdf_filename.stem + "_decrypted.pdf"
    filename_decrypted = pdf_filename.parent / new_name

    with open(filename_decrypted, 'wb') as pdf_file_decrypted:
    pdf_writer.write(pdf_file_decrypted)
    return True


    def break_encryption(pdf_filename: Path, dictionary_filename: str) -> bool:
    """Try's out words from a dictionary to break encryption"""
    with open(dictionary_filename, 'r') as dictionary_file:
    keyword: str = dictionary_file.readline().strip()

    if decrypt(pdf_filename, keyword):
    return keyword
    if decrypt(pdf_filename, keyword.lower()):
    return keyword.lower()

    while keyword:
    keyword = dictionary_file.readline().strip()

    if decrypt(pdf_filename, keyword):
    return keyword
    if decrypt(pdf_filename, keyword.lower()):
    return keyword.lower()
    return None


    def pdf_password_breaker():
    """main loop"""
    filename: Path = get_filename_from_user()
    password: str = break_encryption(filename, "dictionary.txt")

    if password:
    print("File unlocked. Password was:" + password)
    return
    print("File could not be unlocked")

    if __name__ == "__main__":
    pdf_password_breaker()


    I tried a file with a simple password like "hello". It works but it takes a lot of time until it reaches the "hello" in the file.



    I wonder if theres a way to improve the speed, or any other aspect of the code.










    share|improve this question











    $endgroup$















      6












      6








      6


      1



      $begingroup$


      As an exercise, I wrote a program to decrypt a PDF file. The only thing that is known about the encryption password is that it is a single English word (all capital or lowercase).



      The program uses a dictionary file containing over 45000 words to unlock the file. It looks like this:



      dictionary.txt



      AARHUS
      AARON
      ABABA
      ABACK
      ABAFT
      ABANDON
      ABANDONED
      ABANDONING
      ABANDONMENT
      ABANDONS
      ABASE
      ABASED
      ABASEMENT
      ABASEMENTS
      ABASES
      ABASH
      ABASHED
      ABASHES

      ZEROTH
      ZEST
      ZEUS
      ZIEGFELD
      ZIEGFELDS
      ZIEGLER
      ZIGGY
      ZIGZAG
      ZILLIONS
      ZIMMERMAN
      ZINC
      ZION
      ZIONISM
      ZIONIST
      ZIONISTS
      ZIONS
      ZODIAC
      ZOE
      ZOMBA
      ZONAL
      ZONALLY
      ZONE
      ZONED
      ZONES
      ZONING
      ZOO
      ZOOLOGICAL
      ZOOLOGICALLY
      ZOOM
      ZOOMS
      ZOOS
      ZORN
      ZOROASTER
      ZOROASTRIAN
      ZULU
      ZULUS
      ZURICH


      pdf_password_breaker



      """
      Brute force password breaker using a dictionary containing
      English words.
      """

      import sys
      import PyPDF2
      from pathlib import Path

      def get_filename_from_user() -> Path:
      """Asks for a path from the User"""
      while True:
      filename: str = input("Enter filename in folder of script:")
      path: Path = Path(sys.path[0], filename)

      if path.is_file():
      return path.as_posix()
      print("File doesn't existn")


      def decrypt(pdf_filename: Path, password: str) -> bool:
      """
      Try to decrypt a file. If not successful a false is returned.
      If the file passed is not encrypted also a false is passed
      """
      with open(pdf_filename, 'rb') as pdf_file:
      pdf_reader = PyPDF2.PdfFileReader(pdf_file)
      pdf_reader.decrypt(password)
      pdf_writer = PyPDF2.PdfFileWriter()

      try:
      for page_number in range(pdf_reader.numPages):
      pdf_writer.addPage(pdf_reader.getPage(page_number))
      except PyPDF2.utils.PdfReadError:
      return False

      new_name: str = pdf_filename.stem + "_decrypted.pdf"
      filename_decrypted = pdf_filename.parent / new_name

      with open(filename_decrypted, 'wb') as pdf_file_decrypted:
      pdf_writer.write(pdf_file_decrypted)
      return True


      def break_encryption(pdf_filename: Path, dictionary_filename: str) -> bool:
      """Try's out words from a dictionary to break encryption"""
      with open(dictionary_filename, 'r') as dictionary_file:
      keyword: str = dictionary_file.readline().strip()

      if decrypt(pdf_filename, keyword):
      return keyword
      if decrypt(pdf_filename, keyword.lower()):
      return keyword.lower()

      while keyword:
      keyword = dictionary_file.readline().strip()

      if decrypt(pdf_filename, keyword):
      return keyword
      if decrypt(pdf_filename, keyword.lower()):
      return keyword.lower()
      return None


      def pdf_password_breaker():
      """main loop"""
      filename: Path = get_filename_from_user()
      password: str = break_encryption(filename, "dictionary.txt")

      if password:
      print("File unlocked. Password was:" + password)
      return
      print("File could not be unlocked")

      if __name__ == "__main__":
      pdf_password_breaker()


      I tried a file with a simple password like "hello". It works but it takes a lot of time until it reaches the "hello" in the file.



      I wonder if theres a way to improve the speed, or any other aspect of the code.










      share|improve this question











      $endgroup$




      As an exercise, I wrote a program to decrypt a PDF file. The only thing that is known about the encryption password is that it is a single English word (all capital or lowercase).



      The program uses a dictionary file containing over 45000 words to unlock the file. It looks like this:



      dictionary.txt



      AARHUS
      AARON
      ABABA
      ABACK
      ABAFT
      ABANDON
      ABANDONED
      ABANDONING
      ABANDONMENT
      ABANDONS
      ABASE
      ABASED
      ABASEMENT
      ABASEMENTS
      ABASES
      ABASH
      ABASHED
      ABASHES

      ZEROTH
      ZEST
      ZEUS
      ZIEGFELD
      ZIEGFELDS
      ZIEGLER
      ZIGGY
      ZIGZAG
      ZILLIONS
      ZIMMERMAN
      ZINC
      ZION
      ZIONISM
      ZIONIST
      ZIONISTS
      ZIONS
      ZODIAC
      ZOE
      ZOMBA
      ZONAL
      ZONALLY
      ZONE
      ZONED
      ZONES
      ZONING
      ZOO
      ZOOLOGICAL
      ZOOLOGICALLY
      ZOOM
      ZOOMS
      ZOOS
      ZORN
      ZOROASTER
      ZOROASTRIAN
      ZULU
      ZULUS
      ZURICH


      pdf_password_breaker



      """
      Brute force password breaker using a dictionary containing
      English words.
      """

      import sys
      import PyPDF2
      from pathlib import Path

      def get_filename_from_user() -> Path:
      """Asks for a path from the User"""
      while True:
      filename: str = input("Enter filename in folder of script:")
      path: Path = Path(sys.path[0], filename)

      if path.is_file():
      return path.as_posix()
      print("File doesn't existn")


      def decrypt(pdf_filename: Path, password: str) -> bool:
      """
      Try to decrypt a file. If not successful a false is returned.
      If the file passed is not encrypted also a false is passed
      """
      with open(pdf_filename, 'rb') as pdf_file:
      pdf_reader = PyPDF2.PdfFileReader(pdf_file)
      pdf_reader.decrypt(password)
      pdf_writer = PyPDF2.PdfFileWriter()

      try:
      for page_number in range(pdf_reader.numPages):
      pdf_writer.addPage(pdf_reader.getPage(page_number))
      except PyPDF2.utils.PdfReadError:
      return False

      new_name: str = pdf_filename.stem + "_decrypted.pdf"
      filename_decrypted = pdf_filename.parent / new_name

      with open(filename_decrypted, 'wb') as pdf_file_decrypted:
      pdf_writer.write(pdf_file_decrypted)
      return True


      def break_encryption(pdf_filename: Path, dictionary_filename: str) -> bool:
      """Try's out words from a dictionary to break encryption"""
      with open(dictionary_filename, 'r') as dictionary_file:
      keyword: str = dictionary_file.readline().strip()

      if decrypt(pdf_filename, keyword):
      return keyword
      if decrypt(pdf_filename, keyword.lower()):
      return keyword.lower()

      while keyword:
      keyword = dictionary_file.readline().strip()

      if decrypt(pdf_filename, keyword):
      return keyword
      if decrypt(pdf_filename, keyword.lower()):
      return keyword.lower()
      return None


      def pdf_password_breaker():
      """main loop"""
      filename: Path = get_filename_from_user()
      password: str = break_encryption(filename, "dictionary.txt")

      if password:
      print("File unlocked. Password was:" + password)
      return
      print("File could not be unlocked")

      if __name__ == "__main__":
      pdf_password_breaker()


      I tried a file with a simple password like "hello". It works but it takes a lot of time until it reaches the "hello" in the file.



      I wonder if theres a way to improve the speed, or any other aspect of the code.







      python performance beginner pdf






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 16 at 22:37









      200_success

      129k15153415




      129k15153415










      asked Jan 16 at 17:25









      Sandro4912Sandro4912

      1,114221




      1,114221






















          1 Answer
          1






          active

          oldest

          votes


















          14












          $begingroup$

          Looking at the documentation of PdfFileReader.decrypt It states that it return 0 if the file fails or 1 if it succeeds.



          You can also use isEncrypted to check if the file was encrypted in the first place.



          So you can turn the loop around. First open the pdf file see if it was encrypted at all and if so try to call decrypt with every password in your dictionary.






          share|improve this answer









          $endgroup$









          • 1




            $begingroup$
            And in doing that, only open the PDF file once - opening it twice for every password is a huge slow down.
            $endgroup$
            – The6P4C
            Jan 16 at 23:38










          • $begingroup$
            i tryed that approach. it got quite a bit faster. but to crack hello it still takes quite some time
            $endgroup$
            – Sandro4912
            Jan 17 at 17:00











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211632%2fopen-encrypted-pdf-file-by-trying-passwords-from-a-word-list%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          14












          $begingroup$

          Looking at the documentation of PdfFileReader.decrypt It states that it return 0 if the file fails or 1 if it succeeds.



          You can also use isEncrypted to check if the file was encrypted in the first place.



          So you can turn the loop around. First open the pdf file see if it was encrypted at all and if so try to call decrypt with every password in your dictionary.






          share|improve this answer









          $endgroup$









          • 1




            $begingroup$
            And in doing that, only open the PDF file once - opening it twice for every password is a huge slow down.
            $endgroup$
            – The6P4C
            Jan 16 at 23:38










          • $begingroup$
            i tryed that approach. it got quite a bit faster. but to crack hello it still takes quite some time
            $endgroup$
            – Sandro4912
            Jan 17 at 17:00
















          14












          $begingroup$

          Looking at the documentation of PdfFileReader.decrypt It states that it return 0 if the file fails or 1 if it succeeds.



          You can also use isEncrypted to check if the file was encrypted in the first place.



          So you can turn the loop around. First open the pdf file see if it was encrypted at all and if so try to call decrypt with every password in your dictionary.






          share|improve this answer









          $endgroup$









          • 1




            $begingroup$
            And in doing that, only open the PDF file once - opening it twice for every password is a huge slow down.
            $endgroup$
            – The6P4C
            Jan 16 at 23:38










          • $begingroup$
            i tryed that approach. it got quite a bit faster. but to crack hello it still takes quite some time
            $endgroup$
            – Sandro4912
            Jan 17 at 17:00














          14












          14








          14





          $begingroup$

          Looking at the documentation of PdfFileReader.decrypt It states that it return 0 if the file fails or 1 if it succeeds.



          You can also use isEncrypted to check if the file was encrypted in the first place.



          So you can turn the loop around. First open the pdf file see if it was encrypted at all and if so try to call decrypt with every password in your dictionary.






          share|improve this answer









          $endgroup$



          Looking at the documentation of PdfFileReader.decrypt It states that it return 0 if the file fails or 1 if it succeeds.



          You can also use isEncrypted to check if the file was encrypted in the first place.



          So you can turn the loop around. First open the pdf file see if it was encrypted at all and if so try to call decrypt with every password in your dictionary.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 16 at 17:31









          ratchet freakratchet freak

          11.9k1343




          11.9k1343








          • 1




            $begingroup$
            And in doing that, only open the PDF file once - opening it twice for every password is a huge slow down.
            $endgroup$
            – The6P4C
            Jan 16 at 23:38










          • $begingroup$
            i tryed that approach. it got quite a bit faster. but to crack hello it still takes quite some time
            $endgroup$
            – Sandro4912
            Jan 17 at 17:00














          • 1




            $begingroup$
            And in doing that, only open the PDF file once - opening it twice for every password is a huge slow down.
            $endgroup$
            – The6P4C
            Jan 16 at 23:38










          • $begingroup$
            i tryed that approach. it got quite a bit faster. but to crack hello it still takes quite some time
            $endgroup$
            – Sandro4912
            Jan 17 at 17:00








          1




          1




          $begingroup$
          And in doing that, only open the PDF file once - opening it twice for every password is a huge slow down.
          $endgroup$
          – The6P4C
          Jan 16 at 23:38




          $begingroup$
          And in doing that, only open the PDF file once - opening it twice for every password is a huge slow down.
          $endgroup$
          – The6P4C
          Jan 16 at 23:38












          $begingroup$
          i tryed that approach. it got quite a bit faster. but to crack hello it still takes quite some time
          $endgroup$
          – Sandro4912
          Jan 17 at 17:00




          $begingroup$
          i tryed that approach. it got quite a bit faster. but to crack hello it still takes quite some time
          $endgroup$
          – Sandro4912
          Jan 17 at 17:00


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211632%2fopen-encrypted-pdf-file-by-trying-passwords-from-a-word-list%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How do I know what Microsoft account the skydrive app is syncing to?

          Grease: Live!

          When does type information flow backwards in C++?