diff --git a/docs/encryption.md b/docs/encryption.md index 30f843af..94043a73 100644 --- a/docs/encryption.md +++ b/docs/encryption.md @@ -1,7 +1,5 @@ # Encryption -## `pycrypto` - Please note that _all_ of `jrnl`'s encryption functions require `pycrypto`, which can be installed using `pip`: @@ -38,21 +36,21 @@ encryption password in your keychain. This saves you the trouble of having to enter your password every time you want to write in or read your journal. If you don't initially store the password in the keychain but decide to do so at -a later point---or if you want to store it in one computer's keychain but not -in another computer's---you can run `jrnl --encrypt` on an encrypted journal -and use the same password again. This will trigger the keychain storage prompt. +a later point---or if you want to store it in one computer's keychain but not in +another computer's---you can run `jrnl --encrypt` on an encrypted journal and +use the same password again. This will trigger the keychain storage prompt. ## A Note on Security While `jrnl` follows best practices, total security is never possible in the real world. There are a number of ways that people can at least partially -compromise your `jrnl` data. See the [Privacy and Security](./security.md) -page for more information. +compromise your `jrnl` data. See the [Privacy and Security](./security.md) page +for more information. ## Password Recovery There is no method to recover or reset your `jrnl` password. If you lose it, -your data is inaccessible forever. +your data will be inaccessible forever. ## Manual Decryption @@ -67,6 +65,41 @@ Here is a Python script that you can use to decrypt your journal: ``` python #!/usr/bin/env python3 +import base64 +import getpass +from pathlib import Path +from cryptography.fernet import Fernet +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC + + +filepath = input("journal file path: ") +password = getpass.getpass("Password: ") + +with open(Path(filepath),"rb") as f: + ciphertext = f.read() + +password = password.encode("utf-8") +kdf = PBKDF2HMAC( + algorithm=hashes.SHA256(), + length=32, + salt=b"\xf2\xd5q\x0e\xc1\x8d.\xde\xdc\x8e6t\x89\x04\xce\xf8", + iterations=100_000, + backend=default_backend(), +) + +key = base64.urlsafe_b64encode(kdf.derive(password)) + +print(Fernet(key).decrypt(ciphertext).decode('utf-8')) +``` + +If you're still using `jrnl` version 1.X, the following script serves the same +purpose: + +``` python +#!/usr/bin/env python3 + import argparse from Crypto.Cipher import AES import getpass @@ -74,18 +107,18 @@ import hashlib import sys parser = argparse.ArgumentParser() -parser.add_argument(“filepath”, help=”journal file to decrypt”) +parser.add_argument("filepath", help="journal file to decrypt") args = parser.parse_args() pwd = getpass.getpass() -key = hashlib.sha256(pwd.encode(‘utf-8’)).digest() +key = hashlib.sha256(pwd.encode('utf-8')).digest() -with open(args.filepath, ‘rb’) as f: +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”) +plain = plain.decode("utf-8") print(plain) ```