1
0
Fork 0
mirror of https://github.com/HACKERALERT/Picocrypt.git synced 2024-12-29 19:02:43 +00:00

Update Picocrypt.py

This commit is contained in:
Evan Su 2021-03-21 17:35:29 -04:00 committed by GitHub
parent 25c716fd21
commit d3b68e8beb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,34 +1,17 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Dependencies: argon2-cffi, pycryptodome, reedsolo
Picocrypt v1.11 (Beta)
Dependencies: argon2-cffi, pycryptodome, reedsolo, tkinterdnd2
Copyright (c) Evan Su (https://evansu.cc) Copyright (c) Evan Su (https://evansu.cc)
Released under a GNU GPL v3 License Released under a GNU GPL v3 License
https://github.com/HACKERALERT/Picocrypt https://github.com/HACKERALERT/Picocrypt
~ In cryptography we trust ~
""" """
# Test if libraries are installed
try:
from argon2.low_level import hash_secret_raw
from Crypto.Cipher import ChaCha20_Poly1305
try:
from creedsolo import ReedSolomonError
except:
from reedsolo import ReedSolomonError
except:
# Libraries missing, install them
from os import system
try:
# Debian/Ubuntu based
system("sudo apt-get install python3-tk")
except:
# Fedora
system("sudo dnf install python3-tkinter")
system("python3 -m pip install argon2-cffi --no-cache-dir")
system("python3 -m pip install pycryptodome --no-cache-dir")
system("python3 -m pip install reedsolo --no-cache-dir")
# Imports # Imports
from tkinter import filedialog,messagebox from tkinter import filedialog,messagebox
from threading import Thread from threading import Thread
@ -38,19 +21,15 @@ from Crypto.Cipher import ChaCha20_Poly1305
from Crypto.Hash import SHA3_512 as sha3_512 from Crypto.Hash import SHA3_512 as sha3_512
from secrets import compare_digest from secrets import compare_digest
from os import urandom,fsync,remove,system from os import urandom,fsync,remove,system
from os.path import getsize,expanduser,dirname from os.path import getsize,expanduser,isdir
from os.path import abspath from tkinterdnd2 import TkinterDnD,DND_FILES
from TkinterDnD2 import *
import sys import sys
import tkinter import tkinter
import tkinter.ttk import tkinter.ttk
import tkinter.scrolledtext import tkinter.scrolledtext
import webbrowser import webbrowser
import platform import platform
try:
from creedsolo import RSCodec,ReedSolomonError from creedsolo import RSCodec,ReedSolomonError
except:
from reedsolo import RSCodec,ReedSolomonError
# Tk/Tcl is a little barbaric, so I'm disabling # Tk/Tcl is a little barbaric, so I'm disabling
# high DPI so it doesn't scale bad and look horrible # high DPI so it doesn't scale bad and look horrible
@ -92,11 +71,6 @@ tk.title("Picocrypt")
tk.configure(background="#f5f6f7") tk.configure(background="#f5f6f7")
tk.resizable(0,0) tk.resizable(0,0)
def onDrop(e):
print(e)
tk.drop_target_register(DND_FILES)
tk.dnd_bind("<<Drop>>",onDrop)
# Try setting window icon if included with Picocrypt # Try setting window icon if included with Picocrypt
try: try:
favicon = tkinter.PhotoImage(file="./key.png") favicon = tkinter.PhotoImage(file="./key.png")
@ -109,7 +83,7 @@ s = tkinter.ttk.Style()
s.configure("TCheckbutton",background="#f5f6f7") s.configure("TCheckbutton",background="#f5f6f7")
# Event when user selects an input file # Event when user selects an input file
def inputSelected(): def inputSelected(draggedFile=None):
global inputFile,working,headerRsc global inputFile,working,headerRsc
dummy.focus() dummy.focus()
@ -117,6 +91,7 @@ def inputSelected():
try: try:
# Ask for input file # Ask for input file
suffix = "" suffix = ""
if not draggedFile:
tmp = filedialog.askopenfilename( tmp = filedialog.askopenfilename(
initialdir=expanduser("~") initialdir=expanduser("~")
) )
@ -124,6 +99,8 @@ def inputSelected():
# Exception will be caught by except below # Exception will be caught by except below
raise Exception("No file selected.") raise Exception("No file selected.")
inputFile = tmp inputFile = tmp
else:
inputFile = draggedFile
# Decide if encrypting or decrypting # Decide if encrypting or decrypting
if ".pcv" in inputFile.split("/")[-1]: if ".pcv" in inputFile.split("/")[-1]:
@ -163,6 +140,7 @@ def inputSelected():
cpasswordInput["state"] = "normal" cpasswordInput["state"] = "normal"
cpasswordInput.delete(0,"end") cpasswordInput.delete(0,"end")
cpasswordInput["state"] = "disabled" cpasswordInput["state"] = "disabled"
cpasswordString.set("Confirm password (N/A):")
else: else:
# Update the UI # Update the UI
eraseBtn["state"] = "normal" eraseBtn["state"] = "normal"
@ -174,6 +152,7 @@ def inputSelected():
adLabelString.set(adString) adLabelString.set(adString)
cpasswordInput["state"] = "normal" cpasswordInput["state"] = "normal"
cpasswordInput.delete(0,"end") cpasswordInput.delete(0,"end")
cpasswordString.set("Confirm password:")
# Enable password box, etc. # Enable password box, etc.
inputString.set(inputFile.split("/")[-1]+suffix) inputString.set(inputFile.split("/")[-1]+suffix)
@ -197,6 +176,13 @@ def inputSelected():
dummy.focus() dummy.focus()
working = False working = False
# Allow drag and drop
def onDrop(e):
print(e.data)
inputSelected(e.data)
tk.drop_target_register(DND_FILES)
tk.dnd_bind("<<Drop>>",onDrop)
# Button to select input file # Button to select input file
selectFileInput = tkinter.ttk.Button( selectFileInput = tkinter.ttk.Button(
tk, tk,
@ -304,26 +290,11 @@ def start():
pass pass
# Disable inputs and buttons while encrypting/decrypting # Disable inputs and buttons while encrypting/decrypting
selectFileInput["state"] = "disabled" disableAllInputs()
passwordInput["state"] = "disabled"
cpasswordInput["state"] = "disabled"
adArea["state"] = "disabled"
startBtn["state"] = "disabled"
eraseBtn["state"] = "disabled"
keepBtn["state"] = "disabled"
rsBtn["state"] = "disabled"
# Make sure passwords match # Make sure passwords match
if passwordInput.get()!=cpasswordInput.get() and mode=="encrypt": if passwordInput.get()!=cpasswordInput.get() and mode=="encrypt":
selectFileInput["state"] = "normal" resetEncryptionUI()
passwordInput["state"] = "normal"
cpasswordInput["state"] = "normal"
adArea["state"] = "normal"
startBtn["state"] = "normal"
eraseBtn["state"] = "normal"
rsBtn["state"] = "normal"
working = False
progress["value"] = 100
statusString.set("Passwords don't match.") statusString.set("Passwords don't match.")
return return
@ -433,15 +404,7 @@ def start():
fout.close() fout.close()
remove(outputFile) remove(outputFile)
# Reset UI # Reset UI
selectFileInput["state"] = "normal" resetDecryptionUI()
passwordInput["state"] = "normal"
adArea["state"] = "normal"
startBtn["state"] = "normal"
keepBtn["state"] = "normal"
working = False
progress.stop()
progress.config(mode="determinate")
progress["value"] = 100
return return
else: else:
kept = "badlyCorrupted" kept = "badlyCorrupted"
@ -480,14 +443,7 @@ def start():
fout.close() fout.close()
remove(outputFile) remove(outputFile)
# Reset UI # Reset UI
selectFileInput["state"] = "normal" resetDecryptionUI()
passwordInput["state"] = "normal"
adArea["state"] = "normal"
startBtn["state"] = "normal"
keepBtn["state"] = "normal"
working = False
progress["value"] = 100
del key
return return
# Create XChaCha20-Poly1305 object # Create XChaCha20-Poly1305 object
@ -541,12 +497,7 @@ def start():
if keep.get()!=1: if keep.get()!=1:
remove(outputFile) remove(outputFile)
# Reset UI # Reset UI
selectFileInput["state"] = "normal" resetDecryptionUI()
passwordInput["state"] = "normal"
adArea["state"] = "normal"
startBtn["state"] = "normal"
keepBtn["state"] = "normal"
working = False
del fin,fout,cipher,key del fin,fout,cipher,key
return return
else: else:
@ -567,12 +518,7 @@ def start():
if keep.get()!=1: if keep.get()!=1:
remove(outputFile) remove(outputFile)
# Reset UI # Reset UI
selectFileInput["state"] = "normal" resetDecryptionUI()
passwordInput["state"] = "normal"
adArea["state"] = "normal"
startBtn["state"] = "normal"
keepBtn["state"] = "normal"
working = False
del fin,fout,cipher,key del fin,fout,cipher,key
return return
else: else:
@ -606,13 +552,7 @@ def start():
fout.close() fout.close()
remove(outputFile) remove(outputFile)
# Reset UI # Reset UI
selectFileInput["state"] = "normal" resetDecryptionUI()
passwordInput["state"] = "normal"
adArea["state"] = "normal"
startBtn["state"] = "normal"
keepBtn["state"] = "normal"
working = False
progress["value"] = 100
del fin,fout,cipher,key del fin,fout,cipher,key
return return
else: else:
@ -712,27 +652,7 @@ def start():
statusString.set(kVeryCorruptedNotice) statusString.set(kVeryCorruptedNotice)
# Reset variables and UI states # Reset variables and UI states
selectFileInput["state"] = "normal" resetUI()
adArea["state"] = "normal"
adArea.delete("1.0",tkinter.END)
adArea["state"] = "disabled"
startBtn["state"] = "disabled"
passwordInput["state"] = "normal"
passwordInput.delete(0,"end")
passwordInput["state"] = "disabled"
cpasswordInput["state"] = "normal"
cpasswordInput.delete(0,"end")
cpasswordInput["state"] = "disabled"
progress["value"] = 0
inputString.set("Please select a file.")
keepBtn["state"] = "normal"
keep.set(0)
keepBtn["state"] = "disabled"
eraseBtn["state"] = "normal"
erase.set(0)
eraseBtn["state"] = "disabled"
rs.set(0)
rsBtn["state"] = "disabled"
inputFile = "" inputFile = ""
outputFile = "" outputFile = ""
password = "" password = ""
@ -751,36 +671,27 @@ def wrapper():
start() start()
except: except:
# Reset UI accordingly # Reset UI accordingly
progress.stop()
progress.config(mode="determinate")
progress["value"] = 100
selectFileInput["state"] = "normal"
passwordInput["state"] = "normal"
startBtn["state"] = "normal"
if gMode=="decrypt": if gMode=="decrypt":
keepBtn["state"] = "normal" resetDecryptionUI()
else: else:
adArea["state"] = "normal" resetEncryptionUI()
cpasswordInput["state"] = "normal"
rsBtn["state"] = "normal"
eraseBtn["state"] = "normal"
statusString.set(unknownErrorNotice) statusString.set(unknownErrorNotice)
dummy.focus() dummy.focus()
working = False
finally: finally:
sys.exit(0) sys.exit(0)
# Encryption/decrypt is done is a separate thread # Encryption/decrypt is done is a separate thread so the UI
# so the UI isn't blocked. This is a wrapper # isn't blocked. This is a wrapper to spawn a thread and start it.
# to spawn a thread and start it.
def startWorker(): def startWorker():
thread = Thread(target=wrapper,daemon=True) thread = Thread(target=wrapper,daemon=True)
thread.start() thread.start()
# Securely wipe file
def secureWipe(fin): def secureWipe(fin):
statusString.set("Securely erasing original file...") statusString.set("Securely erasing original file...")
# Check platform, erase accordingly
if platform.system()=="Windows": if platform.system()=="Windows":
system(f'sdelete64.exe "{inputFile}" -p 4') system(f'sdelete64.exe "{inputFile}" -p 4')
elif platform.system()=="Darwin": elif platform.system()=="Darwin":
@ -788,6 +699,68 @@ def secureWipe(fin):
else: else:
system(f'shred -uz "{inputFile}"') system(f'shred -uz "{inputFile}"')
# Disable all inputs while encrypting/decrypting
def disableAllInputs():
selectFileInput["state"] = "disabled"
passwordInput["state"] = "disabled"
cpasswordInput["state"] = "disabled"
adArea["state"] = "disabled"
startBtn["state"] = "disabled"
eraseBtn["state"] = "disabled"
keepBtn["state"] = "disabled"
rsBtn["state"] = "disabled"
# Reset UI to encryption state
def resetEncryptionUI():
global working
selectFileInput["state"] = "normal"
passwordInput["state"] = "normal"
cpasswordInput["state"] = "normal"
adArea["state"] = "normal"
startBtn["state"] = "normal"
eraseBtn["state"] = "normal"
rsBtn["state"] = "normal"
working = False
progress["value"] = 100
# Reset UI to decryption state
def resetDecryptionUI():
global working
selectFileInput["state"] = "normal"
passwordInput["state"] = "normal"
adArea["state"] = "normal"
startBtn["state"] = "normal"
keepBtn["state"] = "normal"
working = False
progress.stop()
progress.config(mode="determinate")
progress["value"] = 100
# Reset UI to original state (no file selected)
def resetUI():
selectFileInput["state"] = "normal"
adArea["state"] = "normal"
adArea.delete("1.0",tkinter.END)
adArea["state"] = "disabled"
startBtn["state"] = "disabled"
passwordInput["state"] = "normal"
passwordInput.delete(0,"end")
passwordInput["state"] = "disabled"
cpasswordInput["state"] = "normal"
cpasswordInput.delete(0,"end")
cpasswordInput["state"] = "disabled"
cpasswordString.set("Confirm password:")
progress["value"] = 0
inputString.set("Please select a file.")
keepBtn["state"] = "normal"
keep.set(0)
keepBtn["state"] = "disabled"
eraseBtn["state"] = "normal"
erase.set(0)
eraseBtn["state"] = "disabled"
rs.set(0)
rsBtn["state"] = "disabled"
# ad stands for "associated data"/metadata # ad stands for "associated data"/metadata
adLabelString = tkinter.StringVar(tk) adLabelString = tkinter.StringVar(tk)
adLabelString.set(adString) adLabelString.set(adString)