@mysten/seal 0.4.19 → 0.4.21
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 +17 -0
- package/dist/cjs/bcs.d.ts +68 -121
- package/dist/cjs/bcs.js +7 -7
- package/dist/cjs/bcs.js.map +2 -2
- package/dist/cjs/bls12381.js +8 -2
- package/dist/cjs/bls12381.js.map +2 -2
- package/dist/cjs/client.d.ts +21 -53
- package/dist/cjs/client.js +60 -34
- package/dist/cjs/client.js.map +2 -2
- package/dist/cjs/decrypt.d.ts +6 -1
- package/dist/cjs/decrypt.js +26 -9
- package/dist/cjs/decrypt.js.map +2 -2
- package/dist/cjs/dem.d.ts +1 -1
- package/dist/cjs/dem.js +9 -0
- package/dist/cjs/dem.js.map +2 -2
- package/dist/cjs/encrypt.js +6 -10
- package/dist/cjs/encrypt.js.map +3 -3
- package/dist/cjs/ibe.d.ts +32 -12
- package/dist/cjs/ibe.js +32 -12
- package/dist/cjs/ibe.js.map +2 -2
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/kdf.js.map +1 -1
- package/dist/cjs/key-server.d.ts +47 -1
- package/dist/cjs/key-server.js +57 -4
- package/dist/cjs/key-server.js.map +2 -2
- package/dist/cjs/session-key.d.ts +29 -25
- package/dist/cjs/session-key.js +27 -10
- package/dist/cjs/session-key.js.map +2 -2
- package/dist/cjs/shamir.js +1 -1
- package/dist/cjs/shamir.js.map +2 -2
- package/dist/cjs/types.d.ts +67 -0
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/utils.d.ts +7 -0
- package/dist/cjs/utils.js +7 -0
- package/dist/cjs/utils.js.map +2 -2
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/version.js.map +1 -1
- package/dist/esm/bcs.d.ts +68 -121
- package/dist/esm/bcs.js +7 -7
- package/dist/esm/bcs.js.map +2 -2
- package/dist/esm/bls12381.js +8 -2
- package/dist/esm/bls12381.js.map +2 -2
- package/dist/esm/client.d.ts +21 -53
- package/dist/esm/client.js +62 -36
- package/dist/esm/client.js.map +2 -2
- package/dist/esm/decrypt.d.ts +6 -1
- package/dist/esm/decrypt.js +28 -11
- package/dist/esm/decrypt.js.map +2 -2
- package/dist/esm/dem.d.ts +1 -1
- package/dist/esm/dem.js +9 -0
- package/dist/esm/dem.js.map +2 -2
- package/dist/esm/encrypt.js +4 -8
- package/dist/esm/encrypt.js.map +2 -2
- package/dist/esm/ibe.d.ts +32 -12
- package/dist/esm/ibe.js +32 -12
- package/dist/esm/ibe.js.map +2 -2
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/kdf.js.map +1 -1
- package/dist/esm/key-server.d.ts +47 -1
- package/dist/esm/key-server.js +64 -6
- package/dist/esm/key-server.js.map +2 -2
- package/dist/esm/session-key.d.ts +29 -25
- package/dist/esm/session-key.js +27 -10
- package/dist/esm/session-key.js.map +2 -2
- package/dist/esm/shamir.js +1 -1
- package/dist/esm/shamir.js.map +2 -2
- package/dist/esm/types.d.ts +67 -0
- package/dist/esm/utils.d.ts +7 -0
- package/dist/esm/utils.js +7 -0
- package/dist/esm/utils.js.map +2 -2
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/dist/cjs/keys.d.ts +0 -17
- package/dist/cjs/keys.js +0 -64
- package/dist/cjs/keys.js.map +0 -7
- package/dist/esm/keys.d.ts +0 -17
- package/dist/esm/keys.js +0 -44
- package/dist/esm/keys.js.map +0 -7
package/dist/cjs/ibe.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/ibe.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\n\nimport type { IBEEncryptions } from './bcs.js';\nimport type { G1Element, GTElement } from './bls12381.js';\nimport { G2Element, Scalar } from './bls12381.js';\nimport { deriveKey, hashToG1, kdf, KeyPurpose } from './kdf.js';\nimport type { KeyServer } from './key-server.js';\nimport { xor } from './utils.js';\n\n/**\n * The domain separation tag for the signing proof of possession.\n */\nexport const DST_POP: Uint8Array = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-POP-00');\n\n/**\n * The interface for the key servers.\n */\nexport abstract class IBEServers {\n\tobjectIds: string[];\n\n\tconstructor(objectIds: string[]) {\n\t\tthis.objectIds = objectIds;\n\t}\n\n\t/**\n\t *
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAwB;AAIxB,sBAAkC;AAClC,iBAAqD;AAErD,mBAAoB;
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\n\nimport type { IBEEncryptions } from './bcs.js';\nimport type { G1Element, GTElement } from './bls12381.js';\nimport { G2Element, Scalar } from './bls12381.js';\nimport { deriveKey, hashToG1, kdf, KeyPurpose } from './kdf.js';\nimport type { KeyServer } from './key-server.js';\nimport { xor } from './utils.js';\nimport type { Share } from './shamir.js';\n\n/**\n * The domain separation tag for the signing proof of possession.\n */\nexport const DST_POP: Uint8Array = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-POP-00');\n\n/**\n * The interface for the key servers.\n */\nexport abstract class IBEServers {\n\tobjectIds: string[];\n\n\tconstructor(objectIds: string[]) {\n\t\tthis.objectIds = objectIds;\n\t}\n\n\t/**\n\t * Encrypt a batch of messages for the given identity.\n\t *\n\t * @param id The identity.\n\t * @param msgAndIndices The messages and the corresponding indices of the share being encrypted.\n\t * @returns The encrypted messages.\n\t */\n\tabstract encryptBatched(\n\t\tid: Uint8Array,\n\t\tshares: Share[],\n\t\tbaseKey: Uint8Array,\n\t\tthreshold: number,\n\t): typeof IBEEncryptions.$inferType;\n}\n\n/**\n * Identity-based encryption based on the Boneh-Franklin IBE scheme (https://eprint.iacr.org/2001/090).\n * Note that this implementation is of the \"BasicIdent\" protocol which on its own is not CCA secure, so this IBE implementation should not be used on its own.\n *\n * This object represents a set of key servers that can be used to encrypt messages for a given identity.\n */\nexport class BonehFranklinBLS12381Services extends IBEServers {\n\treadonly publicKeys: G2Element[];\n\n\tconstructor(services: KeyServer[]) {\n\t\tsuper(services.map((service) => service.objectId));\n\t\tthis.publicKeys = services.map((service) => G2Element.fromBytes(service.pk));\n\t}\n\n\tencryptBatched(\n\t\tid: Uint8Array,\n\t\tshares: Share[],\n\t\tbaseKey: Uint8Array,\n\t\tthreshold: number,\n\t): typeof IBEEncryptions.$inferType {\n\t\tif (this.publicKeys.length === 0 || this.publicKeys.length !== shares.length) {\n\t\t\tthrow new Error('Invalid public keys');\n\t\t}\n\t\tconst [r, nonce, keys] = encapBatched(this.publicKeys, id);\n\t\tconst encryptedShares = shares.map(({ share, index }, i) =>\n\t\t\txor(share, kdf(keys[i], nonce, id, this.objectIds[i], index)),\n\t\t);\n\t\tconst randomnessKey = deriveKey(\n\t\t\tKeyPurpose.EncryptedRandomness,\n\t\t\tbaseKey,\n\t\t\tencryptedShares,\n\t\t\tthreshold,\n\t\t\tthis.objectIds,\n\t\t);\n\t\tconst encryptedRandomness = xor(randomnessKey, r.toBytes());\n\n\t\treturn {\n\t\t\tBonehFranklinBLS12381: {\n\t\t\t\tnonce: nonce.toBytes(),\n\t\t\t\tencryptedShares,\n\t\t\t\tencryptedRandomness,\n\t\t\t},\n\t\t\t$kind: 'BonehFranklinBLS12381',\n\t\t};\n\t}\n\n\t/**\n\t * Returns true if the user secret key is valid for the given public key and id.\n\t * @param user_secret_key - The user secret key.\n\t * @param id - The identity.\n\t * @param public_key - The public key.\n\t * @returns True if the user secret key is valid for the given public key and id.\n\t */\n\tstatic verifyUserSecretKey(userSecretKey: G1Element, id: string, publicKey: G2Element): boolean {\n\t\tconst lhs = userSecretKey.pairing(G2Element.generator());\n\t\tconst rhs = hashToG1(fromHex(id)).pairing(publicKey);\n\t\treturn lhs.equals(rhs);\n\t}\n\n\t/**\n\t * Identity-based decryption.\n\t *\n\t * @param nonce The encryption nonce.\n\t * @param sk The user secret key.\n\t * @param ciphertext The encrypted message.\n\t * @param info An info parameter also included in the KDF.\n\t * @returns The decrypted message.\n\t */\n\tstatic decrypt(\n\t\tnonce: G2Element,\n\t\tsk: G1Element,\n\t\tciphertext: Uint8Array,\n\t\tid: Uint8Array,\n\t\t[objectId, index]: [string, number],\n\t): Uint8Array {\n\t\treturn xor(ciphertext, kdf(decap(nonce, sk), nonce, id, objectId, index));\n\t}\n\n\t/**\n\t * Decrypt all shares and verify that the randomness was used to create the given nonce.\n\t *\n\t * @param randomness - The randomness.\n\t * @param encryptedShares - The encrypted shares.\n\t * @param services - The services.\n\t * @param publicKeys - The public keys.\n\t * @param nonce - The nonce.\n\t * @param id - The id.\n\t * @returns All decrypted shares.\n\t */\n\tstatic decryptAllSharesUsingRandomness(\n\t\trandomness: Scalar,\n\t\tencryptedShares: Uint8Array[],\n\t\tservices: [string, number][],\n\t\tpublicKeys: G2Element[],\n\t\tnonce: G2Element,\n\t\tid: Uint8Array,\n\t): { index: number; share: Uint8Array }[] {\n\t\tif (publicKeys.length !== encryptedShares.length || publicKeys.length !== services.length) {\n\t\t\tthrow new Error('The number of public keys, encrypted shares and services must be the same');\n\t\t}\n\t\tconst gid_r = hashToG1(id).multiply(randomness);\n\t\treturn services.map(([objectId, index], i) => {\n\t\t\treturn {\n\t\t\t\tindex,\n\t\t\t\tshare: xor(\n\t\t\t\t\tencryptedShares[i],\n\t\t\t\t\tkdf(gid_r.pairing(publicKeys[i]), nonce, id, objectId, index),\n\t\t\t\t),\n\t\t\t};\n\t\t});\n\t}\n}\n\n/**\n * Batched identity-based key-encapsulation mechanism: encapsulate multiple keys for given identity using different key servers.\n *\n * @param publicKeys Public keys for a set of key servers.\n * @param id The identity used to encapsulate the keys.\n * @returns A common nonce of the keys and a list of keys, 32 bytes each.\n */\nfunction encapBatched(publicKeys: G2Element[], id: Uint8Array): [Scalar, G2Element, GTElement[]] {\n\tif (publicKeys.length === 0) {\n\t\tthrow new Error('No public keys provided');\n\t}\n\tconst r = Scalar.random();\n\tconst nonce = G2Element.generator().multiply(r);\n\tconst gid_r = hashToG1(id).multiply(r);\n\treturn [r, nonce, publicKeys.map((public_key) => gid_r.pairing(public_key))];\n}\n\n/**\n * Decapsulate a key using a user secret key and the nonce.\n *\n * @param usk The user secret key.\n * @param nonce The nonce.\n * @returns The encapsulated key.\n */\nfunction decap(nonce: G2Element, usk: G1Element): GTElement {\n\treturn usk.pairing(nonce);\n}\n\n/**\n * Verify that the given randomness was used to crate the nonce.\n *\n * @param randomness - The randomness.\n * @param nonce - The nonce.\n * @returns True if the randomness was used to create the nonce, false otherwise.\n */\nexport function verifyNonce(nonce: G2Element, randomness: Scalar): boolean {\n\treturn G2Element.generator().multiply(randomness).equals(nonce);\n}\n\n/**\n * Decrypt the randomness using a key.\n *\n * @param encrypted_randomness - The encrypted randomness.\n * @param derived_key - The derived key.\n * @returns The randomness.\n */\nexport function decryptRandomness(\n\tencryptedRandomness: Uint8Array,\n\trandomnessKey: Uint8Array,\n): Scalar {\n\treturn Scalar.fromBytes(xor(encryptedRandomness, randomnessKey));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { getAllowlistedKeyServers } from './key-server.js';
|
|
2
2
|
export { EncryptedObject } from './bcs.js';
|
|
3
|
-
export { SealClient
|
|
4
|
-
export { SessionKey, type
|
|
3
|
+
export { SealClient } from './client.js';
|
|
4
|
+
export { SessionKey, type ExportedSessionKey } from './session-key.js';
|
|
5
5
|
export * from './error.js';
|
|
6
|
-
export type { SealCompatibleClient } from './types.js';
|
|
6
|
+
export type { SealCompatibleClient, SealClientOptions, SealClientExtensionOptions, KeyServerConfig, EncryptOptions, DecryptOptions, FetchKeysOptions, GetDerivedKeysOptions, } from './types.js';
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nexport { getAllowlistedKeyServers } from './key-server.js';\nexport { EncryptedObject } from './bcs.js';\nexport { SealClient
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,wBAAyC;AACzC,iBAAgC;AAChC,
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nexport { getAllowlistedKeyServers } from './key-server.js';\nexport { EncryptedObject } from './bcs.js';\nexport { SealClient } from './client.js';\nexport { SessionKey, type ExportedSessionKey } from './session-key.js';\nexport * from './error.js';\nexport type {\n\tSealCompatibleClient,\n\tSealClientOptions,\n\tSealClientExtensionOptions,\n\tKeyServerConfig,\n\tEncryptOptions,\n\tDecryptOptions,\n\tFetchKeysOptions,\n\tGetDerivedKeysOptions,\n} from './types.js';\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,wBAAyC;AACzC,iBAAgC;AAChC,oBAA2B;AAC3B,yBAAoD;AACpD,0BAAc,uBAPd;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/kdf.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kdf.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\nimport { sha3_256 } from '@noble/hashes/sha3';\n\nimport { G1Element } from './bls12381.js';\nimport type { G2Element, GTElement } from './bls12381.js';\nimport { flatten, MAX_U8 } from './utils.js';\n\n/**\n * The domain separation tag for the hash-to-group function.\n */\nconst DST: Uint8Array = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-00');\nconst KDF_DST = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-H2-00');\nconst DERIVE_KEY_DST = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-H3-00');\n\n/**\n * Hash an id to a G1Element.\n *\n * @param id The id to hash.\n * @returns The G1Element.\n */\nexport function hashToG1(id: Uint8Array): G1Element {\n\treturn G1Element.hashToCurve(flatten([DST, id]));\n}\n\n/**\n * The default key derivation function.\n *\n * @returns The derived key.\n */\nexport function kdf(\n\telement: GTElement,\n\tnonce: G2Element,\n\tid: Uint8Array,\n\tobjectId: string,\n\tindex: number,\n): Uint8Array {\n\tif (index < 0 || index > MAX_U8) {\n\t\tthrow new Error(`Invalid index ${index}`);\n\t}\n\tconst hash = sha3_256.create();\n\thash.update(KDF_DST);\n\thash.update(element.toBytes());\n\thash.update(nonce.toBytes());\n\thash.update(hashToG1(id).toBytes());\n\thash.update(fromHex(objectId));\n\thash.update(new Uint8Array([index]))
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\nimport { sha3_256 } from '@noble/hashes/sha3';\n\nimport { G1Element } from './bls12381.js';\nimport type { G2Element, GTElement } from './bls12381.js';\nimport { flatten, MAX_U8 } from './utils.js';\n\n/**\n * The domain separation tag for the hash-to-group function.\n */\nconst DST: Uint8Array = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-00');\nconst KDF_DST = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-H2-00');\nconst DERIVE_KEY_DST = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-H3-00');\n\n/**\n * Hash an id to a G1Element.\n *\n * @param id The id to hash.\n * @returns The G1Element.\n */\nexport function hashToG1(id: Uint8Array): G1Element {\n\treturn G1Element.hashToCurve(flatten([DST, id]));\n}\n\n/**\n * The default key derivation function.\n *\n * @returns The derived key.\n */\nexport function kdf(\n\telement: GTElement,\n\tnonce: G2Element,\n\tid: Uint8Array,\n\tobjectId: string,\n\tindex: number,\n): Uint8Array {\n\tif (index < 0 || index > MAX_U8) {\n\t\tthrow new Error(`Invalid index ${index}`);\n\t}\n\tconst hash = sha3_256.create();\n\thash.update(KDF_DST);\n\thash.update(element.toBytes());\n\thash.update(nonce.toBytes());\n\thash.update(hashToG1(id).toBytes());\n\thash.update(fromHex(objectId));\n\thash.update(new Uint8Array([index])); // this is safe because index < 256.\n\treturn hash.digest();\n}\n\nexport enum KeyPurpose {\n\tEncryptedRandomness,\n\tDEM,\n}\n\nfunction tag(purpose: KeyPurpose): Uint8Array {\n\tswitch (purpose) {\n\t\tcase KeyPurpose.EncryptedRandomness:\n\t\t\treturn new Uint8Array([0]);\n\t\tcase KeyPurpose.DEM:\n\t\t\treturn new Uint8Array([1]);\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid key purpose ${purpose}`);\n\t}\n}\n\n/**\n * Derive a key from a base key and a list of encrypted shares.\n *\n * @param purpose The purpose of the key.\n * @param baseKey The base key.\n * @param encryptedShares The encrypted shares.\n * @param threshold The threshold.\n * @param keyServers The object ids of the key servers.\n * @returns The derived key.\n */\nexport function deriveKey(\n\tpurpose: KeyPurpose,\n\tbaseKey: Uint8Array,\n\tencryptedShares: Uint8Array[],\n\tthreshold: number,\n\tkeyServers: string[],\n): Uint8Array {\n\tif (threshold <= 0 || threshold > MAX_U8) {\n\t\tthrow new Error(`Invalid threshold ${threshold}`);\n\t}\n\tconst hash = sha3_256.create();\n\thash.update(DERIVE_KEY_DST);\n\thash.update(baseKey);\n\thash.update(tag(purpose));\n\thash.update(new Uint8Array([threshold]));\n\tencryptedShares.forEach((share) => hash.update(share));\n\tkeyServers.forEach((keyServer) => hash.update(fromHex(keyServer)));\n\treturn hash.digest();\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAwB;AACxB,kBAAyB;AAEzB,sBAA0B;AAE1B,mBAAgC;AAKhC,MAAM,MAAkB,IAAI,YAAY,EAAE,OAAO,0BAA0B;AAC3E,MAAM,UAAU,IAAI,YAAY,EAAE,OAAO,6BAA6B;AACtE,MAAM,iBAAiB,IAAI,YAAY,EAAE,OAAO,6BAA6B;AAQtE,SAAS,SAAS,IAA2B;AACnD,SAAO,0BAAU,gBAAY,sBAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;AAChD;AAOO,SAAS,IACf,SACA,OACA,IACA,UACA,OACa;AACb,MAAI,QAAQ,KAAK,QAAQ,qBAAQ;AAChC,UAAM,IAAI,MAAM,iBAAiB,KAAK,EAAE;AAAA,EACzC;AACA,QAAM,OAAO,qBAAS,OAAO;AAC7B,OAAK,OAAO,OAAO;AACnB,OAAK,OAAO,QAAQ,QAAQ,CAAC;AAC7B,OAAK,OAAO,MAAM,QAAQ,CAAC;AAC3B,OAAK,OAAO,SAAS,EAAE,EAAE,QAAQ,CAAC;AAClC,OAAK,WAAO,oBAAQ,QAAQ,CAAC;AAC7B,OAAK,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC;AACnC,SAAO,KAAK,OAAO;AACpB;AAEO,IAAK,aAAL,kBAAKA,gBAAL;AACN,EAAAA,wBAAA;AACA,EAAAA,wBAAA;AAFW,SAAAA;AAAA,GAAA;AAKZ,SAAS,IAAI,SAAiC;AAC7C,UAAQ,SAAS;AAAA,IAChB,KAAK;AACJ,aAAO,IAAI,WAAW,CAAC,CAAC,CAAC;AAAA,IAC1B,KAAK;AACJ,aAAO,IAAI,WAAW,CAAC,CAAC,CAAC;AAAA,IAC1B;AACC,YAAM,IAAI,MAAM,uBAAuB,OAAO,EAAE;AAAA,EAClD;AACD;AAYO,SAAS,UACf,SACA,SACA,iBACA,WACA,YACa;AACb,MAAI,aAAa,KAAK,YAAY,qBAAQ;AACzC,UAAM,IAAI,MAAM,qBAAqB,SAAS,EAAE;AAAA,EACjD;AACA,QAAM,OAAO,qBAAS,OAAO;AAC7B,OAAK,OAAO,cAAc;AAC1B,OAAK,OAAO,OAAO;AACnB,OAAK,OAAO,IAAI,OAAO,CAAC;AACxB,OAAK,OAAO,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;AACvC,kBAAgB,QAAQ,CAAC,UAAU,KAAK,OAAO,KAAK,CAAC;AACrD,aAAW,QAAQ,CAAC,cAAc,KAAK,WAAO,oBAAQ,SAAS,CAAC,CAAC;AACjE,SAAO,KAAK,OAAO;AACpB;",
|
|
6
6
|
"names": ["KeyPurpose"]
|
|
7
7
|
}
|
package/dist/cjs/key-server.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SealCompatibleClient } from './types.js';
|
|
2
2
|
import type { G1Element } from './bls12381.js';
|
|
3
3
|
import { Version } from './utils.js';
|
|
4
|
+
import type { Certificate } from './session-key.js';
|
|
4
5
|
export type KeyServer = {
|
|
5
6
|
objectId: string;
|
|
6
7
|
name: string;
|
|
@@ -12,8 +13,10 @@ export declare enum KeyServerType {
|
|
|
12
13
|
BonehFranklinBLS12381 = 0
|
|
13
14
|
}
|
|
14
15
|
export declare const SERVER_VERSION_REQUIREMENT: Version;
|
|
16
|
+
export declare const MYSTEN_LABS_KEY_SERVER_1 = "0x73d05d62c18d9374e3ea529e8e0ed6161da1a141a94d3f76ae3fe4e99356db75";
|
|
17
|
+
export declare const MYSTEN_LABS_KEY_SERVER_2 = "0xf5d14a81a982144ae441cd7d64b09027f116a468bd36e7eca494f750591623c8";
|
|
15
18
|
/**
|
|
16
|
-
* Returns a static list of Seal key server object ids
|
|
19
|
+
* Returns a static list of Seal key server object ids, corresponding to Mysten ran Seal servers.
|
|
17
20
|
* @param network - The network to use.
|
|
18
21
|
* @returns The object id's of the key servers.
|
|
19
22
|
*/
|
|
@@ -58,3 +61,46 @@ export declare class BonehFranklinBLS12381DerivedKey implements DerivedKey {
|
|
|
58
61
|
constructor(key: G1Element);
|
|
59
62
|
toString(): string;
|
|
60
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Options for fetching keys from the key server.
|
|
66
|
+
*/
|
|
67
|
+
export interface FetchKeysOptions {
|
|
68
|
+
/** The URL of the key server. */
|
|
69
|
+
url: string;
|
|
70
|
+
/** The Base64 string of request signature. */
|
|
71
|
+
requestSignature: string;
|
|
72
|
+
/** The transaction bytes. */
|
|
73
|
+
transactionBytes: Uint8Array;
|
|
74
|
+
/** The ephemeral secret key. */
|
|
75
|
+
encKey: Uint8Array;
|
|
76
|
+
/** The ephemeral public key. */
|
|
77
|
+
encKeyPk: Uint8Array;
|
|
78
|
+
/** The ephemeral verification key. */
|
|
79
|
+
encVerificationKey: Uint8Array;
|
|
80
|
+
/** The certificate. */
|
|
81
|
+
certificate: Certificate;
|
|
82
|
+
/** Request timeout in milliseconds. */
|
|
83
|
+
timeout: number;
|
|
84
|
+
/** Optional API key name. */
|
|
85
|
+
apiKeyName?: string;
|
|
86
|
+
/** Optional API key. */
|
|
87
|
+
apiKey?: string;
|
|
88
|
+
/** Optional abort signal for cancellation. */
|
|
89
|
+
signal?: AbortSignal;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Helper function to request all keys from URL with requestSig, txBytes, ephemeral pubkey.
|
|
93
|
+
* Then decrypt the Seal key with ephemeral secret key. Returns a list decryption keys with
|
|
94
|
+
* their full IDs.
|
|
95
|
+
*
|
|
96
|
+
* @param url - The URL of the key server.
|
|
97
|
+
* @param requestSig - The Base64 string of request signature.
|
|
98
|
+
* @param txBytes - The transaction bytes.
|
|
99
|
+
* @param encKey - The ephemeral secret key.
|
|
100
|
+
* @param certificate - The certificate.
|
|
101
|
+
* @returns - A list of full ID and the decrypted key.
|
|
102
|
+
*/
|
|
103
|
+
export declare function fetchKeysForAllIds({ url, requestSignature, transactionBytes, encKey, encKeyPk, encVerificationKey, certificate, timeout, apiKeyName, apiKey, signal, }: FetchKeysOptions): Promise<{
|
|
104
|
+
fullId: string;
|
|
105
|
+
key: Uint8Array;
|
|
106
|
+
}[]>;
|
package/dist/cjs/key-server.js
CHANGED
|
@@ -20,7 +20,10 @@ var key_server_exports = {};
|
|
|
20
20
|
__export(key_server_exports, {
|
|
21
21
|
BonehFranklinBLS12381DerivedKey: () => BonehFranklinBLS12381DerivedKey,
|
|
22
22
|
KeyServerType: () => KeyServerType,
|
|
23
|
+
MYSTEN_LABS_KEY_SERVER_1: () => MYSTEN_LABS_KEY_SERVER_1,
|
|
24
|
+
MYSTEN_LABS_KEY_SERVER_2: () => MYSTEN_LABS_KEY_SERVER_2,
|
|
23
25
|
SERVER_VERSION_REQUIREMENT: () => SERVER_VERSION_REQUIREMENT,
|
|
26
|
+
fetchKeysForAllIds: () => fetchKeysForAllIds,
|
|
24
27
|
getAllowlistedKeyServers: () => getAllowlistedKeyServers,
|
|
25
28
|
retrieveKeyServers: () => retrieveKeyServers,
|
|
26
29
|
verifyKeyServer: () => verifyKeyServer,
|
|
@@ -34,18 +37,18 @@ var import_error = require("./error.js");
|
|
|
34
37
|
var import_ibe = require("./ibe.js");
|
|
35
38
|
var import_version = require("./version.js");
|
|
36
39
|
var import_utils = require("./utils.js");
|
|
40
|
+
var import_elgamal = require("./elgamal.js");
|
|
37
41
|
const EXPECTED_SERVER_VERSION = 1;
|
|
38
42
|
var KeyServerType = /* @__PURE__ */ ((KeyServerType2) => {
|
|
39
43
|
KeyServerType2[KeyServerType2["BonehFranklinBLS12381"] = 0] = "BonehFranklinBLS12381";
|
|
40
44
|
return KeyServerType2;
|
|
41
45
|
})(KeyServerType || {});
|
|
42
46
|
const SERVER_VERSION_REQUIREMENT = new import_utils.Version("0.4.1");
|
|
47
|
+
const MYSTEN_LABS_KEY_SERVER_1 = "0x73d05d62c18d9374e3ea529e8e0ed6161da1a141a94d3f76ae3fe4e99356db75";
|
|
48
|
+
const MYSTEN_LABS_KEY_SERVER_2 = "0xf5d14a81a982144ae441cd7d64b09027f116a468bd36e7eca494f750591623c8";
|
|
43
49
|
function getAllowlistedKeyServers(network) {
|
|
44
50
|
if (network === "testnet") {
|
|
45
|
-
return [
|
|
46
|
-
"0x73d05d62c18d9374e3ea529e8e0ed6161da1a141a94d3f76ae3fe4e99356db75",
|
|
47
|
-
"0xf5d14a81a982144ae441cd7d64b09027f116a468bd36e7eca494f750591623c8"
|
|
48
|
-
];
|
|
51
|
+
return [MYSTEN_LABS_KEY_SERVER_1, MYSTEN_LABS_KEY_SERVER_2];
|
|
49
52
|
} else {
|
|
50
53
|
throw new import_error.UnsupportedNetworkError(`Unsupported network ${network}`);
|
|
51
54
|
}
|
|
@@ -73,6 +76,11 @@ async function retrieveKeyServers({
|
|
|
73
76
|
}
|
|
74
77
|
});
|
|
75
78
|
const ksVersioned = import_bcs2.KeyServerMoveV1.parse(resVersionedKs.dynamicField.value.bcs);
|
|
79
|
+
if (ksVersioned.keyType !== 0 /* BonehFranklinBLS12381 */) {
|
|
80
|
+
throw new import_error.InvalidKeyServerError(
|
|
81
|
+
`Server ${objectId} has invalid key type: ${ksVersioned.keyType}`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
76
84
|
return {
|
|
77
85
|
objectId,
|
|
78
86
|
name: ksVersioned.name,
|
|
@@ -125,4 +133,49 @@ class BonehFranklinBLS12381DerivedKey {
|
|
|
125
133
|
return this.representation;
|
|
126
134
|
}
|
|
127
135
|
}
|
|
136
|
+
async function fetchKeysForAllIds({
|
|
137
|
+
url,
|
|
138
|
+
requestSignature,
|
|
139
|
+
transactionBytes,
|
|
140
|
+
encKey,
|
|
141
|
+
encKeyPk,
|
|
142
|
+
encVerificationKey,
|
|
143
|
+
certificate,
|
|
144
|
+
timeout,
|
|
145
|
+
apiKeyName,
|
|
146
|
+
apiKey,
|
|
147
|
+
signal
|
|
148
|
+
}) {
|
|
149
|
+
const body = {
|
|
150
|
+
ptb: (0, import_bcs.toBase64)(transactionBytes.slice(1)),
|
|
151
|
+
// removes the byte of the transaction type version
|
|
152
|
+
enc_key: (0, import_bcs.toBase64)(encKeyPk),
|
|
153
|
+
enc_verification_key: (0, import_bcs.toBase64)(encVerificationKey),
|
|
154
|
+
request_signature: requestSignature,
|
|
155
|
+
// already b64
|
|
156
|
+
certificate
|
|
157
|
+
};
|
|
158
|
+
const timeoutSignal = AbortSignal.timeout(timeout);
|
|
159
|
+
const combinedSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
160
|
+
const requestId = crypto.randomUUID();
|
|
161
|
+
const response = await fetch(url + "/v1/fetch_key", {
|
|
162
|
+
method: "POST",
|
|
163
|
+
headers: {
|
|
164
|
+
"Content-Type": "application/json",
|
|
165
|
+
"Request-Id": requestId,
|
|
166
|
+
"Client-Sdk-Type": "typescript",
|
|
167
|
+
"Client-Sdk-Version": import_version.PACKAGE_VERSION,
|
|
168
|
+
...apiKeyName && apiKey ? { apiKeyName: apiKey } : {}
|
|
169
|
+
},
|
|
170
|
+
body: JSON.stringify(body),
|
|
171
|
+
signal: combinedSignal
|
|
172
|
+
});
|
|
173
|
+
await import_error.SealAPIError.assertResponse(response, requestId);
|
|
174
|
+
const resp = await response.json();
|
|
175
|
+
verifyKeyServerVersion(response);
|
|
176
|
+
return resp.decryption_keys.map((dk) => ({
|
|
177
|
+
fullId: (0, import_bcs.toHex)(dk.id),
|
|
178
|
+
key: (0, import_elgamal.elgamalDecrypt)(encKey, dk.encrypted_key.map(import_bcs.fromBase64))
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
128
181
|
//# sourceMappingURL=key-server.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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, toHex } from '@mysten/bcs';\nimport { bls12_381 } from '@noble/curves/bls12-381';\n\nimport { KeyServerMove, KeyServerMoveV1 } from './bcs.js';\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport { bcs, fromBase64, fromHex, toBase64, toHex } from '@mysten/bcs';\nimport { bls12_381 } from '@noble/curves/bls12-381';\n\nimport { KeyServerMove, KeyServerMoveV1 } from './bcs.js';\nimport {\n\tInvalidKeyServerError,\n\tInvalidKeyServerVersionError,\n\tSealAPIError,\n\tUnsupportedNetworkError,\n} 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;\n};\n\nexport enum KeyServerType {\n\tBonehFranklinBLS12381 = 0,\n}\n\nexport const SERVER_VERSION_REQUIREMENT = new Version('0.4.1');\nexport const MYSTEN_LABS_KEY_SERVER_1 =\n\t'0x73d05d62c18d9374e3ea529e8e0ed6161da1a141a94d3f76ae3fe4e99356db75';\nexport const MYSTEN_LABS_KEY_SERVER_2 =\n\t'0xf5d14a81a982144ae441cd7d64b09027f116a468bd36e7eca494f750591623c8';\n\n/**\n * Returns a static list of Seal key server object ids, corresponding to Mysten ran Seal servers.\n * @param network - The network to use.\n * @returns The object id's of the key servers.\n */\nexport function getAllowlistedKeyServers(network: 'testnet' | 'mainnet'): string[] {\n\tif (network === 'testnet') {\n\t\treturn [MYSTEN_LABS_KEY_SERVER_1, MYSTEN_LABS_KEY_SERVER_2];\n\t} else {\n\t\t// TODO: add mainnet key servers\n\t\tthrow new UnsupportedNetworkError(`Unsupported network ${network}`);\n\t}\n}\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 SuiClient 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;\n\t/** The ephemeral public key. */\n\tencKeyPk: Uint8Array;\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 }[]> {\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((dk: { id: Uint8Array; encrypted_key: [string, string] }) => ({\n\t\tfullId: toHex(dk.id),\n\t\tkey: elgamalDecrypt(encKey, dk.encrypted_key.map(fromBase64) as [Uint8Array, Uint8Array]),\n\t}));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_bcs", "KeyServerType"]
|
|
7
7
|
}
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import type { Signer } from '@mysten/sui/cryptography';
|
|
2
2
|
import type { SealCompatibleClient } from './types.js';
|
|
3
|
-
export declare const RequestFormat: import("@mysten/bcs").
|
|
4
|
-
ptb: number[]
|
|
5
|
-
encKey: number[];
|
|
6
|
-
encVerificationKey: number[];
|
|
7
|
-
}, {
|
|
8
|
-
ptb: Iterable<number> & {
|
|
3
|
+
export declare const RequestFormat: import("@mysten/bcs").BcsStruct<{
|
|
4
|
+
ptb: import("@mysten/bcs").BcsType<number[], Iterable<number> & {
|
|
9
5
|
length: number;
|
|
10
|
-
}
|
|
11
|
-
encKey: Iterable<number> & {
|
|
6
|
+
}, string>;
|
|
7
|
+
encKey: import("@mysten/bcs").BcsType<number[], Iterable<number> & {
|
|
12
8
|
length: number;
|
|
13
|
-
}
|
|
14
|
-
encVerificationKey: Iterable<number> & {
|
|
9
|
+
}, string>;
|
|
10
|
+
encVerificationKey: import("@mysten/bcs").BcsType<number[], Iterable<number> & {
|
|
15
11
|
length: number;
|
|
16
|
-
}
|
|
17
|
-
}>;
|
|
12
|
+
}, string>;
|
|
13
|
+
}, string>;
|
|
18
14
|
export type Certificate = {
|
|
19
15
|
user: string;
|
|
20
16
|
session_vk: string;
|
|
@@ -23,7 +19,7 @@ export type Certificate = {
|
|
|
23
19
|
signature: string;
|
|
24
20
|
mvr_name?: string;
|
|
25
21
|
};
|
|
26
|
-
export type
|
|
22
|
+
export type ExportedSessionKey = {
|
|
27
23
|
address: string;
|
|
28
24
|
packageId: string;
|
|
29
25
|
mvrName?: string;
|
|
@@ -34,17 +30,17 @@ export type SessionKeyType = {
|
|
|
34
30
|
};
|
|
35
31
|
export declare class SessionKey {
|
|
36
32
|
#private;
|
|
33
|
+
private constructor();
|
|
37
34
|
/**
|
|
38
|
-
*
|
|
35
|
+
* Create a new SessionKey instance.
|
|
36
|
+
* @param address - The address of the user.
|
|
37
|
+
* @param packageId - The ID of the package.
|
|
38
|
+
* @param mvrName - Optional. The name of the MVR, if there is one.
|
|
39
|
+
* @param ttlMin - The TTL in minutes.
|
|
40
|
+
* @param signer - Optional. The signer instance, e.g. EnokiSigner.
|
|
41
|
+
* @param suiClient - The Sui client.
|
|
42
|
+
* @returns A new SessionKey instance.
|
|
39
43
|
*/
|
|
40
|
-
constructor({ address, packageId, mvrName, ttlMin, signer, suiClient, }: {
|
|
41
|
-
address: string;
|
|
42
|
-
packageId: string;
|
|
43
|
-
mvrName?: string;
|
|
44
|
-
ttlMin: number;
|
|
45
|
-
signer?: Signer;
|
|
46
|
-
suiClient: SealCompatibleClient;
|
|
47
|
-
});
|
|
48
44
|
static create({ address, packageId, mvrName, ttlMin, signer, suiClient, }: {
|
|
49
45
|
address: string;
|
|
50
46
|
packageId: string;
|
|
@@ -60,17 +56,25 @@ export declare class SessionKey {
|
|
|
60
56
|
getPersonalMessage(): Uint8Array;
|
|
61
57
|
setPersonalMessageSignature(personalMessageSignature: string): Promise<void>;
|
|
62
58
|
getCertificate(): Promise<Certificate>;
|
|
59
|
+
/**
|
|
60
|
+
* Create request params for the given transaction bytes.
|
|
61
|
+
* @param txBytes - The transaction bytes.
|
|
62
|
+
* @returns The request params containing the ephemeral secret key,
|
|
63
|
+
* its public key and its verification key.
|
|
64
|
+
*/
|
|
63
65
|
createRequestParams(txBytes: Uint8Array): Promise<{
|
|
64
|
-
|
|
66
|
+
encKey: Uint8Array;
|
|
67
|
+
encKeyPk: Uint8Array;
|
|
68
|
+
encVerificationKey: Uint8Array;
|
|
65
69
|
requestSignature: string;
|
|
66
70
|
}>;
|
|
67
71
|
/**
|
|
68
72
|
* Export the Session Key object from the instance. Store the object in IndexedDB to persist.
|
|
69
73
|
*/
|
|
70
|
-
export():
|
|
74
|
+
export(): ExportedSessionKey;
|
|
71
75
|
/**
|
|
72
76
|
* Restore a SessionKey instance for the given object.
|
|
73
77
|
* @returns A new SessionKey instance with restored state
|
|
74
78
|
*/
|
|
75
|
-
static import(data:
|
|
79
|
+
static import(data: ExportedSessionKey, suiClient: SealCompatibleClient, signer?: Signer): SessionKey;
|
|
76
80
|
}
|
package/dist/cjs/session-key.js
CHANGED
|
@@ -38,14 +38,11 @@ var import_elgamal = require("./elgamal.js");
|
|
|
38
38
|
var import_error = require("./error.js");
|
|
39
39
|
var _address, _packageId, _mvrName, _creationTimeMs, _ttlMin, _sessionKey, _personalMessageSignature, _signer, _suiClient;
|
|
40
40
|
const RequestFormat = import_bcs2.bcs.struct("RequestFormat", {
|
|
41
|
-
ptb: import_bcs2.bcs.vector(import_bcs2.bcs.
|
|
42
|
-
encKey: import_bcs2.bcs.vector(import_bcs2.bcs.
|
|
43
|
-
encVerificationKey: import_bcs2.bcs.vector(import_bcs2.bcs.
|
|
41
|
+
ptb: import_bcs2.bcs.vector(import_bcs2.bcs.u8()),
|
|
42
|
+
encKey: import_bcs2.bcs.vector(import_bcs2.bcs.u8()),
|
|
43
|
+
encVerificationKey: import_bcs2.bcs.vector(import_bcs2.bcs.u8())
|
|
44
44
|
});
|
|
45
45
|
const _SessionKey = class _SessionKey {
|
|
46
|
-
/**
|
|
47
|
-
* @deprecated - Use `await SessionKey.create()` instead.
|
|
48
|
-
*/
|
|
49
46
|
constructor({
|
|
50
47
|
address,
|
|
51
48
|
packageId,
|
|
@@ -84,6 +81,16 @@ const _SessionKey = class _SessionKey {
|
|
|
84
81
|
__privateSet(this, _signer, signer);
|
|
85
82
|
__privateSet(this, _suiClient, suiClient);
|
|
86
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 suiClient - The Sui client.
|
|
92
|
+
* @returns A new SessionKey instance.
|
|
93
|
+
*/
|
|
87
94
|
static async create({
|
|
88
95
|
address,
|
|
89
96
|
packageId,
|
|
@@ -156,18 +163,28 @@ const _SessionKey = class _SessionKey {
|
|
|
156
163
|
mvr_name: __privateGet(this, _mvrName)
|
|
157
164
|
};
|
|
158
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
|
+
*/
|
|
159
172
|
async createRequestParams(txBytes) {
|
|
160
173
|
if (this.isExpired()) {
|
|
161
174
|
throw new import_error.ExpiredSessionKeyError();
|
|
162
175
|
}
|
|
163
|
-
const
|
|
176
|
+
const encKey = (0, import_elgamal.generateSecretKey)();
|
|
177
|
+
const encKeyPk = (0, import_elgamal.toPublicKey)(encKey);
|
|
178
|
+
const encVerificationKey = (0, import_elgamal.toVerificationKey)(encKey);
|
|
164
179
|
const msgToSign = RequestFormat.serialize({
|
|
165
180
|
ptb: txBytes.slice(1),
|
|
166
|
-
encKey:
|
|
167
|
-
encVerificationKey
|
|
181
|
+
encKey: encKeyPk,
|
|
182
|
+
encVerificationKey
|
|
168
183
|
}).toBytes();
|
|
169
184
|
return {
|
|
170
|
-
|
|
185
|
+
encKey,
|
|
186
|
+
encKeyPk,
|
|
187
|
+
encVerificationKey,
|
|
171
188
|
requestSignature: (0, import_bcs.toBase64)(await __privateGet(this, _sessionKey).sign(msgToSign))
|
|
172
189
|
};
|
|
173
190
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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 '@mysten/bcs';\nimport { bcs } from '@mysten/sui/bcs';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport { isValidNamedPackage, isValidSuiAddress, isValidSuiObjectId } from '@mysten/sui/utils';\nimport { verifyPersonalMessageSignature } from '@mysten/sui/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.vector(bcs.
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAyB;AACzB,IAAAA,cAAoB;AAEpB,qBAA+B;AAC/B,mBAA2E;AAC3E,oBAA+C;AAC/C,qBAAkE;AAClE,mBAKO;AAfP;AAkBO,MAAM,gBAAgB,gBAAI,OAAO,iBAAiB;AAAA,EACxD,KAAK,gBAAI,OAAO,gBAAI,
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { toBase64 } from '@mysten/bcs';\nimport { bcs } from '@mysten/sui/bcs';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport { isValidNamedPackage, isValidSuiAddress, isValidSuiObjectId } from '@mysten/sui/utils';\nimport { verifyPersonalMessageSignature } from '@mysten/sui/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.vector(bcs.u8()),\n\tencKey: bcs.vector(bcs.u8()),\n\tencVerificationKey: bcs.vector(bcs.u8()),\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#suiClient: SealCompatibleClient;\n\n\tprivate constructor({\n\t\taddress,\n\t\tpackageId,\n\t\tmvrName,\n\t\tttlMin,\n\t\tsigner,\n\t\tsuiClient,\n\t}: {\n\t\taddress: string;\n\t\tpackageId: string;\n\t\tmvrName?: string;\n\t\tttlMin: number;\n\t\tsigner?: Signer;\n\t\tsuiClient: 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 (!isValidSuiObjectId(packageId) || !isValidSuiAddress(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().toSuiAddress() !== 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.#suiClient = suiClient;\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 suiClient - The Sui 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\tsuiClient,\n\t}: {\n\t\taddress: string;\n\t\tpackageId: string;\n\t\tmvrName?: string;\n\t\tttlMin: number;\n\t\tsigner?: Signer;\n\t\tsuiClient: SealCompatibleClient;\n\t}): Promise<SessionKey> {\n\t\tconst packageObj = await suiClient.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\tsuiClient,\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.#suiClient,\n\t\t\t\t});\n\t\t\t\tthis.#personalMessageSignature = personalMessageSignature;\n\t\t\t} catch (e) {\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;\n\t\tencKeyPk: Uint8Array;\n\t\tencVerificationKey: Uint8Array;\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\tsuiClient: 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\tsuiClient,\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
6
|
"names": ["import_bcs"]
|
|
7
7
|
}
|
package/dist/cjs/shamir.js
CHANGED
|
@@ -715,7 +715,7 @@ function samplePolynomial(constant, degree) {
|
|
|
715
715
|
return Polynomial.fromBytes(new Uint8Array([constant.value, ...randomCoefficients]));
|
|
716
716
|
}
|
|
717
717
|
function split(secret, threshold, total) {
|
|
718
|
-
if (threshold > total || threshold < 1 || total
|
|
718
|
+
if (threshold > total || threshold < 1 || total >= GF256_SIZE) {
|
|
719
719
|
throw new Error(`Invalid threshold ${threshold} or total ${total}`);
|
|
720
720
|
}
|
|
721
721
|
const polynomials = Array.from(secret, (s) => samplePolynomial(new GF256(s), threshold - 1));
|