Sorry to waste everybody's time because I don't know python. I use jrnla lot to write journal entries, and a while ago I encrypted a file that I know the password to, but don't know how to use this script (provided by the developer) to decrypt. I realized I had to make it executable to use it (genius right) but then got an error when I used it. Any help would be much appreciated.
Traceback (most recent call last):
File "/home/usr/src/jrnl_decrypt", line 16, in
with open(args.filepath, 'rb') as f:
AttributeError: 'Namespace' object has no attribute 'filepath'
Here's the script. I also found an alternative one in older documentation. It's below the larger script.
import argparse
from Crypto.Cipher import AES
import getpass
import hashlib
import sys
parser = argparse.ArgumentParser()
parser.add_argument("~", help="old-journal-encrypted.txt")
args = parser.parse_args()
pwd = getpass.getpass()
key = hashlib.sha256(pwd.encode('utf-8')).digest()
with open(args.filepath, 'rb') as f:
ciphertext = f.read()
crypto = AES.new(key, AES.MODE_CBC, ciphertext[:16])
plain = crypto.decrypt(ciphertext[16:])
plain = plain.strip(plain[-1:])
plain = plain.decode("utf-8")
print(plain)
# Python script to manually decrypt jrnl files
//Alt script
import hashlib, Crypto.Cipher
key = hashlib.sha256(my_password).digest()
with open("old-journal-encrypted.txt") as f:
cipher = f.read()
crypto = AES.new(key, AES.MODE_CBC, iv = cipher[:16])
plain = crypto.decrypt(cipher[16:])
plain = plain.strip(plain[-1])
plain = plain.decode("utf-8")
First of all: you're not wasting anyone's time. None of us known everything from the beginning ^^
In this line parser.add_argument("~", help="old-journal-encrypted.txt") you are adding your argument as ~, so you may use it as args.~ (if it was the case). That's not intuitive, so try changin that line to parser.add_argument("filepath", help="old-journal-encrypted.txt"). After that try to run the script again.
Edit: you're not setting the value with the 'help parameter', it's just a tooltip. You must pass the value when you call the script I.E: python my_prog.py old-journal-encrypted.txt. Make sure that the file is reacheable as well
Hope this helps you!
P.S: You have an example here in case you still have some doubts (don't hesitate to add a comment as well if that's the case ^^)
Related
Below is a test. When I try to decode the same string for the second time I get a error message and I really have no clue why or where to search for. Please advise.
Error:
Traceback (most recent call last):
File "test.py", line 28, in <module>
telnr_to_string = str(telnr_decrypt, 'utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9e in position 0: invalid start byte
Code:
from Crypto.Cipher import AES
from Crypto.Util.Padding import *
from urllib.request import urlopen
import os
import urllib
import subprocess
import re
import time
import base64
import random
file_key = open("key.txt")
key = file_key.read()
key = key.encode()
file_iv = open("iv.txt")
iv = file_iv.read()
iv = iv.encode()
obj2 = AES.new(key, AES.MODE_CBC, iv)
z=1
while z < 3:
x=''
telnr_decrypt=''
telnr=''
telnr_to_string=''
telnr_cleaned=''
x=(b'\x9e\xde\x98p:\xa3\x04\x92\xb5!2K[\x8e\\\xee')
telnr_decrypt = obj2.decrypt(x)
telnr_to_string = str(telnr_decrypt, 'utf-8')
telnr_cleaned = re.sub("[^0-9]", "", telnr_to_string)
print (telnr_cleaned)
z=z+1
Just move obj2 = AES.new(key, AES.MODE_CBC, iv) into the while loop. Don't worry, cipher objects are not very stateful objects; they don't do much other than to store the key (or, for AES, probably the internal subkeys) and maintain a small buffer. Generally it is therefore a bad idea to reuse or cache them.
If you call encrypt / decrypt multiple times in succession then the methods act as if you would be encrypting one big message. In other words, they allow you to encryption / decrypt in a piecemeal fashion so that message-sized buffers can be avoided. This is not very explicitly documented, but you can see this in figure 2 in the documentation.
For CBC mode it means that the operation is identical to setting the IV to the last block of ciphertext. If the IV is wrong then the first block of plaintext will be randomized. Random bytes do generally not contain valid UTF-8 encoding, which means that decoding to string will (likely) fail.
I am working on an encryption program with Pycryptodome in Python 3. I am trying to encrypt a (byte) string and then decrypt it and verify the MAC tag. When I get to verify it, an error is thrown.
This is the code:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
aes_key = get_random_bytes(24)
aes_cipher = AES.new(aes_key, AES.MODE_GCM)
encrypted, MACtag = aes_cipher.encrypt_and_digest(b"A random thirty two byte string.")
# Imagine this is happening somewhere else
new_aes_cipher = AES.new(aes_key, AES.MODE_GCM, nonce=aes_cipher.nonce)
new_aes_cipher.verify(MACtag)
decrypted = new_aes_cipher.decrypt(encrypted)
And this is the error:
Traceback (most recent call last):
File "aespractice.py", line 10, in <module>
new_aes_cipher.verify(tag)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-
packages/Crypto/Cipher/_mode_gcm.py", line 441, in verify
raise ValueError("MAC check failed")
ValueError: MAC check failed
I've looked at the documentation, and I it looks to me like everything is all right. Why do you think the program is acting this way? Any help would be appreciated.
If you look at the state diagram for authenticated modes:
You see that verify() should be called at the very end, after any decrypt() has taken place.
So, either you invert the calls or you replace them with a combined decrypt_and_verify().
I'm beginning to use CGI with Python.
After running the following piece of code:
#!c:\python34\python.exe
import cgi
print("Content-type: text/html\n\n") #important
def getData():
formData = cgi.FieldStorage()
InputUN = formData.getvalue('username')
InputPC = formData.getvalue('passcode')
TF = open("TempFile.txt", "w")
TF.write(InputUN)
TF.write(InputPC)
TF.close()
if __name__ =="__main__":
LoginInput = getData()
print("cgi worked")
The following error occurs:
Traceback (most recent call last):
File "C:\xampp\htdocs\actual\loginvalues.cgi", line 21, in <module>
LoginInput = getData()
File "C:\xampp\htdocs\actual\loginvalues.cgi", line 16, in getData
TF.write(InputUN)
TypeError: must be str, not None
>>>
I'm trying to write the values, inputted in html, to a text file.
Any help would be appreciated :)
Your calls to getValue() are returning None, meaning the form either didn't contain them, had them set to an empty string, or had them set by name only. Python's CGI module ignores inputs that aren't set to a non-null string.
Works for Python CGI:
mysite.com/loginvalues.cgi?username=myname&pass=mypass
Doesn't work for Python CGI:
mysite.com/loginvalues.cgi?username=&pass= (null value(s))
mysite.com/loginvalues.cgi?username&pass (Python requires the = part.)
To account for this, introduce a default value for when a form element is missing, or handle the None case manually:
TF.write('anonymous' if InputUN is None else InputUN)
TF.write('password' if InputPC is None else InputUN)
As a note, passwords and other private login credentials should never be used in a URL. URLs are not encrypted. Even in HTTPS, the URL is sent in plain text that anyone on the network(s) between you and your users can read.
The only time a URL is ever encrypted is over a tunneled SSH port or an encrypted VPN, but you can't control that, so never bank on it.
This example works fine example:
import hashlib
m = hashlib.md5()
m.update(b"Nobody inspects")
r= m.digest()
print(r)
Now, I want to do the same thing but with a variable: var= "hash me this text, please". How could I do it following the same logic of the example ?
The hash.update() method requires bytes, always.
Encode unicode text to bytes first; what you encode to is a application decision, but if all you want to do is fingerprint text for then UTF-8 is a great choice:
m.update(var.encode('utf8'))
The exception you get when you don't is quite clear however:
>>> import hashlib
>>> hashlib.md5().update('foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Unicode-objects must be encoded before hashing
If you are getting the hash of a file, open the file in binary mode instead:
from functools import partial
hash = hashlib.md5()
with open(filename, 'rb') as binfile:
for chunk in iter(binfile, partial(binfile.read, 2048)):
hash.update(chunk)
print hash.hexdigest()
Try this. Hope it helps.
The variable var has to be utf-8 encoded. If you type in a string i.e. "Donald Duck", the var variable will be b'Donald Duck'. You can then hash the string with hexdigest()
#!/usr/bin/python3
import hashlib
var = input('Input string: ').encode('utf-8')
hashed_var = hashlib.md5(var).hexdigest()
print(hashed_var)
I had the same issue as the OP. I couldn't get either of the previous answers to work for me for some reason, but a combination of both helped come to this solution.
I was originally hashing a string like this;
str = hashlib.sha256(b'hash this text')
text_hashed = str.hexdigest()
print(text_hashed)
Result;d3dba6081b7f171ec5fa4687182b269c0b46e77a78611ad268182d8a8c245b40
My solution to hash a variable;
text = 'hash this text'
str = hashlib.sha256(text.encode('utf-8'))
text_hashed = str.hexdigest()
print(text_hashed)
Result; d3dba6081b7f171ec5fa4687182b269c0b46e77a78611ad268182d8a8c245b40
Given below is the code(not complete yet) I have written to encrypt and decrypt files using python with the pycrypto module.
from Crypto.Hash import SHA256
from Crypto.Cipher import AES
import getpass
class ED(object):
def getfromuser(self,choice):
if choice=='key':
key=getpass.getpass('Enter AES Key (minimum 16 characters): ')
if len(key)<16:
print 'Key entered too short. Please try again.'
self.getfromuser(choice)
key=key+str(8-len(key)%8)*(8-len(key)%8)
return key
if choice=='IV':
IV_seed=raw_input('Enter a seed for the IV: ')
IV=SHA256.new()
IV.update(IV_seed)
IV.digest()
return str(IV)[0:16]
def AESEncrypt(self,key,IV,source,dest):
f=open(source,"r")
fstream=f.read()
f.close()
AES_stream=AES.new(key,AES.MODE_CBC,IV)
AES_encrypted=AES_stream.encrypt(fstream)
with open(dest,"w") as write_file:
write_file.write(AES_encrypted)
def AESDecrypt(self,key,IV,source,dest):
f=open(source,"r")
fstream=f.read()
f.close()
AES_stream=AES.new(key,AES.MODE_CBC,IV)
AES_decrypted=AES_stream.decrypt(fstream)
with open(dest,"w") as write_file:
write_file.write(AES_decrypted)
When I tried to encrypt a JPG file using this I got the following error:
AES_encrypted=AES_stream.encrypt(fstream)
ValueError: Input strings must be a multiple of 16 in length
I tried it on an mp4 file and it worked fine: the encryption and the decryption too.
What is the cause of this error and how do I fix it?
I found the solution. If one does not want the hassle of padding, one can use the CFB (Cipher feedback) mode as follows:
AES_stream=AES.new(key,AES.MODE_CFB,IV)