Laverna / laverna

Laverna is a JavaScript note taking application with Markdown editor and encryption support. Consider it like open source alternative to Evernote.
https://laverna.cc/index.html
Mozilla Public License 2.0
9.19k stars 801 forks source link

Decrypt with SJCL #700

Open vebose opened 7 years ago

vebose commented 7 years ago

I obtain password, salt, iter, ,ks, ts, iv, mode, adata, cipher, cipher text from laverna's interface, remote storage, json export settings file & insert them to sjcl.decrypt(). But it doesn't work. I notice that password I use & password in json export settings file don't match. Also by defalt SJCL use 64 bit salt but laverna 0.7.1 use 96 bit salt. Perhaps Laverna change password & only then insert it to SJCL. How can I decrypt with SJCL message encrypted with Laverna 0.7.1.

alsacefan commented 7 years ago

I have the same question. I wanted to make sure that I can decrypt all of my notes outside of Laverna, as a failsafe, and I am unable to do so, I have tried https://bitwiseshiftleft.github.io/sjcl/demo/ as well as using a version of the Python Crypto library that supports CCM (https://github.com/Legrandin/pycryptodome). I have no problem using Python to decrypt a ciphertext created on the SJCL website, and vice versa. Does Laverna do anything unusual when generating the derived key or preparing the text for encryption? I've looked at the source code, and everything seems pretty standard. Not sure what I am missing.

I did notice that Lavera's ciphertext (in JSON format) contains the salt in hex format, while the native SJCL routines output base64-encoded strings. I assume that this is just a difference in output, since Laverna seems to store the salt internally as an sjcl bitarray.

Not sure it matters, but I am currently using the nightly build of Laverna.

alsacefan commented 7 years ago

I figured out my issue. The salt was the problem -- for some reason, my salt value was being treated as a string rather than as a hex key, so it was converted to a bitarray by translating each number/letter to its ascii value (including the spaces between groups of digits). I generated a new random salt and now everything works as expected, and the JSON files for each note list the salt as a base64-encoded string, same as the iv and ciphertext.

@vebose - as far as I can tell, Laverna uses the actual password (utf-8 string), together with the salt, to generate a derived key that is stored in session storage to decrypt the notes. It also stores a simple SHA256 hash of the password to compare to the password you enter to unlock the program -- this is the "encryptedPass" entry you see when you export settings.

Here is the simplest way I found to decrypt the ciphertext using the SJCL library:

o = <encryptedData entry from JSON-formatted encrypted file> // this is a string (i.e., "{...}") 
sjcl.decrypt('<your password - plaintext>',o)
vebose commented 7 years ago

@alsacefan I use Laverna 0.7.1 - when i run in browser laverna.cc this version is open. Also in laverna 0.7.1 i can type my own salt I try in SJCL write salt as hex string with & without space - but nothing decrypted as i write base64 converted from hex Laverna take 96 bit hex salt value What salt must be inserted to SJCL to decrypt message

vebose commented 7 years ago

@alsacefan messages made by Laverna 0.7.3 or 0.7.4 desktop version are decrypted using SJCL library. Export data file contains salt in base64 format which insert into the SJCL object with other need parametres.

alsacefan commented 7 years ago

That's right - the salt is stored in base64.