Self-hosted, federated location sharing app and server that prioritizes user privacy and security
end-to-end-encryption location-sharing privacy self-hosted federated

added nonce to auth

+23 -7
+12 -4
app/src/utils/api.ts
··· 76 "sign", 77 ]); 78 79 - const signature = await crypto.subtle.sign("Ed25519", privKey, bodyBytes); 80 - const signature_b64 = bufToBase64(signature); 81 82 const headers = { 83 - "x-auth": JSON.stringify({ user_id, signature: signature_b64 }), 84 "Content-Type": "application/json", // TODO: not always json tho, but does it matter? 85 }; 86 87 const res = await fetch(`${server_url}/${endpoint}`, { 88 method: "POST", 89 headers, 90 - body: bodyBytes, // TODO: do we need to send bodyBytes instead to match server side auth? 91 }); 92 93 if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
··· 76 "sign", 77 ]); 78 79 + const nonce = new Uint8Array(8); 80 + crypto.getRandomValues(nonce); 81 + const data_to_sign = new Uint8Array(bodyBytes.length + nonce.length); 82 + data_to_sign.set(bodyBytes); 83 + data_to_sign.set(nonce, bodyBytes.length); 84 + const signature = await crypto.subtle.sign("Ed25519", privKey, data_to_sign); 85 86 const headers = { 87 + "x-auth": JSON.stringify({ 88 + user_id, 89 + signature: bufToBase64(signature), 90 + nonce: nonce.toBase64(), 91 + }), 92 "Content-Type": "application/json", // TODO: not always json tho, but does it matter? 93 }; 94 95 const res = await fetch(`${server_url}/${endpoint}`, { 96 method: "POST", 97 headers, 98 + body: bodyBytes, 99 }); 100 101 if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
+10 -3
server/src/auth.rs
··· 56 //////////////////////////////////// unsure 57 //////////////////////////////////// 58 59 - let sig_vec = BASE64_STANDARD 60 .decode(&auth_data.signature) 61 .map_err(|e| SrvErr!("base64 decode fail", e))?; 62 let sig_bytes: [u8; 64] = 63 - sig_vec.try_into().map_err(|e| SrvErr!("invalid signature length", e))?; 64 let signature = Signature::from_bytes(&sig_bytes); 65 66 - if let Err(err) = verifying_key.verify_strict(&body_bytes, &signature) { 67 panic!("Signature verification failed: {err}"); 68 } 69
··· 56 //////////////////////////////////// unsure 57 //////////////////////////////////// 58 59 + let sign_vec = BASE64_STANDARD 60 .decode(&auth_data.signature) 61 .map_err(|e| SrvErr!("base64 decode fail", e))?; 62 + let nonce_vec = BASE64_STANDARD 63 + .decode(&auth_data.nonce) 64 + .map_err(|e| SrvErr!("base64 decode fail", e))?; 65 let sig_bytes: [u8; 64] = 66 + sign_vec.try_into().map_err(|e| SrvErr!("invalid signature length", e))?; 67 let signature = Signature::from_bytes(&sig_bytes); 68 69 + let mut combined_vec = Vec::with_capacity(body_bytes.len() + nonce_vec.len()); 70 + combined_vec.extend_from_slice(&body_bytes); 71 + combined_vec.extend_from_slice(&nonce_vec); 72 + 73 + if let Err(err) = verifying_key.verify_strict(&combined_vec, &signature) { 74 panic!("Signature verification failed: {err}"); 75 } 76
+1
server/src/types.rs
··· 26 pub struct AuthData { 27 pub user_id: String, 28 pub signature: String, 29 } 30 31 pub struct RingBuffer {
··· 26 pub struct AuthData { 27 pub user_id: String, 28 pub signature: String, 29 + pub nonce: String, 30 } 31 32 pub struct RingBuffer {