Classification: Public 1
End End-to-end File Encr Encryp yption i in n the the Web Br eb Browser er – A Ca Case e Study dy
Thomas Konrad, SBA Research Vue.js Meetup Vienna, Feb 11, 2020
SBA Research gGmbH, 2020
End End-to-end File Encr Encryp yption i in n the the Web Br - - PowerPoint PPT Presentation
End End-to-end File Encr Encryp yption i in n the the Web Br eb Browser er A Ca Case e Study dy Thomas Konrad, SBA Research Vue.js Meetup Vienna, Feb 11, 2020 SBA Research gGmbH, 2020 Classification: Public 1 ~ $ whoami Thomas
Classification: Public 1
Thomas Konrad, SBA Research Vue.js Meetup Vienna, Feb 11, 2020
SBA Research gGmbH, 2020
Classification: Public 2 SBA Research gGmbH, 2020
~$ whoami Thomas Konrad ~$ id uid=123 gid=1(Vienna, Austria) gid=2(SBA Research) gid=3(Software Security) gid=4(Penetration Testing) gid=5(Secure Development Lifecycle) gid=6(Security Training) gid=7(sec4dev Conference & Bootcamp)
Classification: Public 3
Wha What t we’d e’d like t e to
SBA Research gGmbH, 2020
Classification: Public 4
Wh Why y al all th the e Fuzz? zz?
surface significantly!
server gets worthless to attackers
deployment options
SBA Research gGmbH, 2020
Classification: Public 5
I a I admi mit: I d : I didn’t i n’t inven nvent t th this. s.
SBA Research gGmbH, 2020
taken from there
Classification: Public 6
Req equiremen rements ts
SBA Research gGmbH, 2020
Ensure confidentiality, integrity, and authenticity Encrypt the file in the browser Support big files (> 10 GB) Support old browsers as well as possible Securely distribute keys
Classification: Public 7
Ensure nsure Conf nfiden enti tial ality ty, Int Integri egrity ty, an and Authenti uthentici city ty
First things first: Randomness. 1110 1101 0001 1101 0000 0000 0000 0000 “There is no such thing as a random number – there are
– John von Neumann (1961)
SBA Research gGmbH, 2020
Classification: Public 8
Gener Generate e Secu ecure re Rand ndom B
ytes es in th the e Browser ser
SBA Research gGmbH, 2020
public static generateRandomBytes( length: number ): Uint8Array { return crypto.getRandomValues( new Uint8Array(length) ); }
GitHub Gist - Random Number Generator in TypeScript: https://gist.github.com/thomaskonrad/cfe4c9f6fd26f4382df1f8de3a2b97e8
Classification: Public 9
Ensure nsure Conf nfiden enti tial ality ty, Int Integri egrity ty, an and Authenti uthentici city ty
Let’s take as an example AES in CBC mode. What do you think we can guarantee with it? Confidentiality Integrity Authenticity
SBA Research gGmbH, 2020
Classification: Public 10
CBC (an (and other thers) s) Do N
aran antee ee Int Integri egrity ty
decryption will not fail.
(AEAD)
SBA Research gGmbH, 2020
Classification: Public 11
Req equiremen rements ts
SBA Research gGmbH, 2020
Ensure confidentiality, integrity, and authenticity Encrypt the file in the browser Support big files (> 10 GB) Support old browsers as well as possible Securely distribute keys
Classification: Public 12
Symme ymmetric tric AEAD AEAD Enc Encryp yption tion in in the the Brow
ser r 1/2
SBA Research gGmbH, 2020
export default class AEAD { public static readonly KEY_LENGTH_IN_BYTES = 16; public static readonly IV_LENGTH_IN_BYTES = 16; public static readonly TAG_LENGTH_IN_BYTES = 16; private static readonly ALGORITHM = 'AES-GCM'; private readonly secretKey: CryptoKey; private readonly tagLengthInBytes: number; public constructor(secretKey: CryptoKey, tagLengthInBytes = AEAD.TAG_LENGTH_IN_BYTES) { this.secretKey = secretKey; this.tagLengthInBytes = tagLengthInBytes; } public static async getCryptoKeyFromRawKey(rawKey: Uint8Array): Promise<CryptoKey> { return await crypto.subtle.importKey( 'raw', rawKey, { name: this.ALGORITHM, }, true, ['encrypt', 'decrypt'], ); }
GitHub Gist - Authenticated Secret Key Cryptography (AEAD) in TypeScript: https://gist.github.com/thomaskonrad/c8ed4d73bb200ecc9ecdf5b85e2eb7f0
Classification: Public 13
Symme ymmetric tric AEAD AEAD Enc Encryp yption tion in in the the Brow
ser r 2/2
SBA Research gGmbH, 2020
public async encrypt(iv: Uint8Array, data: Uint8Array): Promise<ArrayBuffer> { return await crypto.subtle.encrypt({ name: AuthenticatedSecretKeyCryptography.ALGORITHM, iv, tagLength: this.tagLengthInBytes * 8, }, this.secretKey, data, ); } public async decrypt(iv: Uint8Array, data: Uint8Array): Promise<ArrayBuffer> { return await crypto.subtle.decrypt({ name: AuthenticatedSecretKeyCryptography.ALGORITHM, iv, tagLength: this.tagLengthInBytes * 8, }, this.secretKey, data, ); } }
GitHub Gist - Authenticated Secret Key Cryptography (AEAD) in TypeScript: https://gist.github.com/thomaskonrad/c8ed4d73bb200ecc9ecdf5b85e2eb7f0
Classification: Public 14
Req equiremen rements ts
SBA Research gGmbH, 2020
Ensure confidentiality, integrity, and authenticity Encrypt the file in the browser Support big files (> 10 GB) Support old browsers as well as possible Securely distribute keys
Classification: Public 15
Upload ad: C : Chu hunk a nk and nd Encr Encryp ypt
SBA Research gGmbH, 2020
Classification: Public 16
Upload load: : Splitting litting a a Fil File using using the the Fil FileRead ader r API API
SBA Research gGmbH, 2020
<template> <input type="file" @change="files = $event.target.files"/> </template> // ... const readChunk = () => { const r = new FileReader(); const blob = file.slice(offset, chunkSize + offset); r.onload = readEventHandler; r.readAsArrayBuffer(blob); };
GitHub Gist - Split files into chunks of a given size using the FileReader API: https://gist.github.com/thomaskonrad/8ced18322ebfcba47d7e8765176eeefb
Classification: Public 17
Upload load: : Splitting litting a a Fil File using using the the Fil FileRead ader r API API
SBA Research gGmbH, 2020
const readEventHandler = async (evt: any) => { if (evt.target.error == null) { const sequenceNumber = (offset / chunkSize);
let data = new Uint8Array(evt.target.result); data = await encrypt(data, sequenceNumber); await upload(data, sequenceNumber); } // Error handling, termination, read next chunk. };
GitHub Gist - Split files into chunks of a given size using the FileReader API: https://gist.github.com/thomaskonrad/8ced18322ebfcba47d7e8765176eeefb
Classification: Public 18
Upload load: : Cre Creating ating the the Enc Encryp yption tion Transf ansforme
SBA Research gGmbH, 2020
const encrypt = async (chunk: Uint8Array, chunkIndex: number) => { return await this.keyChain.encrypt( chunk, file.nonce, // A random, 12-byte nonce! 'fileContents’, chunkIndex // This will be part of the nonce. ); };
Classification: Public 19
Fi FileR eRead eader er API: I: Brow
ser Sup uppor
SBA Research gGmbH, 2020
Classification: Public 20
Dow
nloa
: Dow
nload ad a as s Blob?
SBA Research gGmbH, 2020
async blobDownload(file: File) { const response = await this.$http.get( `/api/v1/files/${file.id}`, { responseType: 'blob' }, ); const cleartext = await this.keyChain.getDecryptedResponseData( response.data, file.nonce, file.totalClearTextSizeInBytes, ); await saveFile(cleartext, file.name, file.mimeType); }
Classification: Public 21
Dow
nloa
: Crea reati ting ng a a ”S ”Save ave as” D s” Dialog
SBA Research gGmbH, 2020
export default async function saveFile(plaintext: ArrayBuffer, fileName: string, fileType: string) { return new Promise((resolve, reject) => { const dataView = new DataView(plaintext); const blob = new Blob([dataView], { type: fileType }); const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = fileName; document.body.appendChild(a); a.click(); URL.revokeObjectURL(downloadUrl); setTimeout(resolve, 100); }); }
GitHub Gist: Downloading an Array Buffer via a "Save as" Dialog in the Browser: https://gist.github.com/thomaskonrad/37772256a86d9f5b0472b3c2440cffee
Classification: Public 22
Dow
nloa
: Dow
nsides es of th f this s Approa
SBA Research gGmbH, 2020
Classification: Public 23
Ser ervi vice ce Worker ers: s: A Quick P k Pri rimer mer
background of your website
the server
access
SBA Research gGmbH, 2020
Classification: Public 24
Ser ervi vice ce Worker ers: s: A Quick P k Pri rimer mer
available (Progressive Web Apps, PWA)
SBA Research gGmbH, 2020
Classification: Public 25
Ser ervi vice ce Worker ers: s: A Quick P k Pri rimer mer
SBA Research gGmbH, 2020
Classification: Public 26
Regi egisteri ering g a a Ser ervi vice ce Wor
er
SBA Research gGmbH, 2020
if ('serviceWorker' in navigator) { // Register a service worker hosted at the root of the // site using a more restrictive scope. navigator.serviceWorker.register('/sw.js’, { scope: './’ }).then((registration) => { console.log(‘Registration succeeded:', registration); }, /*catch*/ (error) => { console.log('Service worker registration failed:', error); }); } else { console.log('Service workers are not supported.'); }
Source: https://developer.mozilla.org/en- US/docs/Web/API/ServiceWorkerContainer/register
Classification: Public 27
Acti ctivat ate e th the e Ser ervi vice ce Wor
er Immed Immediat atel ely
SBA Research gGmbH, 2020
// In sw.js self.addEventListener('install', (event) => { // Activate the Service Worker as soon as it’s // finished installing. event.waitUntil(self.skipWaiting()); }); self.addEventListener('activate', (event) => { // Make the Service Worker become immediately // available to all pages. event.waitUntil(self.clients.claim()); });
Classification: Public 28
Dow
nloa
: Decr ecryp ypt t the the Fi File e in th the e SW
SBA Research gGmbH, 2020
Classification: Public 29
Ser ervi vice ce Wor
ers: s: Brow
ser Sup uppor
SBA Research gGmbH, 2020
Classification: Public 30
Dow
nloa
: The ReadableStream API API
through the body property of the Response
SBA Research gGmbH, 2020
const response = await fetch(file.url, requestOptions); const readableStream: ReadableStream<Uint8Array> = response.body;
Classification: Public 31
Dow
nloa
: The Decr ecryp ypti tion
tream
SBA Research gGmbH, 2020
public async getDecryptionStream( responseBody: ReadableStream<Uint8Array>,
): Promise<ReadableStream> { await this.initializeAEADIfNotInitialized(); const slicesStream = transformStream( responseBody, new StreamSlicer(this.chunkSizeInBytes + this.tagLengthInBytes), ); return transformStream( slicesStream, new DecryptStreamController(this, objectNonce, 'fileContents'), ); }
GitHub Gist - Splits a ReadableStream into chunks of a given size.: https://gist.github.com/thomaskonrad/b8f30e3f18ea2f538bdf422203bdc473
Classification: Public 32
Dow
nloa
: The
DecryptStreamController
SBA Research gGmbH, 2020
export default class DecryptStreamController { public async transform(chunk: any, controller: any){ const clearText = await this.keyChain.decrypt( chunk, this.objectNonce, this.attributeName, this.chunkIndex ); controller.enqueue(Buffer.from(clearText)); this.chunkIndex ++; } }
Classification: Public 33
ReadableStream API API: Br Browser Suppor Support
SBA Research gGmbH, 2020
Classification: Public 34
Req equiremen rements ts
SBA Research gGmbH, 2020
Ensure confidentiality, integrity, and authenticity Encrypt the file in the browser Support big files (> 10 GB) Support old browsers as well as possible Securely distribute keys
Classification: Public 35
Suppor
ting ng Ol Old B Brow
sers
SBA Research gGmbH, 2020
Classification: Public 36
Rememb emember? er? Creati reating g a ”S ”Save ave as” s” Dialog
SBA Research gGmbH, 2020
export default async function saveFile(plaintext: ArrayBuffer, fileName: string, fileType: string) { return new Promise((resolve, reject) => { const dataView = new DataView(plaintext); const blob = new Blob([dataView], { type: fileType }); const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = fileName; document.body.appendChild(a); a.click(); URL.revokeObjectURL(downloadUrl); setTimeout(resolve, 100); }); }
GitHub Gist: Downloading an Array Buffer via a "Save as" Dialog in the Browser: https://gist.github.com/thomaskonrad/37772256a86d9f5b0472b3c2440cffee
Classification: Public 37
Suppor
ting ng Ol Old B Brow
sers
the file size,
SBA Research gGmbH, 2020
Classification: Public 38
Req equiremen rements ts
SBA Research gGmbH, 2020
Ensure confidentiality, integrity, and authenticity Encrypt the file in the browser Support big files (> 10 GB) Support old browsers as well as possible Securely distribute keys
Classification: Public 39
Shari aring ng the the Mas Master er Key ey
transferred to the server
SBA Research gGmbH, 2020
Classification: Public 40
The The URL
https://example.org/path/to/resource?a=b&c=d#x
SBA Research gGmbH, 2020
Scheme Domain Resource path Query Fragment
Classification: Public 41
The The URL L Fragmen gment t Stays s in th the e Browser ser
SBA Research gGmbH, 2020
Classification: Public 42
A Fi File e URL L in n Fi Firef refox
end
https://send.firefox.com/download/9b91257c383393cb/#MlbZpG67ubEXXGTmM-p_6w
SBA Research gGmbH, 2020
Access token Key
Classification: Public 43
Req equiremen rements ts
SBA Research gGmbH, 2020
Ensure confidentiality, integrity, and authenticity Encrypt the file in the browser Support big files (> 10 GB) Support old browsers as well as possible Securely distribute keys
Classification: Public 44 SBA Research gGmbH, 2020
Photo by Yancy Min on Unsplash
Classification: Public 45
What we have learned today
SBA Research gGmbH, 2020
Classification: Public 46
Wrap apping ng up up
authenticity
authenticity
you encrypt something
SBA Research gGmbH, 2020
Classification: Public 47
Wrap apping ng up up
random bytes
crypto.subtle.encrypt and crypto.subtle.decrypt to encrypt data in the browser
SBA Research gGmbH, 2020
Classification: Public 48
Wrap apping ng up up
an <input type="file"/> input
blob download
SBA Research gGmbH, 2020
Classification: Public 49
sec4 ec4dev v Boo
tcamp: : A Builder’s er’s Gu Guide e to Singl gle e Page ge Applicati cation n Secu ecuri rity ty
SBA Research gGmbH, 2020
content
Classification: Public 50 SBA Research gGmbH, 2020
Thomas Konrad SBA Research tkonrad@sba-research.org @_thomaskonrad
Photo by Morvanic Lee on Unsplash