UNPKG

tidecloak-js

Version:

TideCloak client side JS SDK

122 lines (103 loc) 4.93 kB
import NodeClient from "../Clients/NodeClient.js"; //TODO: //import { MarkParticipatingORKs } from "../Tools/Utils.js"; import OrkInfo from "../Models/Infos/OrkInfo.js"; import { CurrentTime, WaitForNumberofORKs } from "../Tools/Utils.js"; import { dKeyGenerationFlow } from "../index.js"; import { Point } from "../Cryptide/Ed25519.js"; import { ElGamal } from "../Cryptide/index.js"; import { bytesToBase64 } from "../Cryptide/Serialization.js"; import { CreateGPrismAuth } from "../Cryptide/Math.js"; import dCMKPasswordFlow from "./AuthenticationFlows/dCMKPasswordFlow.js"; import VoucherFlow from "./VoucherFlows/VoucherFlow.js"; import KeyInfo from "../Models/Infos/KeyInfo.js"; import TideKey from "../Cryptide/TideKey.js"; export default class dAccountRecoveryFlow { /** * @param {string} uid * @param {OrkInfo[]} orks * @param {TideKey} sessKey * @param {string} voucherURL */ constructor(uid, orks, sessKey, voucherURL) { // NOTE: User will only EVER click threshold orks, so for keyGen all of those 14 orks MUST be up. An ork cannot go // down between email sending and key recreation. Otherwise process must start again. this.uid = uid; this.orks = orks; this.sessKey = sessKey; this.voucherURL = voucherURL; this.rState = undefined; } async StartAccountRecovery(homeOrkUrl, pollingClient, signal){ const channelId = await pollingClient.EstablishHttpTunnel(this.uid, this.orks.map(o => o.orkID)); const clients = this.orks.map(ork => new NodeClient(ork.orkURL)) // create node clients const voucherFlow = new VoucherFlow(this.orks.map(o => o.orkPaymentPublic), this.voucherURL, "updateaccount"); const {vouchers} = await voucherFlow.GetVouchers(); // Here we also find out which ORKs are up const pre_ConvertResponses = clients.map((client, i) => client.RecoverAccount(i, this.uid, this.sessKey.get_public_component().public, channelId, homeOrkUrl, vouchers.toORK(i))); await WaitForNumberofORKs(this.orks.slice(), pre_ConvertResponses, "CMK", null, null, null, 30000); // we DON'T want to modify the orks array for this specific flow - we need it in full for the key gen flow below if ( signal.aborted) { return { status: "cancelled" } } return {channelId} } /** * @returns */ async RetrieveEmailAuths( channelId, progressTrackerCallback, pollingClient, signal) { // Start the long polling requests const { encRequests, bitwise, status } = await pollingClient.pollServer(channelId, progressTrackerCallback, signal); if ( status === "recovered"){ const pre_decData = encRequests.map(async (request) => bytesToBase64(await ElGamal.decryptData(request, this.sessKey.get_private_component().rawBytes))); const selfRequesti = await Promise.all(pre_decData); const expiry = CurrentTime() + 3580; this.rState = { bitwise, selfRequesti, expiry, } } // return the status, "recovered" or "cancelled" return { status }; } /** * @param {Point} currentUserPublic * @param {Point} newGPass * @param {Point} gVRK */ async GenerateNewPrism(currentUserPublic, newGPass, gVRK) { if (this.rState == undefined) throw Error("RState must be defined first"); if (this.rState.expiry < CurrentTime()) throw Error("Took too long to open emails.") const newPrismFlow = new dKeyGenerationFlow( this.uid, gVRK.toBase64(), this.orks, this.sessKey.get_private_component().rawBytes, this.sessKey.get_public_component().public, "RECOVER", this.voucherURL, null, this.rState.bitwise, this.rState.selfRequesti, currentUserPublic, this.rState.expiry ); const { gMultiplied } = await newPrismFlow.GenShard(1, [newGPass]); const newGPrismAuth = await CreateGPrismAuth(gMultiplied[0]); const keyM = await newPrismFlow.SetShard(newGPrismAuth.toBase64(), "Prism"); const keyInfo = new KeyInfo(this.uid, currentUserPublic, keyM, this.orks); // test new account const testAuthFlow = new dCMKPasswordFlow(keyInfo, "TEST SESSION", true, false, this.voucherURL); await testAuthFlow.Convert(this.sessKey, newGPass, currentUserPublic, false); await testAuthFlow.Authenticate(gVRK); await newPrismFlow.Commit(); } async CleanUpRecoverySession(channelId){ const homeOrkUrl = window.location.origin; const homeOrkClient = new NodeClient(homeOrkUrl); await homeOrkClient.FinalizeAccountRecovery(this.uid, channelId); } }