@mysten/seal 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +4 -0
  3. package/dist/cjs/aes.d.ts +18 -0
  4. package/dist/cjs/aes.js +111 -0
  5. package/dist/cjs/aes.js.map +7 -0
  6. package/dist/cjs/bls12381.d.ts +37 -0
  7. package/dist/cjs/bls12381.js +110 -0
  8. package/dist/cjs/bls12381.js.map +7 -0
  9. package/dist/cjs/elgamal.d.ts +11 -0
  10. package/dist/cjs/elgamal.js +46 -0
  11. package/dist/cjs/elgamal.js.map +7 -0
  12. package/dist/cjs/encrypt.d.ts +24 -0
  13. package/dist/cjs/encrypt.js +88 -0
  14. package/dist/cjs/encrypt.js.map +7 -0
  15. package/dist/cjs/ibe.d.ts +67 -0
  16. package/dist/cjs/ibe.js +107 -0
  17. package/dist/cjs/ibe.js.map +7 -0
  18. package/dist/cjs/index.d.ts +6 -0
  19. package/dist/cjs/index.js +37 -0
  20. package/dist/cjs/index.js.map +7 -0
  21. package/dist/cjs/kdf.d.ts +9 -0
  22. package/dist/cjs/kdf.js +29 -0
  23. package/dist/cjs/kdf.js.map +7 -0
  24. package/dist/cjs/key-server.d.ts +38 -0
  25. package/dist/cjs/key-server.js +98 -0
  26. package/dist/cjs/key-server.js.map +7 -0
  27. package/dist/cjs/key-store.d.ts +49 -0
  28. package/dist/cjs/key-store.js +203 -0
  29. package/dist/cjs/key-store.js.map +7 -0
  30. package/dist/cjs/package.json +5 -0
  31. package/dist/cjs/session-key.d.ts +36 -0
  32. package/dist/cjs/session-key.js +73 -0
  33. package/dist/cjs/session-key.js.map +7 -0
  34. package/dist/cjs/types.d.ts +86 -0
  35. package/dist/cjs/types.js +49 -0
  36. package/dist/cjs/types.js.map +7 -0
  37. package/dist/cjs/utils.d.ts +9 -0
  38. package/dist/cjs/utils.js +39 -0
  39. package/dist/cjs/utils.js.map +7 -0
  40. package/dist/esm/aes.d.ts +18 -0
  41. package/dist/esm/aes.js +91 -0
  42. package/dist/esm/aes.js.map +7 -0
  43. package/dist/esm/bls12381.d.ts +37 -0
  44. package/dist/esm/bls12381.js +90 -0
  45. package/dist/esm/bls12381.js.map +7 -0
  46. package/dist/esm/elgamal.d.ts +11 -0
  47. package/dist/esm/elgamal.js +26 -0
  48. package/dist/esm/elgamal.js.map +7 -0
  49. package/dist/esm/encrypt.d.ts +24 -0
  50. package/dist/esm/encrypt.js +68 -0
  51. package/dist/esm/encrypt.js.map +7 -0
  52. package/dist/esm/ibe.d.ts +67 -0
  53. package/dist/esm/ibe.js +87 -0
  54. package/dist/esm/ibe.js.map +7 -0
  55. package/dist/esm/index.d.ts +6 -0
  56. package/dist/esm/index.js +17 -0
  57. package/dist/esm/index.js.map +7 -0
  58. package/dist/esm/kdf.d.ts +9 -0
  59. package/dist/esm/kdf.js +9 -0
  60. package/dist/esm/kdf.js.map +7 -0
  61. package/dist/esm/key-server.d.ts +38 -0
  62. package/dist/esm/key-server.js +78 -0
  63. package/dist/esm/key-server.js.map +7 -0
  64. package/dist/esm/key-store.d.ts +49 -0
  65. package/dist/esm/key-store.js +183 -0
  66. package/dist/esm/key-store.js.map +7 -0
  67. package/dist/esm/package.json +5 -0
  68. package/dist/esm/session-key.d.ts +36 -0
  69. package/dist/esm/session-key.js +53 -0
  70. package/dist/esm/session-key.js.map +7 -0
  71. package/dist/esm/types.d.ts +86 -0
  72. package/dist/esm/types.js +29 -0
  73. package/dist/esm/types.js.map +7 -0
  74. package/dist/esm/utils.d.ts +9 -0
  75. package/dist/esm/utils.js +19 -0
  76. package/dist/esm/utils.js.map +7 -0
  77. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  78. package/dist/tsconfig.tsbuildinfo +1 -0
  79. package/package.json +58 -0
@@ -0,0 +1,26 @@
1
+ import { G1Element, G2Element, Scalar } from "./bls12381.js";
2
+ function elgamalDecrypt(sk, ciphertext) {
3
+ return decrypt(Scalar.fromBytes(sk), [
4
+ G1Element.fromBytes(ciphertext[0]),
5
+ G1Element.fromBytes(ciphertext[1])
6
+ ]).toBytes();
7
+ }
8
+ function decrypt(sk, encryption) {
9
+ return encryption[1].subtract(encryption[0].multiply(sk));
10
+ }
11
+ function generateSecretKey() {
12
+ return Scalar.random().toBytes();
13
+ }
14
+ function toPublicKey(sk) {
15
+ return G1Element.generator().multiply(Scalar.fromBytes(sk)).toBytes();
16
+ }
17
+ function toVerificationKey(sk) {
18
+ return G2Element.generator().multiply(Scalar.fromBytes(sk)).toBytes();
19
+ }
20
+ export {
21
+ elgamalDecrypt,
22
+ generateSecretKey,
23
+ toPublicKey,
24
+ toVerificationKey
25
+ };
26
+ //# sourceMappingURL=elgamal.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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, ciphertext: [Uint8Array, Uint8Array]): Uint8Array {\n\treturn decrypt(Scalar.fromBytes(sk), [\n\t\tG1Element.fromBytes(ciphertext[0]),\n\t\tG1Element.fromBytes(ciphertext[1]),\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, encryption: [G1Element, G1Element]): G1Element {\n\treturn encryption[1].subtract(encryption[0].multiply(sk));\n}\n\n// /**\n// * Encrypt a message with a given public key. Both the public key and the message must a compressed G1Element (48 bytes).\n// */\n// function elgamal_encrypt(pk: Uint8Array, message: Uint8Array): [Uint8Array, Uint8Array] {\n// \tconst ciphertext = encrypt(G1Element.fromBytes(pk), G1Element.fromBytes(message));\n// \treturn [ciphertext[0].toBytes(), ciphertext[1].toBytes()];\n// }\n\n// /**\n// * Encrypt a message with a given public key. Both the public key and the message must a compressed G1Element (48 bytes).\n// */\n// function encrypt(pk: G1Element, message: G1Element): [G1Element, G1Element] {\n// \tconst r = Scalar.random();\n// \treturn [G1Element.generator().multiply(r), pk.multiply(r).add(message)];\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": "AAGA,SAAS,WAAW,WAAW,cAAc;AAMtC,SAAS,eAAe,IAAgB,YAAkD;AAChG,SAAO,QAAQ,OAAO,UAAU,EAAE,GAAG;AAAA,IACpC,UAAU,UAAU,WAAW,CAAC,CAAC;AAAA,IACjC,UAAU,UAAU,WAAW,CAAC,CAAC;AAAA,EAClC,CAAC,EAAE,QAAQ;AACZ;AAMA,SAAS,QAAQ,IAAY,YAA+C;AAC3E,SAAO,WAAW,CAAC,EAAE,SAAS,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;AACzD;AAmBO,SAAS,oBAAgC;AAC/C,SAAO,OAAO,OAAO,EAAE,QAAQ;AAChC;AAGO,SAAS,YAAY,IAA4B;AACvD,SAAO,UAAU,UAAU,EAAE,SAAS,OAAO,UAAU,EAAE,CAAC,EAAE,QAAQ;AACrE;AAGO,SAAS,kBAAkB,IAA4B;AAC7D,SAAO,UAAU,UAAU,EAAE,SAAS,OAAO,UAAU,EAAE,CAAC,EAAE,QAAQ;AACrE;",
6
+ "names": []
7
+ }
@@ -0,0 +1,24 @@
1
+ import type { EncryptionInput } from './aes.js';
2
+ import type { KeyServer } from './key-server.js';
3
+ export declare const MAX_U8 = 255;
4
+ /**
5
+ * 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.
6
+ *
7
+ * @param keyServers - A list of KeyServers (same server can be used multiple times)
8
+ * @param packageId - packageId
9
+ * @param id - id
10
+ * @param encryptionInput - Input to the encryption. Should be one of the EncryptionInput types, AesGcmEncryptionInput or Plain.
11
+ * @param threshold - The threshold for the TSS encryption.
12
+ * @returns The bcs bytes of the encrypted object containing all metadata and the 256-bit symmetric key that was used to encrypt the object.
13
+ * Since the key can be used to decrypt, it should not be shared but can be used eg. for backup.
14
+ */
15
+ export declare function encrypt<Input extends EncryptionInput>({ keyServers, threshold, packageId, id, encryptionInput, }: {
16
+ keyServers: KeyServer[];
17
+ threshold: number;
18
+ packageId: Uint8Array;
19
+ id: Uint8Array;
20
+ encryptionInput: Input;
21
+ }): Promise<{
22
+ encryptedObject: Uint8Array;
23
+ key: Uint8Array;
24
+ }>;
@@ -0,0 +1,68 @@
1
+ import { split as externalSplit } from "shamir-secret-sharing";
2
+ import { BonehFranklinBLS12381Services, DST } from "./ibe.js";
3
+ import { KeyServerType } from "./key-server.js";
4
+ import { EncryptedObject } from "./types.js";
5
+ import { createFullId } from "./utils.js";
6
+ const MAX_U8 = 255;
7
+ async function encrypt({
8
+ keyServers,
9
+ threshold,
10
+ packageId,
11
+ id,
12
+ encryptionInput
13
+ }) {
14
+ if (keyServers.length < threshold || threshold === 0 || keyServers.length > MAX_U8 || threshold > MAX_U8 || packageId.length !== 32) {
15
+ throw new Error("Invalid input");
16
+ }
17
+ if (keyServers.some((server) => server.keyType !== KeyServerType.BonehFranklinBLS12381)) {
18
+ throw new Error("Key type is not supported");
19
+ }
20
+ const ibeServers = new BonehFranklinBLS12381Services(keyServers);
21
+ const key = await encryptionInput.generateKey();
22
+ const ciphertext = await encryptionInput.encrypt(key);
23
+ const shares = await split(key, ibeServers.size(), threshold);
24
+ const fullId = createFullId(DST, packageId, id);
25
+ const encrypted_shares = ibeServers.encryptBatched(
26
+ fullId,
27
+ shares.map(({ share, index }) => ({
28
+ msg: share,
29
+ info: new Uint8Array([index])
30
+ }))
31
+ );
32
+ const services = ibeServers.getObjectIds().map((id2, i) => [id2, shares[i].index]);
33
+ return {
34
+ encryptedObject: EncryptedObject.serialize({
35
+ version: 0,
36
+ package_id: packageId,
37
+ id,
38
+ services,
39
+ threshold,
40
+ encrypted_shares,
41
+ ciphertext
42
+ }).toBytes(),
43
+ key
44
+ };
45
+ }
46
+ async function split(secret, n, threshold) {
47
+ if (n === 0 || threshold === 0 || threshold > n) {
48
+ throw new Error("Invalid input");
49
+ } else if (threshold === 1) {
50
+ const result = [];
51
+ for (let i = 0; i < n; i++) {
52
+ result.push({ share: secret, index: i });
53
+ }
54
+ return Promise.resolve(result);
55
+ }
56
+ return externalSplit(secret, n, threshold).then(
57
+ (share) => share.map((s) => ({
58
+ share: s.subarray(0, s.length - 1),
59
+ // split() returns the share index in the last byte
60
+ index: s[s.length - 1]
61
+ }))
62
+ );
63
+ }
64
+ export {
65
+ MAX_U8,
66
+ encrypt
67
+ };
68
+ //# sourceMappingURL=encrypt.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/encrypt.ts"],
4
+ "sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { split as externalSplit } from 'shamir-secret-sharing';\n\nimport type { EncryptionInput } from './aes.js';\nimport { BonehFranklinBLS12381Services, DST } from './ibe.js';\nimport type { KeyServer } from './key-server.js';\nimport { KeyServerType } from './key-server.js';\nimport { EncryptedObject } from './types.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 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<Input extends EncryptionInput>({\n\tkeyServers,\n\tthreshold,\n\tpackageId,\n\tid,\n\tencryptionInput,\n}: {\n\tkeyServers: KeyServer[];\n\tthreshold: number;\n\tpackageId: Uint8Array;\n\tid: Uint8Array;\n\tencryptionInput: Input;\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\tpackageId.length !== 32\n\t) {\n\t\tthrow new Error('Invalid input');\n\t}\n\tif (keyServers.some((server) => server.keyType !== KeyServerType.BonehFranklinBLS12381)) {\n\t\tthrow new Error('Key type is not supported');\n\t}\n\tconst ibeServers = new BonehFranklinBLS12381Services(keyServers);\n\n\t// Generate a random symmetric key and encrypt the encryption input using this key.\n\tconst key = await encryptionInput.generateKey();\n\tconst ciphertext = await encryptionInput.encrypt(key);\n\n\t// Split the symmetric key into shares and encrypt each share with the public keys of the key servers.\n\tconst shares = await split(key, ibeServers.size(), threshold);\n\n\t// Encrypt the shares with the public keys of the key servers.\n\tconst fullId = createFullId(DST, packageId, id);\n\tconst encrypted_shares = ibeServers.encryptBatched(\n\t\tfullId,\n\t\tshares.map(({ share, index }) => ({\n\t\t\tmsg: share,\n\t\t\tinfo: new Uint8Array([index]),\n\t\t})),\n\t);\n\n\t// Services and indices of their shares are stored as a tuple\n\tconst services: [Uint8Array, number][] = ibeServers\n\t\t.getObjectIds()\n\t\t.map((id, i) => [id, shares[i].index]);\n\n\treturn {\n\t\tencryptedObject: EncryptedObject.serialize({\n\t\t\tversion: 0,\n\t\t\tpackage_id: packageId,\n\t\t\tid,\n\t\t\tservices,\n\t\t\tthreshold,\n\t\t\tencrypted_shares,\n\t\t\tciphertext,\n\t\t}).toBytes(),\n\t\tkey,\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 input');\n\t} else if (threshold === 1) {\n\t\t// If the threshold is 1, the secret is not split.\n\t\tconst result = [];\n\t\tfor (let i = 0; i < n; i++) {\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: secret, index: i });\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\n\t\t\tindex: s[s.length - 1],\n\t\t})),\n\t);\n}\n"],
5
+ "mappings": "AAGA,SAAS,SAAS,qBAAqB;AAGvC,SAAS,+BAA+B,WAAW;AAEnD,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAEtB,MAAM,SAAS;AAatB,eAAsB,QAAuC;AAAA,EAC5D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GASG;AAEF,MACC,WAAW,SAAS,aACpB,cAAc,KACd,WAAW,SAAS,UACpB,YAAY,UACZ,UAAU,WAAW,IACpB;AACD,UAAM,IAAI,MAAM,eAAe;AAAA,EAChC;AACA,MAAI,WAAW,KAAK,CAAC,WAAW,OAAO,YAAY,cAAc,qBAAqB,GAAG;AACxF,UAAM,IAAI,MAAM,2BAA2B;AAAA,EAC5C;AACA,QAAM,aAAa,IAAI,8BAA8B,UAAU;AAG/D,QAAM,MAAM,MAAM,gBAAgB,YAAY;AAC9C,QAAM,aAAa,MAAM,gBAAgB,QAAQ,GAAG;AAGpD,QAAM,SAAS,MAAM,MAAM,KAAK,WAAW,KAAK,GAAG,SAAS;AAG5D,QAAM,SAAS,aAAa,KAAK,WAAW,EAAE;AAC9C,QAAM,mBAAmB,WAAW;AAAA,IACnC;AAAA,IACA,OAAO,IAAI,CAAC,EAAE,OAAO,MAAM,OAAO;AAAA,MACjC,KAAK;AAAA,MACL,MAAM,IAAI,WAAW,CAAC,KAAK,CAAC;AAAA,IAC7B,EAAE;AAAA,EACH;AAGA,QAAM,WAAmC,WACvC,aAAa,EACb,IAAI,CAACA,KAAI,MAAM,CAACA,KAAI,OAAO,CAAC,EAAE,KAAK,CAAC;AAEtC,SAAO;AAAA,IACN,iBAAiB,gBAAgB,UAAU;AAAA,MAC1C,SAAS;AAAA,MACT,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAC,EAAE,QAAQ;AAAA,IACX;AAAA,EACD;AACD;AAEA,eAAe,MACd,QACA,GACA,WACkD;AAGlD,MAAI,MAAM,KAAK,cAAc,KAAK,YAAY,GAAG;AAChD,UAAM,IAAI,MAAM,eAAe;AAAA,EAChC,WAAW,cAAc,GAAG;AAE3B,UAAM,SAAS,CAAC;AAChB,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAG3B,aAAO,KAAK,EAAE,OAAO,QAAQ,OAAO,EAAE,CAAC;AAAA,IACxC;AACA,WAAO,QAAQ,QAAQ,MAAM;AAAA,EAC9B;AAEA,SAAO,cAAc,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
+ "names": ["id"]
7
+ }
@@ -0,0 +1,67 @@
1
+ import { G1Element, G2Element } from './bls12381.js';
2
+ import type { KeyServer } from './key-server.js';
3
+ import type { IBEEncryptionsType } from './types.js';
4
+ /**
5
+ * The domain separation tag for the hash-to-group function.
6
+ */
7
+ export declare const DST: Uint8Array;
8
+ /**
9
+ * The domain separation tag for the signing proof of possession.
10
+ */
11
+ export declare const DST_POP: Uint8Array;
12
+ /**
13
+ * The interface for the key servers.
14
+ */
15
+ export declare abstract class IBEServers {
16
+ protected readonly object_ids: Uint8Array[];
17
+ protected constructor(object_ids: Uint8Array[]);
18
+ /**
19
+ * The object IDs of the key servers.
20
+ */
21
+ getObjectIds(): Uint8Array[];
22
+ /**
23
+ * The number of key servers.
24
+ */
25
+ size(): number;
26
+ /**
27
+ * Encrypt a batch of messages for the given identity.
28
+ *
29
+ * @param id The identity.
30
+ * @param msg_and_infos The messages and an additional info parameter which will be included in the KDF.
31
+ * @returns The encrypted messages.
32
+ */
33
+ abstract encryptBatched(id: Uint8Array, msg_and_infos: {
34
+ msg: Uint8Array;
35
+ info: Uint8Array;
36
+ }[]): IBEEncryptionsType;
37
+ }
38
+ /**
39
+ * Identity-based encryption based on the Boneh-Franklin IBE scheme.
40
+ * This object represents a set of key servers that can be used to encrypt messages for a given identity.
41
+ */
42
+ export declare class BonehFranklinBLS12381Services extends IBEServers {
43
+ readonly public_keys: G2Element[];
44
+ constructor(services: KeyServer[]);
45
+ encryptBatched(id: Uint8Array, msg_and_infos: {
46
+ msg: Uint8Array;
47
+ info: Uint8Array;
48
+ }[]): IBEEncryptionsType;
49
+ /**
50
+ * Returns true if the user secret key is valid for the given public key and id.
51
+ * @param user_secret_key - The user secret key.
52
+ * @param id - The identity.
53
+ * @param public_key - The public key.
54
+ * @returns True if the user secret key is valid for the given public key and id.
55
+ */
56
+ static verifyUserSecretKey(user_secret_key: G1Element, id: Uint8Array, public_key: G2Element): boolean;
57
+ /**
58
+ * Identity-based decryption.
59
+ *
60
+ * @param nonce The encryption nonce.
61
+ * @param sk The user secret key.
62
+ * @param ciphertext The encrypted message.
63
+ * @param info An info parameter also included in the KDF.
64
+ * @returns The decrypted message.
65
+ */
66
+ static decrypt(nonce: G2Element, sk: G1Element, ciphertext: Uint8Array, info: Uint8Array): Uint8Array;
67
+ }
@@ -0,0 +1,87 @@
1
+ import { G1Element, G2Element, Scalar } from "./bls12381.js";
2
+ import { kdf } from "./kdf.js";
3
+ import { xor } from "./utils.js";
4
+ const DST = new TextEncoder().encode("SUI-SEAL-IBE-BLS12381-00");
5
+ const DST_POP = new TextEncoder().encode("SUI-SEAL-IBE-BLS12381-00-POP");
6
+ class IBEServers {
7
+ constructor(object_ids) {
8
+ this.object_ids = object_ids;
9
+ }
10
+ /**
11
+ * The object IDs of the key servers.
12
+ */
13
+ getObjectIds() {
14
+ return this.object_ids;
15
+ }
16
+ /**
17
+ * The number of key servers.
18
+ */
19
+ size() {
20
+ return this.object_ids.length;
21
+ }
22
+ }
23
+ class BonehFranklinBLS12381Services extends IBEServers {
24
+ constructor(services) {
25
+ super(services.map((service) => service.objectId));
26
+ this.public_keys = services.map((service) => G2Element.fromBytes(service.pk));
27
+ }
28
+ encryptBatched(id, msg_and_infos) {
29
+ if (this.public_keys.length === 0 || this.public_keys.length !== msg_and_infos.length) {
30
+ throw new Error("Invalid input");
31
+ }
32
+ const [nonce, keys] = encapBatched(this.public_keys, id);
33
+ const encrypted_msgs = msg_and_infos.map(
34
+ (msg_and_info, i) => xor(msg_and_info.msg, kdf(keys[i], msg_and_info.info))
35
+ );
36
+ return {
37
+ BonehFranklinBLS12381: {
38
+ encapsulation: nonce.toBytes(),
39
+ shares: encrypted_msgs
40
+ },
41
+ $kind: "BonehFranklinBLS12381"
42
+ };
43
+ }
44
+ /**
45
+ * Returns true if the user secret key is valid for the given public key and id.
46
+ * @param user_secret_key - The user secret key.
47
+ * @param id - The identity.
48
+ * @param public_key - The public key.
49
+ * @returns True if the user secret key is valid for the given public key and id.
50
+ */
51
+ static verifyUserSecretKey(user_secret_key, id, public_key) {
52
+ const lhs = user_secret_key.pairing(G2Element.generator()).toBytes();
53
+ const rhs = G1Element.hashToCurve(id).pairing(public_key).toBytes();
54
+ return lhs.length === rhs.length && lhs.every((value, index) => value === rhs[index]);
55
+ }
56
+ /**
57
+ * Identity-based decryption.
58
+ *
59
+ * @param nonce The encryption nonce.
60
+ * @param sk The user secret key.
61
+ * @param ciphertext The encrypted message.
62
+ * @param info An info parameter also included in the KDF.
63
+ * @returns The decrypted message.
64
+ */
65
+ static decrypt(nonce, sk, ciphertext, info) {
66
+ return xor(ciphertext, kdf(decap(nonce, sk), info));
67
+ }
68
+ }
69
+ function encapBatched(public_keys, id) {
70
+ if (public_keys.length === 0) {
71
+ throw new Error("Invalid input");
72
+ }
73
+ const r = Scalar.random();
74
+ const nonce = G2Element.generator().multiply(r);
75
+ const gid = G1Element.hashToCurve(id).multiply(r);
76
+ return [nonce, public_keys.map((public_key) => gid.pairing(public_key))];
77
+ }
78
+ function decap(nonce, usk) {
79
+ return usk.pairing(nonce);
80
+ }
81
+ export {
82
+ BonehFranklinBLS12381Services,
83
+ DST,
84
+ DST_POP,
85
+ IBEServers
86
+ };
87
+ //# sourceMappingURL=ibe.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ibe.ts"],
4
+ "sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { GTElement } from './bls12381.js';\nimport { G1Element, G2Element, Scalar } from './bls12381.js';\nimport { kdf } from './kdf.js';\nimport type { KeyServer } from './key-server.js';\nimport type { IBEEncryptionsType } from './types.js';\nimport { xor } from './utils.js';\n\n/**\n * The domain separation tag for the hash-to-group function.\n */\nexport const DST: Uint8Array = new TextEncoder().encode('SUI-SEAL-IBE-BLS12381-00');\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-00-POP');\n\n/**\n * The interface for the key servers.\n */\nexport abstract class IBEServers {\n\tprotected readonly object_ids: Uint8Array[];\n\n\tprotected constructor(object_ids: Uint8Array[]) {\n\t\tthis.object_ids = object_ids;\n\t}\n\n\t/**\n\t * The object IDs of the key servers.\n\t */\n\tgetObjectIds(): Uint8Array[] {\n\t\treturn this.object_ids;\n\t}\n\n\t/**\n\t * The number of key servers.\n\t */\n\tsize(): number {\n\t\treturn this.object_ids.length;\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 msg_and_infos The messages and an additional info parameter which will be included in the KDF.\n\t * @returns The encrypted messages.\n\t */\n\tabstract encryptBatched(\n\t\tid: Uint8Array,\n\t\tmsg_and_infos: { msg: Uint8Array; info: Uint8Array }[],\n\t): IBEEncryptionsType;\n}\n\n/**\n * Identity-based encryption based on the Boneh-Franklin IBE scheme.\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 public_keys: G2Element[];\n\n\tconstructor(services: KeyServer[]) {\n\t\tsuper(services.map((service) => service.objectId));\n\t\tthis.public_keys = services.map((service) => G2Element.fromBytes(service.pk));\n\t}\n\n\tencryptBatched(\n\t\tid: Uint8Array,\n\t\tmsg_and_infos: { msg: Uint8Array; info: Uint8Array }[],\n\t): IBEEncryptionsType {\n\t\tif (this.public_keys.length === 0 || this.public_keys.length !== msg_and_infos.length) {\n\t\t\tthrow new Error('Invalid input');\n\t\t}\n\t\tconst [nonce, keys] = encapBatched(this.public_keys, id);\n\t\tconst encrypted_msgs = msg_and_infos.map((msg_and_info, i) =>\n\t\t\txor(msg_and_info.msg, kdf(keys[i], msg_and_info.info)),\n\t\t);\n\n\t\treturn {\n\t\t\tBonehFranklinBLS12381: {\n\t\t\t\tencapsulation: nonce.toBytes(),\n\t\t\t\tshares: encrypted_msgs,\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(\n\t\tuser_secret_key: G1Element,\n\t\tid: Uint8Array,\n\t\tpublic_key: G2Element,\n\t): boolean {\n\t\tconst lhs = user_secret_key.pairing(G2Element.generator()).toBytes();\n\t\tconst rhs = G1Element.hashToCurve(id).pairing(public_key).toBytes();\n\t\treturn lhs.length === rhs.length && lhs.every((value, index) => value === rhs[index]);\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\tinfo: Uint8Array,\n\t): Uint8Array {\n\t\treturn xor(ciphertext, kdf(decap(nonce, sk), info));\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 public_keys 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(public_keys: G2Element[], id: Uint8Array): [G2Element, GTElement[]] {\n\tif (public_keys.length === 0) {\n\t\tthrow new Error('Invalid input');\n\t}\n\tconst r = Scalar.random();\n\tconst nonce = G2Element.generator().multiply(r);\n\tconst gid = G1Element.hashToCurve(id).multiply(r);\n\treturn [nonce, public_keys.map((public_key) => gid.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"],
5
+ "mappings": "AAIA,SAAS,WAAW,WAAW,cAAc;AAC7C,SAAS,WAAW;AAGpB,SAAS,WAAW;AAKb,MAAM,MAAkB,IAAI,YAAY,EAAE,OAAO,0BAA0B;AAK3E,MAAM,UAAsB,IAAI,YAAY,EAAE,OAAO,8BAA8B;AAKnF,MAAe,WAAW;AAAA,EAGtB,YAAY,YAA0B;AAC/C,SAAK,aAAa;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,eAA6B;AAC5B,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe;AACd,WAAO,KAAK,WAAW;AAAA,EACxB;AAaD;AAMO,MAAM,sCAAsC,WAAW;AAAA,EAG7D,YAAY,UAAuB;AAClC,UAAM,SAAS,IAAI,CAAC,YAAY,QAAQ,QAAQ,CAAC;AACjD,SAAK,cAAc,SAAS,IAAI,CAAC,YAAY,UAAU,UAAU,QAAQ,EAAE,CAAC;AAAA,EAC7E;AAAA,EAEA,eACC,IACA,eACqB;AACrB,QAAI,KAAK,YAAY,WAAW,KAAK,KAAK,YAAY,WAAW,cAAc,QAAQ;AACtF,YAAM,IAAI,MAAM,eAAe;AAAA,IAChC;AACA,UAAM,CAAC,OAAO,IAAI,IAAI,aAAa,KAAK,aAAa,EAAE;AACvD,UAAM,iBAAiB,cAAc;AAAA,MAAI,CAAC,cAAc,MACvD,IAAI,aAAa,KAAK,IAAI,KAAK,CAAC,GAAG,aAAa,IAAI,CAAC;AAAA,IACtD;AAEA,WAAO;AAAA,MACN,uBAAuB;AAAA,QACtB,eAAe,MAAM,QAAQ;AAAA,QAC7B,QAAQ;AAAA,MACT;AAAA,MACA,OAAO;AAAA,IACR;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,oBACN,iBACA,IACA,YACU;AACV,UAAM,MAAM,gBAAgB,QAAQ,UAAU,UAAU,CAAC,EAAE,QAAQ;AACnE,UAAM,MAAM,UAAU,YAAY,EAAE,EAAE,QAAQ,UAAU,EAAE,QAAQ;AAClE,WAAO,IAAI,WAAW,IAAI,UAAU,IAAI,MAAM,CAAC,OAAO,UAAU,UAAU,IAAI,KAAK,CAAC;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,QACN,OACA,IACA,YACA,MACa;AACb,WAAO,IAAI,YAAY,IAAI,MAAM,OAAO,EAAE,GAAG,IAAI,CAAC;AAAA,EACnD;AACD;AASA,SAAS,aAAa,aAA0B,IAA0C;AACzF,MAAI,YAAY,WAAW,GAAG;AAC7B,UAAM,IAAI,MAAM,eAAe;AAAA,EAChC;AACA,QAAM,IAAI,OAAO,OAAO;AACxB,QAAM,QAAQ,UAAU,UAAU,EAAE,SAAS,CAAC;AAC9C,QAAM,MAAM,UAAU,YAAY,EAAE,EAAE,SAAS,CAAC;AAChD,SAAO,CAAC,OAAO,YAAY,IAAI,CAAC,eAAe,IAAI,QAAQ,UAAU,CAAC,CAAC;AACxE;AASA,SAAS,MAAM,OAAkB,KAA2B;AAC3D,SAAO,IAAI,QAAQ,KAAK;AACzB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,6 @@
1
+ export { AesGcm256 } from './aes.js';
2
+ export { encrypt } from './encrypt.js';
3
+ export { getAllowlistedKeyServers, retrieveKeyServers, verifyKeyServer } from './key-server.js';
4
+ export { KeyStore } from './key-store.js';
5
+ export { SessionKey } from './session-key.js';
6
+ export { EncryptedObject } from './types.js';
@@ -0,0 +1,17 @@
1
+ import { AesGcm256 } from "./aes.js";
2
+ import { encrypt } from "./encrypt.js";
3
+ import { getAllowlistedKeyServers, retrieveKeyServers, verifyKeyServer } from "./key-server.js";
4
+ import { KeyStore } from "./key-store.js";
5
+ import { SessionKey } from "./session-key.js";
6
+ import { EncryptedObject } from "./types.js";
7
+ export {
8
+ AesGcm256,
9
+ EncryptedObject,
10
+ KeyStore,
11
+ SessionKey,
12
+ encrypt,
13
+ getAllowlistedKeyServers,
14
+ retrieveKeyServers,
15
+ verifyKeyServer
16
+ };
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.ts"],
4
+ "sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nexport { AesGcm256 } from './aes.js';\nexport { encrypt } from './encrypt.js';\nexport { getAllowlistedKeyServers, retrieveKeyServers, verifyKeyServer } from './key-server.js';\nexport { KeyStore } from './key-store.js';\nexport { SessionKey } from './session-key.js';\nexport { EncryptedObject } from './types.js';\n"],
5
+ "mappings": "AAGA,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,0BAA0B,oBAAoB,uBAAuB;AAC9E,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,9 @@
1
+ import type { GTElement } from './bls12381.js';
2
+ /**
3
+ * The default key derivation function.
4
+ *
5
+ * @param element The GTElement to derive the key from.
6
+ * @param info Optional context and application specific information.
7
+ * @returns The derived key.
8
+ */
9
+ export declare function kdf(element: GTElement, info: Uint8Array): Uint8Array;
@@ -0,0 +1,9 @@
1
+ import { hkdf } from "@noble/hashes/hkdf";
2
+ import { sha3_256 } from "@noble/hashes/sha3";
3
+ function kdf(element, info) {
4
+ return hkdf(sha3_256, element.toBytes(), "", info, 32);
5
+ }
6
+ export {
7
+ kdf
8
+ };
9
+ //# sourceMappingURL=kdf.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/kdf.ts"],
4
+ "sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { hkdf } from '@noble/hashes/hkdf';\nimport { sha3_256 } from '@noble/hashes/sha3';\n\nimport type { GTElement } from './bls12381.js';\n\n/**\n * The default key derivation function.\n *\n * @param element The GTElement to derive the key from.\n * @param info Optional context and application specific information.\n * @returns The derived key.\n */\nexport function kdf(element: GTElement, info: Uint8Array): Uint8Array {\n\treturn hkdf(sha3_256, element.toBytes(), '', info, 32);\n}\n"],
5
+ "mappings": "AAGA,SAAS,YAAY;AACrB,SAAS,gBAAgB;AAWlB,SAAS,IAAI,SAAoB,MAA8B;AACrE,SAAO,KAAK,UAAU,QAAQ,QAAQ,GAAG,IAAI,MAAM,EAAE;AACtD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,38 @@
1
+ import type { SuiClient } from '@mysten/sui/client';
2
+ export type KeyServer = {
3
+ objectId: Uint8Array;
4
+ name: string;
5
+ url: string;
6
+ keyType: KeyServerType;
7
+ pk: Uint8Array;
8
+ };
9
+ export declare enum KeyServerType {
10
+ BonehFranklinBLS12381 = 0
11
+ }
12
+ /**
13
+ * Returns a static list of Seal key server object ids that the dapp can choose to use.
14
+ * @param network - The network to use.
15
+ * @returns The object id's of the key servers.
16
+ */
17
+ export declare function getAllowlistedKeyServers(network: 'testnet' | 'mainnet'): Uint8Array[];
18
+ /**
19
+ * Given a list of key server object IDs, returns a list of SealKeyServer
20
+ * from onchain state containing name, objectId, URL and pk.
21
+ *
22
+ * @param objectIds - The key server object IDs.
23
+ * @param client - The SuiClient to use.
24
+ * @returns - An array of SealKeyServer.
25
+ */
26
+ export declare function retrieveKeyServers({ objectIds, client, }: {
27
+ objectIds: Uint8Array[];
28
+ client: SuiClient;
29
+ }): Promise<KeyServer[]>;
30
+ /**
31
+ * Given a KeyServer, fetch the proof of possesion (PoP) from the URL and verify it
32
+ * against the pubkey. This should be used only rarely when the dapp uses a dynamic
33
+ * set of key servers.
34
+ *
35
+ * @param server - The KeyServer to verify.
36
+ * @returns - True if the key server is valid, false otherwise.
37
+ */
38
+ export declare function verifyKeyServer(server: KeyServer): Promise<boolean>;
@@ -0,0 +1,78 @@
1
+ import { fromBase64, fromHex, toHex } from "@mysten/bcs";
2
+ import { bcs } from "@mysten/sui/bcs";
3
+ import { bls12_381 } from "@noble/curves/bls12-381";
4
+ import { DST_POP } from "./ibe.js";
5
+ var KeyServerType = /* @__PURE__ */ ((KeyServerType2) => {
6
+ KeyServerType2[KeyServerType2["BonehFranklinBLS12381"] = 0] = "BonehFranklinBLS12381";
7
+ return KeyServerType2;
8
+ })(KeyServerType || {});
9
+ const KeyServerMove = bcs.struct("KeyServer", {
10
+ id: bcs.Address,
11
+ name: bcs.string(),
12
+ url: bcs.string(),
13
+ key_type: bcs.u8(),
14
+ pk: bcs.vector(bcs.u8())
15
+ });
16
+ function getAllowlistedKeyServers(network) {
17
+ if (network === "testnet") {
18
+ return [
19
+ fromHex("0xb35a7228d8cf224ad1e828c0217c95a5153bafc2906d6f9c178197dce26fbcf8"),
20
+ fromHex("0x2d6cde8a9d9a65bde3b0a346566945a63b4bfb70e9a06c41bdb70807e2502b06")
21
+ ];
22
+ } else {
23
+ throw new Error("Network not supported");
24
+ }
25
+ }
26
+ async function retrieveKeyServers({
27
+ objectIds,
28
+ client
29
+ }) {
30
+ return await Promise.all(
31
+ objectIds.map(async (objectId) => {
32
+ const res = await client.getObject({
33
+ id: toHex(objectId),
34
+ options: {
35
+ showBcs: true
36
+ }
37
+ });
38
+ if (!res || res.error || !res.data) {
39
+ throw new Error(`KeyServer ${objectId} not found; ${res.error}`);
40
+ }
41
+ if (!res.data.bcs || !("bcsBytes" in res.data.bcs)) {
42
+ throw new Error(`Invalid KeyServer query: ${objectId}, expected object, got package`);
43
+ }
44
+ let ks = KeyServerMove.parse(fromBase64(res.data.bcs.bcsBytes));
45
+ if (ks.key_type !== 0) {
46
+ throw new Error("Unsupported key type");
47
+ }
48
+ return {
49
+ objectId,
50
+ name: ks.name,
51
+ url: ks.url,
52
+ keyType: 0 /* BonehFranklinBLS12381 */,
53
+ pk: new Uint8Array(ks.pk)
54
+ };
55
+ })
56
+ );
57
+ }
58
+ async function verifyKeyServer(server) {
59
+ const response = await fetch(server.url + "/v1/service", {
60
+ method: "GET",
61
+ headers: {
62
+ "Content-Type": "application/json"
63
+ }
64
+ });
65
+ const serviceResponse = await response.json();
66
+ if (serviceResponse.service_id !== server.objectId) {
67
+ return false;
68
+ }
69
+ const fullMsg = new Uint8Array([...DST_POP, ...server.pk, ...server.objectId]);
70
+ return bls12_381.verifyShortSignature(fromBase64(serviceResponse.pop), fullMsg, server.pk);
71
+ }
72
+ export {
73
+ KeyServerType,
74
+ getAllowlistedKeyServers,
75
+ retrieveKeyServers,
76
+ verifyKeyServer
77
+ };
78
+ //# sourceMappingURL=key-server.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/key-server.ts"],
4
+ "sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport { fromBase64, fromHex, toHex } from '@mysten/bcs';\nimport { bcs } from '@mysten/sui/bcs';\nimport type { SuiClient } from '@mysten/sui/client';\nimport { bls12_381 } from '@noble/curves/bls12-381';\n\nimport { DST_POP } from './ibe.js';\n\nexport type KeyServer = {\n\tobjectId: Uint8Array;\n\tname: string;\n\turl: string;\n\tkeyType: KeyServerType;\n\tpk: Uint8Array;\n};\n\nexport enum KeyServerType {\n\tBonehFranklinBLS12381 = 0,\n}\n\n// The Move struct for the KeyServer object.\nconst KeyServerMove = bcs.struct('KeyServer', {\n\tid: bcs.Address,\n\tname: bcs.string(),\n\turl: bcs.string(),\n\tkey_type: bcs.u8(),\n\tpk: bcs.vector(bcs.u8()),\n});\n\n/**\n * Returns a static list of Seal key server object ids that the dapp can choose to use.\n * @param network - The network to use.\n * @returns The object id's of the key servers.\n */\nexport function getAllowlistedKeyServers(network: 'testnet' | 'mainnet'): Uint8Array[] {\n\tif (network === 'testnet') {\n\t\treturn [\n\t\t\tfromHex('0xb35a7228d8cf224ad1e828c0217c95a5153bafc2906d6f9c178197dce26fbcf8'),\n\t\t\tfromHex('0x2d6cde8a9d9a65bde3b0a346566945a63b4bfb70e9a06c41bdb70807e2502b06'),\n\t\t];\n\t} else {\n\t\tthrow new Error('Network not supported');\n\t}\n}\n\n/**\n * Given a list of key server object IDs, returns a list of SealKeyServer\n * from onchain state containing name, objectId, URL and pk.\n *\n * @param objectIds - The key server object IDs.\n * @param client - The SuiClient to use.\n * @returns - An array of SealKeyServer.\n */\nexport async function retrieveKeyServers({\n\tobjectIds,\n\tclient,\n}: {\n\tobjectIds: Uint8Array[];\n\tclient: SuiClient;\n}): Promise<KeyServer[]> {\n\treturn await Promise.all(\n\t\tobjectIds.map(async (objectId) => {\n\t\t\tconst res = await client.getObject({\n\t\t\t\tid: toHex(objectId),\n\t\t\t\toptions: {\n\t\t\t\t\tshowBcs: true,\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (!res || res.error || !res.data) {\n\t\t\t\tthrow new Error(`KeyServer ${objectId} not found; ${res.error}`);\n\t\t\t}\n\n\t\t\tif (!res.data.bcs || !('bcsBytes' in res.data.bcs)) {\n\t\t\t\tthrow new Error(`Invalid KeyServer query: ${objectId}, expected object, got package`);\n\t\t\t}\n\n\t\t\tlet ks = KeyServerMove.parse(fromBase64(res.data.bcs!.bcsBytes));\n\t\t\tif (ks.key_type !== 0) {\n\t\t\t\tthrow new Error('Unsupported key type');\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tobjectId,\n\t\t\t\tname: ks.name,\n\t\t\t\turl: ks.url,\n\t\t\t\tkeyType: KeyServerType.BonehFranklinBLS12381,\n\t\t\t\tpk: new Uint8Array(ks.pk),\n\t\t\t};\n\t\t}),\n\t);\n}\n\n/**\n * Given a KeyServer, fetch the proof of possesion (PoP) from the URL and verify it\n * against the pubkey. This should be used only rarely when the dapp uses a dynamic\n * set of key servers.\n *\n * @param server - The KeyServer to verify.\n * @returns - True if the key server is valid, false otherwise.\n */\nexport async function verifyKeyServer(server: KeyServer): Promise<boolean> {\n\tconst response = await fetch(server.url! + '/v1/service', {\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t},\n\t});\n\tconst serviceResponse = await response.json();\n\n\tif (serviceResponse.service_id !== server.objectId) {\n\t\treturn false;\n\t}\n\tconst fullMsg = new Uint8Array([...DST_POP, ...server.pk, ...server.objectId]);\n\treturn bls12_381.verifyShortSignature(fromBase64(serviceResponse.pop), fullMsg, server.pk);\n}\n"],
5
+ "mappings": "AAEA,SAAS,YAAY,SAAS,aAAa;AAC3C,SAAS,WAAW;AAEpB,SAAS,iBAAiB;AAE1B,SAAS,eAAe;AAUjB,IAAK,gBAAL,kBAAKA,mBAAL;AACN,EAAAA,8BAAA,2BAAwB,KAAxB;AADW,SAAAA;AAAA,GAAA;AAKZ,MAAM,gBAAgB,IAAI,OAAO,aAAa;AAAA,EAC7C,IAAI,IAAI;AAAA,EACR,MAAM,IAAI,OAAO;AAAA,EACjB,KAAK,IAAI,OAAO;AAAA,EAChB,UAAU,IAAI,GAAG;AAAA,EACjB,IAAI,IAAI,OAAO,IAAI,GAAG,CAAC;AACxB,CAAC;AAOM,SAAS,yBAAyB,SAA8C;AACtF,MAAI,YAAY,WAAW;AAC1B,WAAO;AAAA,MACN,QAAQ,oEAAoE;AAAA,MAC5E,QAAQ,oEAAoE;AAAA,IAC7E;AAAA,EACD,OAAO;AACN,UAAM,IAAI,MAAM,uBAAuB;AAAA,EACxC;AACD;AAUA,eAAsB,mBAAmB;AAAA,EACxC;AAAA,EACA;AACD,GAGyB;AACxB,SAAO,MAAM,QAAQ;AAAA,IACpB,UAAU,IAAI,OAAO,aAAa;AACjC,YAAM,MAAM,MAAM,OAAO,UAAU;AAAA,QAClC,IAAI,MAAM,QAAQ;AAAA,QAClB,SAAS;AAAA,UACR,SAAS;AAAA,QACV;AAAA,MACD,CAAC;AACD,UAAI,CAAC,OAAO,IAAI,SAAS,CAAC,IAAI,MAAM;AACnC,cAAM,IAAI,MAAM,aAAa,QAAQ,eAAe,IAAI,KAAK,EAAE;AAAA,MAChE;AAEA,UAAI,CAAC,IAAI,KAAK,OAAO,EAAE,cAAc,IAAI,KAAK,MAAM;AACnD,cAAM,IAAI,MAAM,4BAA4B,QAAQ,gCAAgC;AAAA,MACrF;AAEA,UAAI,KAAK,cAAc,MAAM,WAAW,IAAI,KAAK,IAAK,QAAQ,CAAC;AAC/D,UAAI,GAAG,aAAa,GAAG;AACtB,cAAM,IAAI,MAAM,sBAAsB;AAAA,MACvC;AAEA,aAAO;AAAA,QACN;AAAA,QACA,MAAM,GAAG;AAAA,QACT,KAAK,GAAG;AAAA,QACR,SAAS;AAAA,QACT,IAAI,IAAI,WAAW,GAAG,EAAE;AAAA,MACzB;AAAA,IACD,CAAC;AAAA,EACF;AACD;AAUA,eAAsB,gBAAgB,QAAqC;AAC1E,QAAM,WAAW,MAAM,MAAM,OAAO,MAAO,eAAe;AAAA,IACzD,QAAQ;AAAA,IACR,SAAS;AAAA,MACR,gBAAgB;AAAA,IACjB;AAAA,EACD,CAAC;AACD,QAAM,kBAAkB,MAAM,SAAS,KAAK;AAE5C,MAAI,gBAAgB,eAAe,OAAO,UAAU;AACnD,WAAO;AAAA,EACR;AACA,QAAM,UAAU,IAAI,WAAW,CAAC,GAAG,SAAS,GAAG,OAAO,IAAI,GAAG,OAAO,QAAQ,CAAC;AAC7E,SAAO,UAAU,qBAAqB,WAAW,gBAAgB,GAAG,GAAG,SAAS,OAAO,EAAE;AAC1F;",
6
+ "names": ["KeyServerType"]
7
+ }
@@ -0,0 +1,49 @@
1
+ import { G1Element } from './bls12381.js';
2
+ import type { KeyServer } from './key-server.js';
3
+ import type { SessionKey } from './session-key.js';
4
+ import type { EncryptedObject } from './types.js';
5
+ /**
6
+ * A class to cache user secret keys after they have been fetched from key servers.
7
+ */
8
+ export declare class KeyStore {
9
+ private readonly keys_map;
10
+ constructor();
11
+ private createMapKey;
12
+ /** @internal */
13
+ addKey(fullId: Uint8Array, objectId: Uint8Array, key: G1Element): void;
14
+ /**
15
+ * Get a key from this KeyStore or undefined if the key is not found.
16
+ *
17
+ * @param fullId The full ID used to derive the key.
18
+ * @param objectId The object ID of the key server holding the key.
19
+ */
20
+ private getKey;
21
+ /**
22
+ * Check if the key store has a key for the given full ID and object ID.
23
+ *
24
+ * @param fullId The full ID used to derive the key.
25
+ * @param objectId The object ID of the key server holding the key.
26
+ */
27
+ private hasKey;
28
+ /**
29
+ * Look up URLs of key servers and fetch key from servers with request signature,
30
+ * cert and ephPk, then updates the caching keys_map.
31
+ */
32
+ fetchKeys({ keyServers, threshold: _threshold, packageId, ids, txBytes, sessionKey, }: {
33
+ keyServers: KeyServer[];
34
+ threshold: number;
35
+ packageId: Uint8Array;
36
+ ids: Uint8Array[];
37
+ txBytes: Uint8Array;
38
+ sessionKey: SessionKey;
39
+ }): Promise<void>;
40
+ /**
41
+ * Decrypt the given encrypted bytes with the given cached secret keys for the full ID.
42
+ * It's assumed that fetchKeys has been called to fetch the secret keys for enough key servers
43
+ * otherwise, this will throw an error.
44
+ *
45
+ * @param encryptedObject - EncryptedObject.
46
+ * @returns - The decrypted plaintext corresponding to ciphertext.
47
+ */
48
+ decrypt(encryptedObject: typeof EncryptedObject.$inferType): Promise<Uint8Array>;
49
+ }