@tidecloak/js
Version:
TideCloak client side JS SDK
132 lines • 7.59 kB
JavaScript
//
// 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
//
import NodeClient from "../../Clients/NodeClient.js";
import { DH, Interpolation } from "../../Cryptide/index.js";
import { AuthenticateBasicReply, AuthenticateConsentReply, CmkConvertReply, PrismConvertReply } from "../../Math/KeyAuthentication.js";
import { Math } from "../../Cryptide/index.js";
import { Max, Threshold, WaitForNumberofORKs, sortORKs } from "../../Tools/Utils.js";
import { RandomBigInt } from "../../Cryptide/Math.js";
import { BigIntFromByteArray, GetUID, Hex2Bytes, base64ToBytes, bitArrayToUint8Array, serializeBitArray, uint8ArrayToBitArray } from "../../Cryptide/Serialization.js";
import EnclaveEntry from "../../Models/EnclaveEntry.js";
import VoucherFlow from "../VoucherFlows/VoucherFlow.js";
import KeyInfo from "../../Models/Infos/KeyInfo.js";
import { Point } from "../../Cryptide/Ed25519.js";
import TideKey from "../../Cryptide/TideKey.js";
export default class dCMKPasswordFlow {
/**
* @param {KeyInfo} keyInfo
* @param {string} sessID
* @param {boolean} cmkCommitted
* @param {boolean} prismCommitted
* @param {string} voucherURL
* @param {string} purpose
*/
constructor(keyInfo, sessID, cmkCommitted, prismCommitted, voucherURL, purpose = null) {
this.keyInfo = new KeyInfo(keyInfo.UserId, keyInfo.UserPublic, keyInfo.UserM, keyInfo.OrkInfo.slice());
this.sessID = sessID;
this.keyInfo.OrkInfo = sortORKs(this.keyInfo.OrkInfo);
this.cmkCommitted = cmkCommitted;
this.prismCommitted = prismCommitted;
this.voucherURL = voucherURL;
this.purpose = purpose == null ? "auth" : purpose;
this.cState = undefined;
}
/**
* @param {TideKey} sessKey
* @param {Point} gSessKeyPub
* @param {Point} gPass
* @param {Point} gCMK
* @param {boolean} rememberMe
*/
async Convert(sessKey, gPass, gCMK, rememberMe) {
const clients = this.keyInfo.OrkInfo.map(ork => new NodeClient(ork.orkURL)); // create node clients
const voucherFlow = new VoucherFlow(this.keyInfo.OrkInfo.map(o => o.orkPaymentPublic), this.voucherURL, "signin");
const { vouchers, k } = await voucherFlow.GetVouchers();
const r1 = Math.RandomBigInt();
const gBlurPass = gPass.mul(r1);
// Here we also find out which ORKs are up
const pre_ConvertResponses = clients.map((client, i) => client.Convert(i, this.keyInfo.UserId, gBlurPass, sessKey.get_public_component(), rememberMe, vouchers.toORK(i), this.keyInfo.UserM, this.cmkCommitted, this.prismCommitted));
// To save time
const prkECDHi = await DH.generateECDHi(this.keyInfo.OrkInfo.map(o => o.orkPublic), sessKey.get_private_component().rawBytes);
const { fulfilledResponses, bitwise } = await WaitForNumberofORKs(this.keyInfo.OrkInfo, pre_ConvertResponses, "CMK", Threshold, null, prkECDHi);
const ids = this.keyInfo.OrkInfo.map(c => BigInt(c.orkID));
const { prismAuthis, timestampi, selfRequesti, expired } = await PrismConvertReply(fulfilledResponses.map(c => c.PrismConvertResponse), ids, this.keyInfo.OrkInfo.map(c => c.orkPublic), r1, prkECDHi);
this.cState = {
selfRequesti,
expired,
bitwise,
prkECDHi,
...await CmkConvertReply(fulfilledResponses.map(c => c.CMKConvertResponse), ids, prismAuthis, gCMK, timestampi, this.sessID, this.purpose, Point.fromBytes(Hex2Bytes(vouchers.qPub).slice(-32)), // to translate between tide component and native object
BigIntFromByteArray(base64ToBytes(vouchers.UDeObf).slice(-32)), // to translate between tide component and native object
k.get_private_component().priv, sessKey.get_public_component())
};
return {
VUID: this.cState.VUID
};
}
/**
*
* @param {TideKey} sessKey
* @param {Point} gSessKeyPub
* @param {Point} gPass
*/
async ConvertPassword(sessKey, gPass) {
if (this.cState != undefined)
throw Error("This function must be called as a standlone in this flow");
const r1 = RandomBigInt();
const gBlurPass = gPass.mul(r1);
const clients = this.keyInfo.OrkInfo.map(ork => new NodeClient(ork.orkURL)); // create node clients
const voucherFlow = new VoucherFlow(this.keyInfo.OrkInfo.map(o => o.orkPaymentPublic), this.voucherURL, "updateaccount");
const { vouchers } = await voucherFlow.GetVouchers();
const pre_convertPassResponses = clients.map((client, i) => client.ConvertPass(i, this.keyInfo.UserId, gBlurPass, sessKey.get_public_component(), vouchers.toORK(i), this.keyInfo.UserM));
// To save time
const prkECDHi = await DH.generateECDHi(this.keyInfo.OrkInfo.map(o => o.orkPublic), sessKey.get_private_component().rawBytes);
const { fulfilledResponses, bitwise } = await WaitForNumberofORKs(this.keyInfo.OrkInfo, pre_convertPassResponses, "CMK", Threshold, null, prkECDHi);
const { prismAuthis, timestampi, selfRequesti, expired } = await PrismConvertReply(fulfilledResponses, this.keyInfo.OrkInfo.map(c => BigInt(c.orkID)), this.keyInfo.OrkInfo.map(c => c.orkPublic), r1, prkECDHi);
return {
bitwise: bitwise,
expired,
selfRequesti
};
}
/**
* @param {Point} gVRK If a null value is provided, no encryption is applied.
* @param {Uint8Array} sessKey
* @param {string} consentToSign
*/
async Authenticate(gVRK, sessKey = null, consentToSign = null) {
if (this.cState == undefined)
throw Error("Convert State is undefined");
const cmkClients = this.keyInfo.OrkInfo.map(ork => new NodeClient(ork.orkURL));
const pre_encSig = cmkClients.map((client, i) => client.Authenticate(this.keyInfo.UserId, this.cState.selfRequesti[i], this.cState.blurHCMKMul, serializeBitArray(this.cState.bitwise), this.cmkCommitted, this.prismCommitted));
const encSig = await Promise.all(pre_encSig);
let vendorEncryptedData;
if (consentToSign == null) {
vendorEncryptedData = await AuthenticateBasicReply(this.cState.VUID, this.cState.prkECDHi, encSig, this.cState.gCMKAuth, this.cState.authToken, this.cState.r4, this.cState.gRMul, gVRK);
}
else {
vendorEncryptedData = await AuthenticateConsentReply(this.cState.VUID, this.cState.prkECDHi, encSig, this.cState.gCMKAuth, this.cState.authToken, this.cState.r4, this.cState.gRMul, gVRK, BigIntFromByteArray(sessKey), consentToSign);
}
return {
bitwise: this.cState.bitwise,
expired: this.cState.expired,
selfRequesti: this.cState.selfRequesti,
vendorEncryptedData: vendorEncryptedData
};
}
}
//# sourceMappingURL=dCMKPasswordFlow.js.map