This document describes the technical details of the security systems used to protect the Amplenote API. These systems cover interactions between the client applications and the API, but do not include security measures taken in the client applications to protect against various client-specific risks.
To access your notes in a client application, you must prove that you are who you say you are (authentication), grant the client application access to your account (authorization), and receive an encryption key from the server that will allow the client application to decrypt your note data.
To determine which user is authorizing a client application, and verify that you are that user, the API serves a login flow on https://login.amplenote.com
User passwords are hashed with BCrypt using a cost parameter of 10
All cookies involved are Secure, HttpOnly, and restricted to login.amplenote.com
Headers are set for security-related browser features, including CSP, HSTS, and X-Frame-Options
Each Amplenote client uses the OAuth2 authorization code flow to obtain an access token from the API.
Access tokens expire 2 hours after they are issued
Access tokens are issued with refresh tokens that can be used to obtain a new access token
The authorization code flow supports the
nonce parameter described by OpenID Connect
The authorization code flow supports PKCE
The user's Standard Key is delivered to the client upon successful completion of the authorization code flow.
The user's Standard Key and Vault Key Salt are included in the
id_token payload described by OpenID Connect
id_token is a JWT signed with the server's private key, which can be verified with the public key
Note content is encrypted and decrypted in client applications using AES-256-CBC with a Note Key. The Note Key is encrypted using one of the user's account-wide encryption keys: either their Standard Key or their Vault Key. The user's Standard Key is encrypted at rest with AES-256-GCM - using a key that the database server does not have access to - and a randomly generated Initialization Vector, while the user's Vault Key is never transmitted to the Amplenote servers. Note Keys remain encrypted in transit, only getting decrypted once they reach the client application.
Each user's copy of the Note Key is encrypted using that user's Standard Key or Vault Key and a randomly generated Initialization Vector to produce a Standard Note Key or a Vault Note Key.
A unique Initialization Vector is used for each combination of user and note.
The encrypted Standard Note Key or Vault Note Key is stored in the database along with the Initialization Vector.
The database server's storage is encrypted at rest with AES-256, block-level storage encryption.
Standard Encryption Key
The user's Standard Key is stored encrypted using AES-256-GCM with a randomly generated Initialization Vector
The key used to encrypt the user's Standard Key is not accessible to the database server
Vault Encryption Key
A random 256-bit Vault Key Salt value is generated and stored in the database encrypted with AES-256-GCM using an encryption key that is not available to the database server and a randomly generated Initialization Vector
The Vault Password entered by the user and the Vault Key Salt are used with PBKDF2-HMAC-SHA256 to produce the 256-bit Vault Key
PBKDF2-HMAC-SHA256 is configured to use 100,000 rounds
A Vault Key Verifier is stored on the server, allowing for a zero-knowledge proof to ensure that the same Vault Password is used for all Vault Notes
The encrypted Note Key is delivered to the client application in the
Encryption-Key response header for any request that responds with encrypted note data.
Encryption-Key header value is the encrypted Note Key, clients may cache the response in less secure storage.
To access a note's content, a user needs the Note Key. When a note is shared by a source user with a target user, the following steps are taken on the server:
The source user's Standard Key is used to decrypt the source user's encrypted copy of the Note Key
The target user's Standard Key and a new randomly generated Initialization Vector are used to encrypt the Note Key
The encrypted Note Key and new Initialization Vector are stored in the database associated with the target user
To access a note's content, public notes need the Note Key. When a note is made public by a user, the following steps are taken on the server:
The user's Standard Key is used to decrypt the user's encrypted copy of the Note Key
The Note Key is encrypted using AES-256-CBC with a 256-bit key that the database server does not have access and a randomly generated Initialization Vector
The encrypted Note Key and Initialization Vector are stored in the database, associated with the public URL
When a public note is viewed, the server performs the following process to deliver the decrypted content to the viewer:
The public note's encrypted Note Key is decrypted by the application server
The Note Key is used to decrypt the note content
The decrypted note content is delivered to the client application
Vault Notes disable a number of features - like sharing and public links - that otherwise rely on the server having access to the user's Standard Key. To ensure that the user doesn't lose access to some of their Vault Notes due to a typo, a verification value is stored in the database that allows the client applications to check that the same Vault Password is used for all Vault Notes.
The client requests Vault Note Key setup parameters from the server. The server responds with the Vault Key Challenge and two randomly generated Initialization Vectors. The Initialization Vectors will be used by the client when encrypting the Note Key and the Vault Key Challenge.
If this is the first time the user has changed a Standard Note to a Vault Note, the Initialization Vector used when encrypting the Vault Key Challenge will be randomly generated at this time. Otherwise, the Initialization Vector previously used when encrypting the Vault Key Challenge will be returned.
The client encrypts the Vault Key Challenge with AES-256-CBC using the Vault Key and one of the returned Initialization Vectors to produce the Vault Key Response.
The client encrypts the Note Key with the Vault Key and one of the Initialization Vectors to produce a Vault Note Key.
The Vault Key Response and Vault Note Key are sent to the server with the corresponding Initialization Vectors.
The server uses BCrypt to hash the Vault Key Response and concatenates the Initialization Vector to produce the Vault Key Verifier. The Vault Key Verifier is stored in the database encrypted with AES-256-GCM using a key that the database server does not have access to and a randomly generated Initialization Vector
The server replaces the stored Standard Note Key with the supplied Vault Note Key
As described in this document, Standard Notes in Amplenote are not end-to-end encrypted by default. This allows for a number of key features, such as note sharing; note publishing; server-side note exporting; password reset - and more - which are not currently possible with our end-to-end encrypted Vault Notes. However, all notes are encrypted before they leave your device and they remain encrypted at-rest on the Amplenote servers.
The astute reader may have noticed that attachments - such as images and PDF documents - have not been mentioned in this document. Attachments are not encrypted - even in Vault Notes - rather they are uploaded to a location that is described by a random 122-bit number and the identifier of the note where the attachment was originally uploaded. With knowledge of a note's identifier, there are 5,316,911,983,139,663,491,615,228,241,121,378,304 possible addresses at which an attachment could be found, leaving an infinitesimally small chance of guessing an attachment's address. A more likely scenario is accidental disclosure of the attachment address, for example by referencing an image in an email or on another website. Encrypted attachments are on the roadmap for Vault Notes, and the feasibility will be evaluated at that point for Standard Notes as well.
A random value used when encrypting data with an encryption key to ensure that two matching plain-text inputs do not produce the same encrypted output. This value is not considered a secret, and is typically stored next to the encrypted output. Initialization Vectors used for AES-256-CBC encryption are 128-bit (16 bytes), while those used for AES-256-GCM are 96-bit (12 bytes).
A 256-bit random value generated when a note is created. This value is used with a per-note Initialization Vector to encrypt the content of the note with AES-256-CBC.
A 256-bit random value generated when a user account is created. This key is used with a per-note Initialization Vector to encrypt a Note Key with AES-256-CBC.
A Note Key that has been encrypted with AES-256-CBC using the user's Standard Key and a randomly generated 128-bit Initialization Vector.
A 256-bit value that is derived from the Vault Password and Vault Key Salt using PBKDF2. This value is used with a per-note Initialization Vector to encrypt a Note Key with AES-256-CBC.
A randomly generated 128-bit value used by the client to prove that they are using the same Vault Password for all Vault Notes.
A user-entered password that is never transmitted to the Amplenote servers. This is distinct from the user's login password, which is used to authenticate their identity when logging in.
The Vault Key Challenge encrypted with AES-256-CBC using the Vault Key and a randomly generated 128-bit Initialization Vector.
A 256-bit randomly generated value specific to each user's account. Combined with the user's Vault Password to produce the Vault Key.
The Vault Key Response after being hashed with BCrypt, combined with the Initialization Vector that was used when encrypting the Vault Key Challenge to produce the Vault Key Response.
A Note Key that has been encrypted with AES-256-CBC using the user's Vault Key and a randomly generated 128-bit Initialization Vector.
Notes that have had their Note Key encrypted with a user's Vault Key. Some features are disabled for these notes, such as sharing and generation of public links.