Code Reading: "Firefox Send" encryption
Mozilla Test Pilot Team has released Firefox Send. This post describes how safe Firefox Send is by reading code. Note that The team blog post announces the safety of their service:
Your files are encrypted during transmission. Plus, Send encrypts files on the client side, so that not even Mozilla can read them.
TL;DR
As of v1.1.0,
- File data is encrypted on the client side during uploading.
- File data is decrypted on the client side during downloading.
- File name is not encrypted and stored on the server.
- Secret Key is generated by the client side and shared with the sender/receiver persons by hash (
#
) of the download link URL. It is never sent to the server.
Client side: FileSender#upload()
This clause describes FileSender#upload()
method defined in frontend/src/fileSender.js (to upload with client-side encryption).
first Promise : Generate Key and Load File
The first promise is resolved when both of following two procedures are completed:
- Generate Key:
- using generateKey() of Web Crypto API;
- with a symmetric algorithm "AES-GCM" (AES in Galois/Counter Mode);
- with 128-bit key length.
- Read file
second Promise : Encrypt and Export key
The second promise is resolved when both of following two procedures are completed:
- Encrypt file data
plaintext
- using encrypt() of Web Crypto API;
- with 128-bit authentication tag length.
- Export key
- using exportKey() of Web Crypto API;
- to the JSON Web Key format.
third Promise : Upload
The third promise executes the following procedure:
- Upload the file data
encrypted
- using XHR with Blob;
- with
X-File-Metadata
consisting ofid
: the file ID equivalent toiv
(initial vector);filename
.
return value: File Parameters
The final promise returns following parameters:
url
: URL generated by server;fileId
: File ID generated by server (different thaniv
(initial vector) generated by client side);secretKey
: Secret key "K" exported by the second promise on client side;deleteToken
: Key token to delete the file generated by server.
Note: Download URL is `${url}#${secretKey}`
.
See frontend/src/upload.js for detail.
Server side: POST /upload/
This clause describes "POST /upload/
" handler defined in server/server.js (to store).
Server stores:
newId
: File ID generated by server (different thaniv
(initial vector) generated by client side).file
: File data encrypted (by client side)meta
:X-File-Metadata
consisting ofid
: the file ID equivalent toiv
(initial vector) generated by client side;filename
;delete
: Key token to delete the file generated by server.
Server returns a response:
- with JSON response body consisting of
url
: URL generated by server;delete
: Key token to delete the file generated by server.id
: File ID generated by server (different thaniv
(initial vector) generated by client side).
Client side: FileReceiver#download()
This clause describes FileReceiver#download()
method defined in frontend/src/fileReceiver.js (to download with client side decryption).
first Promise : Import Key
The first promise is resolved when following procedure is completed:
- Import Key:
- using importKey() of Web Crypto API;
- from the URL hash (
#
) parameter; - with a symmetric algorithm "AES-GCM" (AES in Galois/Counter Mode);
- with 128-bit key length.
second Promise : Download
The second promise is resolved when following procedure is completed:
- Download file:
- using XHR with Blob;
- returns parameter consisting of
data
: File data encryptedfilename
;type
: the Content-Type of the HTTP response header;iv
: the file ID equivalent toiv
(initial vector) generated by sender client side.
third Promise : Decrypt
The third promise is resolved when following procedure is completed:
- Encrypt file data
fdata.data
- using encrypt() of Web Crypto API;
- with a symmetric algorithm "AES-GCM" (AES in Galois/Counter Mode);
- with following parameters:
iv
: the file ID equivalent toiv
(initial vector) generated by sender client side;key
: Secret key "K" import by the first promise on client side.
Conclusion
As of v1.1.0,
- File data is encrypted on the client side during uploading.
- File data is decrypted on the client side during downloading.
- File name is not encrypted and stored on the server.
- Secret Key is generated by the client side and shared with the sender/receiver persons by hash (
#
) of the download link URL. It is never sent to the server.
References
- Firefox Send, Firefox Test Pilot
- mozilla/send, v1.1.0, Github
- "Web Crypt API", MDN
- N.Nguyen, "New Test Pilot Experiments Available Today, The Mozilla Blog, Aug 1 2017