andrew-tpfc/pgid — pull request #2 by jyrkive (2014-06-19 14:35:16+00:00)
Title: Ability to store the PGID in Local Storage

As I mentioned in TPFC, I think the most important addition the PGID extension needs is ability to store the PGID in Local Storage. This commit implements that.

Notes about the big choices I have made:

## Encryption algorithm: AES

I chose AES because it's the only currently registered symmetric encryption algorithm in the upcoming [Web Cryptography API](http://msdn.microsoft.com/en-us/library/ie/dn302338%28v=vs.85%29.aspx). It would be nice to change the back end to the Web Crypto API one day, and at this point it's very unlikely choosing AES would make it harder.

Amazingly, AES decryption succeeds (but produces garbage data) even with a wrong master password. My code attempts to detect usage of a wrong password by checking the length of the decrypted private key.

## [Mode of operation](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation): CBC

In the subset of the Web Cryptography API that IE11 supports, available modes of operation for AES are CBC and GCM. Of these modes CBC is much older and more simple, so I expect it to remain popular and be more likely available in crypto libraries.

## Key derivation algorithm: PBKDF2

PBKDF2 was suggested in the README of the crypto library I chose (see below), so I guess it's not a very bad choice. ;)

## Format of encrypted PGID

I decided to only encrypt the private key and keep everything else in plaintext. The main reason is that if we ever allow the user to store an encrypted PGID in a file, it will be easy for software such as [TRiD](http://mark0.net/soft-trid-e.html), or even human beings, to detect that the file is a PGID.

The private key is decoded from Base64 to binary, encrypted and encoded as Base64 again. The reason to encode it again is that this keeps the PGID ASCII-only and allows it to be transmitted via channels that only allow ASCII in case it will ever be useful.

## Crypto library: [Forge](https://github.com/digitalbazaar/forge)

Since PGID is, after all, security software, I think it makes sense to use one large crypto library instead of one script for each algorithm.

Forge is overkill for our purposes as it implements the entire TLS protocol (!). However, it implements everything we need and is actively maintained.

I put Forge's license (3-clause BSD + GPLv2 dual-license) into a file of its own in the root directory.

## base64.js

That script is from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding . According to https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses , the code samples in that page are in the public domain and no license notice is necessary.

## encryption.js

Encryption.js is a wrapper around AES and PBKDF2 functionality in the Forge library. Its API resembles the Web Cryptography API. In particular, while crypto functions in the Forge library are synchronous, the Web Cryptography API will be asynchronous. That wrapper will hopefully keep us from attaching to synchronous functions too strongly. :)

# Future work

Improve UX when the user enters a master password for the first time. Currently he/she needs to write the master password, move his/her hand to the mouse and click the corresponding button (usually "Login with"). It would be better to store the last changed dropdown somewhere and perform the corresponding action when the user presses Enter.

Any ideas on where to store the last changed dropdown? Global variable? A custom attribute in the form?

Allow the user to change the PGID used on a particular website without having to unlock both PGIDs first. The problem here is that there is only one master password field in the popup (and adding another field may not be a good idea) and therefore it's not possible to unlock two PGIDs at once (or currently even know which one the user wants to unlock).

Switch to Forge's RSA and SHA-1 implementations. Get rid of JSEncrypt and the Movable Type SHA1 implementation.

Generate different salt (for the AES encryption key) for each user and store it in the encrypted PGID.

Consider if the encrypted PGID can be synchronized between Chrome instances. Right now it's not allowed. Allowing synchronization would be less secure but more convenient.