One Calendar is a privacy-first calendar web app built with Next.js. It has modern security features, including e2ee, password-protected sharing, and self-destructing share links 馃搮 calendar.xyehr.cn
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 75 lines 1.7 kB view raw
1export type EncryptedPayload = { 2 ciphertext: string 3 iv: string 4} 5 6function b64(u: Uint8Array) { 7 return btoa(String.fromCharCode(...u)) 8} 9 10function ub64(s: string) { 11 return new Uint8Array( 12 atob(s) 13 .split('') 14 .map((c) => c.charCodeAt(0)), 15 ) 16} 17 18async function derive(password: string, salt: Uint8Array) { 19 const k = await crypto.subtle.importKey( 20 'raw', 21 new TextEncoder().encode(password), 22 'PBKDF2', 23 false, 24 ['deriveKey'], 25 ) 26 return crypto.subtle.deriveKey( 27 { name: 'PBKDF2', salt, iterations: 250000, hash: 'SHA-256' }, 28 k, 29 { name: 'AES-GCM', length: 256 }, 30 false, 31 ['encrypt', 'decrypt'], 32 ) 33} 34 35export async function encryptPayload( 36 password: string, 37 text: string, 38): Promise<EncryptedPayload> { 39 const salt = crypto.getRandomValues(new Uint8Array(16)) 40 const iv = crypto.getRandomValues(new Uint8Array(12)) 41 const key = await derive(password, salt) 42 const ct = await crypto.subtle.encrypt( 43 { name: 'AES-GCM', iv }, 44 key, 45 new TextEncoder().encode(text), 46 ) 47 return { 48 ciphertext: JSON.stringify({ 49 v: 1, 50 salt: b64(salt), 51 ct: b64(new Uint8Array(ct)), 52 }), 53 iv: b64(iv), 54 } 55} 56 57export async function decryptPayload( 58 password: string, 59 ciphertext: string, 60 iv: string, 61) { 62 const d = JSON.parse(ciphertext) 63 const key = await derive(password, ub64(d.salt)) 64 const pt = await crypto.subtle.decrypt( 65 { name: 'AES-GCM', iv: ub64(iv) }, 66 key, 67 ub64(d.ct), 68 ) 69 return new TextDecoder().decode(pt) 70} 71 72export function isEncryptedPayload(value: unknown): value is EncryptedPayload { 73 if (!value || typeof value !== 'object') return false 74 return 'ciphertext' in value && 'iv' in value 75}