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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@toruslabs/eslint-config-typescript": "^1.0.4",
"@toruslabs/torus-scripts": "^1.0.6",
"@types/assert": "^1.5.6",
"@types/bn.js": "^5.1.0",
"@types/bn.js": "^5.1.1",
"@types/mocha": "^9.1.1",
"@types/node": "^16",
"@typescript-eslint/eslint-plugin": "^5.31.0",
Expand All @@ -49,8 +49,8 @@
"eslint": "^8.20.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-mocha": "^10.1.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-n": "^15.2.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/common-types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"web3-utils": "^1.7.4"
},
"devDependencies": {
"@types/bn.js": "^5.1.0",
"@types/bn.js": "^5.1.1",
"@types/elliptic": "^6.4.14"
},
"bugs": {
Expand Down
11 changes: 9 additions & 2 deletions packages/common-types/src/base/ShareStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,27 @@ class ShareStore implements ISerializable {

polynomialID: PolynomialID;

constructor(share: Share, polynomialID: PolynomialID) {
tssShare?: Share;

constructor(share: Share, polynomialID: PolynomialID, tssShare?: Share) {
this.share = share;
this.polynomialID = polynomialID;
this.tssShare = tssShare;
}

static fromJSON(value: StringifiedType): ShareStore {
const { share, polynomialID } = value;
const { share, polynomialID, tssShare } = value;
if (tssShare) {
return new ShareStore(Share.fromJSON(share), polynomialID, Share.fromJSON(tssShare));
}
return new ShareStore(Share.fromJSON(share), polynomialID);
}

toJSON(): StringifiedType {
return {
share: this.share,
polynomialID: this.polynomialID.toString(),
tssShare: this.tssShare,
};
}
}
Expand Down
11 changes: 6 additions & 5 deletions packages/common-types/src/baseTypes/aggregateTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ export type ReconstructKeyMiddlewareMap = {
};

export type ShareSerializationMiddleware = {
serialize: (share: BN, type: string) => Promise<unknown>;
deserialize: (serializedShare: unknown, type: string) => Promise<BN>;
serialize: (share: BN, type: string, tssShare: BN) => Promise<unknown>;
deserialize: (serializedShare: unknown, type: string) => Promise<{ share: BN; tssShare?: BN }>;
};

export interface IMetadata extends ISerializable {
Expand Down Expand Up @@ -88,7 +88,7 @@ export interface IMetadata extends ISerializable {
setScopedStore(domain: string, data: unknown): void;
getEncryptedShare(shareStore: ShareStore): Promise<ShareStore>;
getShareDescription(): ShareDescriptionMap;
shareToShareStore(share: BN): ShareStore;
shareToShareStore(share: BN, tssShare: BN): ShareStore;
addShareDescription(shareIndex: string, description: string): void;
deleteShareDescription(shareIndex: string, description: string): void;
updateShareDescription(shareIndex: string, oldDescription: string, newDescription: string): void;
Expand All @@ -103,6 +103,7 @@ export type InitializeNewKeyResult = {

export type ReconstructedKeyResult = {
privKey: BN;
tssShare?: Share;
seedPhrase?: BN[];
allKeys?: BN[];
};
Expand Down Expand Up @@ -257,8 +258,8 @@ export interface ITKeyApi {
): void;
_addReconstructKeyMiddleware(moduleName: string, middleware: () => Promise<Array<BN>>): void;
_addShareSerializationMiddleware(
serialize: (share: BN, type: string) => Promise<unknown>,
deserialize: (serializedShare: unknown, type: string) => Promise<BN>
serialize: (share: BN, type: string, tssShare?: BN) => Promise<unknown>,
deserialize: (serializedShare: unknown, type: string) => Promise<{ share: BN; tssShare?: BN }>
): void;
generateNewShare(): Promise<GenerateNewShareResult>;
outputShareStore(shareIndex: BNString, polyID?: string): ShareStore;
Expand Down
28 changes: 20 additions & 8 deletions packages/common-types/src/baseTypes/commonTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { CustomAuthArgs } from "@toruslabs/customauth";
import BN from "bn.js";
import type { curve } from "elliptic";

import ShareStore from "../base/ShareStore";

export type PubKeyType = "ecc";

// @flow
Expand All @@ -16,14 +18,7 @@ export interface EncryptedMessage {
ephemPublicKey: string;
iv: string;
mac: string;
}
export interface ServiceProviderArgs {
enableLogging?: boolean;
postboxKey?: string;
}

export interface TorusServiceProviderArgs extends ServiceProviderArgs {
customAuthArgs: CustomAuthArgs;
isCompressed: boolean;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -39,13 +34,30 @@ export interface IPoint extends ISerializable {
encode(enc: string, params?: unknown): Buffer;
}

export type GetTSSPubKeyFunc = () => IPoint;
export type GetTSSSignFunc = (msg: BNString, otherShares: ShareStore[]) => Buffer;

export interface ServiceProviderArgs {
enableLogging?: boolean;
postboxKey?: string;
getTSSPubKey?: GetTSSPubKeyFunc; // for now is just sum of key
getTSSSign?: GetTSSSignFunc;
}

export interface TorusServiceProviderArgs extends ServiceProviderArgs {
customAuthArgs: CustomAuthArgs;
}
export interface IServiceProvider extends ISerializable {
enableLogging: boolean;

postboxKey: BN;

serviceProviderName: string;

// Added items for TSSKey
getTSSPubKey?: GetTSSPubKeyFunc; // for now is just sum of key
getTSSSign?: GetTSSSignFunc;

encrypt(msg: Buffer): Promise<EncryptedMessage>;
decrypt(msg: EncryptedMessage): Promise<Buffer>;
retrievePubKey(type: PubKeyType): Buffer;
Expand Down
1 change: 1 addition & 0 deletions packages/common-types/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export async function encrypt(publicKey: Buffer, msg: Buffer): Promise<Encrypted
ephemPublicKey: encryptedDetails.ephemPublicKey.toString("hex"),
iv: encryptedDetails.iv.toString("hex"),
mac: encryptedDetails.mac.toString("hex"),
isCompressed: false,
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"web3-utils": "^1.7.4"
},
"devDependencies": {
"@types/bn.js": "^5.1.0",
"@types/bn.js": "^5.1.1",
"@types/elliptic": "^6.4.14",
"@types/json-stable-stringify": "^1.0.34"
},
Expand Down
62 changes: 44 additions & 18 deletions packages/core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class ThresholdKey implements ITKey {

privKey: BN;

tssClientShare?: Share;

lastFetchedCloudMetadata: Metadata;

metadata: Metadata;
Expand Down Expand Up @@ -412,6 +414,7 @@ class ThresholdKey implements ITKey {

const returnObject = {
privKey,
tssShare: this.tssClientShare,
allKeys: [privKey],
};

Expand Down Expand Up @@ -553,7 +556,7 @@ class ThresholdKey implements ITKey {
const newShareStores = {};
const polyID = poly.getPolynomialID();
newShareIndexes.forEach((shareIndexHex) => {
newShareStores[shareIndexHex] = new ShareStore(shares[shareIndexHex], polyID);
newShareStores[shareIndexHex] = new ShareStore(shares[shareIndexHex], polyID, this.tssClientShare);
});

// evaluate oldPoly for old shares and set new metadata with encrypted share for new polynomial
Expand All @@ -565,7 +568,7 @@ class ThresholdKey implements ITKey {
const oldShare = oldPoly.polyEval(new BN(shareIndex, "hex"));
const encryptedShare = await encrypt(getPubKeyECC(oldShare), Buffer.from(JSON.stringify(newShareStores[shareIndex])));
newScopedStore[getPubKeyPoint(oldShare).x.toString("hex")] = encryptedShare;
oldShareStores[shareIndex] = new ShareStore(new Share(shareIndex, oldShare), previousPolyID);
oldShareStores[shareIndex] = new ShareStore(new Share(shareIndex, oldShare), previousPolyID, this.tssClientShare);
return oldShare;
})
);
Expand Down Expand Up @@ -615,11 +618,13 @@ class ThresholdKey implements ITKey {
initializeModules,
importedKey,
delete1OutOf1,
importedTSSShare,
}: {
determinedShare?: BN;
initializeModules?: boolean;
importedKey?: BN;
delete1OutOf1?: boolean;
importedTSSShare?: BN;
} = {}): Promise<InitializeNewKeyResult> {
if (!importedKey) {
const tmpPriv = generatePrivate();
Expand All @@ -628,6 +633,17 @@ class ThresholdKey implements ITKey {
this._setKey(new BN(importedKey));
}

let tssShare: BN;
if (!importedTSSShare) {
const tmpPriv = generatePrivate();
tssShare = new BN(tmpPriv);
} else {
tssShare = new BN(importedTSSShare);
}

// create our TSS key as well
this._setTSSShare(new Share(new BN(2), tssShare));

// create a random poly and respective shares
// 1 is defined as the serviceProvider share
// 0 is for tKey
Expand All @@ -648,7 +664,7 @@ class ThresholdKey implements ITKey {
const metadata = new Metadata(getPubKeyPoint(this.privKey));
metadata.addFromPolynomialAndShares(poly, shares);
const serviceProviderShare = shares[shareIndexes[0].toString("hex")];
const shareStore = new ShareStore(serviceProviderShare, poly.getPolynomialID());
const shareStore = new ShareStore(serviceProviderShare, poly.getPolynomialID(), this.tssClientShare);
this.metadata = metadata;

// initialize modules
Expand All @@ -675,20 +691,21 @@ class ThresholdKey implements ITKey {
for (let index = 0; index < shareIndexes.length; index += 1) {
const shareIndex = shareIndexes[index];
// also add into our share store
this.inputShareStore(new ShareStore(shares[shareIndex.toString("hex")], poly.getPolynomialID()));
this.inputShareStore(new ShareStore(shares[shareIndex.toString("hex")], poly.getPolynomialID(), this.tssClientShare));
}

if (this.storeDeviceShare) {
await this.storeDeviceShare(new ShareStore(shares[shareIndexes[1].toString("hex")], poly.getPolynomialID()));
await this.storeDeviceShare(new ShareStore(shares[shareIndexes[1].toString("hex")], poly.getPolynomialID(), this.tssClientShare));
}

const result = {
privKey: this.privKey,
deviceShare: new ShareStore(shares[shareIndexes[1].toString("hex")], poly.getPolynomialID()),
tssShare: this.tssClientShare,
deviceShare: new ShareStore(shares[shareIndexes[1].toString("hex")], poly.getPolynomialID(), this.tssClientShare),
userShare: undefined,
};
if (determinedShare) {
result.userShare = new ShareStore(shares[shareIndexes[2].toString("hex")], poly.getPolynomialID());
result.userShare = new ShareStore(shares[shareIndexes[2].toString("hex")], poly.getPolynomialID(), this.tssClientShare);
}
return result;
}
Expand Down Expand Up @@ -784,6 +801,7 @@ class ThresholdKey implements ITKey {
this.shares[ss.polynomialID] = {};
}
this.shares[ss.polynomialID][ss.share.shareIndex.toString("hex")] = ss;
this.tssClientShare = ss.tssShare;
}

// inputs a share ensuring that the share is the latest share AND metadata is updated to its latest state
Expand Down Expand Up @@ -842,13 +860,17 @@ class ThresholdKey implements ITKey {
const poly = this.reconstructLatestPoly();
const shareMap = poly.generateShares([shareIndexParsed]);

return new ShareStore(shareMap[shareIndexParsed.toString("hex")], polyIDToSearch);
return new ShareStore(shareMap[shareIndexParsed.toString("hex")], polyIDToSearch, this.tssClientShare);
}

_setKey(privKey: BN): void {
this.privKey = privKey;
}

_setTSSShare(tssShare: Share): void {
this.tssClientShare = tssShare;
}

getCurrentShareIndexes(): string[] {
if (!this.metadata) {
throw CoreError.metadataUndefined();
Expand Down Expand Up @@ -1075,7 +1097,7 @@ class ThresholdKey implements ITKey {

_addShareSerializationMiddleware(
serialize: (share: BN, type: string) => Promise<unknown>,
deserialize: (serializedShare: unknown, type: string) => Promise<BN>
deserialize: (serializedShare: unknown, type: string) => Promise<{ share: BN; tssShare?: BN }>
): void {
this._shareSerializationMiddleware = {
serialize,
Expand Down Expand Up @@ -1203,22 +1225,26 @@ class ThresholdKey implements ITKey {

// Import export shares
async outputShare(shareIndex: BNString, type?: string): Promise<unknown> {
const { share } = this.outputShareStore(shareIndex).share;
if (!type) return share;
const { share, tssShare } = this.outputShareStore(shareIndex);
if (!type) return share.share;

return this._shareSerializationMiddleware.serialize(share, type);
return this._shareSerializationMiddleware.serialize(share.share, type, tssShare?.share);
}

async inputShare(share: unknown, type?: string): Promise<void> {
async inputShare(_share: unknown, type?: string): Promise<void> {
if (!this.metadata) {
throw CoreError.metadataUndefined();
}
let shareStore: ShareStore;
if (!type) shareStore = this.metadata.shareToShareStore(share as BN);
else {
const deserialized = await this._shareSerializationMiddleware.deserialize(share, type);
shareStore = this.metadata.shareToShareStore(deserialized);

let deserialized: { share: BN; tssShare?: BN };

if (type) {
deserialized = await this._shareSerializationMiddleware.deserialize(_share, type);
} else {
deserialized = { share: _share as BN };
}
const { share, tssShare } = deserialized;
const shareStore = this.metadata.shareToShareStore(share, tssShare);
const pubPoly = this.metadata.getLatestPublicPolynomial();
const pubPolyID = pubPoly.getPolynomialID();
const fullShareIndexesList = this.metadata.getShareIndexesForPolynomial(pubPolyID);
Expand Down
Loading