create a list of word strings by reading this file. Then loop over each word in this list, passing it to the decrypt() method. If this method returns the integer 0, the password was wrong and your program should continue to the next password. If decrypt() returns 1, then your program should break out of the loop and print the hacked password. You should try both the uppercase and lower-case form of each word.
This dictionary.txt file contains words in capital letters.
> import PyPDF2
pdfFile = open('reverse.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFile)
pdfWriter = PyPDF2.PdfFileWriter()
for pageNum in range(pdfReader.numPages):
pdfWriter.addPage(pdfReader.getPage(pageNum))
wrd = input('Please enter one word as a password: ')
pdfWriter.encrypt(wrd)
resultPdf = open('encryptedreverse.pdf', 'wb')
pdfWriter.write(resultPdf)
resultPdf.close()
print(pdfReader.isEncrypted)
helloDict = open('dictionary.txt')
helloDictCont = helloDict.read().splitlines()
liDict = []
for word in helloDictCont:
liDict.extend(word.split())
PdfFile2 = open('encryptedreverse.pdf', 'rb')
pdfReader2 = PyPDF2.PdfFileReader(PdfFile2)
print(pdfReader2.isEncrypted)
for word in liDict:
if pdfReader2.decrypt(word) == 1:
break
print(word)
elif pdfReader2.decrypt(word.lower()) == 1:
break
print(word)
After a few minutes processing ends and I neither get a password printed nor the pdf file is decrypted. Any idea what am I doing wrong?
This works fine for me:
import PyPDF2
pdfFile = open('reverse.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFile)
pdfWriter = PyPDF2.PdfFileWriter()
for pageNum in range(pdfReader.numPages):
pdfWriter.addPage(pdfReader.getPage(pageNum))
wrd = input('Please enter one word as a password: ')
pdfWriter.encrypt(wrd)
resultPdf = open('encryptedreverse.pdf', 'wb')
pdfWriter.write(resultPdf)
resultPdf.close()
print(pdfReader.isEncrypted)
helloDict = open('t.txt')
helloDictCont = helloDict.read().splitlines()
liDict = []
for word in helloDictCont:
liDict.extend(word.split())
PdfFile2 = open('encryptedreverse.pdf', 'rb')
pdfReader2 = PyPDF2.PdfFileReader(PdfFile2)
print(pdfReader2.isEncrypted)
for word in liDict:
if pdfReader2.decrypt(word) == 1:
print('The correct PWD as upper case: ' + word)
break
elif pdfReader2.decrypt(word.lower()) == 1:
print('The correct PWD as lower case: ' + word)
break
else:
print('PWD is not correct: ' + word)
Here's my solution:
'''
Brute-Force PDF Password Breaker
Say you have an encrypted PDF that you have forgotten the password to,
but you remember it was a single English word. Trying to guess your forgot-
ten password is quite a boring task. Instead you can write a program that
will decrypt the PDF by trying every possible English word until it finds one
that works. This is called a brute-force password attack. Download the text file
dictionary.txt from https://nostarch.com/automatestuff2/. This dictionary file
contains over 44,000 English words with one word per line.
Using the file-reading skills you learned in Chapter 9, create a list of
word strings by reading this file. Then loop over each word in this list, pass -
ing it to the decrypt() method. If this method returns the integer 0, the pass-
word was wrong and your program should continue to the next password.
If decrypt() returns 1, then your program should break out of the loop and
print the hacked password. You should try both the uppercase and lower-
case form of each word. (On my laptop, going through all 88,000 uppercase
and lowercase words from the dictionary file takes a couple of minutes. This
is why you shouldn’t use a simple English word for your passwords.)
'''
import PyPDF2
import time
import os
import sys
def decrypt():
ok = False
print(f'Working... {time.asctime()}')
start = time.time()
passwords = open(dictionary).read().split('\n')
pdfReader = PyPDF2.PdfFileReader(pdf)
if pdfReader.isEncrypted:
for password in passwords:
if pdfReader.decrypt(password) or pdfReader.decrypt(password.lower()):
print(f'Password: {password}')
ok = True
break
end = time.time()
hours = int((end - start) / 3600)
minutes = int((end - start) / 60)
secondes = int(end - start - (hours * 3600) - (minutes * 60))
if ok:
print(f'Has been decrypted in {hours}H:{minutes}M:{secondes}S!')
else:
print(f'{pdf} hasn\'t been decrypted... Maybe need a better dictionary?')
else:
print(f'{pdf} isn\'t encrypted')
if len(sys.argv) == 3:
dictionary, pdf = sys.argv[1], sys.argv[2]
if os.path.isfile(dictionary) and dictionary.endswith('.txt'):
if os.path.isfile(pdf) and pdf.endswith('.pdf'):
decrypt()
else:
print('Invalid path to pdf or pdf file')
else:
print('Invalid path to dictionary or dictionary file')
else:
print('Please enter arguments as example:\
\ndictionaryName.txt pdfName.pdf')
Related
Code:
import secrets
import sys
import time
import string
from tenacity import (retry , stop_after_attempt)
#Required Defs
var = open('conf.txt','r+')
content = var.read()
print(content)
def get_random_string(length):
letters = string.ascii_lowercase
num = string.ascii_uppercase
punc = string.punctuation
spec = string.hexdigits
one = str(num) + str(punc) + str(spec)
result_str = ''.join(secrets.choice(one) for i in range(length))
print("Random string of length", length, "is:", result_str)
#Closing All Defs Here
#retry(stop=stop_after_attempt(5))
def start():
pasw = input("Do YOu Want A Random Password: y/n: ")
if pasw == 'y':
leng = input("Please Type The Length Of The Password You Want: ")
try:
len1 = int(leng)
get_random_string(len1)
time.sleep(4)
except ValueError:
print("Only Numbers Accepted")
time.sleep(4)
elif pasw == 'n':
sys.exit("You Don't Want TO Run The Program")
time.sleep(3)
else:
raise Exception("Choose Only From 'y' or 'n'")
start()
Problem:
I want to read contents of file called conf.txt and want to include
only 2 chars 3 letters and it is based on conf.txt. How can I achieve
this? Please tell conf.txt contains:
minspec = 1 #This tells take 2 special chars chars
minnumbers = 3 #This tells take 3 Numbers
minletter = 2 #This tells take 2 lower chars
minhex = 2 #This tells take 2 hex numbers
with open('file.txt', 'r') as data:
contents = data.read()
In the above example we are opening file.txt in read mode with the object name data.
We can use data.read() to read the file and store it in the variable name contents.
One of the advantage of using with is that we don't need to close the file, it automatically closes file for you.
For reading only selected bytes for a file object can be used:
the seek method (to change the file object’s position);
the read method has the optional param - number of bytes to read.
Example:
f = open('workfile', 'rb') # b'0123456789'
f.read(2) # reading only the first two bytes(b'01')
f.seek(6) # go to the 6th byte in the file
f.read(3) # reading 3 bytes after 6 position(b'678')
Hello this exercise says:
Create a Mad Libs program that reads in text files and lets the user add their own text anywhere the word ADJECTIVE, NOUN, ADVERB, or VERB appears in the text file.
textfile = The ADJECTIVE panda walked to the NOUN and then VERB. A nearby NOUN was
unnafected by these events.
What I have so far is :
import re
#filename = input('Input the Filename: ')
with open('madlibs.txt') as file:
content = file.read()
file.close()
regex = re.compile(r'ADJECTIVE|NOUN|VERB|ADVERB')
#regex = re.compile('[A-Z]{3,}')
matches = regex.findall(content)
#newWord = []
for word in matches:
user_input = input('Enter %s: ' % word)
# newWord.append(user_input)
new_content = content.replace(word,user_input,1)
print(new_content)
My input is:
Enter ADJECTIVE: heavy
Enter NOUN: whale
Enter VERB: runs
Enter NOUN: door
And my output:
The ADJECTIVE panda walked to the door and then VERB. A nearby door was
unnafected by these events.
Can someone explain to me what I'm doing wrong? It seems that I can't change ADJECTIVE and VERB for some reason, i also tried the commented regex with uppercase and it does the same so the problem is somewhere else.
You need to change content, but because you aren't, it's overwriting your changes until the very last word:
for word in matches:
user_input = input('Enter %s: ' % word)
content = content.replace(word,user_input) # overwrite content here
print(content)
Or, if you prefer to keep content the same:
new_content = content
for word in matches:
user_input = input('Enter %s: ' % word)
new_content = new_content.replace(word,user_input) # overwrite new_content here
print(new_content)
Strings in python are immutable, meaning that they will not be changed in-place, and instead must be re-assigned:
somestring = "this is a string"
for word in ["is", "a"]:
newstring = somestring.replace(word, "aaaa")
print(newstring)
# this is aaaa string
print(somestring)
# this is a string
Note that somestring is still the original value. The first replace did happen, it just was overwritten when the result of somestring.replace("a", "aaaa") was reassigned.
Broken into steps:
somestring = "this is a string"
newstring = somestring.replace("is", "aaaa")
# this aaaa a string
newstring = somestring.replace("a", "aaaa")
# this is aaaa string
#! /usr/bin/python3
# mad_libs.py - Playing mad libs game
# Usage: python3 mad_libs.py save - Save a mad lib phrase from clip board
# python3 mad_libs.py - Play the mad libs game.
# Caution: Must save at least one phrase before playing.
import shelve, pyclip, random, sys, re
import pyinputplus as pyi
# Open shelve file
shelfFile = shelve.open('mad_libs')
# Add phrase to the database by pasting from clipboard
if len(sys.argv) == 2 and sys.argv[1] == 'save':
shelfFile[str(len(shelfFile))] = pyclip.paste().decode()
print("Phrase saved.")
sys.exit()
# Get a random phrase from database and display
phrase = shelfFile[str(random.randrange(len(shelfFile)))]
# Regex for finding match
matLibsRegex = re.compile(r'(ADJECTIVE)|(NOUN)|(VERB)|(ADVERB)')
print(phrase)
while True:
# Find all the matches and replace with user's input
match = matLibsRegex.search(phrase)
if match == None: # Return None if there is no match
break
prompt = f"Enter an {match.group().lower()}: " if match.group(
)[0] in 'Aa' else f"Enter a {match.group().lower()}: "
substitute = pyi.inputStr(prompt)
phrase = phrase.replace(match.group(), substitute, 1) # Replace the fill-in space with user's input
# Print the final phrase and save it to file
print(phrase)
result = open('mad_libs_result.txt', 'a')
result.write(phrase + '\n')
result.close()
shelfFile.close()
I hope this could enhance your code.
Since this post is about mad libs and I would like to drop my solutions here for upcoming learners. I combine the functionality of Mad Libs exercise and Extend Multi-Clipbaord exercise.
I am trying to create a Password Generator. The program is supposed to generate a List of random passwords and then write them to a .txt file. With the code below, the program is only writing the last password generated, rather than all of them.
#!/usr/bin/python3
import random
#The Characters List
Characters = "abcdefghijklmnopqrstuvwxyz!##$%^&*()_+-=[];'\,./ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
#Password Generator
#Get the Input form the User
Length = input("Password Length > ")
Length = int(Length)
#Get the Input form the User
PasswordNumber = input("Number of Passwords > ")
PasswordNumber = int(PasswordNumber)
for p in range(PasswordNumber):
Password = ""
for i in range(Length):
Password += random.choice(Characters)
print(Password)
f= open("PasswordList.txt","w+")
f.write(Password)
f.close()
My results:
Password Length > 10
Number of Passwords > 5
LgoQ$i%e_O
![i/NxsqQr
n-ydWA/9.5
ksI,jg]#8q
![xrU#=2##
But when I open the "PasswordList.txt" the text that is inside is only: ![xrU#=2##, the last password it generated.
Also I want the passwords to have the same format as seen on the terminal:
LgoQ$i%e_O
![i/NxsqQr
n-ydWA/9.5
ksI,jg]#8q
![xrU#=2##
and not like this:
LgoQ$i%e_O![i/NxsqQrn-ydWA/9.5ksI,jg]#8q![xrU#=2##
You get only one password because that's what you told it to do: generate and print out all the passwords. Once they're all generated, then you write only one password to the file.
You need to pull that print statement into your loop:
f = open("PasswordList.txt","w+")
for p in range(PasswordNumber):
Password = ""
for i in range(Length):
Password += random.choice(Characters)
print(Password)
f.write(Password + "\n")
f.close()
To get the same format, simply add a newline to each write, or use the writeln method.
Sample output, with 10 passwords of length 8:
w#wz+]S2
8t=G#r,F
H$aITs0&
=dMbird6
Y)Dpu]EZ
K\ZDNI*M
L6(2L_7_
VJL3GxF$
.nRt!XIa
=OXP8=aC
I am currently trying to learn Python. I know some basics and I'm trying to practise by making a game. My code so far is:
import time
import datetime
now = datetime.datetime.now()
name = input('What is your name? >> ')
file = open("users.txt","+w")
file.write(name + ' started playing at: ' + now.strftime("%Y-%m-%d %H:%M") + '. \n')
file.close()
account = input('Do you have an account ' + name + '? >> ')
while(account != 'yes'):
if(account == 'no'):
break
account = input('Sorry, I did not understand. Please input yes/no >> ')
if(account == 'yes'):
login = input('Login >>')
passwd = input('Password >>')
if login in open('accounts.txt').read():
if passwd in open('accounts.txt').read():
print('Login Successful ' + login + '!')
else:
print('Password incorrect! The password you typed in is ' + passwd + '.')
else:
print('Login incorrect! The login you typed in is ' + login + '.')
As you probably noticed I am working on a login system. Now please ignore all the bugs and inefficient code etc. I want to focus on how I can get Python to check for a line in a .txt file and, if it's there, check the one below.
My .txt file is:
loggn
pass
__________
I want to make the program multi-account. This is why I am using a .txt file. If you need me to clarify anything, please ask. Thankyou! :)
with open('filename') as f:
for line in f:
if line.startswith('something'):
firstline = line.strip() # strip() removes whitespace surrounding the line
secondline = next(f).strip() # f is an iterator, you can call the next object with next.
Store the results of "open('accounts.txt').read()" yourself, and iterate over them as an array - if you know what line number you are on, it is trivial to check the next. Assuming that every even numbered line is a login, and every odd numbered line is a password, you would have something like this:
success = False
# Storing the value in a variable keeps from reading the file twice
lines = open('account.txt').readlines()
# This removes the newlines at the end of each line
lines = [line.strip() for line in lines]
# Iterate through the number of lines
for idx in range(0, len(lines)):
# Skip password lines
if idx % 2 != 0:
continue
# Check login
if lines[idx] == login:
# Check password
if lines[idx + 1] == password:
success = True
break
if success:
print('Login success!')
else:
print('Login failure')
You may also consider changing your file format: using something that won't occur in the login name (such as a colon, unprintable ASCII character, tab, or similar) followed by the password for each line means you could use your original approach by just checking for (login + "\t" + password) for each line, rather than having to worry about having two lines.
I am able to open the rules file and create a dictionary to use for my encryption. I have to also create a dictionary to use for decrypting text. I assume it's basically the same function with minor changes. The encrypt works fine, but I can't get the decrypt to work. My second problem is that while I encrypted the file I took out all spaces and punctuation. I can't figure out how to get those back in the output file once I run the program. It just prints in a single column. Lastly I have to output this to a .txt file. I am able to create a .txt with a user assigned name, but can't get anything to print on the file.
Here is what I achieved so far.
#import clauses
import string
#function definitions
#encrypt dictionary
def createrulesdictencrypt(openFile):
rulesencrypt1 = {}
for line in openFile:
rulessplit = string.split(string.strip(line))
rulesencrypt1[rulessplit[0]] = rulessplit[1]
return rulesencrypt1
#decrypt dictionary
def createrulesdictdecrypt(openFile):
rulesdecrypt1 = {}
for line in openFile:
rulessplit = string.split(string.strip(line))
rulesdecrypt1[rulessplit[1]] = rulessplit[0]
return rulesdecrypt1
openFile = open('rules.txt', 'r')
rulesencrypt = createrulesdictencrypt(openFile)
rulesdecrypt = createrulesdictdecrypt(openFile)
#print rulesencrypt
#print rulesdecrypt
#function for encrypting file
def encryptfile(openFile2):
for line in openFile2:
for word in line.split():
empty = ''
for char in word:
if char not in string.punctuation:
char=char.lower()
empty = empty+char
if len(empty) == 2:
print rulesencrypt[empty]
empty = ''
if len(empty) == 1:
print rulesencrypt[empty]
#function for decrypting file
def decryptfile(openFile2):
for line in openFile2:
for word in line.split():
empty = ''
for char in word:
if char not in string.punctuation:
char=char.lower()
empty = empty+char
if len(empty) == 2:
print rulesdecrypt[empty]
empty = ''
if len(empty) == 1:
print rulesdecrypt[empty]
#main program
ende = raw_input("To encrypt a file, enter '0':\nTo decrypt a file, enter '1':")
filename = raw_input("Enter the name of the file to be processed:")
outfilename = raw_input("Enter the name of the file to save the result to:")
openFile2 = open(filename, 'r')
outputfile = open(outfilename, 'w')
fileencrypt = encryptfile(openFile2)
filedecrypt = decryptfile(openFile2)
if ende == "0":
print encryptfile(fileencrypt)
if ende == "1":
print decryptfile(filedecrypt)
This is what I am trying to encrypt
Sir Robin: "Oh, you liars!"
Minstrel: [singing] "Bravely taking to his feet, he beat a very brave
retreat. A brave retreat by brave Sir Robin."
Your first problem is that you're not actually writing your encrypted text to a file, instead you're just printing it to sys.stdout. Incidentally, print appends a \n to it's output by default.
You could rewrite your decrypt function as follows:
#function for decrypting file
def decryptfile(openFile2, outfile): # <- CHANGED to add outfile
for line in openFile2:
for word in line.split():
empty = ''
for char in word:
if char not in string.punctuation:
char=char.lower()
empty = empty+char
if len(empty) == 2:
outfile.write(rulesdecrypt[empty]) # <- CHANGED to write to file
empty = ''
if len(empty) == 1:
outfile.write(rulesdecrypt[empty]) # <- CHANGED to write to file
You will then need to invoke the decryptfile function with a file as its second argument. A similar change could be made to the encryptfile function.
With respect to punctuation and whitespace, either encrypt it or just leave it in place. Once you've removed it, there really isn't a good way to replace it.