diff --git a/javascript/src/iframe/viamapi-iframe.js b/javascript/src/iframe/viamapi-iframe.js index f66bd71da8e7067ac14972853aeb910cabe8b036..1dbf23255846c48509596e4fcd46afe84d19a64d 100644 --- a/javascript/src/iframe/viamapi-iframe.js +++ b/javascript/src/iframe/viamapi-iframe.js @@ -6,7 +6,7 @@ import { stringToUtf8Base64, utf8Base64ToString, base64ToByteArray, - byteArrayToBase64 + byteArrayToBase64, } from "../utilities/stringUtilities"; import { extractMessageID } from "../helpers/mailparser"; @@ -17,7 +17,7 @@ import { destroyIdentityFromLocalStorage, encodeResponse, listIdentitiesFromLocalStorage, - makeid + makeid, } from "../utilities/appUtility"; import { LOGIN_MODES } from "../constants/authentication"; import { @@ -29,7 +29,7 @@ import { encryptMessage, parseCertificate, signEmail, - verifySMIME + verifySMIME, } from "../utilities/signingUtilities"; import { signPdf } from "../utilities/pdfUtilities"; import CryptoData from "../CryptoData"; @@ -37,14 +37,14 @@ import Identity from "../Identity"; import { STATUS_DEVICE_REVOKED, STATUS_USER_NOT_ACTIVATED, - STATUS_USER_BLOCKED + STATUS_USER_BLOCKED, } from "../constants/statuses"; import generateQrCode from "../utilities/generateQrCode"; import { generateRecoveryKey, - divideSecretToShares, - combineSecret, - encryptShare + getRecoveryKeyShares, + checkRecoveryKeyCombine, + encryptShare, } from "../utilities/secrets"; const penpalMethods = require("../../temp/penpal-methods").default; @@ -109,7 +109,7 @@ function setIdentityInLocalStorage(identityToStore, extendKey = true) { } return encryptMessage(serializedIdentity, pinCode, "identity").then( - encryptedIdentity => { + (encryptedIdentity) => { let success = true; if (extendKey === true) { success = extendPinCodeTtl(key, pinCode); @@ -129,13 +129,13 @@ function setIdentityInLocalStorage(identityToStore, extendKey = true) { } function getProfileData(identity) { - return new Penpal.Promise(executeResultUpper => { + return new Penpal.Promise((executeResultUpper) => { executeRestfulFunction( "private", viamApi, viamApi.identityGetIdentityProfileData, null - ).then(executeResult => { + ).then((executeResult) => { if (executeResult.code === "200") { const listItem = {}; @@ -232,7 +232,7 @@ function createEvent(actionId, type, payloads) { actionID: actionId, type, stamp: new Date().getTime(), - payloads + payloads, }; } @@ -292,7 +292,7 @@ async function executeRestfulFunction(type, that, fn, config, ...args) { const { currentlyAuthenticatedIdentity, viamApi, - currentlyLoadedIdentity + currentlyLoadedIdentity, } = window; let response; try { @@ -306,7 +306,7 @@ async function executeRestfulFunction(type, that, fn, config, ...args) { const data = { data: "", code: "999", - status: error.message + status: error.message, }; return data; } @@ -371,15 +371,15 @@ async function executeRestfulFunction(type, that, fn, config, ...args) { window.executeRestfulFunction = executeRestfulFunction; function loadIdentityInternal(identityKey, pinCode) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { getIdentityFromLocalStorage(identityKey, pinCode) - .then(async loadedIdentity => { + .then(async (loadedIdentity) => { if (loadedIdentity == null) { result({ data: "", code: "400", status: - "Please restore or authorize your account via another device." + "Please restore or authorize your account via another device.", }); } localStorage.removeItem("attempt"); @@ -407,25 +407,25 @@ function loadIdentityInternal(identityKey, pinCode) { data: { authentication: { publicKey, - x509Certificate - } + x509Certificate, + }, }, code: "200", - status: "Identity loaded" + status: "Identity loaded", }); }) - .catch(e => { + .catch((e) => { result({ data: "", code: "400", - status: "" + e + status: "" + e, }); }); }); } function getCertificateForPassport(passportUUID, internal) { - return new Penpal.Promise(certificateResult => { + return new Penpal.Promise((certificateResult) => { if (window.currentlyAuthenticatedIdentity === null) { return { data: "", code: "400", status: "Identity not authenticated" }; } @@ -433,7 +433,7 @@ function getCertificateForPassport(passportUUID, internal) { const passportIdentity = window.currentlyAuthenticatedIdentity; const passport = passportIdentity.getPassport(passportUUID); if (passport === undefined || passport === null) { - createPassportCertificate(passportUUID).then(function(keys) { + createPassportCertificate(passportUUID).then(function (keys) { const cryptoData = new CryptoData(); cryptoData.setPublicKey(keys["publicKeyPEM"]); cryptoData.setPrivateKey(keys["privateKeyPEM"]); @@ -447,7 +447,7 @@ function getCertificateForPassport(passportUUID, internal) { null, btoa(certificate), passportUUID - ).then(executeResult => { + ).then((executeResult) => { if (executeResult.code === "200") { const signedCertificate = atob( executeResult.data["SignedCertificate"] @@ -469,7 +469,7 @@ function getCertificateForPassport(passportUUID, internal) { passportIdentity.setPassport(passportUUID, cryptoData); - getProfileData(passportIdentity).then(executeResult1 => { + getProfileData(passportIdentity).then((executeResult1) => { setIdentityInLocalStorage(passportIdentity) .then(() => { window.currentlyAuthenticatedIdentity = passportIdentity; @@ -486,14 +486,14 @@ function getCertificateForPassport(passportUUID, internal) { certificateResult({ data: copyOfCryptoData, code: "200", - status: "Certificate got" + status: "Certificate got", }); }) - .catch(e => { + .catch((e) => { certificateResult({ data: "", code: "400", - status: "Can not store certificate " + e + status: "Can not store certificate " + e, }); }); }); @@ -512,7 +512,7 @@ function getCertificateForPassport(passportUUID, internal) { certificateResult({ data: copyOfCryptoData, code: "200", - status: "Certificate got" + status: "Certificate got", }); } }); @@ -550,8 +550,8 @@ const connection = Penpal.connectToParent({ }, ...penpalMethods, createIdentity(pinCode) { - return new Penpal.Promise(result => { - createPassportCertificate(makeid()).then(function(keys) { + return new Penpal.Promise((result) => { + createPassportCertificate(makeid()).then(function (keys) { const newIdentity = new Identity(); const cryptoData = new CryptoData(); cryptoData.setPublicKey(keys["publicKeyPEM"]); @@ -574,17 +574,17 @@ const connection = Penpal.connectToParent({ data: { authentication: { publicKey, - x509Certificate - } + x509Certificate, + }, }, code: "200", - status: "Identity created" + status: "Identity created", }); }); }); }, listIdentities() { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { const identities = listIdentitiesFromLocalStorage(); result({ data: identities, code: "200", status: "Identities listed" }); }); @@ -628,7 +628,7 @@ const connection = Penpal.connectToParent({ } }, getIdentityProfile(identityKey) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { const serializedProfile = localStorage.getItem( "profiles/" + identityKey ); @@ -638,7 +638,7 @@ const connection = Penpal.connectToParent({ result({ data: JSON.parse(serializedProfile), code: "200", - status: "Identities cleared" + status: "Identities cleared", }); } }); @@ -654,7 +654,7 @@ const connection = Penpal.connectToParent({ return encodeResponse("200", "", "Identities cleared"); }, confirmIdentificator(identity, confirmationCodeArg) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity(identity.authentication.publicKey); executeRestfulFunction( @@ -663,13 +663,13 @@ const connection = Penpal.connectToParent({ viamApi.identityConfirmIdentificator, null, confirmationCodeArg - ).then(executeResult => { + ).then((executeResult) => { result(executeResult); }); }); }, identityGetIdentificatorByRegisterToken(identity, tokenArg) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity(identity.authentication.publicKey); executeRestfulFunction( @@ -678,13 +678,13 @@ const connection = Penpal.connectToParent({ viamApi.identityGetIdentificatorByRegisterToken, null, tokenArg - ).then(executeResult => { + ).then((executeResult) => { result(executeResult); }); }); }, submitIdentificator(identity, identificatorArg, registerToken) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity(identity.authentication.publicKey); executeRestfulFunction( @@ -694,7 +694,7 @@ const connection = Penpal.connectToParent({ null, identificatorArg, registerToken - ).then(executeResult => { + ).then((executeResult) => { result(executeResult); }); }); @@ -706,7 +706,7 @@ const connection = Penpal.connectToParent({ emailArg, phonenumberArg ) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity(identity.authentication.publicKey); executeRestfulFunction( @@ -718,7 +718,7 @@ const connection = Penpal.connectToParent({ familynameArg, emailArg, phonenumberArg - ).then(executeResult => { + ).then((executeResult) => { result(executeResult); }); }); @@ -734,7 +734,7 @@ const connection = Penpal.connectToParent({ ); }, agreeOnRegistration(registerIdentity) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity(registerIdentity.authentication.publicKey); executeRestfulFunction( @@ -742,7 +742,7 @@ const connection = Penpal.connectToParent({ viamApi, viamApi.identityAgreeOnRegistration, null - ).then(executeResult => { + ).then((executeResult) => { let sequence = Promise.resolve(); if (executeResult.code === "200") { sequence = sequence.then(() => { @@ -753,18 +753,18 @@ const connection = Penpal.connectToParent({ .then(() => { result(executeResult); }) - .catch(e => { + .catch((e) => { result({ data: "", code: "400", - status: "Can not store identity: " + e + status: "Can not store identity: " + e, }); }); }); }); }, resendConfirmationCode(identity, identificatorArg) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity(identity.authentication.publicKey); executeRestfulFunction( @@ -773,7 +773,7 @@ const connection = Penpal.connectToParent({ viamApi.identityResendConfirmationCode, null, identificatorArg - ).then(executeResult => { + ).then((executeResult) => { result(executeResult); }); }); @@ -783,7 +783,7 @@ const connection = Penpal.connectToParent({ return { data: "", code: "400", - status: "Identity not loaded" + status: "Identity not loaded", }; } @@ -829,7 +829,7 @@ const connection = Penpal.connectToParent({ return responseToClient; }, identityAddNewDevice() { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -838,7 +838,7 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } @@ -846,7 +846,7 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } @@ -856,7 +856,7 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } @@ -865,7 +865,7 @@ const connection = Penpal.connectToParent({ viamApi, viamApi.identityAddNewDevice, null - ).then(async executeResult => { + ).then(async (executeResult) => { if (executeResult.code === "200") { const actionID = executeResult.data["ActionID"]; const QrCode = executeResult.data["QrCode"]; @@ -879,7 +879,7 @@ const connection = Penpal.connectToParent({ }); }, identityDestroyKeysForDevice(authenticationPublicKeyArg) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -887,14 +887,14 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } if (window.loadedIdentities[authenticationPublicKey] === null) { result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } @@ -904,7 +904,7 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } @@ -914,7 +914,7 @@ const connection = Penpal.connectToParent({ viamApi.identityDestroyKeysForDevice, null, btoa(authenticationPublicKeyArg) - ).then(executeResult => { + ).then((executeResult) => { result(executeResult); }); }); @@ -931,7 +931,7 @@ const connection = Penpal.connectToParent({ return { data: "", code: "400", - status: "Identity not loaded" + status: "Identity not loaded", }; } @@ -946,19 +946,19 @@ const connection = Penpal.connectToParent({ window.viamApi, window.viamApi.identityLogout, { - headers + headers, } ); } catch (e) { return { data: "", code: "400", - status: e.message + status: e.message, }; } }, identityRestoreAccess(restoreAccessIdentity, identificator) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setSessionData("", ""); viamApi.setIdentity(restoreAccessIdentity.authentication.publicKey); @@ -968,7 +968,7 @@ const connection = Penpal.connectToParent({ viamApi.identityRestoreAccess, null, identificator - ).then(executeResult => { + ).then((executeResult) => { result(executeResult); }); }); @@ -981,51 +981,42 @@ const connection = Penpal.connectToParent({ window.viamApi.contactsGetTrusteeContactsPublicKeys, null ); - console.log({ response }); const responseData = response.data; - const contactsUuids = Object.keys(responseData); - console.log({ contactsUuids }); - if (!contactsUuids.length) { - return encodeResponse("400", "", response.status); + const trusteesDevices = Object.values(responseData); + + /** Check if there are new trustees without added secret part */ + const hasNewTrustees = trusteesDevices.some( + (device) => !device.hasShamirPart + ); + if (!hasNewTrustees) { + return response; } - const sharesNumber = contactsUuids.length; - const getThreshold = () => - sharesNumber === 3 ? 2 : parseInt(sharesNumber / 2); - const threshold = getThreshold(); - const recoveryKey = generateRecoveryKey(512); - const recoveryKeyShares = divideSecretToShares( + const trusteesUuids = Object.keys(responseData); + const trusteesToDevices = Object.entries(responseData); + const sharesNumber = trusteesUuids.length; + const recoveryKey = generateRecoveryKey(); + const recoveryKeyShares = getRecoveryKeyShares( + recoveryKey, + sharesNumber + ); + const sanityCheckResponse = checkRecoveryKeyCombine( recoveryKey, - sharesNumber, - threshold + recoveryKeyShares ); - // Sanity check - let checkKey; - checkKey = combineSecret(recoveryKeyShares.slice(0, 2)); - if (checkKey !== recoveryKey) { - return encodeResponse("400", "", "First sanity check failed"); - } - checkKey = combineSecret(recoveryKeyShares.slice(0, 1)); - if (checkKey === recoveryKey) { - return encodeResponse("400", "", "Second sanity check failed"); - } - checkKey = combineSecret(recoveryKeyShares); - if (checkKey !== recoveryKey) { - return encodeResponse("400", "", "Third sanity check failed"); + if (sanityCheckResponse.code !== "200") { + return sanityCheckResponse; } - // End of sanity check // Encrypt each share with every publicKey of each contact device - const contactsToDevices = Object.entries(responseData); - console.log({ contactsToDevices }); const shamirPartsList = await Promise.all( - contactsToDevices.map(async ([contactUuid, device], index) => { + trusteesToDevices.map(async ([contactUuid, device], index) => { const deviceIdsToPublicKeys = Object.entries(device); - - const deviceIdsToEncryptedKeysList = await Promise.all( - deviceIdsToPublicKeys.map(async ([deviceId, publicKey]) => { + // Encrypt secret shares in parallel + const deviceIdsToEncryptedPartsList = await Promise.all( + deviceIdsToPublicKeys.map(async ([deviceId, { publicKey }]) => { const encryptedShare = await encryptShare( recoveryKeyShares[index], publicKey @@ -1034,34 +1025,34 @@ const connection = Penpal.connectToParent({ return [deviceId, encryptedShare]; }) ); - - const deviceIdsToEncryptedKeys = Object.fromEntries( - deviceIdsToEncryptedKeysList + // Turn deviceIdsToEncryptedPartsList array to object + const deviceIdsToEncryptedParts = Object.fromEntries( + deviceIdsToEncryptedPartsList ); - return [contactUuid, deviceIdsToEncryptedKeys]; + return [contactUuid, deviceIdsToEncryptedParts]; }) ); + // Turn shamirPartsList array to object const shamirParts = Object.fromEntries(shamirPartsList); - console.log({ shamirParts }); + // Save Shamir parts to database - const savePartsResponse = await executeRestfulFunction( + await executeRestfulFunction( "private", window.viamApi, window.viamApi.contactsSaveShamirParts, null, shamirParts ); - console.log({ savePartsResponse }); + return response; } catch (error) { - console.trace(error); return encodeResponse("400", "", error.message); } }, parseSMIME, getCurrentlyLoggedInUUID() { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -1078,7 +1069,7 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } @@ -1088,12 +1079,12 @@ const connection = Penpal.connectToParent({ result({ data: localStorage.getItem("uuid"), code: "200", - status: "UUID loaded" + status: "UUID loaded", }); }); }, getCertificateByPassport(passportUUID) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -1110,19 +1101,19 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } getCertificateForPassport(passportUUID, false).then( - certificateResult => { + (certificateResult) => { result(certificateResult); } ); }); }, getOneTimeCertificateByPassport(passportUUID, emailArg) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -1139,12 +1130,12 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } getCertificateForPassport(passportUUID, true).then( - certificateResult => { + (certificateResult) => { if (certificateResult.code === "200") { const passportCertificate = certificateResult.data["x509Certificate"]; @@ -1156,7 +1147,7 @@ const connection = Penpal.connectToParent({ emailArg, passportPrivateKey, passportCertificate - ).then(function(keys) { + ).then(function (keys) { const publicKeyOneTime = keys["publicKeyPEM"]; const privateKeyOneTime = keys["privateKeyPEM"]; const certificateOneTime = keys["certificatePEM"]; @@ -1171,7 +1162,7 @@ const connection = Penpal.connectToParent({ result({ data: oneTimeCryptoData, code: "200", - status: "One time certificate generated" + status: "One time certificate generated", }); // Prints PEM formatted signed certificate // -----BEGIN CERTIFICATE-----MIID....7Hyg==-----END CERTIFICATE----- @@ -1180,14 +1171,14 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Can not generate one time certificate" + status: "Can not generate one time certificate", }); } } ); }); }, - verifySMIME: async smimeString => { + verifySMIME: async (smimeString) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -1252,7 +1243,7 @@ const connection = Penpal.connectToParent({ if (signatures) { for (const signature of signatures) { const certificateChain = signature.certificateChainPEM.map( - certificatePEM => { + (certificatePEM) => { const certificate = parseCertificate(certificatePEM); const certificateData = new CertificateData(certificate); return certificateData; @@ -1286,7 +1277,7 @@ const connection = Penpal.connectToParent({ const { x509Certificate: passportCertificate, privateKey: passportPrivateKey, - chain: passportChain + chain: passportChain, } = response.data; const keys = await createOneTimePassportCertificate( @@ -1298,7 +1289,7 @@ const connection = Penpal.connectToParent({ const { privateKeyPEM: privateKeyOneTime, - certificatePEM: certificateOneTime + certificatePEM: certificateOneTime, } = keys; passportChain.push(passportCertificate); @@ -1360,7 +1351,7 @@ const connection = Penpal.connectToParent({ const { x509Certificate: passportCertificate, privateKey: passportPrivateKey, - chain: passportChain + chain: passportChain, } = certResponse.data; const keys = await createOneTimePassportCertificate( @@ -1372,7 +1363,7 @@ const connection = Penpal.connectToParent({ const { privateKeyPEM: privateKeyOneTime, - certificatePEM: certificateOneTime + certificatePEM: certificateOneTime, } = keys; passportChain.reverse(); @@ -1482,7 +1473,7 @@ const connection = Penpal.connectToParent({ const { x509Certificate: passportCertificate, privateKey: passportPrivateKey, - chain: passportChain + chain: passportChain, } = certResponse.data; const keys = await createOneTimePassportCertificate( @@ -1494,7 +1485,7 @@ const connection = Penpal.connectToParent({ const { privateKeyPEM: privateKeyOneTime, - certificatePEM: certificateOneTime + certificatePEM: certificateOneTime, } = keys; passportChain.reverse(); @@ -1578,7 +1569,7 @@ const connection = Penpal.connectToParent({ const vCardAttribs = { ...attribs, passportUUID, - messageUUID + messageUUID, }; let vCardImageData; @@ -1615,7 +1606,7 @@ const connection = Penpal.connectToParent({ vCardImageData = new ImageData({ contentType: "image/png", contentBase64: - "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" //1x1px transparent pixel + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", //1x1px transparent pixel }); } else { const vCardImageResponse = await executeRestfulFunction( @@ -1646,7 +1637,7 @@ const connection = Penpal.connectToParent({ ); qrCodeImageData = new ImageData({ contentType: "image/png", - content: qrCodeBase64Content + content: qrCodeBase64Content, }); } @@ -1660,14 +1651,14 @@ const connection = Penpal.connectToParent({ } const htmlPart = { headers: { - "Content-Type": "text/html" + "Content-Type": "text/html", }, - body: htmlBody + body: htmlBody, }; parts.unshift(htmlPart); } else { console.log("Html body is not passed to signVCard, its value is ", { - html: htmlBody + html: htmlBody, }); } @@ -1677,14 +1668,14 @@ const connection = Penpal.connectToParent({ } const textPart = { headers: { - "Content-Type": "text/plain" + "Content-Type": "text/plain", }, - body: textBody + body: textBody, }; parts.unshift(textPart); } else { console.log("Text body is not passed to signVCard, its value is ", { - text: textBody + text: textBody, }); } @@ -1705,7 +1696,7 @@ const connection = Penpal.connectToParent({ const { x509Certificate: passportCertificate, privateKey: passportPrivateKey, - chain: passportChain + chain: passportChain, } = certResponse.data; const keys = await createOneTimePassportCertificate( @@ -1717,7 +1708,7 @@ const connection = Penpal.connectToParent({ const { privateKeyPEM: privateKeyOneTime, - certificatePEM: certificateOneTime + certificatePEM: certificateOneTime, } = keys; passportChain.reverse(); @@ -1752,7 +1743,7 @@ const connection = Penpal.connectToParent({ "200", { image: signedVCardImageData, - messageUUID: messageUUID + messageUUID: messageUUID, }, "vCard signed" ); @@ -1793,7 +1784,7 @@ const connection = Penpal.connectToParent({ if (signatures) { for (const signature of signatures) { const certificateChain = signature.certificateChainPEM.map( - certificatePEM => { + (certificatePEM) => { const certificate = parseCertificate(certificatePEM); const certificateData = new CertificateData(certificate); return certificateData; @@ -1831,8 +1822,8 @@ const connection = Penpal.connectToParent({ path, passportuuid: passportUUID, contentType, - title - } + title, + }, }; const response = await executeRestfulFunction( "private", @@ -1874,8 +1865,8 @@ const connection = Penpal.connectToParent({ passportuuid: passportUUID, resourceid, contentType, - upload - } + upload, + }, }; const response = await executeRestfulFunction( @@ -1893,7 +1884,7 @@ const connection = Penpal.connectToParent({ return encodeResponse("200", response.data, "Document stored"); }, hasSession() { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -1901,14 +1892,14 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } if (window.loadedIdentities[authenticationPublicKey] === null) { result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } @@ -1918,7 +1909,7 @@ const connection = Penpal.connectToParent({ result({ data: "", code: "400", - status: "Identity not authenticated" + status: "Identity not authenticated", }); } @@ -1927,13 +1918,13 @@ const connection = Penpal.connectToParent({ viamApi, viamApi.identityHasSession, null - ).then(executeResult => { + ).then((executeResult) => { result(executeResult); }); }); }, marketingSignUpIdentificator(identificator, reference) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity("marketingapppublickey"); executeRestfulFunction( @@ -1943,7 +1934,7 @@ const connection = Penpal.connectToParent({ null, identificator, reference - ).then(executeResult => { + ).then((executeResult) => { viamApi.setIdentity(""); viamApi.setSessionData("", ""); result(executeResult); @@ -1951,7 +1942,7 @@ const connection = Penpal.connectToParent({ }); }, marketingGetIdentificatorProfile(identificator, pincode) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity("marketingapppublickey"); executeRestfulFunction( @@ -1961,7 +1952,7 @@ const connection = Penpal.connectToParent({ null, identificator, pincode - ).then(executeResult => { + ).then((executeResult) => { viamApi.setIdentity(""); viamApi.setSessionData("", ""); result(executeResult); @@ -1969,7 +1960,7 @@ const connection = Penpal.connectToParent({ }); }, marketingExecuteEventForIdentificator(identificator, pincode, event) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { viamApi.setIdentity("marketingapppublickey"); executeRestfulFunction( @@ -1980,7 +1971,7 @@ const connection = Penpal.connectToParent({ identificator, pincode, event - ).then(executeResult => { + ).then((executeResult) => { viamApi.setIdentity(""); viamApi.setSessionData("", ""); result(executeResult); @@ -1990,7 +1981,7 @@ const connection = Penpal.connectToParent({ getCurrentlyAuthenticatedIdentity() { const { publicKey, - x509Certificate + x509Certificate, } = window.currentlyAuthenticatedIdentity.authentication; return encodeResponse( @@ -1998,51 +1989,51 @@ const connection = Penpal.connectToParent({ { authentication: { publicKey, - x509Certificate - } + x509Certificate, + }, }, "Currently authenticated identity" ); }, extractMessageID(mime) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { result(extractMessageID(mime)); }); }, stringToUtf8ByteArray(str) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { result(stringToUtf8ByteArray(str)); }); }, utf8ByteArrayToString(ba) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { result(utf8ByteArrayToString(ba)); }); }, stringToUtf8Base64(str) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { result(stringToUtf8Base64(str)); }); }, utf8Base64ToString(strBase64) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { result(utf8Base64ToString(strBase64)); }); }, base64ToByteArray(strBase64) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { result(base64ToByteArray(strBase64)); }); }, byteArrayToBase64(ba) { - return new Penpal.Promise(result => { + return new Penpal.Promise((result) => { result(byteArrayToBase64(ba)); }); }, // Collabora APIs collaboraDiscovery() { - return collaboraApi.discovery().then(apps => apps); + return collaboraApi.discovery().then((apps) => apps); }, // WOPI @@ -2066,7 +2057,7 @@ const connection = Penpal.connectToParent({ return response.data; }, - getPassports: async fileId => { + getPassports: async (fileId) => { const authenticationPublicKey = localStorage.getItem( "authenticatedIdentity" ); @@ -2099,8 +2090,8 @@ const connection = Penpal.connectToParent({ headers: { path, passportuuid: passportUUID, - title - } + title, + }, }; const createDocumentResult = await executeRestfulFunction( "private", @@ -2128,7 +2119,7 @@ const connection = Penpal.connectToParent({ const result = { resourceID, - accessToken + accessToken, }; return encodeResponse("200", result, "ok"); @@ -2170,11 +2161,11 @@ const connection = Penpal.connectToParent({ const response = await wopiAPI.putDocument(resourceID, accessToken, file); return response.data; - } - } + }, + }, }); -connection.promise.then(parent => { +connection.promise.then((parent) => { iframeParent = parent; if (!navigator.cookieEnabled) { @@ -2182,7 +2173,7 @@ connection.promise.then(parent => { return; } - window.addEventListener("storage", event => { + window.addEventListener("storage", (event) => { if (event.key === "authenticatedIdentity" && event.newValue === null) { const publicKey = window.currentlyAuthenticatedIdentity.authentication.publicKey; @@ -2218,18 +2209,20 @@ connection.promise.then(parent => { const pinCode = getPincode(authenticationPublicKey); if (pinCode === "" || pinCode === null) { - loadIdentityInternal(authenticationPublicKey, "00000000").then(result => { - if (result.code !== "200") { - const event = createEvent( - "CanNotGetPincodeForAuthenticatedIdentity", - "IdentityNotLoaded", - [authenticationPublicKey] - ); - parent.onEvent(event); + loadIdentityInternal(authenticationPublicKey, "00000000").then( + (result) => { + if (result.code !== "200") { + const event = createEvent( + "CanNotGetPincodeForAuthenticatedIdentity", + "IdentityNotLoaded", + [authenticationPublicKey] + ); + parent.onEvent(event); + } } - }); + ); } else { - loadIdentityInternal(authenticationPublicKey, pinCode).then(result => { + loadIdentityInternal(authenticationPublicKey, pinCode).then((result) => { if (result.code !== "200") { const event = createEvent( "CanNotLoadIdentity", @@ -2258,7 +2251,7 @@ connection.promise.then(parent => { let previousLocalStorageToken; let previousLocalStorageIdentity; - setInterval(async function() { + setInterval(async function () { if (window.currentlyAuthenticatedIdentity) { const { authentication } = window.currentlyAuthenticatedIdentity; const pinCode = getPincode(authentication.publicKey); @@ -2273,7 +2266,7 @@ connection.promise.then(parent => { if (!identityAuthenticatedEvent && identity) { const event = createEvent("IdentityAuthenticated", "Authenticated", [ - identity.authentication.publicKey + identity.authentication.publicKey, ]); parent.onEvent(event); identityAuthenticatedEvent = true; diff --git a/javascript/src/utilities/secrets.js b/javascript/src/utilities/secrets.js index 49e67cbefd690bc78e236866cfb48fa2edd91ee2..764649eecffbde63c0726baa1b50edd5a89d8725 100644 --- a/javascript/src/utilities/secrets.js +++ b/javascript/src/utilities/secrets.js @@ -1,5 +1,6 @@ -import { encryptMessage } from "./signingUtilities.js"; import secrets from "../lib/secrets"; +import { encryptMessage } from "./signingUtilities.js"; +import { encodeResponse } from "./appUtility"; /** Initialize */ @@ -14,7 +15,7 @@ export const getSecretsConfig = () => secrets.getConfig(); * @param {number} bits * @returns {string} hex */ -export const generateRecoveryKey = bits => secrets.random(bits); +export const generateSecret = bits => secrets.random(bits); /** * Divide a secret expressed in hexadecimal form into numShares number of shares, requiring that threshold number of shares be present for reconstructing the secret @@ -42,3 +43,36 @@ export const combineSecret = shares => secrets.combine(shares); export const encryptShare = async (share, publicKey) => await encryptMessage(share, publicKey, "secretPart"); + +/** Account Recovery key management */ + +export const getSecretThreshold = sharesNumber => + sharesNumber === 3 ? 2 : parseInt(sharesNumber / 2); + +export const generateRecoveryKey = () => { + const recoveryKey = generateSecret(512); + return recoveryKey; +}; + +export const getRecoveryKeyShares = (recoveryKey, sharesNumber) => { + const threshold = getSecretThreshold(sharesNumber); + return divideSecretToShares(recoveryKey, sharesNumber, threshold); +}; + +export const checkRecoveryKeyCombine = (recoveryKey, recoveryKeyShares) => { + let checkKey; + checkKey = combineSecret(recoveryKeyShares.slice(0, 2)); + if (checkKey !== recoveryKey) { + return encodeResponse("400", "", "First sanity check failed"); + } + checkKey = combineSecret(recoveryKeyShares.slice(0, 1)); + if (checkKey === recoveryKey) { + return encodeResponse("400", "", "Second sanity check failed"); + } + checkKey = combineSecret(recoveryKeyShares); + if (checkKey !== recoveryKey) { + return encodeResponse("400", "", "Third sanity check failed"); + } + + return encodeResponse("200", "", "Check passed"); +};