Skip to content
This repository has been archived by the owner on Jun 20, 2022. It is now read-only.

Desktop version: Add an option to ask for password every application start #93

Closed
mirsev opened this issue Sep 5, 2017 · 19 comments
Closed

Comments

@mirsev
Copy link

mirsev commented Sep 5, 2017

Since StandardNotes keeps data locally encrypted, it would be a good idea to ask for password every time when the user starts the application. Otherwise, anybody having access to the computer can read encrypted data by just running this program. Of course, probably not everyone will want this, so this might be an option.

@moughxyz
Copy link
Member

moughxyz commented Sep 6, 2017

For now the threat model is still that your local computer is treated as safe and sound. But this is still an option I want to add soon: password protect the desktop app.

@mirsev
Copy link
Author

mirsev commented Sep 7, 2017

The reason why I'm asking this is that I have a text file with very sensitive data (personal. passwords, bank accounts, etc.) which I keep GnuPG encrypted. I was also looking for PGP/GnuPG applications for Android/iOS in order to have the same encrypted file shared via Dropbox accessible when I'm not home or at work. But it seems that there is no such an application. Then I have found your StandardNotes and thought that this is exactly what I need. I like that data is kept locally encrypted on both desktop and mobile devices, so the latest version could be accessible even without network. It is a good point. But lack of password protection means that anybody who accidentally gets the access to the computer can read this data. Too bad. So, please, add this option as soon as possible. Thank you.

@moughxyz
Copy link
Member

moughxyz commented Sep 8, 2017

Good points, I don't disagree. See here also: standardnotes/forum#79

@mirsev
Copy link
Author

mirsev commented Sep 12, 2017

There is another point regarding security of the desktop version which attracted my attention. When I click "Account" menu in the lower status bar, then "Advanced->Show Credentials" I can see the encryption key, server password and the authentication key. Since the application itself does not ask for the password, I can conclude that this very sensitive information is not encrypted in any way. I think this is a very dangerous security flaw and for now we can not rely on StandardNotes if we need to keep some personal secret data in our computers.

I did not study the source code of the application but I'm sure someone can do this easily and can find where (in which file or which database) the encryption key is stored. Then someone can write another program which reads this data even without StandardNotes running and use it to access user's encrypted data. In this respect, StandardNotes does nothing to protect the user's data.

Please, comment on this because I think this is very important and all users who trust StandardNotes must know is these issues are real or not.

I'm not a security expert but I think that if the application is designed as a secure storage for very sensitive data, nothing should be kept in open non-encrypted form. The application must have a key known only to the valid user which may be used to generate decryption key for credentials which must be kept under strong encryption. Probably, the credentials can be kept encrypted with the same key as the notes. In this case the master encryption key can be generated from the password phrase.

Before this issue is resolved, nobody can consider StandardNotes as secure storage of user's data.

@moughxyz
Copy link
Member

Every application that promises security does so on a set threat model. Our threat model is protecting you from peering eyes over the wire and on the cloud. We've made it clear that our applications are meant to protect your data from ever leaving your computer unencrypted. That's how we've built our applications up to date. We treat your local device as safe. If you want to protect your local data, you need to protect and lock your device.

However, the good news is that we're expanding this threat model with a huge upcoming update on all platforms. This will allow a few things:

  1. Passcode lock. A passcode allows you to lock your application on your device with a PIN code of any length. If you choose to set this up (it's optional), it will encrypt your credentials (encryption key, server password, and authentication key) on your local device. This means if your local device is stolen and hacked into, a hacker would not be able to decrypt your notes or see your keys. A passcode will also allow you to encrypt your notes even if you haven't signed up for an account (offline only usage).

  2. "Stay signed in" option when logging in on desktop and web. This allows for ephemeral login sessions that do not save any data to your local device whatsoever, and instead keeps everything in memory until you close the window.

  3. On iOS and Android, encryption keys will now be stored in the secure, encrypted keychain that the device OS offers. This will require no additional set up. (Not available on desktop/web as a secure enclave is not available on web technologies, yet at least).

The iOS and Android app are nearing completion, and I hope to have all these new features released by the end of the month.

@mirsev
Copy link
Author

mirsev commented Sep 12, 2017

Good news! Thank you.

@mirsev
Copy link
Author

mirsev commented Sep 22, 2017

Before more secure storage is implemented with asking password every time when the application is opened, I will use the following script stdnotes which uses GnuPG for additional encryption in Ubuntu Linux:

#!/bin/sh

keyname="Your key ID for GnuPG"
encfile="$HOME/.pgp/stdnotes.pgp"

stdnotesfls=".config/Standard Notes"
stdnotesexe="$HOME/bin/standard-notes-1.2.7-x86_64.AppImage"

decrypt () {
    gpg -o - "$encfile" | tar -C "$HOME" -zxf - || exit 255
}

encrypt () {
    tar -C "$HOME" -czf - "$stdnotesfls" |
    gpg -o "$encfile" -e -r "$keyname" --force-mdc - && sync || exit 254
}

case "$1" in

    decrypt)
    
        decrypt
        ;;
        
    encrypt)
        
        encrypt && rm -rf "$HOME/$stdnotesfls"
        ;;
    
    *)
        
        decrypt
        "$stdnotesexe"
        encrypt
        rm -rf "$HOME/$stdnotesfls"
        ;;
esac

Before using this script, you need to define a GnuPG public key which will be used to encrypt data to protect it from unauthorized access. Read GnuPG documentation first. Then create public/secret key pair and write its ID in keyname variable in this script.

After that choose the path to the file which you will use to store encrypted data. Here it is $HOME/.pgp/stdnotes.pgp.

Then run stdnotes encrypt. If everything is OK, the Standard Notes storage will be archived, encrypted, stored in specified file. The original Standard Notes will be deleted. So, if your computer is hacked or stolen, your sensitive data will be protected.

When you need to read or edit your data, just run stdnotes without any argument. Data will be decrypted and you can use the application as usual. When you close it, data will be again archived, encrypted and stored in specified place.

To restore the data just run stdnotes decrypt.

And remember: no warranty of any kind! :) When testing this script keep your backup copy in a separate directory. If you see that everything is OK, remove this backup or encrypt it.

@moughxyz
Copy link
Member

Wow, that's very cool!

@mirsev
Copy link
Author

mirsev commented Oct 3, 2017

Hi, Mo Bitar. One question regarding possible local backups: how can I know if after running desktop application anything has been changed in the notes? I mean that if I open Standard Notes only to view the notes, then nothing was changed and I can keep old copy without making additional backup. However, if something is changed (edited locally, or any note was updated from a mobile device and now local data is synchronized with the server) I need to make a new backup and rotate backup copies. Can desktop version provide some exit code? Like 0 if nothing was changed, 1 if data was changed by any reason, and 255 if some error occurred...

@moughxyz
Copy link
Member

moughxyz commented Oct 4, 2017

Hmm there's no way to do this currently. Are you trying to set up a script that downloads backups automatically if changes were made or something?

But I do suppose "There have been changes made since your last backup" would be a helpful feature. I'll take that into consideration.

@mirsev
Copy link
Author

mirsev commented Oct 4, 2017

Look at new version of the script above. Here multiple backup copies of data is kept for better protection from unexpected errors:

#!/bin/sh

keyname="New key for GnuPG"
encfile="$HOME/.pgp/stdnotes.pgp"

stdnotesfls=".config/Standard Notes"
stdnotesexe="$HOME/bin/standard-notes-1.2.7-x86_64.AppImage"

baknum=8

decrypt () {
    gpg2 --try-secret-key "$keyname" -o - "$encfile" | 
    tar -C "$HOME" -zxf - || exit 255
}

encrypt () {
    ( [[ ! -f "$encfile" ]] || mv "$encfile" "$encfile.bak" ) &&
    tar -C "$HOME" -czf - "$stdnotesfls" |
    gpg2 -o "$encfile" -e -R "$keyname" --force-mdc - && sync || exit 254
}

rotatebak () {
    if [[ -f "$encfile.bak" ]] ; then
        for (( n=$baknum ; n>1 ; --n )) ; do
            [[ -f "$encfile.$[n-1]" ]] && mv "$encfile.$[n-1]" "$encfile.$n"
        done
        mv "$encfile.bak" "$encfile.1"
    fi
}

case "$1" in

    decrypt)
    
        decrypt
        ;;
        
    encrypt)
        
        encrypt && rm -rf "$HOME/$stdnotesfls"
        ;;
    
    rotatebak)
        
        rotatebak
        ;;
    
    *)
        
        decrypt
        "$stdnotesexe"
        rc=$?
        echo "StandardNotes exit code: $rc"
        encrypt
        rm -rf "$HOME/$stdnotesfls"
        # If standard-notes returns a code meaning that something
        # was updated in our local copy, we need also to update
        # our backup copies
        
        #if [[ $rc == 1 ]] ; then
            rotatebak
        #fi
        ;;
esac

But we don't need to add a new copy if nothing was changed, right? So, we could use the return code from standard-notes.AppImage if it signals whether changes were made. It it returns 0 (no changes), we don't create a new backup copy of previous data and don't rotate old backups. If it returns 1, we create a copy of last version and rotate old backups.

@moughxyz
Copy link
Member

moughxyz commented Oct 5, 2017

Ah interesting. But I'm still not sure this would be easily possible yet without making some changes. I'm trying to think of a way to use what already exists, but no solution comes to mind. One thing you might be able to manage is looking at the updated_at field of individual items, and see if the latest one is greater than the last value you had saved. What exactly exists at stdnotesfls=".config/Standard Notes"?

@mirsev
Copy link
Author

mirsev commented Oct 8, 2017

Here is the tree of Standard Notes directory in Linux desktop:

$ tree .
.
├── Cache
│   ├── data_0
│   ├── data_1
│   ├── data_2
│   ├── data_3
│   └── index
├── Cookies
├── Cookies-journal
├── databases
│   ├── Databases.db
│   └── Databases.db-journal
├── GPUCache
│   ├── data_0
│   ├── data_1
│   ├── data_2
│   ├── data_3
│   └── index
├── IndexedDB
│   └── file__0.indexeddb.leveldb
│       ├── 000003.log
│       ├── CURRENT
│       ├── LOCK
│       ├── LOG
│       ├── LOG.old
│       └── MANIFEST-000001
├── Local Storage
│   ├── chrome-devtools_devtools_0.localstorage
│   ├── chrome-devtools_devtools_0.localstorage-journal
│   ├── file__0.localstorage
│   └── file__0.localstorage-journal
├── Preferences
├── QuotaManager
├── QuotaManager-journal
└── window-state.json

.config/Standard Notes/Cache/data_2: data
.config/Standard Notes/Cache/data_3: data
.config/Standard Notes/Cache/data_1: dBase III DBT, next free block index 3238316739, block length 1024
.config/Standard Notes/Cache/data_0: data
.config/Standard Notes/Cache/index: data
.config/Standard Notes/Cookies: SQLite 3.x database
.config/Standard Notes/Preferences: ASCII text, with very long lines, with no line terminators
.config/Standard Notes/QuotaManager-journal: empty
.config/Standard Notes/Local Storage/file__0.localstorage: SQLite 3.x database
.config/Standard Notes/Local Storage/file__0.localstorage-journal: empty
.config/Standard Notes/Local Storage/chrome-devtools_devtools_0.localstorage-journal: empty
.config/Standard Notes/Local Storage/chrome-devtools_devtools_0.localstorage: SQLite 3.x database
.config/Standard Notes/QuotaManager: SQLite 3.x database
.config/Standard Notes/window-state.json: ASCII text
.config/Standard Notes/Cookies-journal: empty
.config/Standard Notes/GPUCache/data_2: data
.config/Standard Notes/GPUCache/data_3: data
.config/Standard Notes/GPUCache/data_1: data
.config/Standard Notes/GPUCache/data_0: FoxPro FPT, blocks size 512, next free block index 3284796609, field type 0
.config/Standard Notes/GPUCache/index: data
.config/Standard Notes/databases/Databases.db: SQLite 3.x database
.config/Standard Notes/databases/Databases.db-journal: empty
.config/Standard Notes/IndexedDB/file__0.indexeddb.leveldb/MANIFEST-000001: data
.config/Standard Notes/IndexedDB/file__0.indexeddb.leveldb/000003.log: data
.config/Standard Notes/IndexedDB/file__0.indexeddb.leveldb/LOCK: empty
.config/Standard Notes/IndexedDB/file__0.indexeddb.leveldb/LOG: ASCII text
.config/Standard Notes/IndexedDB/file__0.indexeddb.leveldb/LOG.old: ASCII text
.config/Standard Notes/IndexedDB/file__0.indexeddb.leveldb/CURRENT: ASCII text


6 directories, 28 files

By the way, I have found a dangerous security flaw:
File IndexedDB/file__0.indexeddb.leveldb/000003.log is binary but it contains unencrypted fragments of actual records.

@moughxyz
Copy link
Member

moughxyz commented Oct 8, 2017

Gotcha, v1 doesn't encrypt data for local storage (since keys have to be stored unencrypted anyway), but v2 does (since you can add a passcode lock). You can download the beta here: https://github.com/standardnotes/desktop-beta/releases/tag/v2.0.0-beta2

@mirsev
Copy link
Author

mirsev commented Oct 17, 2017

Due to busy times I could not review beta release but right now I have downloaded 2.0.1 version and have set passcode to encrypt data locally. Still have not time to do some detailed research regarding data safety, however, I have found that after setting passcode new version didn't perform a cleanup of older unencrypted data. Any advice how to remove everything that can be used to look for some sensitive stuff?

@moughxyz
Copy link
Member

Can you describe which data remained unencrypted after adding a passcode? It should have removed all sensitive data. If not, perhaps the data is from a previous, separate installation? What you can try doing is signing out completely, deleting all data that remains on your file system, then sign back in, and re-enable passcode.

@mirsev
Copy link
Author

mirsev commented Oct 17, 2017

The file which had clear-text data was IndexedDB/file__0.indexeddb.leveldb/000003.log.

Then, following your advice, I removed entire data directory, started the application, signed again and enabled passcode lock. Seems that now everything is OK.

BTW, do you have some kind of diagram or description, how the local data is encrypted, the storage structure, etc.?

@moughxyz
Copy link
Member

I actually have a blog post coming out tomorrow that will explain how Device Storage encryption works. Not an extremely technical post, more of a general audience thing, but it should help.

@moughxyz
Copy link
Member

Done in v2.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants