@mysten/seal 0.4.2 → 0.4.4
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 +20 -0
- package/dist/cjs/bls12381.d.ts +5 -0
- package/dist/cjs/bls12381.js +38 -23
- package/dist/cjs/bls12381.js.map +2 -2
- package/dist/cjs/client.d.ts +21 -6
- package/dist/cjs/client.js +111 -55
- package/dist/cjs/client.js.map +2 -2
- package/dist/cjs/decrypt.js +7 -20
- package/dist/cjs/decrypt.js.map +2 -2
- package/dist/cjs/dem.js +20 -16
- package/dist/cjs/dem.js.map +2 -2
- package/dist/cjs/elgamal.d.ts +1 -1
- package/dist/cjs/elgamal.js +5 -5
- package/dist/cjs/elgamal.js.map +2 -2
- package/dist/cjs/encrypt.js +14 -16
- package/dist/cjs/encrypt.js.map +2 -2
- package/dist/cjs/error.d.ts +6 -0
- package/dist/cjs/error.js +9 -0
- package/dist/cjs/error.js.map +2 -2
- package/dist/cjs/ibe.d.ts +3 -1
- package/dist/cjs/ibe.js +4 -4
- package/dist/cjs/ibe.js.map +2 -2
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/kdf.js +6 -16
- package/dist/cjs/kdf.js.map +2 -2
- package/dist/cjs/key-server.d.ts +14 -0
- package/dist/cjs/key-server.js +11 -1
- package/dist/cjs/key-server.js.map +2 -2
- package/dist/cjs/keys.js +1 -1
- package/dist/cjs/keys.js.map +2 -2
- package/dist/cjs/session-key.d.ts +5 -2
- package/dist/cjs/session-key.js +10 -8
- package/dist/cjs/session-key.js.map +2 -2
- package/dist/cjs/utils.d.ts +9 -0
- package/dist/cjs/utils.js +16 -8
- package/dist/cjs/utils.js.map +3 -3
- 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 +5 -0
- package/dist/esm/bls12381.js +38 -23
- package/dist/esm/bls12381.js.map +2 -2
- package/dist/esm/client.d.ts +21 -6
- package/dist/esm/client.js +121 -58
- package/dist/esm/client.js.map +2 -2
- package/dist/esm/decrypt.js +8 -21
- package/dist/esm/decrypt.js.map +2 -2
- package/dist/esm/dem.js +22 -18
- package/dist/esm/dem.js.map +2 -2
- package/dist/esm/elgamal.d.ts +1 -1
- package/dist/esm/elgamal.js +5 -5
- package/dist/esm/elgamal.js.map +2 -2
- package/dist/esm/encrypt.js +14 -16
- package/dist/esm/encrypt.js.map +2 -2
- package/dist/esm/error.d.ts +6 -0
- package/dist/esm/error.js +9 -0
- package/dist/esm/error.js.map +2 -2
- package/dist/esm/ibe.d.ts +3 -1
- package/dist/esm/ibe.js +4 -4
- package/dist/esm/ibe.js.map +2 -2
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/kdf.js +6 -16
- package/dist/esm/kdf.js.map +2 -2
- package/dist/esm/key-server.d.ts +14 -0
- package/dist/esm/key-server.js +13 -3
- package/dist/esm/key-server.js.map +2 -2
- package/dist/esm/keys.js +1 -1
- package/dist/esm/keys.js.map +2 -2
- package/dist/esm/session-key.d.ts +5 -2
- package/dist/esm/session-key.js +10 -8
- package/dist/esm/session-key.js.map +2 -2
- package/dist/esm/utils.d.ts +9 -0
- package/dist/esm/utils.js +16 -8
- package/dist/esm/utils.js.map +3 -3
- 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 +2 -2
package/dist/cjs/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\tInvalidKeyServerError,\n\tInvalidThresholdError,\n\ttoMajorityError,\n} from './error.js';\nimport { BonehFranklinBLS12381Services, DST } from './ibe.js';\nimport { KeyServerType, retrieveKeyServers, verifyKeyServer } from './key-server.js';\nimport type { KeyServer } from './key-server.js';\nimport { fetchKeysForAllIds } from './keys.js';\nimport type { SessionKey } from './session-key.js';\nimport type { KeyCacheKey, SealCompatibleClient } from './types.js';\nimport { createFullId } from './utils.js';\n\n/**\n * Configuration options for initializing a SealClient\n * @property serverObjectIds: Array of object IDs for the key servers to use.\n * @property verifyKeyServers: Whether to verify the key servers' authenticity.\n * \t Should be false if servers are pre-verified (e.g., getAllowlistedKeyServers).\n * \t Defaults to true.\n * @property timeout: Timeout in milliseconds for network requests. Defaults to 10 seconds.\n */\n\nexport interface SealClientExtensionOptions {\n\tserverObjectIds: string[];\n\tverifyKeyServers?: boolean;\n\ttimeout?: number;\n}\n\nexport interface SealClientOptions extends SealClientExtensionOptions {\n\tsuiClient: SealCompatibleClient;\n}\n\nexport class SealClient {\n\t#suiClient: SealCompatibleClient;\n\t#serverObjectIds: string[];\n\t#verifyKeyServers: boolean;\n\t#keyServers: Promise<KeyServer[]> | null = null;\n\t// A caching map for: fullId:object_id -> partial key.\n\t#cachedKeys = new Map<KeyCacheKey, G1Element>();\n\t#timeout: number;\n\n\tconstructor(options: SealClientOptions) {\n\t\tthis.#suiClient = options.suiClient;\n\t\tthis.#serverObjectIds = options.serverObjectIds;\n\t\tthis.#verifyKeyServers = options.verifyKeyServers ?? true;\n\t\tthis.#timeout = options.timeout ?? 10_000;\n\t}\n\n\tstatic experimental_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}: {\n\t\tkemType?: KemType;\n\t\tdemType?: DemType;\n\t\tthreshold: number;\n\t\tpackageId: string;\n\t\tid: string;\n\t\tdata: Uint8Array;\n\t\taad?: Uint8Array;\n\t}) {\n\t\t// TODO: Verify that packageId is first version of its package (else throw error).\n\t\treturn encrypt({\n\t\t\tkeyServers: await this.getKeyServers(),\n\t\t\tkemType,\n\t\t\tthreshold,\n\t\t\tpackageId,\n\t\t\tid,\n\t\t\tencryptionInput: this.#createEncryptionInput(demType, data, aad),\n\t\t});\n\t}\n\n\t#createEncryptionInput(type: DemType, data: Uint8Array, aad: Uint8Array): 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 (including the same weights) or if the\n\t * threshold cannot be met.\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 * @returns - The decrypted plaintext corresponding to ciphertext.\n\t */\n\tasync decrypt({\n\t\tdata,\n\t\tsessionKey,\n\t\ttxBytes,\n\t}: {\n\t\tdata: Uint8Array;\n\t\tsessionKey: SessionKey;\n\t\ttxBytes: Uint8Array;\n\t}) {\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\treturn decrypt({ encryptedObject, keys: this.#cachedKeys });\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\tconst serverObjectIdsMap = new Map<string, number>();\n\t\tfor (const objectId of this.#serverObjectIds) {\n\t\t\tserverObjectIdsMap.set(objectId, (serverObjectIdsMap.get(objectId) ?? 0) + 1);\n\t\t}\n\t\tconst servicesMap = new Map<string, number>();\n\t\tfor (const service of services) {\n\t\t\tservicesMap.set(service, (servicesMap.get(service) ?? 0) + 1);\n\t\t}\n\t\tfor (const [objectId, count] of serverObjectIdsMap) {\n\t\t\tif (servicesMap.get(objectId) !== count) {\n\t\t\t\tthrow new InconsistentKeyServersError(\n\t\t\t\t\t`Client's key servers must be a subset of the encrypted object's key servers`,\n\t\t\t\t);\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.#serverObjectIds.length) {\n\t\t\tthrow new InvalidThresholdError(\n\t\t\t\t`Invalid threshold ${threshold} for ${this.#serverObjectIds.length} servers`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync getKeyServers() {\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\n\t\treturn this.#keyServers;\n\t}\n\n\tasync #loadKeyServers(): Promise<KeyServer[]> {\n\t\tconst keyServers = await retrieveKeyServers({\n\t\t\tobjectIds: this.#serverObjectIds,\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\tif (!(await verifyKeyServer(server, this.#timeout))) {\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\n\t\treturn keyServers;\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 obejcts 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({\n\t\tids,\n\t\ttxBytes,\n\t\tsessionKey,\n\t\tthreshold,\n\t}: {\n\t\tids: string[];\n\t\ttxBytes: Uint8Array;\n\t\tsessionKey: SessionKey;\n\t\tthreshold: number;\n\t}) {\n\t\tconst keyServers = await this.getKeyServers();\n\t\tif (threshold > keyServers.length || threshold < 1 || keyServers.length < 1) {\n\t\t\tthrow new InvalidThresholdError(\n\t\t\t\t`Invalid threshold ${threshold} for ${keyServers.length} servers`,\n\t\t\t);\n\t\t}\n\n\t\tlet completedServerCount = 0;\n\t\tconst remainingKeyServers = new Set<KeyServer>();\n\t\tconst fullIds = ids.map((id) => createFullId(DST, 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\tfor (const server of keyServers) {\n\t\t\tlet hasAllKeys = true;\n\t\t\tfor (const fullId of fullIds) {\n\t\t\t\tif (!this.#cachedKeys.has(`${fullId}:${server.objectId}`)) {\n\t\t\t\t\thasAllKeys = false;\n\t\t\t\t\tremainingKeyServers.add(server);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hasAllKeys) {\n\t\t\t\tcompletedServerCount++;\n\t\t\t}\n\t\t}\n\n\t\t// Return early if we have enough keys from cache.\n\t\tif (completedServerCount >= threshold) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check server validities.\n\t\tfor (const server of remainingKeyServers) {\n\t\t\tif (server.keyType !== KeyServerType.BonehFranklinBLS12381) {\n\t\t\t\tthrow new InvalidKeyServerError(\n\t\t\t\t\t`Server ${server.objectId} has invalid key type: ${server.keyType}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst cert = 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 (server) => {\n\t\t\ttry {\n\t\t\t\tconst allKeys = await fetchKeysForAllIds(\n\t\t\t\t\tserver.url,\n\t\t\t\t\tsignedRequest.requestSignature,\n\t\t\t\t\ttxBytes,\n\t\t\t\t\tsignedRequest.decryptionKey,\n\t\t\t\t\tcert,\n\t\t\t\t\tthis.#timeout,\n\t\t\t\t\tcontroller.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\tconst receivedIds = new Set<string>();\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\treceivedIds.add(fullId);\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\tconst expectedIds = new Set(fullIds);\n\t\t\t\tconst hasAllKeys =\n\t\t\t\t\treceivedIds.size === expectedIds.size &&\n\t\t\t\t\t[...receivedIds].every((id) => expectedIds.has(id));\n\n\t\t\t\t// Return early if the completed servers is more than threshold.\n\t\t\t\tif (hasAllKeys) {\n\t\t\t\t\tcompletedServerCount++;\n\t\t\t\t\tif (completedServerCount >= 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\t// If there are too many errors that the threshold is not attainable, return early with error.\n\t\t\t\tif (remainingKeyServers.size - errors.length < threshold - completedServerCount) {\n\t\t\t\t\tcontroller.abort(error);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tawait Promise.allSettled(keyFetches);\n\n\t\tif (completedServerCount < threshold) {\n\t\t\tthrow toMajorityError(errors);\n\t\t}\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAgC;AAChC,sBAAqC;AACrC,qBAAwB;AAExB,iBAAsC;AACtC,qBAA0C;AAC1C,
|
|
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\tInvalidThresholdError,\n\ttoMajorityError,\n\tTooManyFailedFetchKeyRequestsError,\n} from './error.js';\nimport { BonehFranklinBLS12381Services, DST } from './ibe.js';\nimport {\n\tBonehFranklinBLS12381DerivedKey,\n\tKeyServerType,\n\tretrieveKeyServers,\n\tverifyKeyServer,\n} from './key-server.js';\nimport type { DerivedKey, KeyServer } from './key-server.js';\nimport { fetchKeysForAllIds } from './keys.js';\nimport type { SessionKey } from './session-key.js';\nimport type { KeyCacheKey, SealCompatibleClient } from './types.js';\nimport { createFullId, count } from './utils.js';\n\n/**\n * Configuration options for initializing a SealClient\n * @property serverObjectIds: Array of object IDs for the key servers to use.\n * @property verifyKeyServers: Whether to verify the key servers' authenticity.\n * \t Should be false if servers are pre-verified (e.g., getAllowlistedKeyServers).\n * \t Defaults to true.\n * @property timeout: Timeout in milliseconds for network requests. Defaults to 10 seconds.\n */\n\nexport interface SealClientExtensionOptions {\n\tserverObjectIds: [string, number][];\n\tverifyKeyServers?: boolean;\n\ttimeout?: number;\n}\n\nexport interface SealClientOptions extends SealClientExtensionOptions {\n\tsuiClient: SealCompatibleClient;\n}\n\nexport class SealClient {\n\t#suiClient: SealCompatibleClient;\n\t#weights: Map<string, number>;\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#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.serverObjectIds.map(([objectId, _]) => objectId)).size !==\n\t\t\toptions.serverObjectIds.length\n\t\t) {\n\t\t\tthrow new InvalidClientOptionsError('Duplicate object IDs');\n\t\t}\n\n\t\tthis.#weights = new Map(options.serverObjectIds);\n\t\tthis.#totalWeight = options.serverObjectIds\n\t\t\t.map(([_, weight]) => 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 experimental_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}: {\n\t\tkemType?: KemType;\n\t\tdemType?: DemType;\n\t\tthreshold: number;\n\t\tpackageId: string;\n\t\tid: string;\n\t\tdata: Uint8Array;\n\t\taad?: Uint8Array;\n\t}) {\n\t\t// TODO: Verify that packageId is first version of its package (else throw error).\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(demType, data, aad),\n\t\t});\n\t}\n\n\t#createEncryptionInput(type: DemType, data: Uint8Array, aad: Uint8Array): 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 * @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 * @returns - The decrypted plaintext corresponding to ciphertext.\n\t */\n\tasync decrypt({\n\t\tdata,\n\t\tsessionKey,\n\t\ttxBytes,\n\t}: {\n\t\tdata: Uint8Array;\n\t\tsessionKey: SessionKey;\n\t\ttxBytes: Uint8Array;\n\t}) {\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\treturn decrypt({ encryptedObject, keys: this.#cachedKeys });\n\t}\n\n\t#weight(objectId: string) {\n\t\treturn this.#weights.get(objectId) ?? 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 * 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, weight] of this.#weights) {\n\t\t\tconst keyServer = keyServers.get(objectId)!;\n\t\t\tfor (let i = 0; i < 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.#weights].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\tif (!(await verifyKeyServer(server, this.#timeout))) {\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({\n\t\tids,\n\t\ttxBytes,\n\t\tsessionKey,\n\t\tthreshold,\n\t}: {\n\t\tids: string[];\n\t\ttxBytes: Uint8Array;\n\t\tsessionKey: SessionKey;\n\t\tthreshold: number;\n\t}) {\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.#weights}`,\n\t\t\t);\n\t\t}\n\t\tconst keyServers = await this.getKeyServers();\n\t\tconst fullIds = ids.map((id) => createFullId(DST, 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\t// Check server validities.\n\t\tfor (const objectId of remainingKeyServers) {\n\t\t\tconst server = keyServers.get(objectId)!;\n\t\t\tif (server.keyType !== KeyServerType.BonehFranklinBLS12381) {\n\t\t\t\tthrow new InvalidKeyServerError(\n\t\t\t\t\t`Server ${server.objectId} has invalid key type: ${server.keyType}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst cert = 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 allKeys = await fetchKeysForAllIds(\n\t\t\t\t\tserver.url,\n\t\t\t\t\tsignedRequest.requestSignature,\n\t\t\t\t\ttxBytes,\n\t\t\t\t\tsignedRequest.decryptionKey,\n\t\t\t\t\tcert,\n\t\t\t\t\tthis.#timeout,\n\t\t\t\t\tcontroller.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\tconst receivedIds = new Set<string>();\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\treceivedIds.add(fullId);\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) => receivedIds.has(fullId))) {\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}: {\n\t\tkemType?: KemType;\n\t\tid: string;\n\t\ttxBytes: Uint8Array;\n\t\tsessionKey: SessionKey;\n\t\tthreshold: number;\n\t}): 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(DST, 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/cjs/decrypt.js
CHANGED
|
@@ -56,24 +56,16 @@ async function decrypt({ encryptedObject, keys }) {
|
|
|
56
56
|
);
|
|
57
57
|
return { index, share };
|
|
58
58
|
});
|
|
59
|
-
const
|
|
60
|
-
const demKey = (0, import_kdf.deriveKey)(import_kdf.KeyPurpose.DEM,
|
|
59
|
+
const baseKey = await combine(shares);
|
|
60
|
+
const demKey = (0, import_kdf.deriveKey)(import_kdf.KeyPurpose.DEM, baseKey);
|
|
61
61
|
if (encryptedObject.ciphertext.Aes256Gcm) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
throw new Error("Decryption failed");
|
|
66
|
-
}
|
|
62
|
+
return import_dem.AesGcm256.decrypt(demKey, encryptedObject.ciphertext);
|
|
63
|
+
} else if (encryptedObject.ciphertext.Hmac256Ctr) {
|
|
64
|
+
return import_dem.Hmac256Ctr.decrypt(demKey, encryptedObject.ciphertext);
|
|
67
65
|
} else if (encryptedObject.ciphertext.Plain) {
|
|
68
66
|
return demKey;
|
|
69
|
-
} else if (encryptedObject.ciphertext.Hmac256Ctr) {
|
|
70
|
-
try {
|
|
71
|
-
return import_dem.Hmac256Ctr.decrypt(demKey, encryptedObject.ciphertext);
|
|
72
|
-
} catch {
|
|
73
|
-
throw new Error("Decryption failed");
|
|
74
|
-
}
|
|
75
67
|
} else {
|
|
76
|
-
throw new
|
|
68
|
+
throw new import_error.InvalidCiphertextError("Invalid ciphertext type");
|
|
77
69
|
}
|
|
78
70
|
}
|
|
79
71
|
async function combine(shares) {
|
|
@@ -83,12 +75,7 @@ async function combine(shares) {
|
|
|
83
75
|
return Promise.resolve(shares[0].share);
|
|
84
76
|
}
|
|
85
77
|
return (0, import_shamir_secret_sharing.combine)(
|
|
86
|
-
shares.map(({ index, share }) =>
|
|
87
|
-
const packedShare = new Uint8Array(share.length + 1);
|
|
88
|
-
packedShare.set(share, 0);
|
|
89
|
-
packedShare[share.length] = index;
|
|
90
|
-
return packedShare;
|
|
91
|
-
})
|
|
78
|
+
shares.map(({ index, share }) => (0, import_utils.flatten)([share, new Uint8Array([index])]))
|
|
92
79
|
);
|
|
93
80
|
}
|
|
94
81
|
//# sourceMappingURL=decrypt.js.map
|
package/dist/cjs/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';\nimport { combine as externalCombine } from 'shamir-secret-sharing';\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 { BonehFranklinBLS12381Services, DST } from './ibe.js';\nimport { deriveKey, KeyPurpose } from './kdf.js';\nimport type { KeyCacheKey } from './types.js';\nimport { createFullId } from './utils.js';\n\nexport interface DecryptOptions {\n\tencryptedObject: typeof EncryptedObject.$inferType;\n\tkeys: Map<KeyCacheKey, G1Element>;\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 *\n * @returns - The decrypted plaintext corresponding to ciphertext.\n */\nexport async function decrypt({ encryptedObject, keys }: DecryptOptions): Promise<Uint8Array> {\n\tif (!encryptedObject.encryptedShares.BonehFranklinBLS12381) {\n\t\tthrow new UnsupportedFeatureError('Encryption mode not supported');\n\t}\n\n\tconst fullId = createFullId(DST, 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
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAwB;AACxB,mCAA2C;AAI3C,sBAA0B;AAC1B,iBAAsC;AACtC,mBAAgE;AAChE,iBAAmD;AACnD,iBAAsC;AAEtC,
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\nimport { combine as externalCombine } from 'shamir-secret-sharing';\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 { BonehFranklinBLS12381Services, DST } from './ibe.js';\nimport { deriveKey, KeyPurpose } from './kdf.js';\nimport type { KeyCacheKey } from './types.js';\nimport { createFullId, flatten } from './utils.js';\n\nexport interface DecryptOptions {\n\tencryptedObject: typeof EncryptedObject.$inferType;\n\tkeys: Map<KeyCacheKey, G1Element>;\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 *\n * @returns - The decrypted plaintext corresponding to ciphertext.\n */\nexport async function decrypt({ encryptedObject, keys }: DecryptOptions): Promise<Uint8Array> {\n\tif (!encryptedObject.encryptedShares.BonehFranklinBLS12381) {\n\t\tthrow new UnsupportedFeatureError('Encryption mode not supported');\n\t}\n\n\tconst fullId = createFullId(DST, 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);\n\t\t// The Shamir secret sharing library expects the index/x-coordinate to be at the end of the share.\n\t\treturn { index, share };\n\t});\n\n\t// Combine the decrypted shares into the key.\n\tconst baseKey = await combine(shares);\n\n\tconst demKey = deriveKey(KeyPurpose.DEM, baseKey);\n\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\n/**\n * Helper function that combines the shares into the key.\n * @param shares - The shares to combine.\n * @returns - The combined key.\n */\nasync function combine(shares: { index: number; share: Uint8Array }[]): Promise<Uint8Array> {\n\tif (shares.length === 0) {\n\t\tthrow new Error('Invalid shares length');\n\t} else if (shares.length === 1) {\n\t\t// The Shamir secret sharing library expects at least two shares.\n\t\t// If there is only one and the threshold is 1, the reconstructed secret is the same as the share.\n\t\treturn Promise.resolve(shares[0].share);\n\t}\n\n\t// The Shamir secret sharing library expects the index/x-coordinate to be at the end of the share\n\treturn externalCombine(\n\t\tshares.map(({ index, share }) => flatten([share, new Uint8Array([index])])),\n\t);\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAwB;AACxB,mCAA2C;AAI3C,sBAA0B;AAC1B,iBAAsC;AACtC,mBAAgE;AAChE,iBAAmD;AACnD,iBAAsC;AAEtC,mBAAsC;AActC,eAAsB,QAAQ,EAAE,iBAAiB,KAAK,GAAwC;AAC7F,MAAI,CAAC,gBAAgB,gBAAgB,uBAAuB;AAC3D,UAAM,IAAI,qCAAwB,+BAA+B;AAAA,EAClE;AAEA,QAAM,aAAS,2BAAa,gBAAK,gBAAgB,WAAW,gBAAgB,EAAE;AAG9E,QAAM,aAAa,gBAAgB,SACjC,IAAI,CAAC,GAAG,MAAM,CAAC,EACf,OAAO,CAAC,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,gBAAgB,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAEvE,MAAI,WAAW,SAAS,gBAAgB,WAAW;AAClD,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC7D;AAEA,QAAM,kBAAkB,gBAAgB,gBAAgB,sBAAsB;AAC9E,MAAI,gBAAgB,WAAW,gBAAgB,SAAS,QAAQ;AAC/D,UAAM,IAAI;AAAA,MACT,qBAAqB,gBAAgB,MAAM,iBAAiB,gBAAgB,SAAS,MAAM;AAAA,IAC5F;AAAA,EACD;AAEA,QAAM,QAAQ,0BAAU,UAAU,gBAAgB,gBAAgB,sBAAsB,KAAK;AAG7F,QAAM,SAAS,WAAW,IAAI,CAAC,MAAM;AACpC,UAAM,CAAC,UAAU,KAAK,IAAI,gBAAgB,SAAS,CAAC;AAEpD,UAAM,QAAQ,yCAA8B;AAAA,MAC3C;AAAA,MACA,KAAK,IAAI,GAAG,MAAM,IAAI,QAAQ,EAAE;AAAA,MAChC,gBAAgB,CAAC;AAAA,UACjB,oBAAQ,MAAM;AAAA,MACd,CAAC,UAAU,KAAK;AAAA,IACjB;AAEA,WAAO,EAAE,OAAO,MAAM;AAAA,EACvB,CAAC;AAGD,QAAM,UAAU,MAAM,QAAQ,MAAM;AAEpC,QAAM,aAAS,sBAAU,sBAAW,KAAK,OAAO;AAEhD,MAAI,gBAAgB,WAAW,WAAW;AACzC,WAAO,qBAAU,QAAQ,QAAQ,gBAAgB,UAAU;AAAA,EAC5D,WAAW,gBAAgB,WAAW,YAAY;AACjD,WAAO,sBAAW,QAAQ,QAAQ,gBAAgB,UAAU;AAAA,EAC7D,WAAW,gBAAgB,WAAW,OAAO;AAE5C,WAAO;AAAA,EACR,OAAO;AACN,UAAM,IAAI,oCAAuB,yBAAyB;AAAA,EAC3D;AACD;AAOA,eAAe,QAAQ,QAAqE;AAC3F,MAAI,OAAO,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,uBAAuB;AAAA,EACxC,WAAW,OAAO,WAAW,GAAG;AAG/B,WAAO,QAAQ,QAAQ,OAAO,CAAC,EAAE,KAAK;AAAA,EACvC;AAGA,aAAO,6BAAAA;AAAA,IACN,OAAO,IAAI,CAAC,EAAE,OAAO,MAAM,UAAM,sBAAQ,CAAC,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAAA,EAC3E;AACD;",
|
|
6
6
|
"names": ["externalCombine"]
|
|
7
7
|
}
|
package/dist/cjs/dem.js
CHANGED
|
@@ -91,18 +91,22 @@ class AesGcm256 {
|
|
|
91
91
|
if (!("Aes256Gcm" in ciphertext)) {
|
|
92
92
|
throw new import_error.InvalidCiphertextError(`Invalid ciphertext ${ciphertext}`);
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
94
|
+
try {
|
|
95
|
+
const aesCryptoKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, ["decrypt"]);
|
|
96
|
+
return new Uint8Array(
|
|
97
|
+
await crypto.subtle.decrypt(
|
|
98
|
+
{
|
|
99
|
+
name: "AES-GCM",
|
|
100
|
+
iv,
|
|
101
|
+
additionalData: new Uint8Array(ciphertext.Aes256Gcm.aad ?? [])
|
|
102
|
+
},
|
|
103
|
+
aesCryptoKey,
|
|
104
|
+
new Uint8Array(ciphertext.Aes256Gcm.blob)
|
|
105
|
+
)
|
|
106
|
+
);
|
|
107
|
+
} catch (e) {
|
|
108
|
+
throw new import_error.DecryptionError(`Decryption failed`);
|
|
109
|
+
}
|
|
106
110
|
}
|
|
107
111
|
}
|
|
108
112
|
class Plain {
|
|
@@ -142,22 +146,22 @@ class Hmac256Ctr {
|
|
|
142
146
|
const blob = new Uint8Array(ciphertext.Hmac256Ctr.blob);
|
|
143
147
|
const mac = Hmac256Ctr.computeMac(key, aad, blob);
|
|
144
148
|
if (!(0, import_utils.equalBytes)(mac, new Uint8Array(ciphertext.Hmac256Ctr.mac))) {
|
|
145
|
-
throw new import_error.
|
|
149
|
+
throw new import_error.DecryptionError(`Invalid MAC ${mac}`);
|
|
146
150
|
}
|
|
147
151
|
return Hmac256Ctr.encryptInCtrMode(key, blob);
|
|
148
152
|
}
|
|
149
153
|
static computeMac(key, aad, ciphertext) {
|
|
150
154
|
const macKey = (0, import_hmac.hmac)(import_sha3.sha3_256, key, MacKeyTag);
|
|
151
|
-
const macInput =
|
|
155
|
+
const macInput = (0, import_utils2.flatten)([toBytes(aad.length), aad, ciphertext]);
|
|
152
156
|
const mac = (0, import_hmac.hmac)(import_sha3.sha3_256, macKey, macInput);
|
|
153
157
|
return mac;
|
|
154
158
|
}
|
|
155
159
|
static encryptInCtrMode(key, msg) {
|
|
156
160
|
const blockSize = 32;
|
|
157
|
-
const result = Uint8Array
|
|
161
|
+
const result = new Uint8Array(msg.length);
|
|
158
162
|
const encryptionKey = (0, import_hmac.hmac)(import_sha3.sha3_256, key, EncryptionKeyTag);
|
|
159
163
|
for (let i = 0; i * blockSize < msg.length; i++) {
|
|
160
|
-
const block = msg.
|
|
164
|
+
const block = msg.subarray(i * blockSize, (i + 1) * blockSize);
|
|
161
165
|
const mask = (0, import_hmac.hmac)(import_sha3.sha3_256, encryptionKey, toBytes(i));
|
|
162
166
|
const encryptedBlock = (0, import_utils2.xorUnchecked)(block, mask);
|
|
163
167
|
result.set(encryptedBlock, i * blockSize);
|
package/dist/cjs/dem.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/dem.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { bcs } from '@mysten/bcs';\nimport { equalBytes } from '@noble/curves/abstract/utils';\nimport { hmac } from '@noble/hashes/hmac';\nimport { sha3_256 } from '@noble/hashes/sha3';\n\nimport type { Ciphertext } from './bcs.js';\nimport { InvalidCiphertextError } from './error.js';\nimport { xorUnchecked } from './utils.js';\n\n// Use a fixed IV for AES.\nexport const iv = Uint8Array.from([\n\t138, 55, 153, 253, 198, 46, 121, 219, 160, 128, 89, 7, 214, 156, 148, 220,\n]);\n\nasync function generateAesKey(): Promise<Uint8Array> {\n\tconst key = await crypto.subtle.generateKey(\n\t\t{\n\t\t\tname: 'AES-GCM',\n\t\t\tlength: 256,\n\t\t},\n\t\ttrue,\n\t\t['encrypt', 'decrypt'],\n\t);\n\treturn await crypto.subtle.exportKey('raw', key).then((keyData) => new Uint8Array(keyData));\n}\n\nexport interface EncryptionInput {\n\tencrypt(key: Uint8Array): Promise<typeof Ciphertext.$inferInput>;\n\tgenerateKey(): Promise<Uint8Array>;\n}\n\nexport class AesGcm256 implements EncryptionInput {\n\treadonly plaintext: Uint8Array;\n\treadonly aad: Uint8Array;\n\n\tconstructor(msg: Uint8Array, aad: Uint8Array) {\n\t\tthis.plaintext = msg;\n\t\tthis.aad = aad;\n\t}\n\n\tgenerateKey(): Promise<Uint8Array> {\n\t\treturn generateAesKey();\n\t}\n\n\tasync encrypt(key: Uint8Array): Promise<typeof Ciphertext.$inferInput> {\n\t\tconst aesCryptoKey = await crypto.subtle.importKey('raw', key, 'AES-GCM', false, ['encrypt']);\n\n\t\tconst blob = new Uint8Array(\n\t\t\tawait crypto.subtle.encrypt(\n\t\t\t\t{\n\t\t\t\t\tname: 'AES-GCM',\n\t\t\t\t\tiv,\n\t\t\t\t\tadditionalData: this.aad,\n\t\t\t\t},\n\t\t\t\taesCryptoKey,\n\t\t\t\tthis.plaintext,\n\t\t\t),\n\t\t);\n\n\t\treturn {\n\t\t\tAes256Gcm: {\n\t\t\t\tblob,\n\t\t\t\taad: this.aad ?? [],\n\t\t\t},\n\t\t};\n\t}\n\n\tstatic async decrypt(\n\t\tkey: Uint8Array,\n\t\tciphertext: typeof Ciphertext.$inferInput,\n\t): Promise<Uint8Array> {\n\t\tif (!('Aes256Gcm' in ciphertext)) {\n\t\t\tthrow new InvalidCiphertextError(`Invalid ciphertext ${ciphertext}`);\n\t\t}\n\n\t\tconst aesCryptoKey = await crypto.subtle.importKey('raw', key, 'AES-GCM', false, ['decrypt']);\n\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAoB;AACpB,mBAA2B;AAC3B,kBAAqB;AACrB,kBAAyB;AAGzB,
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { bcs } from '@mysten/bcs';\nimport { equalBytes } from '@noble/curves/abstract/utils';\nimport { hmac } from '@noble/hashes/hmac';\nimport { sha3_256 } from '@noble/hashes/sha3';\n\nimport type { Ciphertext } from './bcs.js';\nimport { DecryptionError, InvalidCiphertextError } from './error.js';\nimport { flatten, xorUnchecked } from './utils.js';\n\n// Use a fixed IV for AES. This is okay because the key is unique for each message.\nexport const iv = Uint8Array.from([\n\t138, 55, 153, 253, 198, 46, 121, 219, 160, 128, 89, 7, 214, 156, 148, 220,\n]);\n\nasync function generateAesKey(): Promise<Uint8Array> {\n\tconst key = await crypto.subtle.generateKey(\n\t\t{\n\t\t\tname: 'AES-GCM',\n\t\t\tlength: 256,\n\t\t},\n\t\ttrue,\n\t\t['encrypt', 'decrypt'],\n\t);\n\treturn await crypto.subtle.exportKey('raw', key).then((keyData) => new Uint8Array(keyData));\n}\n\nexport interface EncryptionInput {\n\tencrypt(key: Uint8Array): Promise<typeof Ciphertext.$inferInput>;\n\tgenerateKey(): Promise<Uint8Array>;\n}\n\nexport class AesGcm256 implements EncryptionInput {\n\treadonly plaintext: Uint8Array;\n\treadonly aad: Uint8Array;\n\n\tconstructor(msg: Uint8Array, aad: Uint8Array) {\n\t\tthis.plaintext = msg;\n\t\tthis.aad = aad;\n\t}\n\n\tgenerateKey(): Promise<Uint8Array> {\n\t\treturn generateAesKey();\n\t}\n\n\tasync encrypt(key: Uint8Array): Promise<typeof Ciphertext.$inferInput> {\n\t\tconst aesCryptoKey = await crypto.subtle.importKey('raw', key, 'AES-GCM', false, ['encrypt']);\n\n\t\tconst blob = new Uint8Array(\n\t\t\tawait crypto.subtle.encrypt(\n\t\t\t\t{\n\t\t\t\t\tname: 'AES-GCM',\n\t\t\t\t\tiv,\n\t\t\t\t\tadditionalData: this.aad,\n\t\t\t\t},\n\t\t\t\taesCryptoKey,\n\t\t\t\tthis.plaintext,\n\t\t\t),\n\t\t);\n\n\t\treturn {\n\t\t\tAes256Gcm: {\n\t\t\t\tblob,\n\t\t\t\taad: this.aad ?? [],\n\t\t\t},\n\t\t};\n\t}\n\n\tstatic async decrypt(\n\t\tkey: Uint8Array,\n\t\tciphertext: typeof Ciphertext.$inferInput,\n\t): Promise<Uint8Array> {\n\t\tif (!('Aes256Gcm' in ciphertext)) {\n\t\t\tthrow new InvalidCiphertextError(`Invalid ciphertext ${ciphertext}`);\n\t\t}\n\n\t\ttry {\n\t\t\tconst aesCryptoKey = await crypto.subtle.importKey('raw', key, 'AES-GCM', false, ['decrypt']);\n\t\t\treturn new Uint8Array(\n\t\t\t\tawait crypto.subtle.decrypt(\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'AES-GCM',\n\t\t\t\t\t\tiv,\n\t\t\t\t\t\tadditionalData: new Uint8Array(ciphertext.Aes256Gcm.aad ?? []),\n\t\t\t\t\t},\n\t\t\t\t\taesCryptoKey,\n\t\t\t\t\tnew Uint8Array(ciphertext.Aes256Gcm.blob),\n\t\t\t\t),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow new DecryptionError(`Decryption failed`);\n\t\t}\n\t}\n}\n\nexport class Plain implements EncryptionInput {\n\tasync encrypt(_key: Uint8Array): Promise<typeof Ciphertext.$inferInput> {\n\t\treturn {\n\t\t\tPlain: {},\n\t\t};\n\t}\n\n\tgenerateKey(): Promise<Uint8Array> {\n\t\treturn generateAesKey();\n\t}\n}\n\n/**\n * Authenticated encryption using CTR mode with HMAC-SHA3-256 as a PRF.\n * 1. Derive an encryption key, <i>k<sub>1</sub> = <b>hmac</b>(key, 1)</i>.\n * 2. Chunk the message into blocks of 32 bytes, <i>m = m<sub>1</sub> || ... || m<sub>n</sub></i>.\n * 3. Let the ciphertext be defined by <i>c = c<sub>1</sub> || ... || c<sub>n</sub></i> where <i>c<sub>i</sub> = m<sub>i</sub> \u2295 <b>hmac</b>(k<sub>1</sub>, i)</i>.\n * 4. Compute a MAC over the AAD and the ciphertext, <i>mac = <b>hmac</b>(k<sub>2</sub>, aad || c) where k<sub>2</sub> = <b>hmac</b>(key, 2)</i>.\n * 5. Return <i>mac || c</i>.\n */\nexport class Hmac256Ctr implements EncryptionInput {\n\treadonly plaintext: Uint8Array;\n\treadonly aad: Uint8Array;\n\n\tconstructor(msg: Uint8Array, aad: Uint8Array) {\n\t\tthis.plaintext = msg;\n\t\tthis.aad = aad;\n\t}\n\n\tgenerateKey(): Promise<Uint8Array> {\n\t\treturn generateAesKey();\n\t}\n\n\tasync encrypt(key: Uint8Array): Promise<typeof Ciphertext.$inferInput> {\n\t\tconst blob = Hmac256Ctr.encryptInCtrMode(key, this.plaintext);\n\t\tconst mac = Hmac256Ctr.computeMac(key, this.aad, blob);\n\t\treturn {\n\t\t\tHmac256Ctr: {\n\t\t\t\tblob,\n\t\t\t\tmac,\n\t\t\t\taad: this.aad ?? [],\n\t\t\t},\n\t\t};\n\t}\n\n\tstatic async decrypt(\n\t\tkey: Uint8Array,\n\t\tciphertext: typeof Ciphertext.$inferInput,\n\t): Promise<Uint8Array> {\n\t\tif (!('Hmac256Ctr' in ciphertext)) {\n\t\t\tthrow new InvalidCiphertextError(`Invalid ciphertext ${ciphertext}`);\n\t\t}\n\t\tconst aad = new Uint8Array(ciphertext.Hmac256Ctr.aad ?? []);\n\t\tconst blob = new Uint8Array(ciphertext.Hmac256Ctr.blob);\n\t\tconst mac = Hmac256Ctr.computeMac(key, aad, blob);\n\t\tif (!equalBytes(mac, new Uint8Array(ciphertext.Hmac256Ctr.mac))) {\n\t\t\tthrow new DecryptionError(`Invalid MAC ${mac}`);\n\t\t}\n\t\treturn Hmac256Ctr.encryptInCtrMode(key, blob);\n\t}\n\n\tprivate static computeMac(key: Uint8Array, aad: Uint8Array, ciphertext: Uint8Array): Uint8Array {\n\t\tconst macKey = hmac(sha3_256, key, MacKeyTag);\n\t\tconst macInput = flatten([toBytes(aad.length), aad, ciphertext]);\n\t\tconst mac = hmac(sha3_256, macKey, macInput);\n\t\treturn mac;\n\t}\n\n\tprivate static encryptInCtrMode(key: Uint8Array, msg: Uint8Array): Uint8Array {\n\t\tconst blockSize = 32;\n\t\tconst result = new Uint8Array(msg.length);\n\t\tconst encryptionKey = hmac(sha3_256, key, EncryptionKeyTag);\n\t\tfor (let i = 0; i * blockSize < msg.length; i++) {\n\t\t\tconst block = msg.subarray(i * blockSize, (i + 1) * blockSize);\n\t\t\tconst mask = hmac(sha3_256, encryptionKey, toBytes(i));\n\t\t\tconst encryptedBlock = xorUnchecked(block, mask);\n\t\t\tresult.set(encryptedBlock, i * blockSize);\n\t\t}\n\t\treturn result;\n\t}\n}\n\n/**\n * Convert a u64 to bytes using little-endian representation.\n */\nfunction toBytes(n: number): Uint8Array {\n\treturn bcs.u64().serialize(n).toBytes();\n}\n\nconst EncryptionKeyTag = new Uint8Array([1]);\nconst MacKeyTag = new Uint8Array([2]);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_utils"]
|
|
7
7
|
}
|
package/dist/cjs/elgamal.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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
4
|
*/
|
|
5
|
-
export declare function elgamalDecrypt(sk: Uint8Array,
|
|
5
|
+
export declare function elgamalDecrypt(sk: Uint8Array, [c0, c1]: [Uint8Array, Uint8Array]): Uint8Array;
|
|
6
6
|
/** Generate a random secret key. */
|
|
7
7
|
export declare function generateSecretKey(): Uint8Array;
|
|
8
8
|
/** Derive the BLS public key for a given secret key. */
|
package/dist/cjs/elgamal.js
CHANGED
|
@@ -25,14 +25,14 @@ __export(elgamal_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(elgamal_exports);
|
|
27
27
|
var import_bls12381 = require("./bls12381.js");
|
|
28
|
-
function elgamalDecrypt(sk,
|
|
28
|
+
function elgamalDecrypt(sk, [c0, c1]) {
|
|
29
29
|
return decrypt(import_bls12381.Scalar.fromBytes(sk), [
|
|
30
|
-
import_bls12381.G1Element.fromBytes(
|
|
31
|
-
import_bls12381.G1Element.fromBytes(
|
|
30
|
+
import_bls12381.G1Element.fromBytes(c0),
|
|
31
|
+
import_bls12381.G1Element.fromBytes(c1)
|
|
32
32
|
]).toBytes();
|
|
33
33
|
}
|
|
34
|
-
function decrypt(sk,
|
|
35
|
-
return
|
|
34
|
+
function decrypt(sk, [c0, c1]) {
|
|
35
|
+
return c1.subtract(c0.multiply(sk));
|
|
36
36
|
}
|
|
37
37
|
function generateSecretKey() {
|
|
38
38
|
return import_bls12381.Scalar.random().toBytes();
|
package/dist/cjs/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,
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,sBAA6C;AAMtC,SAAS,eAAe,IAAgB,
|
|
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 {\n\treturn Scalar.random().toBytes();\n}\n\n/** Derive the BLS public key for a given secret key. */\nexport function toPublicKey(sk: Uint8Array): Uint8Array {\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): Uint8Array {\n\treturn G2Element.generator().multiply(Scalar.fromBytes(sk)).toBytes();\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,sBAA6C;AAMtC,SAAS,eAAe,IAAgB,CAAC,IAAI,EAAE,GAAyC;AAC9F,SAAO,QAAQ,uBAAO,UAAU,EAAE,GAAG;AAAA,IACpC,0BAAU,UAAU,EAAE;AAAA,IACtB,0BAAU,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,oBAAgC;AAC/C,SAAO,uBAAO,OAAO,EAAE,QAAQ;AAChC;AAGO,SAAS,YAAY,IAA4B;AACvD,SAAO,0BAAU,UAAU,EAAE,SAAS,uBAAO,UAAU,EAAE,CAAC,EAAE,QAAQ;AACrE;AAGO,SAAS,kBAAkB,IAA4B;AAC7D,SAAO,0BAAU,UAAU,EAAE,SAAS,uBAAO,UAAU,EAAE,CAAC,EAAE,QAAQ;AACrE;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/encrypt.js
CHANGED
|
@@ -46,11 +46,10 @@ async function encrypt({
|
|
|
46
46
|
`Invalid key servers or threshold ${threshold} for ${keyServers.length} key servers for package ${packageId}`
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
const ciphertext = await encryptionInput.encrypt(demKey);
|
|
52
|
-
const shares = await split(key, keyServers.length, threshold);
|
|
49
|
+
const baseKey = await encryptionInput.generateKey();
|
|
50
|
+
const shares = await split(baseKey, keyServers.length, threshold);
|
|
53
51
|
const fullId = (0, import_utils2.createFullId)(import_ibe.DST, packageId, id);
|
|
52
|
+
const randomnessKey = (0, import_kdf.deriveKey)(import_kdf.KeyPurpose.EncryptedRandomness, baseKey);
|
|
54
53
|
const encryptedShares = encryptBatched(
|
|
55
54
|
keyServers,
|
|
56
55
|
kemType,
|
|
@@ -59,10 +58,12 @@ async function encrypt({
|
|
|
59
58
|
msg: share,
|
|
60
59
|
index
|
|
61
60
|
})),
|
|
62
|
-
|
|
61
|
+
randomnessKey
|
|
63
62
|
);
|
|
64
|
-
const
|
|
65
|
-
|
|
63
|
+
const demKey = (0, import_kdf.deriveKey)(import_kdf.KeyPurpose.DEM, baseKey);
|
|
64
|
+
const ciphertext = await encryptionInput.encrypt(demKey);
|
|
65
|
+
const services = keyServers.map(({ objectId }, i) => [
|
|
66
|
+
objectId,
|
|
66
67
|
shares[i].index
|
|
67
68
|
]);
|
|
68
69
|
return {
|
|
@@ -87,30 +88,27 @@ var DemType = /* @__PURE__ */ ((DemType2) => {
|
|
|
87
88
|
DemType2[DemType2["Hmac256Ctr"] = 1] = "Hmac256Ctr";
|
|
88
89
|
return DemType2;
|
|
89
90
|
})(DemType || {});
|
|
90
|
-
function encryptBatched(keyServers, kemType, id,
|
|
91
|
+
function encryptBatched(keyServers, kemType, id, msgs, randomnessKey) {
|
|
91
92
|
switch (kemType) {
|
|
92
93
|
case 0 /* BonehFranklinBLS12381DemCCA */:
|
|
93
|
-
return new import_ibe.BonehFranklinBLS12381Services(keyServers).encryptBatched(
|
|
94
|
-
id,
|
|
95
|
-
shares,
|
|
96
|
-
randomnessKey
|
|
97
|
-
);
|
|
94
|
+
return new import_ibe.BonehFranklinBLS12381Services(keyServers).encryptBatched(id, msgs, randomnessKey);
|
|
98
95
|
}
|
|
99
96
|
}
|
|
100
97
|
async function split(secret, n, threshold) {
|
|
101
98
|
if (n === 0 || threshold === 0 || threshold > n) {
|
|
102
99
|
throw new Error("Invalid threshold or number of shares");
|
|
103
100
|
} else if (threshold === 1) {
|
|
101
|
+
const share = secret;
|
|
104
102
|
const result = [];
|
|
105
|
-
for (let
|
|
106
|
-
result.push({ share
|
|
103
|
+
for (let index = 1; index <= n; index++) {
|
|
104
|
+
result.push({ share, index });
|
|
107
105
|
}
|
|
108
106
|
return Promise.resolve(result);
|
|
109
107
|
}
|
|
110
108
|
return (0, import_shamir_secret_sharing.split)(secret, n, threshold).then(
|
|
111
109
|
(share) => share.map((s) => ({
|
|
112
110
|
share: s.subarray(0, s.length - 1),
|
|
113
|
-
// split() returns the share index in the last byte
|
|
111
|
+
// split() returns the share index in the last byte. See https://github.com/privy-io/shamir-secret-sharing/blob/b59534d03e66d44ae36fc074aaf0684aa39c7505/src/index.ts#L247.
|
|
114
112
|
index: s[s.length - 1]
|
|
115
113
|
}))
|
|
116
114
|
);
|
package/dist/cjs/encrypt.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/encrypt.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\nimport { isValidSuiObjectId } from '@mysten/sui/utils';\nimport { split as externalSplit } from 'shamir-secret-sharing';\n\nimport type { IBEEncryptions } from './bcs.js';\nimport { EncryptedObject } from './bcs.js';\nimport type { EncryptionInput } from './dem.js';\nimport { UserError } from './error.js';\nimport { BonehFranklinBLS12381Services, DST } from './ibe.js';\nimport { deriveKey, KeyPurpose } from './kdf.js';\nimport type { KeyServer } from './key-server.js';\nimport { createFullId } from './utils.js';\n\nexport const MAX_U8 = 255;\n\n/**\n * Given full ID and what key servers to use, return the encrypted message under the identity and return the bcs bytes of the encrypted object.\n *\n * @param keyServers - A list of KeyServers (same server can be used multiple times)\n * @param kemType - The type of KEM to use.\n * @param packageId - packageId\n * @param id - id\n * @param encryptionInput - Input to the encryption. Should be one of the EncryptionInput types, AesGcmEncryptionInput or Plain.\n * @param threshold - The threshold for the TSS encryption.\n * @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 * Since the key can be used to decrypt, it should not be shared but can be used eg. for backup.\n */\nexport async function encrypt({\n\tkeyServers,\n\tkemType,\n\tthreshold,\n\tpackageId,\n\tid,\n\tencryptionInput,\n}: {\n\tkeyServers: KeyServer[];\n\tkemType: KemType;\n\tthreshold: number;\n\tpackageId: string;\n\tid: string;\n\tencryptionInput: EncryptionInput;\n}): Promise<{\n\tencryptedObject: Uint8Array;\n\tkey: Uint8Array;\n}> {\n\t// Check inputs\n\tif (\n\t\tkeyServers.length < threshold ||\n\t\tthreshold === 0 ||\n\t\tkeyServers.length > MAX_U8 ||\n\t\tthreshold > MAX_U8 ||\n\t\t!isValidSuiObjectId(packageId)\n\t) {\n\t\tthrow new UserError(\n\t\t\t`Invalid key servers or threshold ${threshold} for ${keyServers.length} key servers for package ${packageId}`,\n\t\t);\n\t}\n\n\t// Generate a random
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAwB;AACxB,mBAAmC;AACnC,mCAAuC;AAGvC,IAAAA,cAAgC;AAEhC,mBAA0B;AAC1B,iBAAmD;AACnD,iBAAsC;AAEtC,IAAAC,gBAA6B;AAEtB,MAAM,SAAS;AActB,eAAsB,QAAQ;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAUG;AAEF,MACC,WAAW,SAAS,aACpB,cAAc,KACd,WAAW,SAAS,UACpB,YAAY,UACZ,KAAC,iCAAmB,SAAS,GAC5B;AACD,UAAM,IAAI;AAAA,MACT,oCAAoC,SAAS,QAAQ,WAAW,MAAM,4BAA4B,SAAS;AAAA,IAC5G;AAAA,EACD;AAGA,QAAM,
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromHex } from '@mysten/bcs';\nimport { isValidSuiObjectId } from '@mysten/sui/utils';\nimport { split as externalSplit } from 'shamir-secret-sharing';\n\nimport type { IBEEncryptions } from './bcs.js';\nimport { EncryptedObject } from './bcs.js';\nimport type { EncryptionInput } from './dem.js';\nimport { UserError } from './error.js';\nimport { BonehFranklinBLS12381Services, DST } from './ibe.js';\nimport { deriveKey, KeyPurpose } from './kdf.js';\nimport type { KeyServer } from './key-server.js';\nimport { createFullId } from './utils.js';\n\nexport const MAX_U8 = 255;\n\n/**\n * Given full ID and what key servers to use, return the encrypted message under the identity and return the bcs bytes of the encrypted object.\n *\n * @param keyServers - A list of KeyServers (same server can be used multiple times)\n * @param kemType - The type of KEM to use.\n * @param packageId - packageId\n * @param id - id\n * @param encryptionInput - Input to the encryption. Should be one of the EncryptionInput types, AesGcmEncryptionInput or Plain.\n * @param threshold - The threshold for the TSS encryption.\n * @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 * Since the key can be used to decrypt, it should not be shared but can be used eg. for backup.\n */\nexport async function encrypt({\n\tkeyServers,\n\tkemType,\n\tthreshold,\n\tpackageId,\n\tid,\n\tencryptionInput,\n}: {\n\tkeyServers: KeyServer[];\n\tkemType: KemType;\n\tthreshold: number;\n\tpackageId: string;\n\tid: string;\n\tencryptionInput: EncryptionInput;\n}): Promise<{\n\tencryptedObject: Uint8Array;\n\tkey: Uint8Array;\n}> {\n\t// Check inputs\n\tif (\n\t\tkeyServers.length < threshold ||\n\t\tthreshold === 0 ||\n\t\tkeyServers.length > MAX_U8 ||\n\t\tthreshold > MAX_U8 ||\n\t\t!isValidSuiObjectId(packageId)\n\t) {\n\t\tthrow new UserError(\n\t\t\t`Invalid key servers or threshold ${threshold} for ${keyServers.length} key servers for package ${packageId}`,\n\t\t);\n\t}\n\n\t// Generate a random base key.\n\tconst baseKey = await encryptionInput.generateKey();\n\n\t// Split the key into shares and encrypt each share with the public keys of the key servers.\n\tconst shares = await split(baseKey, keyServers.length, threshold);\n\n\t// Encrypt the shares with the public keys of the key servers.\n\tconst fullId = createFullId(DST, packageId, id);\n\tconst randomnessKey = deriveKey(KeyPurpose.EncryptedRandomness, baseKey);\n\tconst encryptedShares = encryptBatched(\n\t\tkeyServers,\n\t\tkemType,\n\t\tfromHex(fullId),\n\t\tshares.map(({ share, index }) => ({\n\t\t\tmsg: share,\n\t\t\tindex,\n\t\t})),\n\t\trandomnessKey,\n\t);\n\n\t// Encrypt the object with the derived DEM key.\n\tconst demKey = deriveKey(KeyPurpose.DEM, baseKey);\n\tconst ciphertext = await encryptionInput.encrypt(demKey);\n\n\t// Services and indices of their shares are stored as a tuple\n\tconst services: [string, number][] = keyServers.map(({ objectId }, i) => [\n\t\tobjectId,\n\t\tshares[i].index,\n\t]);\n\n\treturn {\n\t\tencryptedObject: EncryptedObject.serialize({\n\t\t\tversion: 0,\n\t\t\tpackageId,\n\t\t\tid,\n\t\t\tservices,\n\t\t\tthreshold,\n\t\t\tencryptedShares,\n\t\t\tciphertext,\n\t\t}).toBytes(),\n\t\tkey: demKey,\n\t};\n}\n\nexport enum KemType {\n\tBonehFranklinBLS12381DemCCA = 0,\n}\n\nexport enum DemType {\n\tAesGcm256 = 0,\n\tHmac256Ctr = 1,\n}\n\nfunction encryptBatched(\n\tkeyServers: KeyServer[],\n\tkemType: KemType,\n\tid: Uint8Array,\n\tmsgs: { msg: Uint8Array; index: number }[],\n\trandomnessKey: Uint8Array,\n): typeof IBEEncryptions.$inferType {\n\tswitch (kemType) {\n\t\tcase KemType.BonehFranklinBLS12381DemCCA:\n\t\t\treturn new BonehFranklinBLS12381Services(keyServers).encryptBatched(id, msgs, randomnessKey);\n\t}\n}\n\nasync function split(\n\tsecret: Uint8Array,\n\tn: number,\n\tthreshold: number,\n): Promise<{ index: number; share: Uint8Array }[]> {\n\t// The externalSplit function is from the 'shamir-secret-sharing' package and requires t > 1 and n >= 2.\n\t// So we handle the special cases here.\n\tif (n === 0 || threshold === 0 || threshold > n) {\n\t\tthrow new Error('Invalid threshold or number of shares');\n\t} else if (threshold === 1) {\n\t\t// If the threshold is 1, the secret is not split.\n\t\tconst share = secret;\n\n\t\tconst result = [];\n\t\tfor (let index = 1; index <= n; index++) {\n\t\t\t// The shared polynomial is a constant in this case, so the index doesn't matter.\n\t\t\t// To make sure they are unique, we use a counter.\n\t\t\tresult.push({ share, index });\n\t\t}\n\t\treturn Promise.resolve(result);\n\t}\n\n\treturn externalSplit(secret, n, threshold).then((share) =>\n\t\tshare.map((s) => ({\n\t\t\tshare: s.subarray(0, s.length - 1),\n\t\t\t// split() returns the share index in the last byte. See https://github.com/privy-io/shamir-secret-sharing/blob/b59534d03e66d44ae36fc074aaf0684aa39c7505/src/index.ts#L247.\n\t\t\tindex: s[s.length - 1],\n\t\t})),\n\t);\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAwB;AACxB,mBAAmC;AACnC,mCAAuC;AAGvC,IAAAA,cAAgC;AAEhC,mBAA0B;AAC1B,iBAAmD;AACnD,iBAAsC;AAEtC,IAAAC,gBAA6B;AAEtB,MAAM,SAAS;AActB,eAAsB,QAAQ;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAUG;AAEF,MACC,WAAW,SAAS,aACpB,cAAc,KACd,WAAW,SAAS,UACpB,YAAY,UACZ,KAAC,iCAAmB,SAAS,GAC5B;AACD,UAAM,IAAI;AAAA,MACT,oCAAoC,SAAS,QAAQ,WAAW,MAAM,4BAA4B,SAAS;AAAA,IAC5G;AAAA,EACD;AAGA,QAAM,UAAU,MAAM,gBAAgB,YAAY;AAGlD,QAAM,SAAS,MAAM,MAAM,SAAS,WAAW,QAAQ,SAAS;AAGhE,QAAM,aAAS,4BAAa,gBAAK,WAAW,EAAE;AAC9C,QAAM,oBAAgB,sBAAU,sBAAW,qBAAqB,OAAO;AACvE,QAAM,kBAAkB;AAAA,IACvB;AAAA,IACA;AAAA,QACA,oBAAQ,MAAM;AAAA,IACd,OAAO,IAAI,CAAC,EAAE,OAAO,MAAM,OAAO;AAAA,MACjC,KAAK;AAAA,MACL;AAAA,IACD,EAAE;AAAA,IACF;AAAA,EACD;AAGA,QAAM,aAAS,sBAAU,sBAAW,KAAK,OAAO;AAChD,QAAM,aAAa,MAAM,gBAAgB,QAAQ,MAAM;AAGvD,QAAM,WAA+B,WAAW,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM;AAAA,IACxE;AAAA,IACA,OAAO,CAAC,EAAE;AAAA,EACX,CAAC;AAED,SAAO;AAAA,IACN,iBAAiB,4BAAgB,UAAU;AAAA,MAC1C,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAC,EAAE,QAAQ;AAAA,IACX,KAAK;AAAA,EACN;AACD;AAEO,IAAK,UAAL,kBAAKC,aAAL;AACN,EAAAA,kBAAA,iCAA8B,KAA9B;AADW,SAAAA;AAAA,GAAA;AAIL,IAAK,UAAL,kBAAKC,aAAL;AACN,EAAAA,kBAAA,eAAY,KAAZ;AACA,EAAAA,kBAAA,gBAAa,KAAb;AAFW,SAAAA;AAAA,GAAA;AAKZ,SAAS,eACR,YACA,SACA,IACA,MACA,eACmC;AACnC,UAAQ,SAAS;AAAA,IAChB,KAAK;AACJ,aAAO,IAAI,yCAA8B,UAAU,EAAE,eAAe,IAAI,MAAM,aAAa;AAAA,EAC7F;AACD;AAEA,eAAe,MACd,QACA,GACA,WACkD;AAGlD,MAAI,MAAM,KAAK,cAAc,KAAK,YAAY,GAAG;AAChD,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACxD,WAAW,cAAc,GAAG;AAE3B,UAAM,QAAQ;AAEd,UAAM,SAAS,CAAC;AAChB,aAAS,QAAQ,GAAG,SAAS,GAAG,SAAS;AAGxC,aAAO,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,IAC7B;AACA,WAAO,QAAQ,QAAQ,MAAM;AAAA,EAC9B;AAEA,aAAO,6BAAAC,OAAc,QAAQ,GAAG,SAAS,EAAE;AAAA,IAAK,CAAC,UAChD,MAAM,IAAI,CAAC,OAAO;AAAA,MACjB,OAAO,EAAE,SAAS,GAAG,EAAE,SAAS,CAAC;AAAA;AAAA,MAEjC,OAAO,EAAE,EAAE,SAAS,CAAC;AAAA,IACtB,EAAE;AAAA,EACH;AACD;",
|
|
6
6
|
"names": ["import_bcs", "import_utils", "KemType", "DemType", "externalSplit"]
|
|
7
7
|
}
|
package/dist/cjs/error.d.ts
CHANGED
|
@@ -63,4 +63,10 @@ export declare class InvalidThresholdError extends UserError {
|
|
|
63
63
|
}
|
|
64
64
|
export declare class InconsistentKeyServersError extends UserError {
|
|
65
65
|
}
|
|
66
|
+
export declare class DecryptionError extends UserError {
|
|
67
|
+
}
|
|
68
|
+
export declare class InvalidClientOptionsError extends UserError {
|
|
69
|
+
}
|
|
70
|
+
export declare class TooManyFailedFetchKeyRequestsError extends UserError {
|
|
71
|
+
}
|
|
66
72
|
export declare function toMajorityError(errors: Error[]): Error;
|
package/dist/cjs/error.js
CHANGED
|
@@ -24,12 +24,14 @@ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot
|
|
|
24
24
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
25
25
|
var error_exports = {};
|
|
26
26
|
__export(error_exports, {
|
|
27
|
+
DecryptionError: () => DecryptionError,
|
|
27
28
|
DeprecatedSDKVersionError: () => DeprecatedSDKVersionError,
|
|
28
29
|
ExpiredSessionKeyError: () => ExpiredSessionKeyError,
|
|
29
30
|
GeneralError: () => GeneralError,
|
|
30
31
|
InconsistentKeyServersError: () => InconsistentKeyServersError,
|
|
31
32
|
InternalError: () => InternalError,
|
|
32
33
|
InvalidCiphertextError: () => InvalidCiphertextError,
|
|
34
|
+
InvalidClientOptionsError: () => InvalidClientOptionsError,
|
|
33
35
|
InvalidGetObjectError: () => InvalidGetObjectError,
|
|
34
36
|
InvalidKeyServerError: () => InvalidKeyServerError,
|
|
35
37
|
InvalidKeyServerVersionError: () => InvalidKeyServerVersionError,
|
|
@@ -44,6 +46,7 @@ __export(error_exports, {
|
|
|
44
46
|
OldPackageError: () => OldPackageError,
|
|
45
47
|
SealAPIError: () => SealAPIError,
|
|
46
48
|
SealError: () => SealError,
|
|
49
|
+
TooManyFailedFetchKeyRequestsError: () => TooManyFailedFetchKeyRequestsError,
|
|
47
50
|
UnsupportedFeatureError: () => UnsupportedFeatureError,
|
|
48
51
|
UnsupportedNetworkError: () => UnsupportedNetworkError,
|
|
49
52
|
UserError: () => UserError,
|
|
@@ -177,6 +180,12 @@ class InvalidThresholdError extends UserError {
|
|
|
177
180
|
}
|
|
178
181
|
class InconsistentKeyServersError extends UserError {
|
|
179
182
|
}
|
|
183
|
+
class DecryptionError extends UserError {
|
|
184
|
+
}
|
|
185
|
+
class InvalidClientOptionsError extends UserError {
|
|
186
|
+
}
|
|
187
|
+
class TooManyFailedFetchKeyRequestsError extends UserError {
|
|
188
|
+
}
|
|
180
189
|
function toMajorityError(errors) {
|
|
181
190
|
let maxCount = 0;
|
|
182
191
|
let majorityError = errors[0];
|
package/dist/cjs/error.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/error.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nexport class SealError extends Error {}\n\nexport class UserError extends SealError {}\n\n// Errors returned by the Seal server\nexport class SealAPIError extends SealError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic requestId?: string,\n\t\tpublic status?: number,\n\t) {\n\t\tsuper(message);\n\t}\n\n\tstatic #generate(error: string, message: string, requestId: string, status?: number) {\n\t\tswitch (error) {\n\t\t\tcase 'InvalidPTB':\n\t\t\t\treturn new InvalidPTBError(requestId, message);\n\t\t\tcase 'InvalidPackage':\n\t\t\t\treturn new InvalidPackageError(requestId);\n\t\t\tcase 'NoAccess':\n\t\t\t\treturn new NoAccessError(requestId);\n\t\t\tcase 'InvalidCertificate':\n\t\t\t\treturn new ExpiredSessionKeyError(requestId);\n\t\t\tcase 'OldPackageVersion':\n\t\t\t\treturn new OldPackageError(requestId);\n\t\t\tcase 'InvalidSignature':\n\t\t\t\treturn new InvalidUserSignatureError(requestId);\n\t\t\tcase 'InvalidSessionSignature':\n\t\t\t\treturn new InvalidSessionKeySignatureError(requestId);\n\t\t\tcase 'InvalidSDKVersion':\n\t\t\t\treturn new InvalidSDKVersionError(requestId);\n\t\t\tcase 'DeprecatedSDKVersion':\n\t\t\t\treturn new DeprecatedSDKVersionError(requestId);\n\t\t\tcase 'Failure':\n\t\t\t\treturn new InternalError(requestId);\n\t\t\tdefault:\n\t\t\t\treturn new GeneralError(message, requestId, status);\n\t\t}\n\t}\n\n\tstatic async assertResponse(response: Response, requestId: string) {\n\t\tif (response.ok) {\n\t\t\treturn;\n\t\t}\n\t\tlet errorInstance: SealAPIError;\n\t\ttry {\n\t\t\tconst text = await response.text();\n\t\t\tconst error = JSON.parse(text)['error'];\n\t\t\tconst message = JSON.parse(text)['message'];\n\t\t\terrorInstance = SealAPIError.#generate(error, message, requestId);\n\t\t} catch (e) {\n\t\t\t// If we can't parse the response as JSON or if it doesn't have the expected format,\n\t\t\t// fall back to using the status text\n\t\t\terrorInstance = new GeneralError(response.statusText, requestId, response.status);\n\t\t}\n\t\tthrow errorInstance;\n\t}\n}\n\n// Errors returned by the Seal server that indicate that the PTB is invalid\n\nexport class InvalidPTBError extends SealAPIError {\n\tconstructor(requestId?: string, message?: string) {\n\t\tsuper('PTB does not conform to the expected format ' + message, requestId);\n\t}\n}\n\nexport class InvalidPackageError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('Package ID used in PTB is invalid', requestId);\n\t}\n}\n\nexport class OldPackageError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('PTB must call the latest version of the package', requestId);\n\t}\n}\n\n// Errors returned by the Seal server that indicate that the user's signature is invalid\n\nexport class InvalidUserSignatureError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('User signature on the session key is invalid', requestId);\n\t}\n}\n\nexport class InvalidSessionKeySignatureError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('Session key signature is invalid', requestId);\n\t}\n}\n\n// Errors returned by the Seal server that indicate that the SDK version is invalid (implying that HTTP headers used by the SDK are being removed) or deprecated (implying that the SDK should be upgraded).\n\nexport class InvalidSDKVersionError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('SDK version is invalid', requestId);\n\t}\n}\n\nexport class DeprecatedSDKVersionError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('SDK version is deprecated', requestId);\n\t}\n}\n\n/** Server error indicating that the user does not have access to one or more of the requested keys */\nexport class NoAccessError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('User does not have access to one or more of the requested keys', requestId);\n\t}\n}\n\n/** Server error indicating that the session key has expired */\nexport class ExpiredSessionKeyError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('Session key has expired', requestId);\n\t}\n}\n\n/** Internal server error, caller should retry */\nexport class InternalError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('Internal server error, caller should retry', requestId);\n\t}\n}\n\n/** General server errors that are not specific to the Seal API (e.g., 404 \"Not Found\") */\nexport class GeneralError extends SealAPIError {}\n\n// Errors returned by the SDK\nexport class InvalidPersonalMessageSignatureError extends UserError {}\nexport class InvalidGetObjectError extends UserError {}\nexport class UnsupportedFeatureError extends UserError {}\nexport class UnsupportedNetworkError extends UserError {}\nexport class InvalidKeyServerError extends UserError {}\nexport class InvalidKeyServerVersionError extends UserError {}\nexport class InvalidCiphertextError extends UserError {}\nexport class InvalidThresholdError extends UserError {}\nexport class InconsistentKeyServersError extends UserError {}\n\nexport function toMajorityError(errors: Error[]): Error {\n\tlet maxCount = 0;\n\tlet majorityError = errors[0];\n\tconst counts = new Map<string, number>();\n\tfor (const error of errors) {\n\t\tconst errorName = error.constructor.name;\n\t\tconst newCount = (counts.get(errorName) || 0) + 1;\n\t\tcounts.set(errorName, newCount);\n\n\t\tif (newCount > maxCount) {\n\t\t\tmaxCount = newCount;\n\t\t\tmajorityError = error;\n\t\t}\n\t}\n\n\treturn majorityError;\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nexport class SealError extends Error {}\n\nexport class UserError extends SealError {}\n\n// Errors returned by the Seal server\nexport class SealAPIError extends SealError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic requestId?: string,\n\t\tpublic status?: number,\n\t) {\n\t\tsuper(message);\n\t}\n\n\tstatic #generate(error: string, message: string, requestId: string, status?: number) {\n\t\tswitch (error) {\n\t\t\tcase 'InvalidPTB':\n\t\t\t\treturn new InvalidPTBError(requestId, message);\n\t\t\tcase 'InvalidPackage':\n\t\t\t\treturn new InvalidPackageError(requestId);\n\t\t\tcase 'NoAccess':\n\t\t\t\treturn new NoAccessError(requestId);\n\t\t\tcase 'InvalidCertificate':\n\t\t\t\treturn new ExpiredSessionKeyError(requestId);\n\t\t\tcase 'OldPackageVersion':\n\t\t\t\treturn new OldPackageError(requestId);\n\t\t\tcase 'InvalidSignature':\n\t\t\t\treturn new InvalidUserSignatureError(requestId);\n\t\t\tcase 'InvalidSessionSignature':\n\t\t\t\treturn new InvalidSessionKeySignatureError(requestId);\n\t\t\tcase 'InvalidSDKVersion':\n\t\t\t\treturn new InvalidSDKVersionError(requestId);\n\t\t\tcase 'DeprecatedSDKVersion':\n\t\t\t\treturn new DeprecatedSDKVersionError(requestId);\n\t\t\tcase 'Failure':\n\t\t\t\treturn new InternalError(requestId);\n\t\t\tdefault:\n\t\t\t\treturn new GeneralError(message, requestId, status);\n\t\t}\n\t}\n\n\tstatic async assertResponse(response: Response, requestId: string) {\n\t\tif (response.ok) {\n\t\t\treturn;\n\t\t}\n\t\tlet errorInstance: SealAPIError;\n\t\ttry {\n\t\t\tconst text = await response.text();\n\t\t\tconst error = JSON.parse(text)['error'];\n\t\t\tconst message = JSON.parse(text)['message'];\n\t\t\terrorInstance = SealAPIError.#generate(error, message, requestId);\n\t\t} catch (e) {\n\t\t\t// If we can't parse the response as JSON or if it doesn't have the expected format,\n\t\t\t// fall back to using the status text\n\t\t\terrorInstance = new GeneralError(response.statusText, requestId, response.status);\n\t\t}\n\t\tthrow errorInstance;\n\t}\n}\n\n// Errors returned by the Seal server that indicate that the PTB is invalid\n\nexport class InvalidPTBError extends SealAPIError {\n\tconstructor(requestId?: string, message?: string) {\n\t\tsuper('PTB does not conform to the expected format ' + message, requestId);\n\t}\n}\n\nexport class InvalidPackageError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('Package ID used in PTB is invalid', requestId);\n\t}\n}\n\nexport class OldPackageError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('PTB must call the latest version of the package', requestId);\n\t}\n}\n\n// Errors returned by the Seal server that indicate that the user's signature is invalid\n\nexport class InvalidUserSignatureError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('User signature on the session key is invalid', requestId);\n\t}\n}\n\nexport class InvalidSessionKeySignatureError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('Session key signature is invalid', requestId);\n\t}\n}\n\n// Errors returned by the Seal server that indicate that the SDK version is invalid (implying that HTTP headers used by the SDK are being removed) or deprecated (implying that the SDK should be upgraded).\n\nexport class InvalidSDKVersionError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('SDK version is invalid', requestId);\n\t}\n}\n\nexport class DeprecatedSDKVersionError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('SDK version is deprecated', requestId);\n\t}\n}\n\n/** Server error indicating that the user does not have access to one or more of the requested keys */\nexport class NoAccessError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('User does not have access to one or more of the requested keys', requestId);\n\t}\n}\n\n/** Server error indicating that the session key has expired */\nexport class ExpiredSessionKeyError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('Session key has expired', requestId);\n\t}\n}\n\n/** Internal server error, caller should retry */\nexport class InternalError extends SealAPIError {\n\tconstructor(requestId?: string) {\n\t\tsuper('Internal server error, caller should retry', requestId);\n\t}\n}\n\n/** General server errors that are not specific to the Seal API (e.g., 404 \"Not Found\") */\nexport class GeneralError extends SealAPIError {}\n\n// Errors returned by the SDK\nexport class InvalidPersonalMessageSignatureError extends UserError {}\nexport class InvalidGetObjectError extends UserError {}\nexport class UnsupportedFeatureError extends UserError {}\nexport class UnsupportedNetworkError extends UserError {}\nexport class InvalidKeyServerError extends UserError {}\nexport class InvalidKeyServerVersionError extends UserError {}\nexport class InvalidCiphertextError extends UserError {}\nexport class InvalidThresholdError extends UserError {}\nexport class InconsistentKeyServersError extends UserError {}\nexport class DecryptionError extends UserError {}\nexport class InvalidClientOptionsError extends UserError {}\nexport class TooManyFailedFetchKeyRequestsError extends UserError {}\n\nexport function toMajorityError(errors: Error[]): Error {\n\tlet maxCount = 0;\n\tlet majorityError = errors[0];\n\tconst counts = new Map<string, number>();\n\tfor (const error of errors) {\n\t\tconst errorName = error.constructor.name;\n\t\tconst newCount = (counts.get(errorName) || 0) + 1;\n\t\tcounts.set(errorName, newCount);\n\n\t\tif (newCount > maxCount) {\n\t\t\tmaxCount = newCount;\n\t\t\tmajorityError = error;\n\t\t}\n\t}\n\n\treturn majorityError;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/ibe.d.ts
CHANGED
|
@@ -32,7 +32,9 @@ export declare abstract class IBEServers {
|
|
|
32
32
|
}[], randomnessKey: Uint8Array): typeof IBEEncryptions.$inferType;
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
* Identity-based encryption based on the Boneh-Franklin IBE scheme.
|
|
35
|
+
* Identity-based encryption based on the Boneh-Franklin IBE scheme (https://eprint.iacr.org/2001/090).
|
|
36
|
+
* 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.
|
|
37
|
+
*
|
|
36
38
|
* This object represents a set of key servers that can be used to encrypt messages for a given identity.
|
|
37
39
|
*/
|
|
38
40
|
export declare class BonehFranklinBLS12381Services extends IBEServers {
|
package/dist/cjs/ibe.js
CHANGED
|
@@ -52,7 +52,7 @@ class BonehFranklinBLS12381Services extends IBEServers {
|
|
|
52
52
|
}
|
|
53
53
|
const [r, nonce, keys] = encapBatched(this.publicKeys, id);
|
|
54
54
|
const encryptedShares = msgAndIndices.map(
|
|
55
|
-
(
|
|
55
|
+
({ msg, index }, i) => (0, import_utils.xor)(msg, (0, import_kdf.kdf)(keys[i], nonce, id, this.objectIds[i], index))
|
|
56
56
|
);
|
|
57
57
|
const encryptedRandomness = (0, import_utils.xor)(randomnessKey, r.toBytes());
|
|
58
58
|
return {
|
|
@@ -72,9 +72,9 @@ class BonehFranklinBLS12381Services extends IBEServers {
|
|
|
72
72
|
* @returns True if the user secret key is valid for the given public key and id.
|
|
73
73
|
*/
|
|
74
74
|
static verifyUserSecretKey(userSecretKey, id, publicKey) {
|
|
75
|
-
const lhs = userSecretKey.pairing(import_bls12381.G2Element.generator())
|
|
76
|
-
const rhs = import_bls12381.G1Element.hashToCurve((0, import_bcs.fromHex)(id)).pairing(publicKey)
|
|
77
|
-
return lhs.
|
|
75
|
+
const lhs = userSecretKey.pairing(import_bls12381.G2Element.generator());
|
|
76
|
+
const rhs = import_bls12381.G1Element.hashToCurve((0, import_bcs.fromHex)(id)).pairing(publicKey);
|
|
77
|
+
return lhs.equals(rhs);
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
80
|
* Identity-based decryption.
|