diff --git a/public/js/main.js b/public/js/main.js index 789ee50..e327ace 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -28,11 +28,25 @@ let certDB = null; let localCert = null; // Utilities -function getCertificateChecksum(cert) { - let fp = cert.getFingerprints().reduce((res, curr) => - curr.algorithm === 'sha-256' ? curr : res, null); - console.assert(fp !== null, 'Certificate does not have a sha256sum'); - return fp.value.split(':').join(''); +function getCertificateChecksumFromSDP(desc) { + let fp = desc.sdp.split('\n').reduce((res, curr) => + curr.startsWith('a=fingerprint:sha-256 ') ? curr : res, null); + console.assert(fp !== null, 'Description does not have a sha256sum'); + return fp.trim().split(' ')[1].split(':').join('').toLowerCase(); +} + +async function getCertificateChecksum(cert) { + if (cert.getFingerprints) { + let fp = cert.getFingerprints().reduce((res, curr) => + curr.algorithm === 'sha-256' ? curr : res, null); + console.assert(fp !== null, 'Certificate does not have a sha256sum'); + return fp.value.split(':').join(''); + } else { // Firefox shim + let testConn = new RTCPeerConnection({certificates: [cert]}); + let desc = await testConn.createOffer(); + testConn.close(); + return getCertificateChecksumFromSDP(desc); + } } // IndexedDB @@ -87,8 +101,10 @@ function onLoadCert() { loadCertificate(certDB, cert => { if (cert !== null) { - console.log('Loaded certificate:', getCertificateChecksum(cert)); - console.log('Expires:', cert.expires); + getCertificateChecksum(cert).then(fp => { + let ts = new Date(cert.expires).toISOString(); + console.log(`Loaded certificate (expires ${ts}): ${fp}`); + }); localCert = cert; setCertStatusDisplay('Loaded'); setButtonClickable('certUpload', true); @@ -128,8 +144,10 @@ function onNewCert() { hash: 'SHA-256', namedCurve: 'P-256', }).then(cert => { - console.log('Generated new certificate:', getCertificateChecksum(cert)); - console.log('Expires:', cert.expires); + getCertificateChecksum(cert).then(fp => { + let ts = new Date(cert.expires).toISOString(); + console.log(`Generated new certificate (expires ${ts}): ${fp}`); + }); localCert = cert; setCertStatusDisplay('Available'); setButtonClickable('certUpload', true); @@ -142,50 +160,53 @@ function onNewCert() { // Upload Button function onUploadCert() { console.assert(localCert !== null, 'No local certificate available'); - fetch('/keys', { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - 'key': getCertificateChecksum(localCert), - 'expires': localCert.expires, - }), - }).then(res => { - if (res.status === 200) { - setCertStatusDisplay('Uploaded'); - } else { - res.json().then(res => { - setCertStatusDisplay(`Upload Failed (${res.status})`); - }) - } + getCertificateChecksum(localCert).then(fp => { + fetch('/keys', { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + 'key': fp, + 'expires': localCert.expires, + }), + }).then(res => { + if (res.status === 200) { + setCertStatusDisplay('Uploaded'); + } else { + res.json().then(res => { + setCertStatusDisplay(`Upload Failed (${res.status})`); + }) + } + }) }); } // Clear Button function onClearCert() { console.assert(localCert !== null, 'No local certificate available'); - let fp = getCertificateChecksum(localCert); - fetch(`/keys/${fp}`, { - method: 'DELETE', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - }, - }).then(res => { - if (res.status === 200) { - setCertStatusDisplay('Cleared'); - localCert = null; - setButtonClickable('certUpload', false); - setButtonClickable('certClear', false); - setButtonClickable('certSave', false); - setButtonClickable('chatJoin', false); - } else { - res.json().then(res => { - setCertStatusDisplay(`Delete Failed (${res.status})`); - }) - } + getCertificateChecksum(localCert).then(fp => { + fetch(`/keys/${fp}`, { + method: 'DELETE', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + }).then(res => { + if (res.status === 200) { + setCertStatusDisplay('Cleared'); + localCert = null; + setButtonClickable('certUpload', false); + setButtonClickable('certClear', false); + setButtonClickable('certSave', false); + setButtonClickable('chatJoin', false); + } else { + res.json().then(res => { + setCertStatusDisplay(`Delete Failed (${res.status})`); + }) + } + }); }); } @@ -202,13 +223,6 @@ function setChatStatusDisplay(status) { document.getElementById('chatStatus').innerText = status; } -function getCertificateChecksumFromSDP(desc) { - let fp = desc.sdp.split('\n').reduce((res, curr) => - curr.startsWith('a=fingerprint:sha-256 ') ? curr : res, null); - console.assert(fp !== null, 'Description does not have a sha256sum'); - return fp.trim().split(' ')[1].split(':').join('').toLowerCase(); -} - function verifyFingerprint(desc) { let fp = getCertificateChecksumFromSDP(desc); fetch(`/keys/${fp}`, { @@ -319,6 +333,9 @@ function onRTCConnectionStateChange(event) { let state = connection.connectionState; console.log('WebRTC connection state update:', state); + if (state === 'failed') { + onLeaveChat(); + } } // Join Button