Skip to content

Commit

Permalink
add auth for fetching nonce
Browse files Browse the repository at this point in the history
  • Loading branch information
himanshu committed May 14, 2024
1 parent d0c6036 commit 3531df7
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 28 deletions.
31 changes: 23 additions & 8 deletions src/helpers/metadataUtils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { decrypt } from "@toruslabs/eccrypto";
import { Data, post } from "@toruslabs/http-helpers";
import BN from "bn.js";
import { ec } from "elliptic";
import { ec as EC } from "elliptic";
import stringify from "json-stable-stringify";
import log from "loglevel";

import { SAPPHIRE_METADATA_URL } from "../constants";
import { EciesHex, GetOrSetNonceResult, MetadataParams } from "../interfaces";
import { EciesHex, GetOrSetNonceResult, MetadataParams, SapphireMetadataParams } from "../interfaces";
import { encParamsHexToBuf } from "./common";
import { keccak256 } from "./keyUtils";

const secp256k1Curve = new EC("secp256k1");
export function convertMetadataToNonce(params: { message?: string }) {
if (!params || !params.message) {
return new BN(0);
Expand All @@ -26,7 +27,7 @@ export async function decryptNodeData(eciesData: EciesHex, ciphertextHex: string
return decryptedSigBuffer;
}

export function generateMetadataParams(ecCurve: ec, serverTimeOffset: number, message: string, privateKey: BN): MetadataParams {
export function generateMetadataParams(ecCurve: EC, serverTimeOffset: number, message: string, privateKey: BN): MetadataParams {
const key = ecCurve.keyFromPrivate(privateKey.toString("hex", 64));
const setData = {
data: message,
Expand Down Expand Up @@ -60,7 +61,7 @@ export async function getMetadata(

export async function getOrSetNonce(
legacyMetadataHost: string,
ecCurve: ec,
ecCurve: EC,
serverTimeOffset: number,
X: string,
Y: string,
Expand All @@ -83,21 +84,35 @@ export async function getOrSetNonce(

export async function getNonce(
legacyMetadataHost: string,
ecCurve: ec,
ecCurve: EC,
serverTimeOffset: number,
X: string,
Y: string,
privKey?: BN
): Promise<GetOrSetNonceResult> {
return getOrSetNonce(legacyMetadataHost, ecCurve, serverTimeOffset, X, Y, privKey, true);
}

export async function getOrSetSapphireMetadataNonce(X: string, Y: string): Promise<GetOrSetNonceResult> {
const data = {
export async function getOrSetSapphireMetadataNonce(X: string, Y: string, serverTimeOffset?: number, privKey?: BN): Promise<GetOrSetNonceResult> {
let data: SapphireMetadataParams = {
pub_key_X: X,
pub_key_Y: Y,
key_type: "secp256k1",
set_data: { operation: "getOrSetNonce" },
};
if (privKey) {
const key = secp256k1Curve.keyFromPrivate(privKey.toString("hex", 64));

const setData = {
operation: "getOrSetNonce",
timestamp: new BN(~~(serverTimeOffset + Date.now() / 1000)).toString(16),
};
const sig = key.sign(keccak256(Buffer.from(stringify(setData), "utf8")).slice(2));
data = {
...data,
set_data: setData,
signature: Buffer.from(sig.r.toString(16, 64) + sig.s.toString(16, 64) + new BN("").toString(16, 2), "hex").toString("base64"),
};
}

return post<GetOrSetNonceResult>(`${SAPPHIRE_METADATA_URL}/get_or_set_nonce`, data, undefined, { useAPIKey: true });
}
40 changes: 20 additions & 20 deletions src/helpers/nodeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ export const GetPubKeyOrKeyAssign = async (params: {
// rechecking nonceResult to avoid promise race condition.
if (!nonceResult && metadataNonceResult) {
nonceResult = metadataNonceResult;
if (nonceResult.nonce) {
delete nonceResult.nonce;
}
}
}
}
Expand Down Expand Up @@ -375,29 +378,11 @@ export async function retrieveOrImportShare(params: {
}
});

// if both thresholdNonceData and extended_verifier_id are not available
// then we need to throw other wise address would be incorrect.
if (!thresholdNonceData && !verifierParams.extended_verifier_id && !LEGACY_NETWORKS_ROUTE_MAP[network as TORUS_LEGACY_NETWORK_TYPE]) {
const metadataNonceResult = await getOrSetSapphireMetadataNonce(thresholdPublicKey.X, thresholdPublicKey.Y);
// rechecking nonceResult to avoid promise race condition.
if (metadataNonceResult && !thresholdNonceData) {
thresholdNonceData = metadataNonceResult;
} else {
throw new Error(
`invalid metadata result from nodes, nonce metadata is empty for verifier: ${verifier} and verifierId: ${verifierParams.verifier_id}`
);
}
}

const thresholdReqCount = importedShares.length > 0 ? endpoints.length : minThreshold;
// optimistically run lagrange interpolation once threshold number of shares have been received
// this is matched against the user public key to ensure that shares are consistent
// Note: no need of thresholdMetadataNonce for extended_verifier_id key
if (
completedRequests.length >= thresholdReqCount &&
thresholdPublicKey &&
(thresholdNonceData || verifierParams.extended_verifier_id || LEGACY_NETWORKS_ROUTE_MAP[network as TORUS_LEGACY_NETWORK_TYPE])
) {
if (completedRequests.length >= thresholdReqCount && thresholdPublicKey) {
const sharePromises: Promise<void | Buffer>[] = [];
const sessionTokenSigPromises: Promise<void | Buffer>[] = [];
const sessionTokenPromises: Promise<void | Buffer>[] = [];
Expand Down Expand Up @@ -564,13 +549,28 @@ export async function retrieveOrImportShare(params: {
});
})
.then(async (res) => {
const { privateKey, sessionTokenData, thresholdNonceData, nodeIndexes, isNewKey, serverTimeOffsetResponse } = res;
const { privateKey, sessionTokenData, nodeIndexes, thresholdNonceData, isNewKey, serverTimeOffsetResponse } = res;
let nonceResult = thresholdNonceData;
if (!privateKey) throw new Error("Invalid private key returned");

const oAuthKey = privateKey;
const oAuthPubKey = getPublic(Buffer.from(oAuthKey.toString(16, 64), "hex")).toString("hex");
const oAuthPubkeyX = oAuthPubKey.slice(2, 66);
const oAuthPubkeyY = oAuthPubKey.slice(66);

// if both thresholdNonceData and extended_verifier_id are not available
// then we need to throw other wise address would be incorrect.
if (!nonceResult && !verifierParams.extended_verifier_id && !LEGACY_NETWORKS_ROUTE_MAP[network as TORUS_LEGACY_NETWORK_TYPE]) {
const metadataNonceResult = await getOrSetSapphireMetadataNonce(oAuthPubkeyX, oAuthPubkeyY, serverTimeOffset, oAuthKey);
// rechecking nonceResult to avoid promise race condition.
if (metadataNonceResult && !thresholdNonceData) {
nonceResult = metadataNonceResult;
} else {
throw new Error(
`invalid metadata result from nodes, nonce metadata is empty for verifier: ${verifier} and verifierId: ${verifierParams.verifier_id}`
);
}
}
let metadataNonce = new BN(nonceResult?.nonce ? nonceResult.nonce.padStart(64, "0") : "0", "hex");
let finalPubKey: curve.base.BasePoint;
let pubNonce: { X: string; Y: string } | undefined;
Expand Down
12 changes: 12 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,15 @@ export interface MetadataParams {
};
signature: string;
}

export interface SapphireMetadataParams {
namespace?: string;
pub_key_X: string;
pub_key_Y: string;
key_type: "secp256k1" | "ed25519";
set_data: {
operation: "getNonce" | "getOrSetNonce" | string;
timestamp?: string;
};
signature?: string;
}

0 comments on commit 3531df7

Please sign in to comment.