@haneullabs/seal 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +459 -0
- package/README.md +4 -0
- package/dist/cjs/bcs.d.ts +71 -0
- package/dist/cjs/bcs.js +74 -0
- package/dist/cjs/bcs.js.map +7 -0
- package/dist/cjs/bls12381.d.ts +44 -0
- package/dist/cjs/bls12381.js +151 -0
- package/dist/cjs/bls12381.js.map +7 -0
- package/dist/cjs/client.d.ts +84 -0
- package/dist/cjs/client.js +414 -0
- package/dist/cjs/client.js.map +7 -0
- package/dist/cjs/decrypt.d.ts +22 -0
- package/dist/cjs/decrypt.js +109 -0
- package/dist/cjs/decrypt.js.map +7 -0
- package/dist/cjs/dem.d.ts +38 -0
- package/dist/cjs/dem.js +185 -0
- package/dist/cjs/dem.js.map +7 -0
- package/dist/cjs/elgamal.d.ts +13 -0
- package/dist/cjs/elgamal.js +46 -0
- package/dist/cjs/elgamal.js.map +7 -0
- package/dist/cjs/encrypt.d.ts +32 -0
- package/dist/cjs/encrypt.js +104 -0
- package/dist/cjs/encrypt.js.map +7 -0
- package/dist/cjs/error.d.ts +86 -0
- package/dist/cjs/error.js +239 -0
- package/dist/cjs/error.js.map +7 -0
- package/dist/cjs/ibe.d.ts +98 -0
- package/dist/cjs/ibe.js +167 -0
- package/dist/cjs/ibe.js.map +7 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +33 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/kdf.d.ts +30 -0
- package/dist/cjs/kdf.js +97 -0
- package/dist/cjs/kdf.js.map +7 -0
- package/dist/cjs/key-server.d.ts +98 -0
- package/dist/cjs/key-server.js +171 -0
- package/dist/cjs/key-server.js.map +7 -0
- package/dist/cjs/package.json +5 -0
- package/dist/cjs/session-key.d.ts +74 -0
- package/dist/cjs/session-key.js +245 -0
- package/dist/cjs/session-key.js.map +7 -0
- package/dist/cjs/shamir.d.ts +91 -0
- package/dist/cjs/shamir.js +770 -0
- package/dist/cjs/shamir.js.map +7 -0
- package/dist/cjs/types.d.ts +83 -0
- package/dist/cjs/types.js +17 -0
- package/dist/cjs/types.js.map +7 -0
- package/dist/cjs/utils.d.ts +47 -0
- package/dist/cjs/utils.js +106 -0
- package/dist/cjs/utils.js.map +7 -0
- package/dist/cjs/version.d.ts +1 -0
- package/dist/cjs/version.js +25 -0
- package/dist/cjs/version.js.map +7 -0
- package/dist/esm/bcs.d.ts +71 -0
- package/dist/esm/bcs.js +54 -0
- package/dist/esm/bcs.js.map +7 -0
- package/dist/esm/bls12381.d.ts +44 -0
- package/dist/esm/bls12381.js +131 -0
- package/dist/esm/bls12381.js.map +7 -0
- package/dist/esm/client.d.ts +84 -0
- package/dist/esm/client.js +407 -0
- package/dist/esm/client.js.map +7 -0
- package/dist/esm/decrypt.d.ts +22 -0
- package/dist/esm/decrypt.js +94 -0
- package/dist/esm/decrypt.js.map +7 -0
- package/dist/esm/dem.d.ts +38 -0
- package/dist/esm/dem.js +165 -0
- package/dist/esm/dem.js.map +7 -0
- package/dist/esm/elgamal.d.ts +13 -0
- package/dist/esm/elgamal.js +26 -0
- package/dist/esm/elgamal.js.map +7 -0
- package/dist/esm/encrypt.d.ts +32 -0
- package/dist/esm/encrypt.js +84 -0
- package/dist/esm/encrypt.js.map +7 -0
- package/dist/esm/error.d.ts +86 -0
- package/dist/esm/error.js +219 -0
- package/dist/esm/error.js.map +7 -0
- package/dist/esm/ibe.d.ts +98 -0
- package/dist/esm/ibe.js +147 -0
- package/dist/esm/ibe.js.map +7 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/esm/kdf.d.ts +30 -0
- package/dist/esm/kdf.js +83 -0
- package/dist/esm/kdf.js.map +7 -0
- package/dist/esm/key-server.d.ts +98 -0
- package/dist/esm/key-server.js +151 -0
- package/dist/esm/key-server.js.map +7 -0
- package/dist/esm/package.json +5 -0
- package/dist/esm/session-key.d.ts +74 -0
- package/dist/esm/session-key.js +230 -0
- package/dist/esm/session-key.js.map +7 -0
- package/dist/esm/shamir.d.ts +91 -0
- package/dist/esm/shamir.js +750 -0
- package/dist/esm/shamir.js.map +7 -0
- package/dist/esm/types.d.ts +83 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +7 -0
- package/dist/esm/utils.d.ts +47 -0
- package/dist/esm/utils.js +86 -0
- package/dist/esm/utils.js.map +7 -0
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +5 -0
- package/dist/esm/version.js.map +7 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/key-server.ts"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport { bcs, fromBase64, fromHex, toBase64, toHex } from '@haneullabs/bcs';\nimport { bls12_381 } from '@noble/curves/bls12-381';\n\nimport { KeyServerMove, KeyServerMoveV1 } from './bcs.js';\nimport { InvalidKeyServerError, InvalidKeyServerVersionError, SealAPIError } from './error.js';\nimport { DST_POP } from './ibe.js';\nimport { PACKAGE_VERSION } from './version.js';\nimport type { SealCompatibleClient } from './types.js';\nimport type { G1Element } from './bls12381.js';\nimport { flatten, Version } from './utils.js';\nimport { elgamalDecrypt } from './elgamal.js';\nimport type { Certificate } from './session-key.js';\n\nconst EXPECTED_SERVER_VERSION = 1;\n\nexport type KeyServer = {\n\tobjectId: string;\n\tname: string;\n\turl: string;\n\tkeyType: KeyServerType;\n\tpk: Uint8Array<ArrayBuffer>;\n};\n\nexport enum KeyServerType {\n\tBonehFranklinBLS12381 = 0,\n}\n\nexport const SERVER_VERSION_REQUIREMENT = new Version('0.4.1');\n\n/**\n * Given a list of key server object IDs, returns a list of SealKeyServer\n * from onchain state containing name, objectId, URL and pk.\n *\n * @param objectIds - The key server object IDs.\n * @param client - The HaneulClient to use.\n * @returns - An array of SealKeyServer.\n */\nexport async function retrieveKeyServers({\n\tobjectIds,\n\tclient,\n}: {\n\tobjectIds: string[];\n\tclient: SealCompatibleClient;\n}): Promise<KeyServer[]> {\n\treturn await Promise.all(\n\t\tobjectIds.map(async (objectId) => {\n\t\t\t// First get the KeyServer object and validate it.\n\t\t\tconst res = await client.core.getObject({\n\t\t\t\tobjectId,\n\t\t\t});\n\t\t\tconst ks = KeyServerMove.parse(await res.object.content);\n\t\t\tif (\n\t\t\t\tEXPECTED_SERVER_VERSION < Number(ks.firstVersion) ||\n\t\t\t\tEXPECTED_SERVER_VERSION > Number(ks.lastVersion)\n\t\t\t) {\n\t\t\t\tthrow new InvalidKeyServerVersionError(\n\t\t\t\t\t`Key server ${objectId} supports versions between ${ks.firstVersion} and ${ks.lastVersion} (inclusive), but SDK expects version ${EXPECTED_SERVER_VERSION}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Then fetch the expected versioned object and parse it.\n\t\t\tconst resVersionedKs = await client.core.getDynamicField({\n\t\t\t\tparentId: objectId,\n\t\t\t\tname: {\n\t\t\t\t\ttype: 'u64',\n\t\t\t\t\tbcs: bcs.u64().serialize(EXPECTED_SERVER_VERSION).toBytes(),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst ksVersioned = KeyServerMoveV1.parse(resVersionedKs.dynamicField.value.bcs);\n\n\t\t\tif (ksVersioned.keyType !== KeyServerType.BonehFranklinBLS12381) {\n\t\t\t\tthrow new InvalidKeyServerError(\n\t\t\t\t\t`Server ${objectId} has invalid key type: ${ksVersioned.keyType}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tobjectId,\n\t\t\t\tname: ksVersioned.name,\n\t\t\t\turl: ksVersioned.url,\n\t\t\t\tkeyType: ksVersioned.keyType,\n\t\t\t\tpk: new Uint8Array(ksVersioned.pk),\n\t\t\t};\n\t\t}),\n\t);\n}\n\n/**\n * Given a KeyServer, fetch the proof of possession (PoP) from the URL and verify it\n * against the pubkey. This should be used only rarely when the dapp uses a dynamic\n * set of key servers.\n *\n * @param server - The KeyServer to verify.\n * @returns - True if the key server is valid, false otherwise.\n */\nexport async function verifyKeyServer(\n\tserver: KeyServer,\n\ttimeout: number,\n\tapiKeyName?: string,\n\tapiKey?: string,\n): Promise<boolean> {\n\tconst requestId = crypto.randomUUID();\n\tconst response = await fetch(server.url! + '/v1/service?service_id=' + server.objectId, {\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'Request-Id': requestId,\n\t\t\t'Client-Sdk-Type': 'typescript',\n\t\t\t'Client-Sdk-Version': PACKAGE_VERSION,\n\t\t\t...(apiKeyName && apiKey ? { [apiKeyName]: apiKey } : {}),\n\t\t},\n\t\tsignal: AbortSignal.timeout(timeout),\n\t});\n\n\tawait SealAPIError.assertResponse(response, requestId);\n\tverifyKeyServerVersion(response);\n\tconst serviceResponse = await response.json();\n\n\tif (serviceResponse.service_id !== server.objectId) {\n\t\treturn false;\n\t}\n\tconst fullMsg = flatten([DST_POP, server.pk, fromHex(server.objectId)]);\n\treturn bls12_381.verifyShortSignature(fromBase64(serviceResponse.pop), fullMsg, server.pk);\n}\n\n/**\n * Verify the key server version. Throws an `InvalidKeyServerError` if the version is not supported.\n *\n * @param response - The response from the key server.\n */\nexport function verifyKeyServerVersion(response: Response) {\n\tconst keyServerVersion = response.headers.get('X-KeyServer-Version');\n\tif (keyServerVersion == null) {\n\t\tthrow new InvalidKeyServerVersionError('Key server version not found');\n\t}\n\tif (new Version(keyServerVersion).older_than(SERVER_VERSION_REQUIREMENT)) {\n\t\tthrow new InvalidKeyServerVersionError(\n\t\t\t`Key server version ${keyServerVersion} is not supported`,\n\t\t);\n\t}\n}\n\nexport interface DerivedKey {\n\ttoString(): string;\n}\n\n/**\n * A user secret key for the Boneh-Franklin BLS12381 scheme.\n * This is a wrapper around the G1Element type.\n */\nexport class BonehFranklinBLS12381DerivedKey implements DerivedKey {\n\trepresentation: string;\n\n\tconstructor(public key: G1Element) {\n\t\tthis.representation = toHex(key.toBytes());\n\t}\n\n\ttoString(): string {\n\t\treturn this.representation;\n\t}\n}\n\n/**\n * Options for fetching keys from the key server.\n */\nexport interface FetchKeysOptions {\n\t/** The URL of the key server. */\n\turl: string;\n\t/** The Base64 string of request signature. */\n\trequestSignature: string;\n\t/** The transaction bytes. */\n\ttransactionBytes: Uint8Array;\n\t/** The ephemeral secret key. */\n\tencKey: Uint8Array<ArrayBuffer>;\n\t/** The ephemeral public key. */\n\tencKeyPk: Uint8Array<ArrayBuffer>;\n\t/** The ephemeral verification key. */\n\tencVerificationKey: Uint8Array;\n\t/** The certificate. */\n\tcertificate: Certificate;\n\t/** Request timeout in milliseconds. */\n\ttimeout: number;\n\t/** Optional API key name. */\n\tapiKeyName?: string;\n\t/** Optional API key. */\n\tapiKey?: string;\n\t/** Optional abort signal for cancellation. */\n\tsignal?: AbortSignal;\n}\n\n/**\n * Helper function to request all keys from URL with requestSig, txBytes, ephemeral pubkey.\n * Then decrypt the Seal key with ephemeral secret key. Returns a list decryption keys with\n * their full IDs.\n *\n * @param url - The URL of the key server.\n * @param requestSig - The Base64 string of request signature.\n * @param txBytes - The transaction bytes.\n * @param encKey - The ephemeral secret key.\n * @param certificate - The certificate.\n * @returns - A list of full ID and the decrypted key.\n */\nexport async function fetchKeysForAllIds({\n\turl,\n\trequestSignature,\n\ttransactionBytes,\n\tencKey,\n\tencKeyPk,\n\tencVerificationKey,\n\tcertificate,\n\ttimeout,\n\tapiKeyName,\n\tapiKey,\n\tsignal,\n}: FetchKeysOptions): Promise<{ fullId: string; key: Uint8Array<ArrayBuffer> }[]> {\n\tconst body = {\n\t\tptb: toBase64(transactionBytes.slice(1)), // removes the byte of the transaction type version\n\t\tenc_key: toBase64(encKeyPk),\n\t\tenc_verification_key: toBase64(encVerificationKey),\n\t\trequest_signature: requestSignature, // already b64\n\t\tcertificate,\n\t};\n\n\tconst timeoutSignal = AbortSignal.timeout(timeout);\n\tconst combinedSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;\n\n\tconst requestId = crypto.randomUUID();\n\tconst response = await fetch(url + '/v1/fetch_key', {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'Request-Id': requestId,\n\t\t\t'Client-Sdk-Type': 'typescript',\n\t\t\t'Client-Sdk-Version': PACKAGE_VERSION,\n\t\t\t...(apiKeyName && apiKey ? { [apiKeyName]: apiKey } : {}),\n\t\t},\n\t\tbody: JSON.stringify(body),\n\t\tsignal: combinedSignal,\n\t});\n\tawait SealAPIError.assertResponse(response, requestId);\n\tconst resp = await response.json();\n\tverifyKeyServerVersion(response);\n\n\treturn resp.decryption_keys.map(\n\t\t(dk: { id: Uint8Array<ArrayBuffer>; encrypted_key: [string, string] }) => ({\n\t\t\tfullId: toHex(dk.id),\n\t\t\tkey: elgamalDecrypt(encKey, dk.encrypted_key.map(fromBase64) as [Uint8Array, Uint8Array]),\n\t\t}),\n\t);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_bcs", "KeyServerType"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Signer } from '@haneullabs/haneul/cryptography';
|
|
2
|
+
import type { SealCompatibleClient } from './types.js';
|
|
3
|
+
export declare const RequestFormat: import("@haneullabs/bcs").BcsStruct<{
|
|
4
|
+
ptb: import("@haneullabs/bcs").BcsType<Uint8Array<ArrayBufferLike>, Iterable<number>, "vector<u8>">;
|
|
5
|
+
encKey: import("@haneullabs/bcs").BcsType<Uint8Array<ArrayBufferLike>, Iterable<number>, "vector<u8>">;
|
|
6
|
+
encVerificationKey: import("@haneullabs/bcs").BcsType<Uint8Array<ArrayBufferLike>, Iterable<number>, "vector<u8>">;
|
|
7
|
+
}, string>;
|
|
8
|
+
export type Certificate = {
|
|
9
|
+
user: string;
|
|
10
|
+
session_vk: string;
|
|
11
|
+
creation_time: number;
|
|
12
|
+
ttl_min: number;
|
|
13
|
+
signature: string;
|
|
14
|
+
mvr_name?: string;
|
|
15
|
+
};
|
|
16
|
+
export type ExportedSessionKey = {
|
|
17
|
+
address: string;
|
|
18
|
+
packageId: string;
|
|
19
|
+
mvrName?: string;
|
|
20
|
+
creationTimeMs: number;
|
|
21
|
+
ttlMin: number;
|
|
22
|
+
personalMessageSignature?: string;
|
|
23
|
+
sessionKey: string;
|
|
24
|
+
};
|
|
25
|
+
export declare class SessionKey {
|
|
26
|
+
#private;
|
|
27
|
+
private constructor();
|
|
28
|
+
/**
|
|
29
|
+
* Create a new SessionKey instance.
|
|
30
|
+
* @param address - The address of the user.
|
|
31
|
+
* @param packageId - The ID of the package.
|
|
32
|
+
* @param mvrName - Optional. The name of the MVR, if there is one.
|
|
33
|
+
* @param ttlMin - The TTL in minutes.
|
|
34
|
+
* @param signer - Optional. The signer instance, e.g. EnokiSigner.
|
|
35
|
+
* @param haneulClient - The Haneul client.
|
|
36
|
+
* @returns A new SessionKey instance.
|
|
37
|
+
*/
|
|
38
|
+
static create({ address, packageId, mvrName, ttlMin, signer, haneulClient, }: {
|
|
39
|
+
address: string;
|
|
40
|
+
packageId: string;
|
|
41
|
+
mvrName?: string;
|
|
42
|
+
ttlMin: number;
|
|
43
|
+
signer?: Signer;
|
|
44
|
+
haneulClient: SealCompatibleClient;
|
|
45
|
+
}): Promise<SessionKey>;
|
|
46
|
+
isExpired(): boolean;
|
|
47
|
+
getAddress(): string;
|
|
48
|
+
getPackageName(): string;
|
|
49
|
+
getPackageId(): string;
|
|
50
|
+
getPersonalMessage(): Uint8Array;
|
|
51
|
+
setPersonalMessageSignature(personalMessageSignature: string): Promise<void>;
|
|
52
|
+
getCertificate(): Promise<Certificate>;
|
|
53
|
+
/**
|
|
54
|
+
* Create request params for the given transaction bytes.
|
|
55
|
+
* @param txBytes - The transaction bytes.
|
|
56
|
+
* @returns The request params containing the ephemeral secret key,
|
|
57
|
+
* its public key and its verification key.
|
|
58
|
+
*/
|
|
59
|
+
createRequestParams(txBytes: Uint8Array): Promise<{
|
|
60
|
+
encKey: Uint8Array<ArrayBuffer>;
|
|
61
|
+
encKeyPk: Uint8Array<ArrayBuffer>;
|
|
62
|
+
encVerificationKey: Uint8Array<ArrayBuffer>;
|
|
63
|
+
requestSignature: string;
|
|
64
|
+
}>;
|
|
65
|
+
/**
|
|
66
|
+
* Export the Session Key object from the instance. Store the object in IndexedDB to persist.
|
|
67
|
+
*/
|
|
68
|
+
export(): ExportedSessionKey;
|
|
69
|
+
/**
|
|
70
|
+
* Restore a SessionKey instance for the given object.
|
|
71
|
+
* @returns A new SessionKey instance with restored state
|
|
72
|
+
*/
|
|
73
|
+
static import(data: ExportedSessionKey, haneulClient: SealCompatibleClient, signer?: Signer): SessionKey;
|
|
74
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __typeError = (msg) => {
|
|
7
|
+
throw TypeError(msg);
|
|
8
|
+
};
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
23
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
24
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
25
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
26
|
+
var session_key_exports = {};
|
|
27
|
+
__export(session_key_exports, {
|
|
28
|
+
RequestFormat: () => RequestFormat,
|
|
29
|
+
SessionKey: () => SessionKey
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(session_key_exports);
|
|
32
|
+
var import_bcs = require("@haneullabs/bcs");
|
|
33
|
+
var import_bcs2 = require("@haneullabs/haneul/bcs");
|
|
34
|
+
var import_ed25519 = require("@haneullabs/haneul/keypairs/ed25519");
|
|
35
|
+
var import_utils = require("@haneullabs/haneul/utils");
|
|
36
|
+
var import_verify = require("@haneullabs/haneul/verify");
|
|
37
|
+
var import_elgamal = require("./elgamal.js");
|
|
38
|
+
var import_error = require("./error.js");
|
|
39
|
+
var _address, _packageId, _mvrName, _creationTimeMs, _ttlMin, _sessionKey, _personalMessageSignature, _signer, _haneulClient;
|
|
40
|
+
const RequestFormat = import_bcs2.bcs.struct("RequestFormat", {
|
|
41
|
+
ptb: import_bcs2.bcs.byteVector(),
|
|
42
|
+
encKey: import_bcs2.bcs.byteVector(),
|
|
43
|
+
encVerificationKey: import_bcs2.bcs.byteVector()
|
|
44
|
+
});
|
|
45
|
+
const _SessionKey = class _SessionKey {
|
|
46
|
+
constructor({
|
|
47
|
+
address,
|
|
48
|
+
packageId,
|
|
49
|
+
mvrName,
|
|
50
|
+
ttlMin,
|
|
51
|
+
signer,
|
|
52
|
+
haneulClient
|
|
53
|
+
}) {
|
|
54
|
+
__privateAdd(this, _address);
|
|
55
|
+
__privateAdd(this, _packageId);
|
|
56
|
+
__privateAdd(this, _mvrName);
|
|
57
|
+
__privateAdd(this, _creationTimeMs);
|
|
58
|
+
__privateAdd(this, _ttlMin);
|
|
59
|
+
__privateAdd(this, _sessionKey);
|
|
60
|
+
__privateAdd(this, _personalMessageSignature);
|
|
61
|
+
__privateAdd(this, _signer);
|
|
62
|
+
__privateAdd(this, _haneulClient);
|
|
63
|
+
if (mvrName && !(0, import_utils.isValidNamedPackage)(mvrName)) {
|
|
64
|
+
throw new import_error.UserError(`Invalid package name ${mvrName}`);
|
|
65
|
+
}
|
|
66
|
+
if (!(0, import_utils.isValidHaneulObjectId)(packageId) || !(0, import_utils.isValidHaneulAddress)(address)) {
|
|
67
|
+
throw new import_error.UserError(`Invalid package ID ${packageId} or address ${address}`);
|
|
68
|
+
}
|
|
69
|
+
if (ttlMin > 30 || ttlMin < 1) {
|
|
70
|
+
throw new import_error.UserError(`Invalid TTL ${ttlMin}, must be between 1 and 30`);
|
|
71
|
+
}
|
|
72
|
+
if (signer && signer.getPublicKey().toHaneulAddress() !== address) {
|
|
73
|
+
throw new import_error.UserError("Signer address does not match session key address");
|
|
74
|
+
}
|
|
75
|
+
__privateSet(this, _address, address);
|
|
76
|
+
__privateSet(this, _packageId, packageId);
|
|
77
|
+
__privateSet(this, _mvrName, mvrName);
|
|
78
|
+
__privateSet(this, _creationTimeMs, Date.now());
|
|
79
|
+
__privateSet(this, _ttlMin, ttlMin);
|
|
80
|
+
__privateSet(this, _sessionKey, import_ed25519.Ed25519Keypair.generate());
|
|
81
|
+
__privateSet(this, _signer, signer);
|
|
82
|
+
__privateSet(this, _haneulClient, haneulClient);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Create a new SessionKey instance.
|
|
86
|
+
* @param address - The address of the user.
|
|
87
|
+
* @param packageId - The ID of the package.
|
|
88
|
+
* @param mvrName - Optional. The name of the MVR, if there is one.
|
|
89
|
+
* @param ttlMin - The TTL in minutes.
|
|
90
|
+
* @param signer - Optional. The signer instance, e.g. EnokiSigner.
|
|
91
|
+
* @param haneulClient - The Haneul client.
|
|
92
|
+
* @returns A new SessionKey instance.
|
|
93
|
+
*/
|
|
94
|
+
static async create({
|
|
95
|
+
address,
|
|
96
|
+
packageId,
|
|
97
|
+
mvrName,
|
|
98
|
+
ttlMin,
|
|
99
|
+
signer,
|
|
100
|
+
haneulClient
|
|
101
|
+
}) {
|
|
102
|
+
const packageObj = await haneulClient.core.getObject({ objectId: packageId });
|
|
103
|
+
if (String(packageObj.object.version) !== "1") {
|
|
104
|
+
throw new import_error.InvalidPackageError(`Package ${packageId} is not the first version`);
|
|
105
|
+
}
|
|
106
|
+
return new _SessionKey({
|
|
107
|
+
address,
|
|
108
|
+
packageId,
|
|
109
|
+
mvrName,
|
|
110
|
+
ttlMin,
|
|
111
|
+
signer,
|
|
112
|
+
haneulClient
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
isExpired() {
|
|
116
|
+
return __privateGet(this, _creationTimeMs) + __privateGet(this, _ttlMin) * 60 * 1e3 - 1e4 < Date.now();
|
|
117
|
+
}
|
|
118
|
+
getAddress() {
|
|
119
|
+
return __privateGet(this, _address);
|
|
120
|
+
}
|
|
121
|
+
getPackageName() {
|
|
122
|
+
if (__privateGet(this, _mvrName)) {
|
|
123
|
+
return __privateGet(this, _mvrName);
|
|
124
|
+
}
|
|
125
|
+
return __privateGet(this, _packageId);
|
|
126
|
+
}
|
|
127
|
+
getPackageId() {
|
|
128
|
+
return __privateGet(this, _packageId);
|
|
129
|
+
}
|
|
130
|
+
getPersonalMessage() {
|
|
131
|
+
const creationTimeUtc = new Date(__privateGet(this, _creationTimeMs)).toISOString().slice(0, 19).replace("T", " ") + " UTC";
|
|
132
|
+
const message = `Accessing keys of package ${this.getPackageName()} for ${__privateGet(this, _ttlMin)} mins from ${creationTimeUtc}, session key ${(0, import_bcs.toBase64)(__privateGet(this, _sessionKey).getPublicKey().toRawBytes())}`;
|
|
133
|
+
return new TextEncoder().encode(message);
|
|
134
|
+
}
|
|
135
|
+
async setPersonalMessageSignature(personalMessageSignature) {
|
|
136
|
+
if (!__privateGet(this, _personalMessageSignature)) {
|
|
137
|
+
try {
|
|
138
|
+
await (0, import_verify.verifyPersonalMessageSignature)(this.getPersonalMessage(), personalMessageSignature, {
|
|
139
|
+
address: __privateGet(this, _address),
|
|
140
|
+
client: __privateGet(this, _haneulClient)
|
|
141
|
+
});
|
|
142
|
+
__privateSet(this, _personalMessageSignature, personalMessageSignature);
|
|
143
|
+
} catch {
|
|
144
|
+
throw new import_error.InvalidPersonalMessageSignatureError("Not valid");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async getCertificate() {
|
|
149
|
+
if (!__privateGet(this, _personalMessageSignature)) {
|
|
150
|
+
if (__privateGet(this, _signer)) {
|
|
151
|
+
const { signature } = await __privateGet(this, _signer).signPersonalMessage(this.getPersonalMessage());
|
|
152
|
+
__privateSet(this, _personalMessageSignature, signature);
|
|
153
|
+
} else {
|
|
154
|
+
throw new import_error.InvalidPersonalMessageSignatureError("Personal message signature is not set");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
user: __privateGet(this, _address),
|
|
159
|
+
session_vk: (0, import_bcs.toBase64)(__privateGet(this, _sessionKey).getPublicKey().toRawBytes()),
|
|
160
|
+
creation_time: __privateGet(this, _creationTimeMs),
|
|
161
|
+
ttl_min: __privateGet(this, _ttlMin),
|
|
162
|
+
signature: __privateGet(this, _personalMessageSignature),
|
|
163
|
+
mvr_name: __privateGet(this, _mvrName)
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Create request params for the given transaction bytes.
|
|
168
|
+
* @param txBytes - The transaction bytes.
|
|
169
|
+
* @returns The request params containing the ephemeral secret key,
|
|
170
|
+
* its public key and its verification key.
|
|
171
|
+
*/
|
|
172
|
+
async createRequestParams(txBytes) {
|
|
173
|
+
if (this.isExpired()) {
|
|
174
|
+
throw new import_error.ExpiredSessionKeyError();
|
|
175
|
+
}
|
|
176
|
+
const encKey = (0, import_elgamal.generateSecretKey)();
|
|
177
|
+
const encKeyPk = (0, import_elgamal.toPublicKey)(encKey);
|
|
178
|
+
const encVerificationKey = (0, import_elgamal.toVerificationKey)(encKey);
|
|
179
|
+
const msgToSign = RequestFormat.serialize({
|
|
180
|
+
ptb: txBytes.slice(1),
|
|
181
|
+
encKey: encKeyPk,
|
|
182
|
+
encVerificationKey
|
|
183
|
+
}).toBytes();
|
|
184
|
+
return {
|
|
185
|
+
encKey,
|
|
186
|
+
encKeyPk,
|
|
187
|
+
encVerificationKey,
|
|
188
|
+
requestSignature: (0, import_bcs.toBase64)(await __privateGet(this, _sessionKey).sign(msgToSign))
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Export the Session Key object from the instance. Store the object in IndexedDB to persist.
|
|
193
|
+
*/
|
|
194
|
+
export() {
|
|
195
|
+
const obj = {
|
|
196
|
+
address: __privateGet(this, _address),
|
|
197
|
+
packageId: __privateGet(this, _packageId),
|
|
198
|
+
mvrName: __privateGet(this, _mvrName),
|
|
199
|
+
creationTimeMs: __privateGet(this, _creationTimeMs),
|
|
200
|
+
ttlMin: __privateGet(this, _ttlMin),
|
|
201
|
+
personalMessageSignature: __privateGet(this, _personalMessageSignature),
|
|
202
|
+
sessionKey: __privateGet(this, _sessionKey).getSecretKey()
|
|
203
|
+
// bech32 encoded string
|
|
204
|
+
};
|
|
205
|
+
Object.defineProperty(obj, "toJSON", {
|
|
206
|
+
enumerable: false,
|
|
207
|
+
value: () => {
|
|
208
|
+
throw new Error("This object is not serializable");
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
return obj;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Restore a SessionKey instance for the given object.
|
|
215
|
+
* @returns A new SessionKey instance with restored state
|
|
216
|
+
*/
|
|
217
|
+
static import(data, haneulClient, signer) {
|
|
218
|
+
const instance = new _SessionKey({
|
|
219
|
+
address: data.address,
|
|
220
|
+
packageId: data.packageId,
|
|
221
|
+
mvrName: data.mvrName,
|
|
222
|
+
ttlMin: data.ttlMin,
|
|
223
|
+
signer,
|
|
224
|
+
haneulClient
|
|
225
|
+
});
|
|
226
|
+
__privateSet(instance, _creationTimeMs, data.creationTimeMs);
|
|
227
|
+
__privateSet(instance, _sessionKey, import_ed25519.Ed25519Keypair.fromSecretKey(data.sessionKey));
|
|
228
|
+
__privateSet(instance, _personalMessageSignature, data.personalMessageSignature);
|
|
229
|
+
if (instance.isExpired()) {
|
|
230
|
+
throw new import_error.ExpiredSessionKeyError();
|
|
231
|
+
}
|
|
232
|
+
return instance;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
_address = new WeakMap();
|
|
236
|
+
_packageId = new WeakMap();
|
|
237
|
+
_mvrName = new WeakMap();
|
|
238
|
+
_creationTimeMs = new WeakMap();
|
|
239
|
+
_ttlMin = new WeakMap();
|
|
240
|
+
_sessionKey = new WeakMap();
|
|
241
|
+
_personalMessageSignature = new WeakMap();
|
|
242
|
+
_signer = new WeakMap();
|
|
243
|
+
_haneulClient = new WeakMap();
|
|
244
|
+
let SessionKey = _SessionKey;
|
|
245
|
+
//# sourceMappingURL=session-key.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/session-key.ts"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { toBase64 } from '@haneullabs/bcs';\nimport { bcs } from '@haneullabs/haneul/bcs';\nimport type { Signer } from '@haneullabs/haneul/cryptography';\nimport { Ed25519Keypair } from '@haneullabs/haneul/keypairs/ed25519';\nimport { isValidNamedPackage, isValidHaneulAddress, isValidHaneulObjectId } from '@haneullabs/haneul/utils';\nimport { verifyPersonalMessageSignature } from '@haneullabs/haneul/verify';\nimport { generateSecretKey, toPublicKey, toVerificationKey } from './elgamal.js';\nimport {\n\tExpiredSessionKeyError,\n\tInvalidPackageError,\n\tInvalidPersonalMessageSignatureError,\n\tUserError,\n} from './error.js';\nimport type { SealCompatibleClient } from './types.js';\n\nexport const RequestFormat = bcs.struct('RequestFormat', {\n\tptb: bcs.byteVector(),\n\tencKey: bcs.byteVector(),\n\tencVerificationKey: bcs.byteVector(),\n});\n\nexport type Certificate = {\n\tuser: string;\n\tsession_vk: string;\n\tcreation_time: number;\n\tttl_min: number;\n\tsignature: string;\n\tmvr_name?: string;\n};\n\nexport type ExportedSessionKey = {\n\taddress: string;\n\tpackageId: string;\n\tmvrName?: string;\n\tcreationTimeMs: number;\n\tttlMin: number;\n\tpersonalMessageSignature?: string;\n\tsessionKey: string;\n};\n\nexport class SessionKey {\n\t#address: string;\n\t#packageId: string;\n\t#mvrName?: string;\n\t#creationTimeMs: number;\n\t#ttlMin: number;\n\t#sessionKey: Ed25519Keypair;\n\t#personalMessageSignature?: string;\n\t#signer?: Signer;\n\t#haneulClient: SealCompatibleClient;\n\n\tprivate constructor({\n\t\taddress,\n\t\tpackageId,\n\t\tmvrName,\n\t\tttlMin,\n\t\tsigner,\n\t\thaneulClient,\n\t}: {\n\t\taddress: string;\n\t\tpackageId: string;\n\t\tmvrName?: string;\n\t\tttlMin: number;\n\t\tsigner?: Signer;\n\t\thaneulClient: SealCompatibleClient;\n\t}) {\n\t\tif (mvrName && !isValidNamedPackage(mvrName)) {\n\t\t\tthrow new UserError(`Invalid package name ${mvrName}`);\n\t\t}\n\t\tif (!isValidHaneulObjectId(packageId) || !isValidHaneulAddress(address)) {\n\t\t\tthrow new UserError(`Invalid package ID ${packageId} or address ${address}`);\n\t\t}\n\t\tif (ttlMin > 30 || ttlMin < 1) {\n\t\t\tthrow new UserError(`Invalid TTL ${ttlMin}, must be between 1 and 30`);\n\t\t}\n\t\tif (signer && signer.getPublicKey().toHaneulAddress() !== address) {\n\t\t\tthrow new UserError('Signer address does not match session key address');\n\t\t}\n\n\t\tthis.#address = address;\n\t\tthis.#packageId = packageId;\n\t\tthis.#mvrName = mvrName;\n\t\tthis.#creationTimeMs = Date.now();\n\t\tthis.#ttlMin = ttlMin;\n\t\tthis.#sessionKey = Ed25519Keypair.generate();\n\t\tthis.#signer = signer;\n\t\tthis.#haneulClient = haneulClient;\n\t}\n\n\t/**\n\t * Create a new SessionKey instance.\n\t * @param address - The address of the user.\n\t * @param packageId - The ID of the package.\n\t * @param mvrName - Optional. The name of the MVR, if there is one.\n\t * @param ttlMin - The TTL in minutes.\n\t * @param signer - Optional. The signer instance, e.g. EnokiSigner.\n\t * @param haneulClient - The Haneul client.\n\t * @returns A new SessionKey instance.\n\t */\n\tstatic async create({\n\t\taddress,\n\t\tpackageId,\n\t\tmvrName,\n\t\tttlMin,\n\t\tsigner,\n\t\thaneulClient,\n\t}: {\n\t\taddress: string;\n\t\tpackageId: string;\n\t\tmvrName?: string;\n\t\tttlMin: number;\n\t\tsigner?: Signer;\n\t\thaneulClient: SealCompatibleClient;\n\t}): Promise<SessionKey> {\n\t\tconst packageObj = await haneulClient.core.getObject({ objectId: packageId });\n\t\tif (String(packageObj.object.version) !== '1') {\n\t\t\tthrow new InvalidPackageError(`Package ${packageId} is not the first version`);\n\t\t}\n\n\t\treturn new SessionKey({\n\t\t\taddress,\n\t\t\tpackageId,\n\t\t\tmvrName,\n\t\t\tttlMin,\n\t\t\tsigner,\n\t\t\thaneulClient,\n\t\t});\n\t}\n\tisExpired(): boolean {\n\t\t// Allow 10 seconds for clock skew\n\t\treturn this.#creationTimeMs + this.#ttlMin * 60 * 1000 - 10_000 < Date.now();\n\t}\n\n\tgetAddress(): string {\n\t\treturn this.#address;\n\t}\n\n\tgetPackageName(): string {\n\t\tif (this.#mvrName) {\n\t\t\treturn this.#mvrName;\n\t\t}\n\t\treturn this.#packageId;\n\t}\n\n\tgetPackageId(): string {\n\t\treturn this.#packageId;\n\t}\n\n\tgetPersonalMessage(): Uint8Array {\n\t\tconst creationTimeUtc =\n\t\t\tnew Date(this.#creationTimeMs).toISOString().slice(0, 19).replace('T', ' ') + ' UTC';\n\t\tconst message = `Accessing keys of package ${this.getPackageName()} for ${this.#ttlMin} mins from ${creationTimeUtc}, session key ${toBase64(this.#sessionKey.getPublicKey().toRawBytes())}`;\n\t\treturn new TextEncoder().encode(message);\n\t}\n\n\tasync setPersonalMessageSignature(personalMessageSignature: string) {\n\t\tif (!this.#personalMessageSignature) {\n\t\t\ttry {\n\t\t\t\tawait verifyPersonalMessageSignature(this.getPersonalMessage(), personalMessageSignature, {\n\t\t\t\t\taddress: this.#address,\n\t\t\t\t\tclient: this.#haneulClient,\n\t\t\t\t});\n\t\t\t\tthis.#personalMessageSignature = personalMessageSignature;\n\t\t\t} catch {\n\t\t\t\tthrow new InvalidPersonalMessageSignatureError('Not valid');\n\t\t\t}\n\t\t}\n\t}\n\n\tasync getCertificate(): Promise<Certificate> {\n\t\tif (!this.#personalMessageSignature) {\n\t\t\tif (this.#signer) {\n\t\t\t\tconst { signature } = await this.#signer.signPersonalMessage(this.getPersonalMessage());\n\t\t\t\tthis.#personalMessageSignature = signature;\n\t\t\t} else {\n\t\t\t\tthrow new InvalidPersonalMessageSignatureError('Personal message signature is not set');\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tuser: this.#address,\n\t\t\tsession_vk: toBase64(this.#sessionKey.getPublicKey().toRawBytes()),\n\t\t\tcreation_time: this.#creationTimeMs,\n\t\t\tttl_min: this.#ttlMin,\n\t\t\tsignature: this.#personalMessageSignature,\n\t\t\tmvr_name: this.#mvrName,\n\t\t};\n\t}\n\n\t/**\n\t * Create request params for the given transaction bytes.\n\t * @param txBytes - The transaction bytes.\n\t * @returns The request params containing the ephemeral secret key,\n\t * its public key and its verification key.\n\t */\n\tasync createRequestParams(txBytes: Uint8Array): Promise<{\n\t\tencKey: Uint8Array<ArrayBuffer>;\n\t\tencKeyPk: Uint8Array<ArrayBuffer>;\n\t\tencVerificationKey: Uint8Array<ArrayBuffer>;\n\t\trequestSignature: string;\n\t}> {\n\t\tif (this.isExpired()) {\n\t\t\tthrow new ExpiredSessionKeyError();\n\t\t}\n\t\tconst encKey = generateSecretKey();\n\t\tconst encKeyPk = toPublicKey(encKey);\n\t\tconst encVerificationKey = toVerificationKey(encKey);\n\n\t\tconst msgToSign = RequestFormat.serialize({\n\t\t\tptb: txBytes.slice(1),\n\t\t\tencKey: encKeyPk,\n\t\t\tencVerificationKey,\n\t\t}).toBytes();\n\t\treturn {\n\t\t\tencKey,\n\t\t\tencKeyPk,\n\t\t\tencVerificationKey,\n\t\t\trequestSignature: toBase64(await this.#sessionKey.sign(msgToSign)),\n\t\t};\n\t}\n\n\t/**\n\t * Export the Session Key object from the instance. Store the object in IndexedDB to persist.\n\t */\n\texport(): ExportedSessionKey {\n\t\tconst obj = {\n\t\t\taddress: this.#address,\n\t\t\tpackageId: this.#packageId,\n\t\t\tmvrName: this.#mvrName,\n\t\t\tcreationTimeMs: this.#creationTimeMs,\n\t\t\tttlMin: this.#ttlMin,\n\t\t\tpersonalMessageSignature: this.#personalMessageSignature,\n\t\t\tsessionKey: this.#sessionKey.getSecretKey(), // bech32 encoded string\n\t\t};\n\n\t\tObject.defineProperty(obj, 'toJSON', {\n\t\t\tenumerable: false,\n\t\t\tvalue: () => {\n\t\t\t\tthrow new Error('This object is not serializable');\n\t\t\t},\n\t\t});\n\t\treturn obj;\n\t}\n\n\t/**\n\t * Restore a SessionKey instance for the given object.\n\t * @returns A new SessionKey instance with restored state\n\t */\n\tstatic import(\n\t\tdata: ExportedSessionKey,\n\t\thaneulClient: SealCompatibleClient,\n\t\tsigner?: Signer,\n\t): SessionKey {\n\t\tconst instance = new SessionKey({\n\t\t\taddress: data.address,\n\t\t\tpackageId: data.packageId,\n\t\t\tmvrName: data.mvrName,\n\t\t\tttlMin: data.ttlMin,\n\t\t\tsigner,\n\t\t\thaneulClient,\n\t\t});\n\n\t\tinstance.#creationTimeMs = data.creationTimeMs;\n\t\tinstance.#sessionKey = Ed25519Keypair.fromSecretKey(data.sessionKey);\n\t\tinstance.#personalMessageSignature = data.personalMessageSignature;\n\n\t\tif (instance.isExpired()) {\n\t\t\tthrow new ExpiredSessionKeyError();\n\t\t}\n\t\treturn instance;\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_bcs"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A field element in the Rijndael finite field GF(2⁸) with a fixed generator g = 0x03.
|
|
3
|
+
*/
|
|
4
|
+
export declare class GF256 {
|
|
5
|
+
value: number;
|
|
6
|
+
constructor(value: number);
|
|
7
|
+
log(): number;
|
|
8
|
+
static exp(x: number): GF256;
|
|
9
|
+
add(other: GF256): GF256;
|
|
10
|
+
sub(other: GF256): GF256;
|
|
11
|
+
neg(): GF256;
|
|
12
|
+
mul(other: GF256): GF256;
|
|
13
|
+
div(other: GF256): GF256;
|
|
14
|
+
equals(other: GF256): boolean;
|
|
15
|
+
static zero(): GF256;
|
|
16
|
+
static one(): GF256;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A polynomial over the field GF(2⁸).
|
|
20
|
+
*/
|
|
21
|
+
export declare class Polynomial {
|
|
22
|
+
coefficients: GF256[];
|
|
23
|
+
/**
|
|
24
|
+
* Construct a new Polynomial over [GF256] from the given coefficients.
|
|
25
|
+
* The first coefficient is the constant term.
|
|
26
|
+
*/
|
|
27
|
+
constructor(coefficients: GF256[]);
|
|
28
|
+
/**
|
|
29
|
+
* Construct a polynomial from the given bytes.
|
|
30
|
+
* Each byte is a coefficient of the polynomial starting from the constant term.
|
|
31
|
+
*/
|
|
32
|
+
static fromBytes(bytes: Uint8Array): Polynomial;
|
|
33
|
+
degree(): number;
|
|
34
|
+
/** Get the coefficient of the polynomial at the given index. */
|
|
35
|
+
getCoefficient(index: number): GF256;
|
|
36
|
+
/** Add two polynomials. */
|
|
37
|
+
add(other: Polynomial): Polynomial;
|
|
38
|
+
/** Multiply two polynomials. */
|
|
39
|
+
mul(other: Polynomial): Polynomial;
|
|
40
|
+
/** The polynomial s * this. */
|
|
41
|
+
scale(s: GF256): Polynomial;
|
|
42
|
+
/** The polynomial (1 / s) * this. */
|
|
43
|
+
div(s: GF256): Polynomial;
|
|
44
|
+
/** The polynomial x + c. */
|
|
45
|
+
static monic_linear(c: GF256): Polynomial;
|
|
46
|
+
/** The zero polynomial. */
|
|
47
|
+
static zero(): Polynomial;
|
|
48
|
+
/** The polynomial 1. */
|
|
49
|
+
static one(): Polynomial;
|
|
50
|
+
/** Given a set of coordinates, interpolate a polynomial. */
|
|
51
|
+
static interpolate(coordinates: {
|
|
52
|
+
x: GF256;
|
|
53
|
+
y: GF256;
|
|
54
|
+
}[]): Polynomial;
|
|
55
|
+
/** Given a set of coordinates, interpolate a polynomial and evaluate it at x = 0. */
|
|
56
|
+
static combine(coordinates: {
|
|
57
|
+
x: GF256;
|
|
58
|
+
y: GF256;
|
|
59
|
+
}[]): GF256;
|
|
60
|
+
/** Evaluate the polynomial at x. */
|
|
61
|
+
evaluate(x: GF256): GF256;
|
|
62
|
+
}
|
|
63
|
+
/** Representation of a share of a secret. The index is a number between 1 and 255. */
|
|
64
|
+
export type Share = {
|
|
65
|
+
index: number;
|
|
66
|
+
share: Uint8Array<ArrayBuffer>;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Split a secret into shares.
|
|
70
|
+
*
|
|
71
|
+
* @param secret The secret to split.
|
|
72
|
+
* @param threshold The minimum number of shares required to reconstruct the secret.
|
|
73
|
+
* @param total The total number of shares to generate.
|
|
74
|
+
* @returns The shares.
|
|
75
|
+
*/
|
|
76
|
+
export declare function split(secret: Uint8Array, threshold: number, total: number): Share[];
|
|
77
|
+
/**
|
|
78
|
+
* Combine shares into a secret. If fewer than the threshold number of shares are provided,
|
|
79
|
+
* the result will be indistinguishable from random.
|
|
80
|
+
*
|
|
81
|
+
* @param shares The shares to combine.
|
|
82
|
+
* @returns The secret.
|
|
83
|
+
*/
|
|
84
|
+
export declare function combine(shares: Share[]): Uint8Array<ArrayBuffer>;
|
|
85
|
+
/**
|
|
86
|
+
* Interpolate a polynomial from the given shares.
|
|
87
|
+
*
|
|
88
|
+
* @param shares The shares to interpolate from.
|
|
89
|
+
* @returns A function that evaluates the polynomial at a given x.
|
|
90
|
+
*/
|
|
91
|
+
export declare function interpolate(shares: Share[]): (x: number) => Uint8Array;
|