Personal diary app (in the browser) which uses client-side encryption and zero-knowledge authentication.
Try it at https://web.heartnotes.me.
Get it from https://heartnotes.me.
Features:
- 256-bit AES encryption done client-side for maximum security
- Auto-save-as-you-type, with cloud sync running the background
- Full-text search using lunr.js
- Continue editing even if connection goes down.
## Technology
Main ingredients: React.js, Redux, Electron.js.
This uses the SJCL library for AES-256 encryption as well as for the PRNG algorithm to generate random seed data and salts.
We first derive a "master" key from the user's password as follows:
- Use Fortuna PRNG with multiple event inputs (mouse, keyboard, accelerometer etc) to generate a salt.
- Use salt and password as inputs to PBKDF2-SHA512 to generate a 512-bit key. (The number of iterations of PBKDF2 is set such that generation takes 1 second on the user's machine- on a Macbook Air 2012 this easily results in >10000 iterations.
- Store the input salt and PBKDF2 iteration count in the user's account online.
- Set the first 256 bits of the key as the MASTER key.
- Set the second 256 bits of the key as the authentication key (i.e. to login to server).
Now let's generate the encryption key:
- Generate a SHA-256 hash of: user's password + random number (generated using a non-CSRNG)
- Use Fortuna PRNG with multiple event inputs (mouse, keyboard, accelerometer etc) to generate a salt.
- Use salt and hash as inputs to PBKDF2-SHA512 to generate a 512-bit key. (The number of iterations of PBKDF2 is set such that generation takes 1 second on the user's machine- on a Macbook Air 2012 this easily results in >10000 iterations.
- Set the first 256 bits of the key as the ENCRYPTION key.
The next time the user enters the right password, we:
- Use the stored salt and iteration count to regenerate the right MASTER key.
- We use this to decrypt the bundle containing the ENCRYPTION key.
Notes:
- We use the ENCRYPTION key to encrypt the actual entry data (AES-256-GCM, random IV).
- We encrypt the ENCRYPTION key using the MASTER key (AES-256-GCM, random IV) and save it as a bundle in the user's diary file.
- The ENCRYPTION key is currently never changed. Changing the user password simply changes the master key. This allows password change without having to re-encrypt everything.
Node.js 4.4.5+ required.
Setup:
$ npm install
Run web version (http://localhost:3000):
$ gulp
NOTE: Add --minified
on the command-line to enable JS and CSS minification during build.
$ npm run release_web
You will find build assets in the build/
folder.
- Make final commits
- Update
version
inpackage.json
- Commit version update and push
- Tag commit as
- Push tag
- Do a production build (see above)
- Test production build
- Create release entry on Github and attach built executable
- Announce to world!
Copyright (C) 2015-2016 Ramesh Nair
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see http://www.gnu.org/licenses/.