@mysten/seal 0.7.0 → 0.8.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 +10 -0
- package/dist/cjs/bls12381.d.ts +8 -7
- package/dist/cjs/bls12381.js +36 -16
- package/dist/cjs/bls12381.js.map +2 -2
- package/dist/cjs/client.d.ts +2 -1
- package/dist/cjs/client.js +16 -3
- package/dist/cjs/client.js.map +2 -2
- package/dist/cjs/decrypt.d.ts +2 -1
- package/dist/cjs/decrypt.js +3 -2
- package/dist/cjs/decrypt.js.map +2 -2
- package/dist/cjs/elgamal.d.ts +2 -0
- package/dist/cjs/elgamal.js.map +2 -2
- package/dist/cjs/ibe.d.ts +18 -5
- package/dist/cjs/ibe.js +34 -5
- package/dist/cjs/ibe.js.map +2 -2
- package/dist/cjs/types.d.ts +2 -0
- package/dist/cjs/types.js.map +1 -1
- 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/bls12381.d.ts +8 -7
- package/dist/esm/bls12381.js +37 -17
- package/dist/esm/bls12381.js.map +2 -2
- package/dist/esm/client.d.ts +2 -1
- package/dist/esm/client.js +16 -3
- package/dist/esm/client.js.map +2 -2
- package/dist/esm/decrypt.d.ts +2 -1
- package/dist/esm/decrypt.js +9 -3
- package/dist/esm/decrypt.js.map +2 -2
- package/dist/esm/elgamal.d.ts +2 -0
- package/dist/esm/elgamal.js.map +2 -2
- package/dist/esm/ibe.d.ts +18 -5
- package/dist/esm/ibe.js +34 -5
- package/dist/esm/ibe.js.map +2 -2
- package/dist/esm/types.d.ts +2 -0
- 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 +1 -1
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';\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:
|
|
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';\nimport { InvalidCiphertextError } from './error.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: Uint8Array,\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\tlet r;\n\t\ttry {\n\t\t\tr = Scalar.fromBytes(randomness);\n\t\t} catch {\n\t\t\tthrow new InvalidCiphertextError('Invalid randomness');\n\t\t}\n\t\tconst gid_r = hashToG1(id).multiply(r);\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 * Throws an error if the given randomness is invalid (not a BLS scalar).\n *\n * @param randomness - The randomness.\n * @param nonce - The nonce.\n * @param useBE - Flag to indicate if BE encoding is used for the randomness. Defaults to true.\n * @returns True if the randomness was used to create the nonce, false otherwise.\n */\nexport function verifyNonce(\n\tnonce: G2Element,\n\trandomness: Uint8Array,\n\tuseBE: boolean = true,\n): boolean {\n\ttry {\n\t\tconst r = decodeRandomness(randomness, useBE);\n\t\treturn G2Element.generator().multiply(r).equals(nonce);\n\t} catch {\n\t\tthrow new InvalidCiphertextError('Invalid randomness');\n\t}\n}\n\nfunction decodeRandomness(bytes: Uint8Array, useBE: boolean): Scalar {\n\tif (useBE) {\n\t\treturn Scalar.fromBytes(bytes);\n\t} else {\n\t\treturn Scalar.fromBytesLE(bytes);\n\t}\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. Returns both the scalar interpreted in big-endian and little-endian encoding.\n */\nexport function decryptRandomness(\n\tencryptedRandomness: Uint8Array,\n\trandomnessKey: Uint8Array,\n): Uint8Array {\n\treturn xor(encryptedRandomness, randomnessKey);\n}\n\n/**\n * Verify that the given randomness was used to crate the nonce.\n * Check using both big-endian and little-endian encoding of the randomness.\n *\n * Throws an error if the nonce check doesn't pass using LE encoding _and_ the randomness is invalid as a BE encoded scalar.\n *\n * @param randomness - The randomness.\n * @param nonce - The nonce.\n * @returns True if the randomness was used to create the nonce using either LE or BE encoding, false otherwise.\n */\nexport function verifyNonceWithLE(nonce: G2Element, randomness: Uint8Array): boolean {\n\ttry {\n\t\t// First try little-endian encoding\n\t\tif (verifyNonce(nonce, randomness, false)) {\n\t\t\treturn true;\n\t\t}\n\t} catch {\n\t\t// Ignore error and try big-endian encoding\n\t}\n\treturn verifyNonce(nonce, randomness, true);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export interface DecryptOptions {
|
|
|
48
48
|
txBytes: Uint8Array;
|
|
49
49
|
/** Whether to check share consistency. */
|
|
50
50
|
checkShareConsistency?: boolean;
|
|
51
|
+
/** Whether to check also using an LE encoded nonce. */
|
|
52
|
+
checkLEEncoding?: boolean;
|
|
51
53
|
}
|
|
52
54
|
export interface FetchKeysOptions {
|
|
53
55
|
/** The ids of the encrypted objects. */
|
package/dist/cjs/types.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/types.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithExtensions, Experimental_CoreClient } from '@mysten/sui/experimental';\nimport type { DemType, KemType } from './encrypt.js';\nimport type { SessionKey } from './session-key.js';\n\nexport type KeyCacheKey = `${string}:${string}`;\nexport type SealCompatibleClient = ClientWithExtensions<{\n\tcore: Experimental_CoreClient;\n}>;\n\n/** Configuration options for initializing a SealClient*/\nexport interface SealClientExtensionOptions {\n\t/** Array of key server configs consisting of objectId, weight, optional API key name and API key */\n\tserverConfigs: KeyServerConfig[];\n\t/** Whether to verify the key servers' authenticity. */\n\tverifyKeyServers?: boolean;\n\t/** Timeout in milliseconds for network requests. */\n\ttimeout?: number;\n}\n\nexport interface KeyServerConfig {\n\tobjectId: string;\n\tweight: number;\n\tapiKeyName?: string;\n\tapiKey?: string;\n}\n\nexport interface SealClientOptions extends SealClientExtensionOptions {\n\tsuiClient: SealCompatibleClient;\n}\n\nexport interface EncryptOptions {\n\t/** The type of KEM to use. */\n\tkemType?: KemType;\n\t/** The type of DEM to use. */\n\tdemType?: DemType;\n\t/** The threshold for the TSS encryption. */\n\tthreshold: number;\n\t/** The packageId namespace. */\n\tpackageId: string;\n\t/** The identity to use. */\n\tid: string;\n\t/** The data to encrypt. */\n\tdata: Uint8Array;\n\t/** Optional additional authenticated data. */\n\taad?: Uint8Array;\n}\n\nexport interface DecryptOptions {\n\t/** The encrypted bytes to decrypt. */\n\tdata: Uint8Array;\n\t/** The session key to use. */\n\tsessionKey: SessionKey;\n\t/** The transaction bytes to use (that calls seal_approve* functions). */\n\ttxBytes: Uint8Array;\n\t/** Whether to check share consistency. */\n\tcheckShareConsistency?: boolean;\n}\n\nexport interface FetchKeysOptions {\n\t/** The ids of the encrypted objects. */\n\tids: string[];\n\t/** The transaction bytes to use (that calls seal_approve* functions). */\n\ttxBytes: Uint8Array;\n\t/** The session key to use. */\n\tsessionKey: SessionKey;\n\t/** The threshold. */\n\tthreshold: number;\n}\n\nexport interface GetDerivedKeysOptions {\n\tkemType?: KemType;\n\t/** The id of the encrypted object. */\n\tid: string;\n\t/** The transaction bytes to use (that calls seal_approve* functions). */\n\ttxBytes: Uint8Array;\n\t/** The session key to use. */\n\tsessionKey: SessionKey;\n\t/** The threshold. */\n\tthreshold: number;\n}\n"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithExtensions, Experimental_CoreClient } from '@mysten/sui/experimental';\nimport type { DemType, KemType } from './encrypt.js';\nimport type { SessionKey } from './session-key.js';\n\nexport type KeyCacheKey = `${string}:${string}`;\nexport type SealCompatibleClient = ClientWithExtensions<{\n\tcore: Experimental_CoreClient;\n}>;\n\n/** Configuration options for initializing a SealClient*/\nexport interface SealClientExtensionOptions {\n\t/** Array of key server configs consisting of objectId, weight, optional API key name and API key */\n\tserverConfigs: KeyServerConfig[];\n\t/** Whether to verify the key servers' authenticity. */\n\tverifyKeyServers?: boolean;\n\t/** Timeout in milliseconds for network requests. */\n\ttimeout?: number;\n}\n\nexport interface KeyServerConfig {\n\tobjectId: string;\n\tweight: number;\n\tapiKeyName?: string;\n\tapiKey?: string;\n}\n\nexport interface SealClientOptions extends SealClientExtensionOptions {\n\tsuiClient: SealCompatibleClient;\n}\n\nexport interface EncryptOptions {\n\t/** The type of KEM to use. */\n\tkemType?: KemType;\n\t/** The type of DEM to use. */\n\tdemType?: DemType;\n\t/** The threshold for the TSS encryption. */\n\tthreshold: number;\n\t/** The packageId namespace. */\n\tpackageId: string;\n\t/** The identity to use. */\n\tid: string;\n\t/** The data to encrypt. */\n\tdata: Uint8Array;\n\t/** Optional additional authenticated data. */\n\taad?: Uint8Array;\n}\n\nexport interface DecryptOptions {\n\t/** The encrypted bytes to decrypt. */\n\tdata: Uint8Array;\n\t/** The session key to use. */\n\tsessionKey: SessionKey;\n\t/** The transaction bytes to use (that calls seal_approve* functions). */\n\ttxBytes: Uint8Array;\n\t/** Whether to check share consistency. */\n\tcheckShareConsistency?: boolean;\n\t/** Whether to check also using an LE encoded nonce. */\n\tcheckLEEncoding?: boolean;\n}\n\nexport interface FetchKeysOptions {\n\t/** The ids of the encrypted objects. */\n\tids: string[];\n\t/** The transaction bytes to use (that calls seal_approve* functions). */\n\ttxBytes: Uint8Array;\n\t/** The session key to use. */\n\tsessionKey: SessionKey;\n\t/** The threshold. */\n\tthreshold: number;\n}\n\nexport interface GetDerivedKeysOptions {\n\tkemType?: KemType;\n\t/** The id of the encrypted object. */\n\tid: string;\n\t/** The transaction bytes to use (that calls seal_approve* functions). */\n\ttxBytes: Uint8Array;\n\t/** The session key to use. */\n\tsessionKey: SessionKey;\n\t/** The threshold. */\n\tthreshold: number;\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "0.
|
|
1
|
+
export declare const PACKAGE_VERSION = "0.8.0";
|
package/dist/cjs/version.js
CHANGED
package/dist/cjs/version.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/version.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n// This file is generated by genversion.mjs. Do not edit it directly.\n\nexport const PACKAGE_VERSION = '0.
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n// This file is generated by genversion.mjs. Do not edit it directly.\n\nexport const PACKAGE_VERSION = '0.8.0';\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKO,MAAM,kBAAkB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/bls12381.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Fp2, Fp12 } from '@noble/curves/abstract/tower';
|
|
2
|
-
import type {
|
|
2
|
+
import type { WeierstrassPoint } from '@noble/curves/abstract/weierstrass';
|
|
3
3
|
export declare class G1Element {
|
|
4
|
-
point:
|
|
4
|
+
point: WeierstrassPoint<bigint>;
|
|
5
5
|
static readonly SIZE = 48;
|
|
6
|
-
constructor(point:
|
|
6
|
+
constructor(point: WeierstrassPoint<bigint>);
|
|
7
7
|
static generator(): G1Element;
|
|
8
8
|
static fromBytes(bytes: Uint8Array): G1Element;
|
|
9
9
|
toBytes(): Uint8Array<ArrayBuffer>;
|
|
@@ -14,9 +14,9 @@ export declare class G1Element {
|
|
|
14
14
|
pairing(other: G2Element): GTElement;
|
|
15
15
|
}
|
|
16
16
|
export declare class G2Element {
|
|
17
|
-
point:
|
|
17
|
+
point: WeierstrassPoint<Fp2>;
|
|
18
18
|
static readonly SIZE = 96;
|
|
19
|
-
constructor(point:
|
|
19
|
+
constructor(point: WeierstrassPoint<Fp2>);
|
|
20
20
|
static generator(): G2Element;
|
|
21
21
|
static fromBytes(bytes: Uint8Array): G2Element;
|
|
22
22
|
toBytes(): Uint8Array<ArrayBuffer>;
|
|
@@ -36,8 +36,9 @@ export declare class Scalar {
|
|
|
36
36
|
scalar: bigint;
|
|
37
37
|
static readonly SIZE = 32;
|
|
38
38
|
constructor(scalar: bigint);
|
|
39
|
+
static fromBigint(scalar: bigint): Scalar;
|
|
39
40
|
static random(): Scalar;
|
|
40
|
-
toBytes(): Uint8Array
|
|
41
|
+
toBytes(): Uint8Array;
|
|
41
42
|
static fromBytes(bytes: Uint8Array): Scalar;
|
|
42
|
-
static
|
|
43
|
+
static fromBytesLE(bytes: Uint8Array): Scalar;
|
|
43
44
|
}
|
package/dist/esm/bls12381.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { bls12_381, bls12_381_Fr } from "@noble/curves/bls12-381";
|
|
2
|
+
import { bytesToNumberBE, bytesToNumberLE, numberToBytesBE } from "@noble/curves/utils";
|
|
3
3
|
const _G1Element = class _G1Element {
|
|
4
4
|
constructor(point) {
|
|
5
5
|
this.point = point;
|
|
6
6
|
}
|
|
7
7
|
static generator() {
|
|
8
|
-
return new _G1Element(bls12_381.G1.
|
|
8
|
+
return new _G1Element(bls12_381.G1.Point.BASE);
|
|
9
9
|
}
|
|
10
10
|
static fromBytes(bytes) {
|
|
11
|
-
|
|
11
|
+
try {
|
|
12
|
+
return new _G1Element(bls12_381.G1.Point.fromBytes(bytes));
|
|
13
|
+
} catch {
|
|
14
|
+
throw new Error("Invalid G1 point");
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
toBytes() {
|
|
14
18
|
return this.point.toBytes();
|
|
@@ -23,9 +27,7 @@ const _G1Element = class _G1Element {
|
|
|
23
27
|
return new _G1Element(this.point.subtract(other.point));
|
|
24
28
|
}
|
|
25
29
|
static hashToCurve(data) {
|
|
26
|
-
return new _G1Element(
|
|
27
|
-
bls12_381.G1.ProjectivePoint.fromAffine(bls12_381.G1.hashToCurve(data).toAffine())
|
|
28
|
-
);
|
|
30
|
+
return new _G1Element(bls12_381.G1.Point.fromAffine(bls12_381.G1.hashToCurve(data).toAffine()));
|
|
29
31
|
}
|
|
30
32
|
pairing(other) {
|
|
31
33
|
return new GTElement(bls12_381.pairing(this.point, other.point));
|
|
@@ -38,10 +40,14 @@ const _G2Element = class _G2Element {
|
|
|
38
40
|
this.point = point;
|
|
39
41
|
}
|
|
40
42
|
static generator() {
|
|
41
|
-
return new _G2Element(bls12_381.G2.
|
|
43
|
+
return new _G2Element(bls12_381.G2.Point.BASE);
|
|
42
44
|
}
|
|
43
45
|
static fromBytes(bytes) {
|
|
44
|
-
|
|
46
|
+
try {
|
|
47
|
+
return new _G2Element(bls12_381.G2.Point.fromBytes(bytes));
|
|
48
|
+
} catch {
|
|
49
|
+
throw new Error("Invalid G2 point");
|
|
50
|
+
}
|
|
45
51
|
}
|
|
46
52
|
toBytes() {
|
|
47
53
|
return this.point.toBytes();
|
|
@@ -53,9 +59,7 @@ const _G2Element = class _G2Element {
|
|
|
53
59
|
return new _G2Element(this.point.add(other.point));
|
|
54
60
|
}
|
|
55
61
|
static hashToCurve(data) {
|
|
56
|
-
return new _G2Element(
|
|
57
|
-
bls12_381.G2.ProjectivePoint.fromAffine(bls12_381.G2.hashToCurve(data).toAffine())
|
|
58
|
-
);
|
|
62
|
+
return new _G2Element(bls12_381.G2.Point.fromAffine(bls12_381.G2.hashToCurve(data).toAffine()));
|
|
59
63
|
}
|
|
60
64
|
equals(other) {
|
|
61
65
|
return this.point.equals(other.point);
|
|
@@ -90,17 +94,33 @@ const _Scalar = class _Scalar {
|
|
|
90
94
|
constructor(scalar) {
|
|
91
95
|
this.scalar = scalar;
|
|
92
96
|
}
|
|
97
|
+
static fromBigint(scalar) {
|
|
98
|
+
if (scalar < 0n || scalar >= bls12_381.fields.Fr.ORDER) {
|
|
99
|
+
throw new Error("Scalar out of range");
|
|
100
|
+
}
|
|
101
|
+
return new _Scalar(scalar);
|
|
102
|
+
}
|
|
93
103
|
static random() {
|
|
94
|
-
|
|
104
|
+
const randomSecretKey = bls12_381.utils.randomSecretKey();
|
|
105
|
+
if (bls12_381_Fr.isLE) {
|
|
106
|
+
return _Scalar.fromBytesLE(randomSecretKey);
|
|
107
|
+
}
|
|
108
|
+
return _Scalar.fromBytes(randomSecretKey);
|
|
95
109
|
}
|
|
96
110
|
toBytes() {
|
|
97
|
-
return
|
|
111
|
+
return numberToBytesBE(this.scalar, _Scalar.SIZE);
|
|
98
112
|
}
|
|
99
113
|
static fromBytes(bytes) {
|
|
100
|
-
|
|
114
|
+
if (bytes.length !== _Scalar.SIZE) {
|
|
115
|
+
throw new Error("Invalid scalar length");
|
|
116
|
+
}
|
|
117
|
+
return this.fromBigint(bytesToNumberBE(bytes));
|
|
101
118
|
}
|
|
102
|
-
static
|
|
103
|
-
|
|
119
|
+
static fromBytesLE(bytes) {
|
|
120
|
+
if (bytes.length !== _Scalar.SIZE) {
|
|
121
|
+
throw new Error("Invalid scalar length");
|
|
122
|
+
}
|
|
123
|
+
return this.fromBigint(bytesToNumberLE(bytes));
|
|
104
124
|
}
|
|
105
125
|
};
|
|
106
126
|
_Scalar.SIZE = 32;
|
package/dist/esm/bls12381.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/bls12381.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Fp2, Fp12 } from '@noble/curves/abstract/tower';\nimport type { WeierstrassPoint } from '@noble/curves/abstract/weierstrass';\nimport { bls12_381, bls12_381_Fr } from '@noble/curves/bls12-381';\nimport { bytesToNumberBE, bytesToNumberLE, numberToBytesBE } from '@noble/curves/utils';\n\nexport class G1Element {\n\tpoint: WeierstrassPoint<bigint>;\n\n\tpublic static readonly SIZE = 48;\n\n\tconstructor(point: WeierstrassPoint<bigint>) {\n\t\tthis.point = point;\n\t}\n\n\tstatic generator(): G1Element {\n\t\treturn new G1Element(bls12_381.G1.Point.BASE);\n\t}\n\n\tstatic fromBytes(bytes: Uint8Array): G1Element {\n\t\ttry {\n\t\t\treturn new G1Element(bls12_381.G1.Point.fromBytes(bytes));\n\t\t} catch {\n\t\t\tthrow new Error('Invalid G1 point');\n\t\t}\n\t}\n\n\ttoBytes(): Uint8Array<ArrayBuffer> {\n\t\treturn this.point.toBytes() as Uint8Array<ArrayBuffer>;\n\t}\n\n\tmultiply(scalar: Scalar): G1Element {\n\t\treturn new G1Element(this.point.multiply(scalar.scalar));\n\t}\n\n\tadd(other: G1Element): G1Element {\n\t\treturn new G1Element(this.point.add(other.point));\n\t}\n\n\tsubtract(other: G1Element): G1Element {\n\t\treturn new G1Element(this.point.subtract(other.point));\n\t}\n\n\tstatic hashToCurve(data: Uint8Array): G1Element {\n\t\treturn new G1Element(bls12_381.G1.Point.fromAffine(bls12_381.G1.hashToCurve(data).toAffine()));\n\t}\n\n\tpairing(other: G2Element): GTElement {\n\t\treturn new GTElement(bls12_381.pairing(this.point, other.point));\n\t}\n}\n\nexport class G2Element {\n\tpoint: WeierstrassPoint<Fp2>;\n\n\tpublic static readonly SIZE = 96;\n\n\tconstructor(point: WeierstrassPoint<Fp2>) {\n\t\tthis.point = point;\n\t}\n\n\tstatic generator(): G2Element {\n\t\treturn new G2Element(bls12_381.G2.Point.BASE);\n\t}\n\n\tstatic fromBytes(bytes: Uint8Array): G2Element {\n\t\ttry {\n\t\t\treturn new G2Element(bls12_381.G2.Point.fromBytes(bytes));\n\t\t} catch {\n\t\t\tthrow new Error('Invalid G2 point');\n\t\t}\n\t}\n\n\ttoBytes(): Uint8Array<ArrayBuffer> {\n\t\treturn this.point.toBytes() as Uint8Array<ArrayBuffer>;\n\t}\n\n\tmultiply(scalar: Scalar): G2Element {\n\t\treturn new G2Element(this.point.multiply(scalar.scalar));\n\t}\n\n\tadd(other: G2Element): G2Element {\n\t\treturn new G2Element(this.point.add(other.point));\n\t}\n\n\tstatic hashToCurve(data: Uint8Array): G2Element {\n\t\treturn new G2Element(bls12_381.G2.Point.fromAffine(bls12_381.G2.hashToCurve(data).toAffine()));\n\t}\n\n\tequals(other: G2Element): boolean {\n\t\treturn this.point.equals(other.point);\n\t}\n}\n\nexport class GTElement {\n\telement: Fp12;\n\n\tpublic static readonly SIZE = 576;\n\n\tconstructor(element: Fp12) {\n\t\tthis.element = element;\n\t}\n\n\ttoBytes(): Uint8Array<ArrayBuffer> {\n\t\t// This permutation reorders the 6 pairs of coefficients of the GT element for compatability with the Rust and Move implementations.\n\t\t//\n\t\t// The permutation P may be computed as:\n\t\t// for i in 0..3 {\n\t\t// for j in 0..2 {\n\t\t// P[2 * i + j] = i + 3 * j;\n\t\t// }\n\t\t// }\n\t\tconst P = [0, 3, 1, 4, 2, 5];\n\t\tconst PAIR_SIZE = GTElement.SIZE / P.length;\n\n\t\tconst bytes = bls12_381.fields.Fp12.toBytes(this.element);\n\t\tconst result = new Uint8Array(GTElement.SIZE);\n\n\t\tfor (let i = 0; i < P.length; i++) {\n\t\t\tconst sourceStart = P[i] * PAIR_SIZE;\n\t\t\tconst sourceEnd = sourceStart + PAIR_SIZE;\n\t\t\tconst targetStart = i * PAIR_SIZE;\n\t\t\tresult.set(bytes.subarray(sourceStart, sourceEnd), targetStart);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tequals(other: GTElement): boolean {\n\t\treturn bls12_381.fields.Fp12.eql(this.element, other.element);\n\t}\n}\n\nexport class Scalar {\n\tscalar: bigint;\n\n\tpublic static readonly SIZE = 32;\n\n\tconstructor(scalar: bigint) {\n\t\tthis.scalar = scalar;\n\t}\n\n\tstatic fromBigint(scalar: bigint): Scalar {\n\t\tif (scalar < 0n || scalar >= bls12_381.fields.Fr.ORDER) {\n\t\t\tthrow new Error('Scalar out of range');\n\t\t}\n\t\treturn new Scalar(scalar);\n\t}\n\n\tstatic random(): Scalar {\n\t\tconst randomSecretKey = bls12_381.utils.randomSecretKey();\n\t\tif (bls12_381_Fr.isLE) {\n\t\t\treturn Scalar.fromBytesLE(randomSecretKey)!;\n\t\t}\n\t\treturn Scalar.fromBytes(randomSecretKey)!;\n\t}\n\n\ttoBytes(): Uint8Array {\n\t\treturn numberToBytesBE(this.scalar, Scalar.SIZE);\n\t}\n\n\tstatic fromBytes(bytes: Uint8Array): Scalar {\n\t\tif (bytes.length !== Scalar.SIZE) {\n\t\t\tthrow new Error('Invalid scalar length');\n\t\t}\n\t\treturn this.fromBigint(bytesToNumberBE(bytes));\n\t}\n\n\tstatic fromBytesLE(bytes: Uint8Array): Scalar {\n\t\tif (bytes.length !== Scalar.SIZE) {\n\t\t\tthrow new Error('Invalid scalar length');\n\t\t}\n\t\treturn this.fromBigint(bytesToNumberLE(bytes));\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/client.d.ts
CHANGED
|
@@ -40,9 +40,10 @@ export declare class SealClient {
|
|
|
40
40
|
* @param sessionKey - The session key to use.
|
|
41
41
|
* @param txBytes - The transaction bytes to use (that calls seal_approve* functions).
|
|
42
42
|
* @param checkShareConsistency - If true, the shares are checked for consistency.
|
|
43
|
+
* @param checkLEEncoding - If true, the encryption is also checked using an LE encoded nonce.
|
|
43
44
|
* @returns - The decrypted plaintext corresponding to ciphertext.
|
|
44
45
|
*/
|
|
45
|
-
decrypt({ data, sessionKey, txBytes, checkShareConsistency }: DecryptOptions): Promise<Uint8Array<ArrayBufferLike>>;
|
|
46
|
+
decrypt({ data, sessionKey, txBytes, checkShareConsistency, checkLEEncoding, }: DecryptOptions): Promise<Uint8Array<ArrayBufferLike>>;
|
|
46
47
|
getKeyServers(): Promise<Map<string, KeyServer>>;
|
|
47
48
|
/**
|
|
48
49
|
* Get the public keys for the given services.
|
package/dist/esm/client.js
CHANGED
|
@@ -116,9 +116,16 @@ const _SealClient = class _SealClient {
|
|
|
116
116
|
* @param sessionKey - The session key to use.
|
|
117
117
|
* @param txBytes - The transaction bytes to use (that calls seal_approve* functions).
|
|
118
118
|
* @param checkShareConsistency - If true, the shares are checked for consistency.
|
|
119
|
+
* @param checkLEEncoding - If true, the encryption is also checked using an LE encoded nonce.
|
|
119
120
|
* @returns - The decrypted plaintext corresponding to ciphertext.
|
|
120
121
|
*/
|
|
121
|
-
async decrypt({
|
|
122
|
+
async decrypt({
|
|
123
|
+
data,
|
|
124
|
+
sessionKey,
|
|
125
|
+
txBytes,
|
|
126
|
+
checkShareConsistency,
|
|
127
|
+
checkLEEncoding
|
|
128
|
+
}) {
|
|
122
129
|
const encryptedObject = EncryptedObject.parse(data);
|
|
123
130
|
__privateMethod(this, _SealClient_instances, validateEncryptionServices_fn).call(this, encryptedObject.services.map((s) => s[0]), encryptedObject.threshold);
|
|
124
131
|
await this.fetchKeys({
|
|
@@ -131,9 +138,15 @@ const _SealClient = class _SealClient {
|
|
|
131
138
|
const publicKeys = await this.getPublicKeys(
|
|
132
139
|
encryptedObject.services.map(([objectId, _]) => objectId)
|
|
133
140
|
);
|
|
134
|
-
return decrypt({
|
|
141
|
+
return decrypt({
|
|
142
|
+
encryptedObject,
|
|
143
|
+
keys: __privateGet(this, _cachedKeys),
|
|
144
|
+
publicKeys,
|
|
145
|
+
checkLEEncoding: false
|
|
146
|
+
// We intentionally do not support other encodings here
|
|
147
|
+
});
|
|
135
148
|
}
|
|
136
|
-
return decrypt({ encryptedObject, keys: __privateGet(this, _cachedKeys) });
|
|
149
|
+
return decrypt({ encryptedObject, keys: __privateGet(this, _cachedKeys), checkLEEncoding });
|
|
137
150
|
}
|
|
138
151
|
async getKeyServers() {
|
|
139
152
|
if (!__privateGet(this, _keyServers)) {
|
package/dist/esm/client.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/client.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { EncryptedObject } from './bcs.js';\nimport { G1Element, G2Element } from './bls12381.js';\nimport { decrypt } from './decrypt.js';\nimport type { EncryptionInput } from './dem.js';\nimport { AesGcm256, Hmac256Ctr } from './dem.js';\nimport { DemType, encrypt, KemType } from './encrypt.js';\nimport {\n\tInconsistentKeyServersError,\n\tInvalidClientOptionsError,\n\tInvalidKeyServerError,\n\tInvalidPackageError,\n\tInvalidThresholdError,\n\ttoMajorityError,\n\tTooManyFailedFetchKeyRequestsError,\n} from './error.js';\nimport { BonehFranklinBLS12381Services } from './ibe.js';\nimport {\n\tBonehFranklinBLS12381DerivedKey,\n\tretrieveKeyServers,\n\tverifyKeyServer,\n\tfetchKeysForAllIds,\n} from './key-server.js';\nimport type { DerivedKey, KeyServer } from './key-server.js';\nimport type {\n\tDecryptOptions,\n\tEncryptOptions,\n\tFetchKeysOptions,\n\tGetDerivedKeysOptions,\n\tKeyCacheKey,\n\tKeyServerConfig,\n\tSealClientExtensionOptions,\n\tSealClientOptions,\n\tSealCompatibleClient,\n} from './types.js';\nimport { createFullId, count } from './utils.js';\n\nexport class SealClient {\n\t#suiClient: SealCompatibleClient;\n\t#configs: Map<string, KeyServerConfig>;\n\t#keyServers: Promise<Map<string, KeyServer>> | null = null;\n\t#verifyKeyServers: boolean;\n\t// A caching map for: fullId:object_id -> partial key.\n\t#cachedKeys = new Map<KeyCacheKey, G1Element>();\n\t#cachedPublicKeys = new Map<string, G2Element>();\n\t#timeout: number;\n\t#totalWeight: number;\n\n\tconstructor(options: SealClientOptions) {\n\t\tthis.#suiClient = options.suiClient;\n\n\t\tif (\n\t\t\tnew Set(options.serverConfigs.map((s) => s.objectId)).size !== options.serverConfigs.length\n\t\t) {\n\t\t\tthrow new InvalidClientOptionsError('Duplicate object IDs');\n\t\t}\n\n\t\tif (\n\t\t\toptions.serverConfigs.some((s) => (s.apiKeyName && !s.apiKey) || (!s.apiKeyName && s.apiKey))\n\t\t) {\n\t\t\tthrow new InvalidClientOptionsError(\n\t\t\t\t'Both apiKeyName and apiKey must be provided or not provided for all key servers',\n\t\t\t);\n\t\t}\n\n\t\tthis.#configs = new Map(options.serverConfigs.map((server) => [server.objectId, server]));\n\t\tthis.#totalWeight = options.serverConfigs\n\t\t\t.map((server) => server.weight)\n\t\t\t.reduce((sum, term) => sum + term, 0);\n\n\t\tthis.#verifyKeyServers = options.verifyKeyServers ?? true;\n\t\tthis.#timeout = options.timeout ?? 10_000;\n\t}\n\n\tstatic asClientExtension(options: SealClientExtensionOptions) {\n\t\treturn {\n\t\t\tname: 'seal' as const,\n\t\t\tregister: (client: SealCompatibleClient) => {\n\t\t\t\treturn new SealClient({\n\t\t\t\t\tsuiClient: client,\n\t\t\t\t\t...options,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Return an encrypted message under the identity.\n\t *\n\t * @param kemType - The type of KEM to use.\n\t * @param demType - The type of DEM to use.\n\t * @param threshold - The threshold for the TSS encryption.\n\t * @param packageId - the packageId namespace.\n\t * @param id - the identity to use.\n\t * @param data - the data to encrypt.\n\t * @param aad - optional additional authenticated data.\n\t * @returns The bcs bytes of the encrypted object containing all metadata and the 256-bit symmetric key that was used to encrypt the object.\n\t * \tSince the symmetric key can be used to decrypt, it should not be shared but can be used e.g. for backup.\n\t */\n\tasync encrypt({\n\t\tkemType = KemType.BonehFranklinBLS12381DemCCA,\n\t\tdemType = DemType.AesGcm256,\n\t\tthreshold,\n\t\tpackageId,\n\t\tid,\n\t\tdata,\n\t\taad = new Uint8Array(),\n\t}: EncryptOptions) {\n\t\tconst packageObj = await this.#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 encrypt({\n\t\t\tkeyServers: await this.#getWeightedKeyServers(),\n\t\t\tkemType,\n\t\t\tthreshold,\n\t\t\tpackageId,\n\t\t\tid,\n\t\t\tencryptionInput: this.#createEncryptionInput(\n\t\t\t\tdemType,\n\t\t\t\tdata as Uint8Array<ArrayBuffer>,\n\t\t\t\taad as Uint8Array<ArrayBuffer>,\n\t\t\t),\n\t\t});\n\t}\n\n\t#createEncryptionInput(\n\t\ttype: DemType,\n\t\tdata: Uint8Array<ArrayBuffer>,\n\t\taad: Uint8Array<ArrayBuffer>,\n\t): EncryptionInput {\n\t\tswitch (type) {\n\t\t\tcase DemType.AesGcm256:\n\t\t\t\treturn new AesGcm256(data, aad);\n\t\t\tcase DemType.Hmac256Ctr:\n\t\t\t\treturn new Hmac256Ctr(data, aad);\n\t\t}\n\t}\n\n\t/**\n\t * Decrypt the given encrypted bytes using cached keys.\n\t * Calls fetchKeys in case one or more of the required keys is not cached yet.\n\t * The function throws an error if the client's key servers are not a subset of\n\t * the encrypted object's key servers or if the threshold cannot be met.\n\t *\n\t * If checkShareConsistency is true, the decrypted shares are checked for consistency, meaning that\n\t * any combination of at least threshold shares should either succesfully combine to the plaintext or fail.\n\t * This is useful in case the encryptor is not trusted and the decryptor wants to ensure all decryptors\n\t * receive the same output (e.g., for onchain encrypted voting).\n\t *\n\t * @param data - The encrypted bytes to decrypt.\n\t * @param sessionKey - The session key to use.\n\t * @param txBytes - The transaction bytes to use (that calls seal_approve* functions).\n\t * @param checkShareConsistency - If true, the shares are checked for consistency.\n\t * @returns - The decrypted plaintext corresponding to ciphertext.\n\t */\n\tasync decrypt({ data, sessionKey, txBytes, checkShareConsistency }: DecryptOptions) {\n\t\tconst encryptedObject = EncryptedObject.parse(data);\n\n\t\tthis.#validateEncryptionServices(\n\t\t\tencryptedObject.services.map((s) => s[0]),\n\t\t\tencryptedObject.threshold,\n\t\t);\n\n\t\tawait this.fetchKeys({\n\t\t\tids: [encryptedObject.id],\n\t\t\ttxBytes,\n\t\t\tsessionKey,\n\t\t\tthreshold: encryptedObject.threshold,\n\t\t});\n\n\t\tif (checkShareConsistency) {\n\t\t\tconst publicKeys = await this.getPublicKeys(\n\t\t\t\tencryptedObject.services.map(([objectId, _]) => objectId),\n\t\t\t);\n\t\t\treturn decrypt({ encryptedObject, keys: this.#cachedKeys, publicKeys });\n\t\t}\n\t\treturn decrypt({ encryptedObject, keys: this.#cachedKeys });\n\t}\n\n\t#weight(objectId: string) {\n\t\treturn this.#configs.get(objectId)?.weight ?? 0;\n\t}\n\n\t#validateEncryptionServices(services: string[], threshold: number) {\n\t\t// Check that the client's key servers are a subset of the encrypted object's key servers.\n\t\tif (\n\t\t\tservices.some((objectId) => {\n\t\t\t\tconst countInClient = this.#weight(objectId);\n\t\t\t\treturn countInClient > 0 && countInClient !== count(services, objectId);\n\t\t\t})\n\t\t) {\n\t\t\tthrow new InconsistentKeyServersError(\n\t\t\t\t`Client's key servers must be a subset of the encrypted object's key servers`,\n\t\t\t);\n\t\t}\n\t\t// Check that the threshold can be met with the client's key servers.\n\t\tif (threshold > this.#totalWeight) {\n\t\t\tthrow new InvalidThresholdError(\n\t\t\t\t`Invalid threshold ${threshold} for ${this.#totalWeight} servers`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync getKeyServers(): Promise<Map<string, KeyServer>> {\n\t\tif (!this.#keyServers) {\n\t\t\tthis.#keyServers = this.#loadKeyServers().catch((error) => {\n\t\t\t\tthis.#keyServers = null;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t}\n\t\treturn this.#keyServers;\n\t}\n\n\t/**\n\t * Get the public keys for the given services.\n\t * If all public keys are not in the cache, they are retrieved.\n\t *\n\t * @param services - The services to get the public keys for.\n\t * @returns The public keys for the given services in the same order as the given services.\n\t */\n\tasync getPublicKeys(services: string[]): Promise<G2Element[]> {\n\t\tconst keyServers = await this.getKeyServers();\n\n\t\t// Collect the key servers not already in store or cache.\n\t\tconst missingKeyServers = services.filter(\n\t\t\t(objectId) => !keyServers.has(objectId) && !this.#cachedPublicKeys.has(objectId),\n\t\t);\n\n\t\t// If there are missing key servers, retrieve them and update the cache.\n\t\tif (missingKeyServers.length > 0) {\n\t\t\t(\n\t\t\t\tawait retrieveKeyServers({\n\t\t\t\t\tobjectIds: missingKeyServers,\n\t\t\t\t\tclient: this.#suiClient,\n\t\t\t\t})\n\t\t\t).forEach((keyServer) =>\n\t\t\t\tthis.#cachedPublicKeys.set(keyServer.objectId, G2Element.fromBytes(keyServer.pk)),\n\t\t\t);\n\t\t}\n\n\t\treturn services.map((objectId) => {\n\t\t\tconst keyServer = keyServers.get(objectId);\n\t\t\tif (keyServer) {\n\t\t\t\treturn G2Element.fromBytes(keyServer.pk);\n\t\t\t}\n\t\t\treturn this.#cachedPublicKeys.get(objectId)!;\n\t\t});\n\t}\n\n\t/**\n\t * Returns a list of key servers with multiplicity according to their weights.\n\t * The list is used for encryption.\n\t */\n\tasync #getWeightedKeyServers() {\n\t\tconst keyServers = await this.getKeyServers();\n\t\tconst keyServersWithMultiplicity = [];\n\t\tfor (const [objectId, config] of this.#configs) {\n\t\t\tconst keyServer = keyServers.get(objectId)!;\n\t\t\tfor (let i = 0; i < config.weight; i++) {\n\t\t\t\tkeyServersWithMultiplicity.push(keyServer);\n\t\t\t}\n\t\t}\n\t\treturn keyServersWithMultiplicity;\n\t}\n\n\tasync #loadKeyServers(): Promise<Map<string, KeyServer>> {\n\t\tconst keyServers = await retrieveKeyServers({\n\t\t\tobjectIds: [...this.#configs].map(([objectId]) => objectId),\n\t\t\tclient: this.#suiClient,\n\t\t});\n\n\t\tif (keyServers.length === 0) {\n\t\t\tthrow new InvalidKeyServerError('No key servers found');\n\t\t}\n\n\t\tif (this.#verifyKeyServers) {\n\t\t\tawait Promise.all(\n\t\t\t\tkeyServers.map(async (server) => {\n\t\t\t\t\tconst config = this.#configs.get(server.objectId);\n\t\t\t\t\tif (!(await verifyKeyServer(server, this.#timeout, config?.apiKeyName, config?.apiKey))) {\n\t\t\t\t\t\tthrow new InvalidKeyServerError(`Key server ${server.objectId} is not valid`);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn new Map(keyServers.map((server) => [server.objectId, server]));\n\t}\n\n\t/**\n\t * Fetch keys from the key servers and update the cache.\n\t *\n\t * It is recommended to call this function once for all ids of all encrypted objects if\n\t * there are multiple, then call decrypt for each object. This avoids calling fetchKey\n\t * individually for each decrypt.\n\t *\n\t * @param ids - The ids of the encrypted objects.\n\t * @param txBytes - The transaction bytes to use (that calls seal_approve* functions).\n\t * @param sessionKey - The session key to use.\n\t * @param threshold - The threshold for the TSS encryptions. The function returns when a threshold of key servers had returned keys for all ids.\n\t */\n\tasync fetchKeys({ ids, txBytes, sessionKey, threshold }: FetchKeysOptions) {\n\t\tif (threshold > this.#totalWeight || threshold < 1) {\n\t\t\tthrow new InvalidThresholdError(\n\t\t\t\t`Invalid threshold ${threshold} servers with weights ${this.#configs}`,\n\t\t\t);\n\t\t}\n\t\tconst keyServers = await this.getKeyServers();\n\t\tconst fullIds = ids.map((id) => createFullId(sessionKey.getPackageId(), id));\n\n\t\t// Count a server as completed if it has keys for all fullIds.\n\t\t// Duplicated key server ids will be counted towards the threshold.\n\t\tlet completedWeight = 0;\n\t\tconst remainingKeyServers = [];\n\t\tlet remainingKeyServersWeight = 0;\n\t\tfor (const objectId of keyServers.keys()) {\n\t\t\tif (fullIds.every((fullId) => this.#cachedKeys.has(`${fullId}:${objectId}`))) {\n\t\t\t\tcompletedWeight += this.#weight(objectId);\n\t\t\t} else {\n\t\t\t\tremainingKeyServers.push(objectId);\n\t\t\t\tremainingKeyServersWeight += this.#weight(objectId);\n\t\t\t}\n\t\t}\n\n\t\t// Return early if we have enough keys from cache.\n\t\tif (completedWeight >= threshold) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst certificate = await sessionKey.getCertificate();\n\t\tconst signedRequest = await sessionKey.createRequestParams(txBytes);\n\n\t\tconst controller = new AbortController();\n\t\tconst errors: Error[] = [];\n\n\t\tconst keyFetches = remainingKeyServers.map(async (objectId) => {\n\t\t\tconst server = keyServers.get(objectId)!;\n\t\t\ttry {\n\t\t\t\tconst config = this.#configs.get(objectId);\n\t\t\t\tconst allKeys = await fetchKeysForAllIds({\n\t\t\t\t\turl: server.url,\n\t\t\t\t\trequestSignature: signedRequest.requestSignature,\n\t\t\t\t\ttransactionBytes: txBytes,\n\t\t\t\t\tencKey: signedRequest.encKey,\n\t\t\t\t\tencKeyPk: signedRequest.encKeyPk,\n\t\t\t\t\tencVerificationKey: signedRequest.encVerificationKey,\n\t\t\t\t\tcertificate,\n\t\t\t\t\ttimeout: this.#timeout,\n\t\t\t\t\tapiKeyName: config?.apiKeyName,\n\t\t\t\t\tapiKey: config?.apiKey,\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t\t// Check validity of the keys and add them to the cache.\n\t\t\t\tfor (const { fullId, key } of allKeys) {\n\t\t\t\t\tconst keyElement = G1Element.fromBytes(key);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!BonehFranklinBLS12381Services.verifyUserSecretKey(\n\t\t\t\t\t\t\tkeyElement,\n\t\t\t\t\t\t\tfullId,\n\t\t\t\t\t\t\tG2Element.fromBytes(server.pk),\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconsole.warn('Received invalid key from key server ' + server.objectId);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tthis.#cachedKeys.set(`${fullId}:${server.objectId}`, keyElement);\n\t\t\t\t}\n\n\t\t\t\t// Check if all the receivedIds are consistent with the requested fullIds.\n\t\t\t\t// If so, consider the key server got all keys and mark as completed.\n\t\t\t\tif (fullIds.every((fullId) => this.#cachedKeys.has(`${fullId}:${server.objectId}`))) {\n\t\t\t\t\tcompletedWeight += this.#weight(objectId);\n\n\t\t\t\t\t// Return early if the completed servers is more than the threshold.\n\t\t\t\t\tif (completedWeight >= threshold) {\n\t\t\t\t\t\tcontroller.abort();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\terrors.push(error as Error);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\t// If there are too many errors that the threshold is not attainable, return early with error.\n\t\t\t\tremainingKeyServersWeight -= this.#weight(objectId);\n\t\t\t\tif (remainingKeyServersWeight < threshold - completedWeight) {\n\t\t\t\t\tcontroller.abort(new TooManyFailedFetchKeyRequestsError());\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tawait Promise.allSettled(keyFetches);\n\n\t\tif (completedWeight < threshold) {\n\t\t\tthrow toMajorityError(errors);\n\t\t}\n\t}\n\n\t/**\n\t * Get derived keys from the given services.\n\t *\n\t * @param id - The id of the encrypted object.\n\t * @param txBytes - The transaction bytes to use (that calls seal_approve* functions).\n\t * @param sessionKey - The session key to use.\n\t * @param threshold - The threshold.\n\t * @returns - Derived keys for the given services that are in the cache as a \"service object ID\" -> derived key map. If the call is succesful, exactly threshold keys will be returned.\n\t */\n\tasync getDerivedKeys({\n\t\tkemType = KemType.BonehFranklinBLS12381DemCCA,\n\t\tid,\n\t\ttxBytes,\n\t\tsessionKey,\n\t\tthreshold,\n\t}: GetDerivedKeysOptions): Promise<Map<string, DerivedKey>> {\n\t\tswitch (kemType) {\n\t\t\tcase KemType.BonehFranklinBLS12381DemCCA:\n\t\t\t\tconst keyServers = await this.getKeyServers();\n\t\t\t\tif (threshold > this.#totalWeight) {\n\t\t\t\t\tthrow new InvalidThresholdError(\n\t\t\t\t\t\t`Invalid threshold ${threshold} for ${this.#totalWeight} servers`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait this.fetchKeys({\n\t\t\t\t\tids: [id],\n\t\t\t\t\ttxBytes,\n\t\t\t\t\tsessionKey,\n\t\t\t\t\tthreshold,\n\t\t\t\t});\n\n\t\t\t\t// After calling fetchKeys, we can be sure that there are at least `threshold` of the required keys in the cache.\n\t\t\t\t// It is also checked there that the KeyServerType is BonehFranklinBLS12381 for all services.\n\n\t\t\t\tconst fullId = createFullId(sessionKey.getPackageId(), id);\n\n\t\t\t\tconst derivedKeys = new Map();\n\t\t\t\tlet weight = 0;\n\t\t\t\tfor (const objectId of keyServers.keys()) {\n\t\t\t\t\t// The code below assumes that the KeyServerType is BonehFranklinBLS12381.\n\t\t\t\t\tconst cachedKey = this.#cachedKeys.get(`${fullId}:${objectId}`);\n\t\t\t\t\tif (cachedKey) {\n\t\t\t\t\t\tderivedKeys.set(objectId, new BonehFranklinBLS12381DerivedKey(cachedKey));\n\t\t\t\t\t\tweight += this.#weight(objectId);\n\t\t\t\t\t\tif (weight >= threshold) {\n\t\t\t\t\t\t\t// We have enough keys, so we can stop.\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn derivedKeys;\n\t\t}\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;AAAA;AAGA,SAAS,uBAAuB;AAChC,SAAS,WAAW,iBAAiB;AACrC,SAAS,eAAe;AAExB,SAAS,WAAW,kBAAkB;AACtC,SAAS,SAAS,SAAS,eAAe;AAC1C;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,qCAAqC;AAC9C;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAaP,SAAS,cAAc,aAAa;AAE7B,MAAM,cAAN,MAAM,YAAW;AAAA,EAWvB,YAAY,SAA4B;AAXlC;AACN;AACA;AACA,oCAAsD;AACtD;AAEA;AAAA,oCAAc,oBAAI,IAA4B;AAC9C,0CAAoB,oBAAI,IAAuB;AAC/C;AACA;AAGC,uBAAK,YAAa,QAAQ;AAE1B,QACC,IAAI,IAAI,QAAQ,cAAc,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,QAAQ,cAAc,QACpF;AACD,YAAM,IAAI,0BAA0B,sBAAsB;AAAA,IAC3D;AAEA,QACC,QAAQ,cAAc,KAAK,CAAC,MAAO,EAAE,cAAc,CAAC,EAAE,UAAY,CAAC,EAAE,cAAc,EAAE,MAAO,GAC3F;AACD,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAEA,uBAAK,UAAW,IAAI,IAAI,QAAQ,cAAc,IAAI,CAAC,WAAW,CAAC,OAAO,UAAU,MAAM,CAAC,CAAC;AACxF,uBAAK,cAAe,QAAQ,cAC1B,IAAI,CAAC,WAAW,OAAO,MAAM,EAC7B,OAAO,CAAC,KAAK,SAAS,MAAM,MAAM,CAAC;AAErC,uBAAK,mBAAoB,QAAQ,oBAAoB;AACrD,uBAAK,UAAW,QAAQ,WAAW;AAAA,EACpC;AAAA,EAEA,OAAO,kBAAkB,SAAqC;AAC7D,WAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU,CAAC,WAAiC;AAC3C,eAAO,IAAI,YAAW;AAAA,UACrB,WAAW;AAAA,UACX,GAAG;AAAA,QACJ,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,QAAQ;AAAA,IACb,UAAU,QAAQ;AAAA,IAClB,UAAU,QAAQ;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,IAAI,WAAW;AAAA,EACtB,GAAmB;AAClB,UAAM,aAAa,MAAM,mBAAK,YAAW,KAAK,UAAU,EAAE,UAAU,UAAU,CAAC;AAC/E,QAAI,OAAO,WAAW,OAAO,OAAO,MAAM,KAAK;AAC9C,YAAM,IAAI,oBAAoB,WAAW,SAAS,2BAA2B;AAAA,IAC9E;AAEA,WAAO,QAAQ;AAAA,MACd,YAAY,MAAM,sBAAK,iDAAL;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB,sBAAK,iDAAL,WAChB,SACA,MACA;AAAA,IAEF,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { EncryptedObject } from './bcs.js';\nimport { G1Element, G2Element } from './bls12381.js';\nimport { decrypt } from './decrypt.js';\nimport type { EncryptionInput } from './dem.js';\nimport { AesGcm256, Hmac256Ctr } from './dem.js';\nimport { DemType, encrypt, KemType } from './encrypt.js';\nimport {\n\tInconsistentKeyServersError,\n\tInvalidClientOptionsError,\n\tInvalidKeyServerError,\n\tInvalidPackageError,\n\tInvalidThresholdError,\n\ttoMajorityError,\n\tTooManyFailedFetchKeyRequestsError,\n} from './error.js';\nimport { BonehFranklinBLS12381Services } from './ibe.js';\nimport {\n\tBonehFranklinBLS12381DerivedKey,\n\tretrieveKeyServers,\n\tverifyKeyServer,\n\tfetchKeysForAllIds,\n} from './key-server.js';\nimport type { DerivedKey, KeyServer } from './key-server.js';\nimport type {\n\tDecryptOptions,\n\tEncryptOptions,\n\tFetchKeysOptions,\n\tGetDerivedKeysOptions,\n\tKeyCacheKey,\n\tKeyServerConfig,\n\tSealClientExtensionOptions,\n\tSealClientOptions,\n\tSealCompatibleClient,\n} from './types.js';\nimport { createFullId, count } from './utils.js';\n\nexport class SealClient {\n\t#suiClient: SealCompatibleClient;\n\t#configs: Map<string, KeyServerConfig>;\n\t#keyServers: Promise<Map<string, KeyServer>> | null = null;\n\t#verifyKeyServers: boolean;\n\t// A caching map for: fullId:object_id -> partial key.\n\t#cachedKeys = new Map<KeyCacheKey, G1Element>();\n\t#cachedPublicKeys = new Map<string, G2Element>();\n\t#timeout: number;\n\t#totalWeight: number;\n\n\tconstructor(options: SealClientOptions) {\n\t\tthis.#suiClient = options.suiClient;\n\n\t\tif (\n\t\t\tnew Set(options.serverConfigs.map((s) => s.objectId)).size !== options.serverConfigs.length\n\t\t) {\n\t\t\tthrow new InvalidClientOptionsError('Duplicate object IDs');\n\t\t}\n\n\t\tif (\n\t\t\toptions.serverConfigs.some((s) => (s.apiKeyName && !s.apiKey) || (!s.apiKeyName && s.apiKey))\n\t\t) {\n\t\t\tthrow new InvalidClientOptionsError(\n\t\t\t\t'Both apiKeyName and apiKey must be provided or not provided for all key servers',\n\t\t\t);\n\t\t}\n\n\t\tthis.#configs = new Map(options.serverConfigs.map((server) => [server.objectId, server]));\n\t\tthis.#totalWeight = options.serverConfigs\n\t\t\t.map((server) => server.weight)\n\t\t\t.reduce((sum, term) => sum + term, 0);\n\n\t\tthis.#verifyKeyServers = options.verifyKeyServers ?? true;\n\t\tthis.#timeout = options.timeout ?? 10_000;\n\t}\n\n\tstatic asClientExtension(options: SealClientExtensionOptions) {\n\t\treturn {\n\t\t\tname: 'seal' as const,\n\t\t\tregister: (client: SealCompatibleClient) => {\n\t\t\t\treturn new SealClient({\n\t\t\t\t\tsuiClient: client,\n\t\t\t\t\t...options,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Return an encrypted message under the identity.\n\t *\n\t * @param kemType - The type of KEM to use.\n\t * @param demType - The type of DEM to use.\n\t * @param threshold - The threshold for the TSS encryption.\n\t * @param packageId - the packageId namespace.\n\t * @param id - the identity to use.\n\t * @param data - the data to encrypt.\n\t * @param aad - optional additional authenticated data.\n\t * @returns The bcs bytes of the encrypted object containing all metadata and the 256-bit symmetric key that was used to encrypt the object.\n\t * \tSince the symmetric key can be used to decrypt, it should not be shared but can be used e.g. for backup.\n\t */\n\tasync encrypt({\n\t\tkemType = KemType.BonehFranklinBLS12381DemCCA,\n\t\tdemType = DemType.AesGcm256,\n\t\tthreshold,\n\t\tpackageId,\n\t\tid,\n\t\tdata,\n\t\taad = new Uint8Array(),\n\t}: EncryptOptions) {\n\t\tconst packageObj = await this.#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 encrypt({\n\t\t\tkeyServers: await this.#getWeightedKeyServers(),\n\t\t\tkemType,\n\t\t\tthreshold,\n\t\t\tpackageId,\n\t\t\tid,\n\t\t\tencryptionInput: this.#createEncryptionInput(\n\t\t\t\tdemType,\n\t\t\t\tdata as Uint8Array<ArrayBuffer>,\n\t\t\t\taad as Uint8Array<ArrayBuffer>,\n\t\t\t),\n\t\t});\n\t}\n\n\t#createEncryptionInput(\n\t\ttype: DemType,\n\t\tdata: Uint8Array<ArrayBuffer>,\n\t\taad: Uint8Array<ArrayBuffer>,\n\t): EncryptionInput {\n\t\tswitch (type) {\n\t\t\tcase DemType.AesGcm256:\n\t\t\t\treturn new AesGcm256(data, aad);\n\t\t\tcase DemType.Hmac256Ctr:\n\t\t\t\treturn new Hmac256Ctr(data, aad);\n\t\t}\n\t}\n\n\t/**\n\t * Decrypt the given encrypted bytes using cached keys.\n\t * Calls fetchKeys in case one or more of the required keys is not cached yet.\n\t * The function throws an error if the client's key servers are not a subset of\n\t * the encrypted object's key servers or if the threshold cannot be met.\n\t *\n\t * If checkShareConsistency is true, the decrypted shares are checked for consistency, meaning that\n\t * any combination of at least threshold shares should either succesfully combine to the plaintext or fail.\n\t * This is useful in case the encryptor is not trusted and the decryptor wants to ensure all decryptors\n\t * receive the same output (e.g., for onchain encrypted voting).\n\t *\n\t * @param data - The encrypted bytes to decrypt.\n\t * @param sessionKey - The session key to use.\n\t * @param txBytes - The transaction bytes to use (that calls seal_approve* functions).\n\t * @param checkShareConsistency - If true, the shares are checked for consistency.\n\t * @param checkLEEncoding - If true, the encryption is also checked using an LE encoded nonce.\n\t * @returns - The decrypted plaintext corresponding to ciphertext.\n\t */\n\tasync decrypt({\n\t\tdata,\n\t\tsessionKey,\n\t\ttxBytes,\n\t\tcheckShareConsistency,\n\t\tcheckLEEncoding,\n\t}: DecryptOptions) {\n\t\tconst encryptedObject = EncryptedObject.parse(data);\n\n\t\tthis.#validateEncryptionServices(\n\t\t\tencryptedObject.services.map((s) => s[0]),\n\t\t\tencryptedObject.threshold,\n\t\t);\n\n\t\tawait this.fetchKeys({\n\t\t\tids: [encryptedObject.id],\n\t\t\ttxBytes,\n\t\t\tsessionKey,\n\t\t\tthreshold: encryptedObject.threshold,\n\t\t});\n\n\t\tif (checkShareConsistency) {\n\t\t\tconst publicKeys = await this.getPublicKeys(\n\t\t\t\tencryptedObject.services.map(([objectId, _]) => objectId),\n\t\t\t);\n\t\t\treturn decrypt({\n\t\t\t\tencryptedObject,\n\t\t\t\tkeys: this.#cachedKeys,\n\t\t\t\tpublicKeys,\n\t\t\t\tcheckLEEncoding: false, // We intentionally do not support other encodings here\n\t\t\t});\n\t\t}\n\t\treturn decrypt({ encryptedObject, keys: this.#cachedKeys, checkLEEncoding });\n\t}\n\n\t#weight(objectId: string) {\n\t\treturn this.#configs.get(objectId)?.weight ?? 0;\n\t}\n\n\t#validateEncryptionServices(services: string[], threshold: number) {\n\t\t// Check that the client's key servers are a subset of the encrypted object's key servers.\n\t\tif (\n\t\t\tservices.some((objectId) => {\n\t\t\t\tconst countInClient = this.#weight(objectId);\n\t\t\t\treturn countInClient > 0 && countInClient !== count(services, objectId);\n\t\t\t})\n\t\t) {\n\t\t\tthrow new InconsistentKeyServersError(\n\t\t\t\t`Client's key servers must be a subset of the encrypted object's key servers`,\n\t\t\t);\n\t\t}\n\t\t// Check that the threshold can be met with the client's key servers.\n\t\tif (threshold > this.#totalWeight) {\n\t\t\tthrow new InvalidThresholdError(\n\t\t\t\t`Invalid threshold ${threshold} for ${this.#totalWeight} servers`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync getKeyServers(): Promise<Map<string, KeyServer>> {\n\t\tif (!this.#keyServers) {\n\t\t\tthis.#keyServers = this.#loadKeyServers().catch((error) => {\n\t\t\t\tthis.#keyServers = null;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t}\n\t\treturn this.#keyServers;\n\t}\n\n\t/**\n\t * Get the public keys for the given services.\n\t * If all public keys are not in the cache, they are retrieved.\n\t *\n\t * @param services - The services to get the public keys for.\n\t * @returns The public keys for the given services in the same order as the given services.\n\t */\n\tasync getPublicKeys(services: string[]): Promise<G2Element[]> {\n\t\tconst keyServers = await this.getKeyServers();\n\n\t\t// Collect the key servers not already in store or cache.\n\t\tconst missingKeyServers = services.filter(\n\t\t\t(objectId) => !keyServers.has(objectId) && !this.#cachedPublicKeys.has(objectId),\n\t\t);\n\n\t\t// If there are missing key servers, retrieve them and update the cache.\n\t\tif (missingKeyServers.length > 0) {\n\t\t\t(\n\t\t\t\tawait retrieveKeyServers({\n\t\t\t\t\tobjectIds: missingKeyServers,\n\t\t\t\t\tclient: this.#suiClient,\n\t\t\t\t})\n\t\t\t).forEach((keyServer) =>\n\t\t\t\tthis.#cachedPublicKeys.set(keyServer.objectId, G2Element.fromBytes(keyServer.pk)),\n\t\t\t);\n\t\t}\n\n\t\treturn services.map((objectId) => {\n\t\t\tconst keyServer = keyServers.get(objectId);\n\t\t\tif (keyServer) {\n\t\t\t\treturn G2Element.fromBytes(keyServer.pk);\n\t\t\t}\n\t\t\treturn this.#cachedPublicKeys.get(objectId)!;\n\t\t});\n\t}\n\n\t/**\n\t * Returns a list of key servers with multiplicity according to their weights.\n\t * The list is used for encryption.\n\t */\n\tasync #getWeightedKeyServers() {\n\t\tconst keyServers = await this.getKeyServers();\n\t\tconst keyServersWithMultiplicity = [];\n\t\tfor (const [objectId, config] of this.#configs) {\n\t\t\tconst keyServer = keyServers.get(objectId)!;\n\t\t\tfor (let i = 0; i < config.weight; i++) {\n\t\t\t\tkeyServersWithMultiplicity.push(keyServer);\n\t\t\t}\n\t\t}\n\t\treturn keyServersWithMultiplicity;\n\t}\n\n\tasync #loadKeyServers(): Promise<Map<string, KeyServer>> {\n\t\tconst keyServers = await retrieveKeyServers({\n\t\t\tobjectIds: [...this.#configs].map(([objectId]) => objectId),\n\t\t\tclient: this.#suiClient,\n\t\t});\n\n\t\tif (keyServers.length === 0) {\n\t\t\tthrow new InvalidKeyServerError('No key servers found');\n\t\t}\n\n\t\tif (this.#verifyKeyServers) {\n\t\t\tawait Promise.all(\n\t\t\t\tkeyServers.map(async (server) => {\n\t\t\t\t\tconst config = this.#configs.get(server.objectId);\n\t\t\t\t\tif (!(await verifyKeyServer(server, this.#timeout, config?.apiKeyName, config?.apiKey))) {\n\t\t\t\t\t\tthrow new InvalidKeyServerError(`Key server ${server.objectId} is not valid`);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn new Map(keyServers.map((server) => [server.objectId, server]));\n\t}\n\n\t/**\n\t * Fetch keys from the key servers and update the cache.\n\t *\n\t * It is recommended to call this function once for all ids of all encrypted objects if\n\t * there are multiple, then call decrypt for each object. This avoids calling fetchKey\n\t * individually for each decrypt.\n\t *\n\t * @param ids - The ids of the encrypted objects.\n\t * @param txBytes - The transaction bytes to use (that calls seal_approve* functions).\n\t * @param sessionKey - The session key to use.\n\t * @param threshold - The threshold for the TSS encryptions. The function returns when a threshold of key servers had returned keys for all ids.\n\t */\n\tasync fetchKeys({ ids, txBytes, sessionKey, threshold }: FetchKeysOptions) {\n\t\tif (threshold > this.#totalWeight || threshold < 1) {\n\t\t\tthrow new InvalidThresholdError(\n\t\t\t\t`Invalid threshold ${threshold} servers with weights ${this.#configs}`,\n\t\t\t);\n\t\t}\n\t\tconst keyServers = await this.getKeyServers();\n\t\tconst fullIds = ids.map((id) => createFullId(sessionKey.getPackageId(), id));\n\n\t\t// Count a server as completed if it has keys for all fullIds.\n\t\t// Duplicated key server ids will be counted towards the threshold.\n\t\tlet completedWeight = 0;\n\t\tconst remainingKeyServers = [];\n\t\tlet remainingKeyServersWeight = 0;\n\t\tfor (const objectId of keyServers.keys()) {\n\t\t\tif (fullIds.every((fullId) => this.#cachedKeys.has(`${fullId}:${objectId}`))) {\n\t\t\t\tcompletedWeight += this.#weight(objectId);\n\t\t\t} else {\n\t\t\t\tremainingKeyServers.push(objectId);\n\t\t\t\tremainingKeyServersWeight += this.#weight(objectId);\n\t\t\t}\n\t\t}\n\n\t\t// Return early if we have enough keys from cache.\n\t\tif (completedWeight >= threshold) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst certificate = await sessionKey.getCertificate();\n\t\tconst signedRequest = await sessionKey.createRequestParams(txBytes);\n\n\t\tconst controller = new AbortController();\n\t\tconst errors: Error[] = [];\n\n\t\tconst keyFetches = remainingKeyServers.map(async (objectId) => {\n\t\t\tconst server = keyServers.get(objectId)!;\n\t\t\ttry {\n\t\t\t\tconst config = this.#configs.get(objectId);\n\t\t\t\tconst allKeys = await fetchKeysForAllIds({\n\t\t\t\t\turl: server.url,\n\t\t\t\t\trequestSignature: signedRequest.requestSignature,\n\t\t\t\t\ttransactionBytes: txBytes,\n\t\t\t\t\tencKey: signedRequest.encKey,\n\t\t\t\t\tencKeyPk: signedRequest.encKeyPk,\n\t\t\t\t\tencVerificationKey: signedRequest.encVerificationKey,\n\t\t\t\t\tcertificate,\n\t\t\t\t\ttimeout: this.#timeout,\n\t\t\t\t\tapiKeyName: config?.apiKeyName,\n\t\t\t\t\tapiKey: config?.apiKey,\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t\t// Check validity of the keys and add them to the cache.\n\t\t\t\tfor (const { fullId, key } of allKeys) {\n\t\t\t\t\tconst keyElement = G1Element.fromBytes(key);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!BonehFranklinBLS12381Services.verifyUserSecretKey(\n\t\t\t\t\t\t\tkeyElement,\n\t\t\t\t\t\t\tfullId,\n\t\t\t\t\t\t\tG2Element.fromBytes(server.pk),\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconsole.warn('Received invalid key from key server ' + server.objectId);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tthis.#cachedKeys.set(`${fullId}:${server.objectId}`, keyElement);\n\t\t\t\t}\n\n\t\t\t\t// Check if all the receivedIds are consistent with the requested fullIds.\n\t\t\t\t// If so, consider the key server got all keys and mark as completed.\n\t\t\t\tif (fullIds.every((fullId) => this.#cachedKeys.has(`${fullId}:${server.objectId}`))) {\n\t\t\t\t\tcompletedWeight += this.#weight(objectId);\n\n\t\t\t\t\t// Return early if the completed servers is more than the threshold.\n\t\t\t\t\tif (completedWeight >= threshold) {\n\t\t\t\t\t\tcontroller.abort();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\terrors.push(error as Error);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\t// If there are too many errors that the threshold is not attainable, return early with error.\n\t\t\t\tremainingKeyServersWeight -= this.#weight(objectId);\n\t\t\t\tif (remainingKeyServersWeight < threshold - completedWeight) {\n\t\t\t\t\tcontroller.abort(new TooManyFailedFetchKeyRequestsError());\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tawait Promise.allSettled(keyFetches);\n\n\t\tif (completedWeight < threshold) {\n\t\t\tthrow toMajorityError(errors);\n\t\t}\n\t}\n\n\t/**\n\t * Get derived keys from the given services.\n\t *\n\t * @param id - The id of the encrypted object.\n\t * @param txBytes - The transaction bytes to use (that calls seal_approve* functions).\n\t * @param sessionKey - The session key to use.\n\t * @param threshold - The threshold.\n\t * @returns - Derived keys for the given services that are in the cache as a \"service object ID\" -> derived key map. If the call is succesful, exactly threshold keys will be returned.\n\t */\n\tasync getDerivedKeys({\n\t\tkemType = KemType.BonehFranklinBLS12381DemCCA,\n\t\tid,\n\t\ttxBytes,\n\t\tsessionKey,\n\t\tthreshold,\n\t}: GetDerivedKeysOptions): Promise<Map<string, DerivedKey>> {\n\t\tswitch (kemType) {\n\t\t\tcase KemType.BonehFranklinBLS12381DemCCA:\n\t\t\t\tconst keyServers = await this.getKeyServers();\n\t\t\t\tif (threshold > this.#totalWeight) {\n\t\t\t\t\tthrow new InvalidThresholdError(\n\t\t\t\t\t\t`Invalid threshold ${threshold} for ${this.#totalWeight} servers`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait this.fetchKeys({\n\t\t\t\t\tids: [id],\n\t\t\t\t\ttxBytes,\n\t\t\t\t\tsessionKey,\n\t\t\t\t\tthreshold,\n\t\t\t\t});\n\n\t\t\t\t// After calling fetchKeys, we can be sure that there are at least `threshold` of the required keys in the cache.\n\t\t\t\t// It is also checked there that the KeyServerType is BonehFranklinBLS12381 for all services.\n\n\t\t\t\tconst fullId = createFullId(sessionKey.getPackageId(), id);\n\n\t\t\t\tconst derivedKeys = new Map();\n\t\t\t\tlet weight = 0;\n\t\t\t\tfor (const objectId of keyServers.keys()) {\n\t\t\t\t\t// The code below assumes that the KeyServerType is BonehFranklinBLS12381.\n\t\t\t\t\tconst cachedKey = this.#cachedKeys.get(`${fullId}:${objectId}`);\n\t\t\t\t\tif (cachedKey) {\n\t\t\t\t\t\tderivedKeys.set(objectId, new BonehFranklinBLS12381DerivedKey(cachedKey));\n\t\t\t\t\t\tweight += this.#weight(objectId);\n\t\t\t\t\t\tif (weight >= threshold) {\n\t\t\t\t\t\t\t// We have enough keys, so we can stop.\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn derivedKeys;\n\t\t}\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/decrypt.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface DecryptOptions {
|
|
|
6
6
|
encryptedObject: typeof EncryptedObject.$inferType;
|
|
7
7
|
keys: Map<KeyCacheKey, G1Element>;
|
|
8
8
|
publicKeys?: G2Element[];
|
|
9
|
+
checkLEEncoding?: boolean;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* Decrypt the given encrypted bytes with the given cached secret keys for the full ID.
|
|
@@ -18,4 +19,4 @@ export interface DecryptOptions {
|
|
|
18
19
|
*
|
|
19
20
|
* @returns - The decrypted plaintext corresponding to ciphertext.
|
|
20
21
|
*/
|
|
21
|
-
export declare function decrypt({ encryptedObject, keys, publicKeys, }: DecryptOptions): Promise<Uint8Array>;
|
|
22
|
+
export declare function decrypt({ encryptedObject, keys, publicKeys, checkLEEncoding, }: DecryptOptions): Promise<Uint8Array>;
|
package/dist/esm/decrypt.js
CHANGED
|
@@ -2,14 +2,20 @@ import { fromHex } from "@mysten/bcs";
|
|
|
2
2
|
import { G2Element } from "./bls12381.js";
|
|
3
3
|
import { AesGcm256, Hmac256Ctr } from "./dem.js";
|
|
4
4
|
import { InvalidCiphertextError, UnsupportedFeatureError } from "./error.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
BonehFranklinBLS12381Services,
|
|
7
|
+
decryptRandomness,
|
|
8
|
+
verifyNonce,
|
|
9
|
+
verifyNonceWithLE
|
|
10
|
+
} from "./ibe.js";
|
|
6
11
|
import { deriveKey, KeyPurpose } from "./kdf.js";
|
|
7
12
|
import { createFullId, equals } from "./utils.js";
|
|
8
13
|
import { combine, interpolate } from "./shamir.js";
|
|
9
14
|
async function decrypt({
|
|
10
15
|
encryptedObject,
|
|
11
16
|
keys,
|
|
12
|
-
publicKeys
|
|
17
|
+
publicKeys,
|
|
18
|
+
checkLEEncoding
|
|
13
19
|
}) {
|
|
14
20
|
if (!encryptedObject.encryptedShares.BonehFranklinBLS12381) {
|
|
15
21
|
throw new UnsupportedFeatureError("Encryption mode not supported");
|
|
@@ -49,7 +55,7 @@ async function decrypt({
|
|
|
49
55
|
encryptedObject.encryptedShares.BonehFranklinBLS12381.encryptedRandomness,
|
|
50
56
|
randomnessKey
|
|
51
57
|
);
|
|
52
|
-
if (!verifyNonce(nonce, randomness)) {
|
|
58
|
+
if (!(checkLEEncoding ? verifyNonceWithLE(nonce, randomness) : verifyNonce(nonce, randomness))) {
|
|
53
59
|
throw new InvalidCiphertextError("Invalid nonce");
|
|
54
60
|
}
|
|
55
61
|
const checkShareConsistency = publicKeys !== void 0;
|
package/dist/esm/decrypt.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/decrypt.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\n\nimport type { EncryptedObject } from './bcs.js';\nimport type { G1Element } from './bls12381.js';\nimport { G2Element } from './bls12381.js';\nimport { AesGcm256, Hmac256Ctr } from './dem.js';\nimport { InvalidCiphertextError, UnsupportedFeatureError } from './error.js';\nimport {
|
|
5
|
-
"mappings": "AAGA,SAAS,eAAe;AAIxB,SAAS,iBAAiB;AAC1B,SAAS,WAAW,kBAAkB;AACtC,SAAS,wBAAwB,+BAA+B;AAChE,
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\n\nimport type { EncryptedObject } from './bcs.js';\nimport type { G1Element } from './bls12381.js';\nimport { G2Element } from './bls12381.js';\nimport { AesGcm256, Hmac256Ctr } from './dem.js';\nimport { InvalidCiphertextError, UnsupportedFeatureError } from './error.js';\nimport {\n\tBonehFranklinBLS12381Services,\n\tdecryptRandomness,\n\tverifyNonce,\n\tverifyNonceWithLE,\n} from './ibe.js';\nimport { deriveKey, KeyPurpose } from './kdf.js';\nimport type { KeyCacheKey } from './types.js';\nimport { createFullId, equals } from './utils.js';\nimport { combine, interpolate } from './shamir.js';\n\nexport interface DecryptOptions {\n\tencryptedObject: typeof EncryptedObject.$inferType;\n\tkeys: Map<KeyCacheKey, G1Element>;\n\tpublicKeys?: G2Element[];\n\tcheckLEEncoding?: boolean;\n}\n\n/**\n * Decrypt the given encrypted bytes with the given cached secret keys for the full ID.\n * It's assumed that fetchKeys has been called to fetch the secret keys for enough key servers\n * otherwise, this will throw an error.\n * Also, it's assumed that the keys were verified by the caller.\n *\n * If publicKeys are provided, the decrypted shares are checked for consistency, meaning that\n * any combination of at least threshold shares should either succesfully combine to the plaintext or fail.\n *\n * @returns - The decrypted plaintext corresponding to ciphertext.\n */\nexport async function decrypt({\n\tencryptedObject,\n\tkeys,\n\tpublicKeys,\n\tcheckLEEncoding,\n}: DecryptOptions): Promise<Uint8Array> {\n\tif (!encryptedObject.encryptedShares.BonehFranklinBLS12381) {\n\t\tthrow new UnsupportedFeatureError('Encryption mode not supported');\n\t}\n\n\tconst fullId = createFullId(encryptedObject.packageId, encryptedObject.id);\n\n\t// Get the indices of the service whose keys are in the keystore.\n\tconst inKeystore = encryptedObject.services\n\t\t.map((_, i) => i)\n\t\t.filter((i) => keys.has(`${fullId}:${encryptedObject.services[i][0]}`));\n\n\tif (inKeystore.length < encryptedObject.threshold) {\n\t\tthrow new Error('Not enough shares. Please fetch more keys.');\n\t}\n\n\tconst encryptedShares = encryptedObject.encryptedShares.BonehFranklinBLS12381.encryptedShares;\n\tif (encryptedShares.length !== encryptedObject.services.length) {\n\t\tthrow new InvalidCiphertextError(\n\t\t\t`Mismatched shares ${encryptedShares.length} and services ${encryptedObject.services.length}`,\n\t\t);\n\t}\n\n\tconst nonce = G2Element.fromBytes(encryptedObject.encryptedShares.BonehFranklinBLS12381.nonce);\n\n\t// Decrypt each share.\n\tconst shares = inKeystore.map((i) => {\n\t\tconst [objectId, index] = encryptedObject.services[i];\n\t\t// Use the index as the unique info parameter to allow for multiple shares per key server.\n\t\tconst share = BonehFranklinBLS12381Services.decrypt(\n\t\t\tnonce,\n\t\t\tkeys.get(`${fullId}:${objectId}`)!,\n\t\t\tencryptedShares[i],\n\t\t\tfromHex(fullId),\n\t\t\t[objectId, index],\n\t\t) as Uint8Array<ArrayBuffer>;\n\t\treturn { index, share };\n\t});\n\n\t// Combine the decrypted shares into the key\n\tconst baseKey = combine(shares);\n\n\t// Decrypt randomness\n\tconst randomnessKey = deriveKey(\n\t\tKeyPurpose.EncryptedRandomness,\n\t\tbaseKey,\n\t\tencryptedShares,\n\t\tencryptedObject.threshold,\n\t\tencryptedObject.services.map(([objectIds, _]) => objectIds),\n\t);\n\tconst randomness = decryptRandomness(\n\t\tencryptedObject.encryptedShares.BonehFranklinBLS12381.encryptedRandomness,\n\t\trandomnessKey,\n\t);\n\n\t// Verify that the nonce was created with the randomness.\n\tif (!(checkLEEncoding ? verifyNonceWithLE(nonce, randomness) : verifyNonce(nonce, randomness))) {\n\t\tthrow new InvalidCiphertextError('Invalid nonce');\n\t}\n\n\t// If public keys are provided, check consistency of the shares.\n\tconst checkShareConsistency = publicKeys !== undefined;\n\tif (checkShareConsistency) {\n\t\tconst polynomial = interpolate(shares);\n\t\tconst allShares = BonehFranklinBLS12381Services.decryptAllSharesUsingRandomness(\n\t\t\trandomness,\n\t\t\tencryptedShares,\n\t\t\tencryptedObject.services,\n\t\t\tpublicKeys,\n\t\t\tnonce,\n\t\t\tfromHex(fullId),\n\t\t);\n\t\tif (allShares.some(({ index, share }) => !equals(polynomial(index), share))) {\n\t\t\tthrow new InvalidCiphertextError('Invalid shares');\n\t\t}\n\t}\n\n\t// Derive the DEM key\n\tconst demKey = deriveKey(\n\t\tKeyPurpose.DEM,\n\t\tbaseKey,\n\t\tencryptedShares,\n\t\tencryptedObject.threshold,\n\t\tencryptedObject.services.map(([objectId, _]) => objectId),\n\t);\n\n\t// Decrypt the ciphertext\n\tif (encryptedObject.ciphertext.Aes256Gcm) {\n\t\treturn AesGcm256.decrypt(demKey, encryptedObject.ciphertext);\n\t} else if (encryptedObject.ciphertext.Hmac256Ctr) {\n\t\treturn Hmac256Ctr.decrypt(demKey, encryptedObject.ciphertext);\n\t} else if (encryptedObject.ciphertext.Plain) {\n\t\t// In case `Plain` mode is used, return the key.\n\t\treturn demKey;\n\t} else {\n\t\tthrow new InvalidCiphertextError('Invalid ciphertext type');\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/elgamal.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Decrypt a ciphertext with a given secret key. The secret key must be a 32-byte scalar.
|
|
3
3
|
* The ciphertext is a pair of G1Elements (48 bytes).
|
|
4
|
+
*
|
|
5
|
+
* Throws an error if the secret key is not a valid scalar or if the ciphertext elements are not valid G1 points.
|
|
4
6
|
*/
|
|
5
7
|
export declare function elgamalDecrypt(sk: Uint8Array, [c0, c1]: [Uint8Array, Uint8Array]): Uint8Array;
|
|
6
8
|
/** Generate a random secret key. */
|
package/dist/esm/elgamal.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/elgamal.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { G1Element, G2Element, Scalar } from './bls12381.js';\n\n/**\n * Decrypt a ciphertext with a given secret key. The secret key must be a 32-byte scalar.\n * The ciphertext is a pair of G1Elements (48 bytes).\n */\nexport function elgamalDecrypt(sk: Uint8Array, [c0, c1]: [Uint8Array, Uint8Array]): Uint8Array {\n\treturn decrypt(Scalar.fromBytes(sk), [\n\t\tG1Element.fromBytes(c0),\n\t\tG1Element.fromBytes(c1),\n\t]).toBytes();\n}\n\n/**\n * Decrypt a ciphertext with a given secret key. The secret key must be a 32-byte scalar.\n * The ciphertext is a pair of G1Elements (48 bytes).\n */\nfunction decrypt(sk: Scalar, [c0, c1]: [G1Element, G1Element]): G1Element {\n\treturn c1.subtract(c0.multiply(sk));\n}\n\n/** Generate a random secret key. */\nexport function generateSecretKey(): Uint8Array<ArrayBuffer> {\n\treturn Scalar.random().toBytes() as Uint8Array<ArrayBuffer>;\n}\n\n/** Derive the BLS public key for a given secret key. */\nexport function toPublicKey(sk: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer> {\n\treturn G1Element.generator().multiply(Scalar.fromBytes(sk)).toBytes();\n}\n\n/** Derive the BLS verification key for a given secret key. */\nexport function toVerificationKey(sk: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer> {\n\treturn G2Element.generator().multiply(Scalar.fromBytes(sk)).toBytes();\n}\n"],
|
|
5
|
-
"mappings": "AAGA,SAAS,WAAW,WAAW,cAAc;
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { G1Element, G2Element, Scalar } from './bls12381.js';\n\n/**\n * Decrypt a ciphertext with a given secret key. The secret key must be a 32-byte scalar.\n * The ciphertext is a pair of G1Elements (48 bytes).\n *\n * Throws an error if the secret key is not a valid scalar or if the ciphertext elements are not valid G1 points.\n */\nexport function elgamalDecrypt(sk: Uint8Array, [c0, c1]: [Uint8Array, Uint8Array]): Uint8Array {\n\treturn decrypt(Scalar.fromBytes(sk), [\n\t\tG1Element.fromBytes(c0),\n\t\tG1Element.fromBytes(c1),\n\t]).toBytes();\n}\n\n/**\n * Decrypt a ciphertext with a given secret key. The secret key must be a 32-byte scalar.\n * The ciphertext is a pair of G1Elements (48 bytes).\n */\nfunction decrypt(sk: Scalar, [c0, c1]: [G1Element, G1Element]): G1Element {\n\treturn c1.subtract(c0.multiply(sk));\n}\n\n/** Generate a random secret key. */\nexport function generateSecretKey(): Uint8Array<ArrayBuffer> {\n\treturn Scalar.random().toBytes() as Uint8Array<ArrayBuffer>;\n}\n\n/** Derive the BLS public key for a given secret key. */\nexport function toPublicKey(sk: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer> {\n\treturn G1Element.generator().multiply(Scalar.fromBytes(sk)).toBytes();\n}\n\n/** Derive the BLS verification key for a given secret key. */\nexport function toVerificationKey(sk: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer> {\n\treturn G2Element.generator().multiply(Scalar.fromBytes(sk)).toBytes();\n}\n"],
|
|
5
|
+
"mappings": "AAGA,SAAS,WAAW,WAAW,cAAc;AAQtC,SAAS,eAAe,IAAgB,CAAC,IAAI,EAAE,GAAyC;AAC9F,SAAO,QAAQ,OAAO,UAAU,EAAE,GAAG;AAAA,IACpC,UAAU,UAAU,EAAE;AAAA,IACtB,UAAU,UAAU,EAAE;AAAA,EACvB,CAAC,EAAE,QAAQ;AACZ;AAMA,SAAS,QAAQ,IAAY,CAAC,IAAI,EAAE,GAAsC;AACzE,SAAO,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;AACnC;AAGO,SAAS,oBAA6C;AAC5D,SAAO,OAAO,OAAO,EAAE,QAAQ;AAChC;AAGO,SAAS,YAAY,IAAsD;AACjF,SAAO,UAAU,UAAU,EAAE,SAAS,OAAO,UAAU,EAAE,CAAC,EAAE,QAAQ;AACrE;AAGO,SAAS,kBAAkB,IAAsD;AACvF,SAAO,UAAU,UAAU,EAAE,SAAS,OAAO,UAAU,EAAE,CAAC,EAAE,QAAQ;AACrE;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|