UNPKG

@tidecloak/js

Version:

TideCloak client side JS SDK

219 lines 11.4 kB
"use strict"; // // Tide Protocol - Infrastructure for a TRUE Zero-Trust paradigm // Copyright (C) 2022 Tide Foundation Ltd // // This program is free software and is subject to the terms of // the Tide Community Open Code License as published by the // Tide Foundation Limited. You may modify it and redistribute // it in accordance with and subject to the terms of that License. // This program is distributed WITHOUT WARRANTY of any kind, // including without any implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // See the Tide Community Open Code License for more details. // You should have received a copy of the Tide Community Open // Code License along with this program. // If not, see https://tide.org/licenses_tcoc2-0-0-en // var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const NodeClient_js_1 = __importDefault(require("../Clients/NodeClient.js")); const OrkInfo_js_1 = __importDefault(require("../Models/Infos/OrkInfo.js")); const KeyGeneration_js_1 = require("../Math/KeyGeneration.js"); const Utils_js_1 = require("../Tools/Utils.js"); const Math_js_1 = require("../Cryptide/Math.js"); const Ed25519_js_1 = require("../Cryptide/Ed25519.js"); const Serialization_js_1 = require("../Cryptide/Serialization.js"); const index_js_1 = require("../Cryptide/index.js"); const VoucherFlow_js_1 = __importDefault(require("./VoucherFlows/VoucherFlow.js")); const NetworkClient_js_1 = __importDefault(require("../Clients/NetworkClient.js")); const SimulatorFlow_js_1 = __importDefault(require("./SimulatorFlow.js")); const Ed25519Components_js_1 = require("../Cryptide/Components/Schemes/Ed25519/Ed25519Components.js"); class dKeyGenerationFlow { /** * @param {string} uid * @param {string} gVRK * @param {OrkInfo[]} orks * @param {Uint8Array} sessKey * @param {Point} gSessKeyPub * @param {string} purpose * @param {string} voucherURL * @param {string[]} emails * @param {(0|1)[]} bitwise * @param {string[]} selfRequesti * @param {Point} userPublic * @param {number} expired */ constructor(uid, gVRK, orks, sessKey, gSessKeyPub, purpose, voucherURL, emails = null, bitwise = null, selfRequesti = [], userPublic = null, expired = null) { if (expired != null) if (expired < (0, Utils_js_1.CurrentTime)()) throw Error("Time has expired. Try again"); if (orks.length < Utils_js_1.Max) throw Error("Not enough orks available to create an account"); this.uid = uid; this.gVRK = Ed25519_js_1.Point.fromBase64(gVRK); this.bitwise = bitwise == null ? null : bitwise; this.orks = (0, Utils_js_1.sortORKs)(orks); this.selfRequesti = selfRequesti; this.userPublic = userPublic; this.sessKey = sessKey; this.gSessKeyPub = gSessKeyPub; this.purpose = purpose; this.voucherURL = voucherURL; this.emails = emails; this.getVouchersFunction = null; this.savedOrkPublics = this.orks.map(o => o.orkPublic); this.orksToWaitFor = purpose == "NEW" ? Utils_js_1.Max : Utils_js_1.Threshold; } static async ReserveUID(uid, voucherURL, gSessKeyPub) { const simClient = new NetworkClient_js_1.default(); const availableOrks = (await simClient.FindReservers(uid)); const pre_activeOrks = SimulatorFlow_js_1.default.FilterInactiveOrks(availableOrks); const reservers = availableOrks.slice(0, 5); // super unlikely all 5 orks are down const voucherFlow = new VoucherFlow_js_1.default(reservers.map(o => o.orkPaymentPublic), voucherURL, "reserve"); const vouchers = (await voucherFlow.GetVouchers()).vouchers; const reserveClients = reservers.map(r => new NodeClient_js_1.default(r.orkURL)); const pre_ReserveResponses = reserveClients.map((client, i) => client.ReserveUID(i, uid, 'SESSIONID', vouchers.toORK(i), gSessKeyPub)); const { fulfilledResponses } = await (0, Utils_js_1.WaitForNumberofORKs)(reservers, pre_ReserveResponses, "NEW", 1); const lowestProximityresConf = fulfilledResponses.reduce((prev, curr) => (curr.proximity < prev.proximity ? curr : prev)); // get closest proximity return { reservationConfirmation: lowestProximityresConf.toString(), activeOrks: (await pre_activeOrks) }; } /** * @param {(request: string) => Promise<string> } getVouchersFunction * @returns {dKeyGenerationFlow} */ setVoucherRetrievalFunction(getVouchersFunction) { this.getVouchersFunction = getVouchersFunction; return this; } /** * @param {number} numKeys * @param {Point[]} gMultipliers * @param {string} reservationAuth */ async GenShard(numKeys, gMultipliers, reservationAuth = null) { const clients = this.orks.map(ork => new NodeClient_js_1.default(ork.orkURL)); // create node clients let vouchers; if (this.purpose == "NEW") { if (reservationAuth == null) throw Error("reservationAuth must not be null for new keys"); const voucherFlow = new VoucherFlow_js_1.default(this.orks.map(o => o.orkPaymentPublic), this.voucherURL, "signup"); vouchers = (await voucherFlow.GetVouchers()).vouchers; } let blurs = []; const gBluredMultipliers = gMultipliers.map(gMul => { if (gMul != null) { const b = (0, Math_js_1.RandomBigInt)(); blurs.push(b); return gMul.mul(b); } else { blurs.push(null); return null; } }); const ids = this.orks.map(ork => ork.orkID); let count = 0; const pre_GenShardResponses = clients.map((client, i) => { let auth = ""; if (this.bitwise != null) { if (this.bitwise[i] == true) { auth = this.selfRequesti[count]; count++; } } if (this.purpose == "NEW") return client.GenShard(i, this.uid, vouchers.toORK(i), reservationAuth, this.purpose, ids, numKeys, gBluredMultipliers, this.gSessKeyPub); else return client.UpdateShard(i, this.uid, this.purpose, gBluredMultipliers, auth, this.gSessKeyPub, auth == ""); }); // create prkECDHi here to save time const prkECHi = await index_js_1.DH.generateECDHi(this.orks.map(o => o.orkPublic), this.sessKey); const { fulfilledResponses, bitwise } = await (0, Utils_js_1.WaitForNumberofORKs)(this.orks, pre_GenShardResponses, this.purpose, this.orksToWaitFor, null, prkECHi, null, this.purpose == "NEW" ? null : (result) => { if (result.tag == true) return false; // tag == "", inactive ork, don't add to promises to wait for else return true; // active ork }); this.gState = { bitwise: bitwise, keyUse: ["", ""], // not VVK, doesn't matter prkECHi, ...await (0, KeyGeneration_js_1.ProcessShards)(fulfilledResponses, bitwise, this.sessKey) }; const UnblurredGMultipled = this.gState.gMultiplied.map((gMultiplied, i) => { if (gMultiplied != null) { return gMultiplied.public.divide(blurs[i]); } else { return null; } }); return { gMultiplied: UnblurredGMultipled, gK: this.gState.gK }; } /** * @param {string} auth * @param {string} authSig */ async GenVVKShard(auth, authSig) { const clients = this.orks.map(ork => new NodeClient_js_1.default(ork.orkURL)); // create node clients const { vouchers } = await (new VoucherFlow_js_1.default(this.orks.map(o => o.orkPaymentPublic), this.voucherURL, "vendorcreation").GetVouchers(this.getVouchersFunction)); const ids = this.orks.map(ork => ork.orkID); const pre_GenShardResponses = clients.map((client, i) => client.GenVVKShard(this.uid, this.gVRK, auth, authSig, ids, vouchers.toORK(i))); // create prkECDHi here to save time const prkECHi = await index_js_1.DH.generateECDHi(this.orks.map(o => o.orkPublic), this.sessKey); const fulfilledResponses = await Promise.all(pre_GenShardResponses); const bitwise = new Array(Utils_js_1.Max).fill(1); // all must respond this.gState = { bitwise: bitwise, prkECHi, ...await (0, KeyGeneration_js_1.ProcessShards)(fulfilledResponses, bitwise, this.sessKey, true) }; return { gK: this.gState.gK }; } /** * @param {string} authorizer * @param {string} keyType */ async SetShard(authorizer, keyType) { if (this.gState == undefined) throw Error("GState is not defined"); const clients = this.orks.map(ork => new NodeClient_js_1.default(ork.orkURL)); // create node clients const randomisedEmails = (0, Utils_js_1.randomiseEmails)(this.emails); // No pretty place to put this line const pre_encAuthi = this.gState.prkECHi.map(async (dh, i) => await index_js_1.AES.encryptData(JSON.stringify({ 'GR': this.gState.gR.toBase64(), 'Auth': authorizer, 'Email': randomisedEmails[i], 'InitGVRK_GR': keyType == "VVK" ? this.gState.VRK_gR.map(gr => gr.toBase64()) : [], }), dh)); const encAuthi = await Promise.all(pre_encAuthi); const pre_SendShardResponses = clients.map((client, i) => client.SetShard(this.uid, this.gState.sortedShares[i], encAuthi[i], this.gSessKeyPub, keyType)); const SendShardResponses = await Promise.all(pre_SendShardResponses); this.sState = await (0, KeyGeneration_js_1.CommitShardPrep)(this.uid, SendShardResponses, this.savedOrkPublics, this.gState.timestamp, this.gState.gR, this.userPublic == null ? this.gState.gK : this.userPublic, this.bitwise == null ? this.gState.bitwise : (0, Serialization_js_1.bitArrayAND)(this.gState.bitwise, this.bitwise), // given a list of orks that responded to genshard, and a list that were requested to be active, determine the particpating orks this.purpose, this.sessKey, this.gSessKeyPub, keyType == "VVK" ? this.gState.VRK_gR : null, keyType == "VVK" ? authorizer : null); this.gState = undefined; const resp = { "VRK_SIGNATURE_TO_STORE": this.sState.vrkSignatureToStore, "M": (0, Serialization_js_1.bytesToBase64)(this.sState.M), "FIRST_ADMIN": this.sState.firstAdmin }; return resp; } /** */ async Commit() { if (this.sState == undefined) throw Error("SState is undefined"); const clients = this.orks.map(ork => new NodeClient_js_1.default(ork.orkURL)); // create node clients const pre_CommitResponses = clients.map(client => client.Commit(this.uid, this.sState.S, this.sState.gSessKeyPub)); await Promise.all(pre_CommitResponses); } } exports.default = dKeyGenerationFlow; //# sourceMappingURL=dKeyGenerationFlow.js.map