Skip to content

Instantly share code, notes, and snippets.

@0xpizza
Created January 5, 2019 00:21
Show Gist options
  • Save 0xpizza/d1670de4c657353bc1c2886631dfc1e1 to your computer and use it in GitHub Desktop.
Save 0xpizza/d1670de4c657353bc1c2886631dfc1e1 to your computer and use it in GitHub Desktop.
from Crypto.Cipher import AES
from sys import argv
import os
AES_KEY_LEN = 32 # AES-256 GCM
AES_NONCE_LEN = 12 # NIST SP800-38D recommends 96 bits
AES_HMAC_LEN = 16 # for later
FOUR_KiB = 2**10*4 # standard OS block size
EXT = '.happyencryption'
def encrypt_file(filename):
c = AES.new(os.urandom(AES_KEY_LEN), mode=AES.MODE_GCM, nonce=os.urandom(AES_NONCE_LEN))
with open(filename, 'rb+') as f:
data = b'junk'
while data: # encrypt file in-place
data = f.read(FOUR_KiB)
data = c.encrypt(data)
f.seek(-len(data), 1)
f.write(data)
with open(filename, 'ab') as f:
f.write(c._key + c.nonce + c.digest())
os.rename(filename, filename+EXT)
def decrypt_file(filename):
with open(filename, 'rb+') as f:
tmp = AES_KEY_LEN + AES_NONCE_LEN + AES_HMAC_LEN
f.seek(-tmp, 2)
tmp = f.read(tmp)
t,m,p = tmp[:AES_KEY_LEN], tmp[AES_KEY_LEN:AES_KEY_LEN+AES_NONCE_LEN], tmp[-AES_HMAC_LEN:]
c = AES.new(t, mode=AES.MODE_GCM, nonce=m)
f.seek(0)
f.truncate(os.path.getsize(filename)-len(tmp)) # remove encryption data
data = b'junk'
while data: # decrypt in-place
data = f.read(FOUR_KiB)
data = c.decrypt(data)
f.seek(-len(data), 1)
f.write(data)
try:
c.verify(p)
except:
print('verify failed :(')
os.rename(filename, filename.replace(EXT, ''))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment