Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions packages/common-types/src/baseTypes/aggregateTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
ISerializable,
IServiceProvider,
IStorageLayer,
KeyType,
PolyIDAndShares,
PolynomialID,
ShareDescriptionMap,
Expand Down Expand Up @@ -62,6 +63,30 @@ export type FactorEnc = {
serverEncs: EncryptedMessage[];
};

export interface ITssMetadata {
Copy link

@lwin-kyaw lwin-kyaw Feb 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good if we can provide some comments for the interface fields

tssTag: string;

tssKeyType: KeyType;

tssNonce: number;

tssPolyCommits: Point[];

/**
* Public Key Points of all factor keys
*/
factorPubs: Point[];

/**
* Encrypted threshold signature scheme (TSS) share managed by FactorKey.
* This share is securely encrypted to ensure confidentiality and is used in multi-party
* cryptographic signing processes without exposing the full private key.
*/
factorEncs: {
[factorPubID: string]: FactorEnc;
};
}

export interface IMetadata extends ISerializable {
pubKey: Point;

Expand All @@ -85,6 +110,8 @@ export interface IMetadata extends ISerializable {

nonce: number;

version: string;

getShareIndexesForPolynomial(polyID: PolynomialID): string[];
getLatestPublicPolynomial(): PublicPolynomial;
addPublicShare(polynomialID: PolynomialID, publicShare: PublicShare): void;
Expand Down Expand Up @@ -112,6 +139,7 @@ export interface IMetadata extends ISerializable {
[factorPubID: string]: FactorEnc;
};
}): void;
getTssData(keyType: KeyType, tssTag: string): ITssMetadata;
}

export type InitializeNewKeyResult = {
Expand Down Expand Up @@ -164,6 +192,7 @@ export type TKeyArgs = {
customAuthArgs?: CustomAuthArgs;
manualSync?: boolean;
serverTimeOffset?: number;
legacyMetadataFlag?: boolean;
};

export interface SecurityQuestionStoreArgs {
Expand Down
7 changes: 4 additions & 3 deletions packages/core/src/authMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import BN from "bn.js";
import stringify from "json-stable-stringify";

import CoreError from "./errors";
import Metadata from "./metadata";
import Metadata, { createMetadataFromJson } from "./metadata";

class AuthMetadata implements IAuthMetadata {
metadata: Metadata;
Expand All @@ -17,10 +17,11 @@ class AuthMetadata implements IAuthMetadata {
}

static fromJSON(value: StringifiedType): AuthMetadata {
const { data, sig } = value;
// need to inject legacyMetadata flag
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this comment a TODO? or can be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a todo.
It remind that for tkeyTss deserialization, legacyMetadata Flag needed to be injected as we are trying to force upgrade the metadata format to v1.0.0 from v0.0.1 when the legacyMetadataFlag is false

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what this means. where do you inject the flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const { data, sig, legacyMetadataFlag } = value;
if (!data) throw CoreError.metadataUndefined();

const m = Metadata.fromJSON(data);
const m = createMetadataFromJson(legacyMetadataFlag, data);
if (!m.pubKey) throw CoreError.metadataPubKeyUnavailable();

const keyPair = secp256k1.keyFromPublic(m.pubKey.toSEC1(secp256k1));
Expand Down
41 changes: 33 additions & 8 deletions packages/core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import stringify from "json-stable-stringify";
import AuthMetadata from "./authMetadata";
import CoreError from "./errors";
import { generatePrivateBN, generateRandomPolynomial, lagrangeInterpolatePolynomial, lagrangeInterpolation } from "./lagrangeInterpolatePolynomial";
import Metadata from "./metadata";
import { createMetadataFromJson, createMetadataInstance, Metadata } from "./metadata";

const ed25519SeedConst = "ed25519Seed";

Expand Down Expand Up @@ -90,13 +90,23 @@ class ThresholdKey implements ITKey {

serverTimeOffset?: number = 0;

private _legacyMetadataFlag: boolean = false;

// secp256k1 key
private privKey: BN;

private _ed25519Seed?: Buffer;

constructor(args?: TKeyArgs) {
const { enableLogging = false, modules = {}, serviceProvider, storageLayer, manualSync = false, serverTimeOffset } = args || {};
const {
enableLogging = false,
modules = {},
serviceProvider,
storageLayer,
manualSync = false,
serverTimeOffset,
legacyMetadataFlag,
} = args || {};
this.enableLogging = enableLogging;
this.serviceProvider = serviceProvider;
this.storageLayer = storageLayer;
Expand All @@ -112,6 +122,7 @@ class ThresholdKey implements ITKey {
this.setModuleReferences(); // Providing ITKeyApi access to modules
this.haveWriteMetadataLock = "";
this.serverTimeOffset = serverTimeOffset;
this._legacyMetadataFlag = legacyMetadataFlag;
}

get secp256k1Key(): BN | null {
Expand All @@ -129,6 +140,10 @@ class ThresholdKey implements ITKey {
return null;
}

get legacyMetadataFlag() {
return this._legacyMetadataFlag;
}

protected set secp256k1Key(privKey: BN) {
this.privKey = privKey;
}
Expand All @@ -148,6 +163,7 @@ class ThresholdKey implements ITKey {
manualSync,
lastFetchedCloudMetadata,
serverTimeOffset,
legacyMetadataFlag,
} = value;
const { storageLayer, serviceProvider, modules } = args;

Expand All @@ -159,6 +175,8 @@ class ThresholdKey implements ITKey {
manualSync,
serverTimeOffset,
});
// overwrite legacyMetadataFlag
tb._legacyMetadataFlag = legacyMetadataFlag ?? false;

// this will computed during reconstructKey should we restore here?
if (privKey) tb.privKey = new BN(privKey, "hex");
Expand All @@ -167,7 +185,9 @@ class ThresholdKey implements ITKey {
tb.shares = shares;

// switch to deserialize local metadata transition based on Object.keys() of authMetadata, ShareStore's and, IMessageMetadata
const AuthMetadataKeys = Object.keys(JSON.parse(stringify(new AuthMetadata(new Metadata(new Point("0", "0")), new BN("0", "hex")))));
const AuthMetadataKeys = Object.keys(
JSON.parse(stringify(new AuthMetadata(createMetadataInstance(legacyMetadataFlag, new Point("0", "0")), new BN("0", "hex"))))
);
const ShareStoreKeys = Object.keys(JSON.parse(stringify(new ShareStore(new Share("0", "0"), ""))));
const sampleMessageMetadata: IMessageMetadata = { message: "Sample message", dateAdded: Date.now() };
const MessageMetadataKeys = Object.keys(sampleMessageMetadata);
Expand All @@ -184,7 +204,7 @@ class ThresholdKey implements ITKey {

const keys = Object.keys(_localMetadataTransitions[1][index]);
if (keys.length === AuthMetadataKeys.length && keys.every((val) => AuthMetadataKeys.includes(val))) {
const tempAuth = AuthMetadata.fromJSON(_localMetadataTransitions[1][index]);
const tempAuth = AuthMetadata.fromJSON({ ..._localMetadataTransitions[1][index], legacyMetadataFlag });
tempAuth.privKey = privKey;
localTransitionData.push(tempAuth);
} else if (keys.length === ShareStoreKeys.length && keys.every((val) => ShareStoreKeys.includes(val))) {
Expand All @@ -200,8 +220,9 @@ class ThresholdKey implements ITKey {
let tempMetadata: Metadata;
let tempCloud: Metadata;

if (metadata) tempMetadata = Metadata.fromJSON(metadata);
if (lastFetchedCloudMetadata) tempCloud = Metadata.fromJSON(lastFetchedCloudMetadata);
// check configuration before decide the metadata
if (metadata) tempMetadata = createMetadataFromJson(legacyMetadataFlag, metadata);
if (lastFetchedCloudMetadata) tempCloud = createMetadataFromJson(legacyMetadataFlag, lastFetchedCloudMetadata);
// check if cloud metadata is updated before

tb.metadata = tempMetadata;
Expand Down Expand Up @@ -911,7 +932,10 @@ class ThresholdKey implements ITKey {
if ((raw as IMessageMetadata).message === SHARE_DELETED) {
throw CoreError.fromCode(1308);
}
return params.fromJSONConstructor.fromJSON(raw);

// inject legacyMetadata flag for AuthMetadata deserialization
// it wont affect other fromJSONConstruct as it is just extra parameter
return params.fromJSONConstructor.fromJSON({ ...raw, legacyMetadataFlag: this._legacyMetadataFlag });
}

// Lock functions
Expand Down Expand Up @@ -1181,6 +1205,7 @@ class ThresholdKey implements ITKey {
manualSync: this.manualSync,
serviceProvider: this.serviceProvider,
storageLayer: this.storageLayer,
legacyMetadataFlag: this._legacyMetadataFlag,
};
}

Expand Down Expand Up @@ -1409,7 +1434,7 @@ class ThresholdKey implements ITKey {
const shares = poly.generateShares(shareIndexes);

// create metadata to be stored
const metadata = new Metadata(getPubKeyPoint(this.privKey));
const metadata = createMetadataInstance(this._legacyMetadataFlag, getPubKeyPoint(this.privKey));
metadata.addFromPolynomialAndShares(poly, shares);
const serviceProviderShare = shares[shareIndexes[0].toString("hex")];
const shareStore = new ShareStore(serviceProviderShare, poly.getPolynomialID());
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export { default as AuthMetadata } from "./authMetadata";
export { default as TKey } from "./core";
export { default as CoreError } from "./errors";
export * from "./lagrangeInterpolatePolynomial";
export { default as Metadata } from "./metadata";
export { LegacyMetadata, Metadata } from "./metadata";
Loading
Loading