Open encrypted PDF file by trying passwords from a word list












5












$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$












  • $begingroup$
    The link to your dictionary gives me a 404 page.
    $endgroup$
    – Mast
    5 hours ago










  • $begingroup$
    i fixed the link
    $endgroup$
    – Sandro4912
    5 hours ago
















5












$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$












  • $begingroup$
    The link to your dictionary gives me a 404 page.
    $endgroup$
    – Mast
    5 hours ago










  • $begingroup$
    i fixed the link
    $endgroup$
    – Sandro4912
    5 hours ago














5












5








5


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 22 mins ago









200_success

129k15152415




129k15152415










asked 5 hours ago









Sandro4912Sandro4912

1,037121




1,037121












  • $begingroup$
    The link to your dictionary gives me a 404 page.
    $endgroup$
    – Mast
    5 hours ago










  • $begingroup$
    i fixed the link
    $endgroup$
    – Sandro4912
    5 hours ago


















  • $begingroup$
    The link to your dictionary gives me a 404 page.
    $endgroup$
    – Mast
    5 hours ago










  • $begingroup$
    i fixed the link
    $endgroup$
    – Sandro4912
    5 hours ago
















$begingroup$
The link to your dictionary gives me a 404 page.
$endgroup$
– Mast
5 hours ago




$begingroup$
The link to your dictionary gives me a 404 page.
$endgroup$
– Mast
5 hours ago












$begingroup$
i fixed the link
$endgroup$
– Sandro4912
5 hours ago




$begingroup$
i fixed the link
$endgroup$
– Sandro4912
5 hours ago










1 Answer
1






active

oldest

votes


















6












$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$













    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









    6












    $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$


















      6












      $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$
















        6












        6








        6





        $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 5 hours ago









        ratchet freakratchet freak

        11.8k1341




        11.8k1341






























            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

            Polycentropodidae

            Magento 2 Error message: Invalid state change requested

            Paulmy