A privacy-first period tracker?
Is it even possible?
@raae
Encryption
Consumer Benedicte
Developer Benedicte


Don't be evil
vs.
Can't be evil


Thank you Jeffrey Goldberg!
@jpgoldberg on Twitter
1
n00b
Encryption
Basic
Encryption

jcy8BRD4&NidjK6zXBw<w1Jw#gqkmEwcRWev@@41D5H@9K}#>=)+Qw0,kVv}U6p

Entropy
A long random sequence of characters has high entropy, a short human memorable password has low entropy.

Web Crypto API
const key = await window.crypto.subtle.generateKey(
{
name: "AES-GCM",
length: 256
},
true,
["encrypt", "decrypt"]
);Key generation
AES-GCM
Advanced Encryption Standard
with Galois Counter Mode
const note = "A very secret note";
const noteBuffer = new TextEncoder("utf-8").encode(note);
const nonce = window.crypto.getRandomValues(new Uint8Array(12));
const cyphertext = await window.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: nonce
},
key,
noteBuffer
);Encryption
const plaintext = await window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: nonce
},
key,
cyphertext
);
const decoder = new TextDecoder("utf-8");
const decryptedNote = decoder.decode(new Uint8Array(plaintext));
console.log(decryptedNote); // A very secret noteDecryption
Basic
Encryption


Client Storage

const password = "The user's secret password"
const enc = new TextEncoder();
const passwordAsKey = await window.crypto.subtle.importKey(
"raw",
enc.encode(password),
{name: "PBKDF2"},
false,
["deriveBits", "deriveKey"]
);Import Key
PBKDF2
Password-Based Key Derivation Function 2
const salt = window.crypto.getRandomValues(new Uint8Array(12));
const key = await window.crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt: salt,
iterations: 100000,
hash: "SHA-256"
},
passwordAsKey,
{ name: "AES-GCM", length: 256},
true,
[ "encrypt", "decrypt" ]
);
Derive Key
PBKDF2
Password-Based Key Derivation Function 2

Basic
Encryption
with key
derivation


Cloud Storage
What goes where?

Moving between devices

End-to-end encryption

Sharing
Async
Encryption




const keyPair = window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
["encrypt", "decrypt"]
);Async Key Generation
RSA-OAEP
Rivest–Shamir–Adleman
Optimal Asymmetric Encryption Padding
Sharing


Encryption
Decryption
Sharing

Private key management
Sharing

Decryption
Authentication
Secure Remote Password
1Password
Hashes the encryption key
Last Password
Is it possible?
raae.codes/privacy-first
https://
Thank you!
@raae

A privacy-first period tracker?
By Benedicte Raae
A privacy-first period tracker?
Slides from JSConf Budapest and RuhrJS 2019.
- 247