@evolu/common 8.16.0 → 8.17.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.
@@ -84,6 +84,13 @@ type Entropy = typeof Entropy.Output;
84
84
  */
85
85
  export declare const Entropy16: import("./Type.ts").BrandType<import("./Type.ts").BrandType<import("./Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("./Type.ts").ObjectTagError<"Uint8Array">, null, import("./Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length16", import("./Type.ts").LengthError<16>>;
86
86
  export type Entropy16 = typeof Entropy16.Output;
87
+ /**
88
+ * Cryptographic entropy of exactly 20 bytes.
89
+ *
90
+ * @group Random bytes
91
+ */
92
+ export declare const Entropy20: import("./Type.ts").BrandType<import("./Type.ts").BrandType<import("./Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("./Type.ts").ObjectTagError<"Uint8Array">, null, import("./Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length20", import("./Type.ts").LengthError<20>>;
93
+ export type Entropy20 = typeof Entropy20.Output;
87
94
  /**
88
95
  * Cryptographic entropy of exactly 24 bytes.
89
96
  *
@@ -91,6 +98,13 @@ export type Entropy16 = typeof Entropy16.Output;
91
98
  */
92
99
  export declare const Entropy24: import("./Type.ts").BrandType<import("./Type.ts").BrandType<import("./Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("./Type.ts").ObjectTagError<"Uint8Array">, null, import("./Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length24", import("./Type.ts").LengthError<24>>;
93
100
  export type Entropy24 = typeof Entropy24.Output;
101
+ /**
102
+ * Cryptographic entropy of exactly 28 bytes.
103
+ *
104
+ * @group Random bytes
105
+ */
106
+ export declare const Entropy28: import("./Type.ts").BrandType<import("./Type.ts").BrandType<import("./Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("./Type.ts").ObjectTagError<"Uint8Array">, null, import("./Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length28", import("./Type.ts").LengthError<28>>;
107
+ export type Entropy28 = typeof Entropy28.Output;
94
108
  /**
95
109
  * Cryptographic entropy of exactly 32 bytes.
96
110
  *
@@ -119,13 +133,17 @@ export declare const createRandomBytes: () => RandomBytes;
119
133
  */
120
134
  export declare const testCreateRandomBytes: (deps: RandomLibDep) => RandomBytes;
121
135
  /**
122
- * SLIP21.
136
+ * Derives a 32-byte key from a seed and a path using
137
+ * [SLIP-21](https://github.com/satoshilabs/slips/blob/master/slip-0021.md).
123
138
  *
124
- * https://github.com/satoshilabs/slips/blob/master/slip-0021.md
139
+ * Derived keys are no stronger than the seed. A 16-byte seed gives 128 bits of
140
+ * security, or about 64 against a quantum computer, whatever the output length.
141
+ * Use a 32-byte random seed for keys that must stay safe against a quantum
142
+ * computer.
125
143
  *
126
144
  * @group Key derivation
127
145
  */
128
- export declare const createSlip21: (seed: Entropy16 | Entropy32 | Entropy64, path: ReadonlyArray<string | number>) => Entropy32;
146
+ export declare const createSlip21: (seed: Entropy16 | Entropy20 | Entropy24 | Entropy28 | Entropy32 | Entropy64, path: ReadonlyArray<string | number>) => Entropy32;
129
147
  /**
130
148
  * Derives a single node in the SLIP-21 hierarchical key derivation.
131
149
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Crypto.d.ts","sourceRoot":"","sources":["../../src/Crypto.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Crypto.d.ts","sourceRoot":"","sources":["../../src/Crypto.ts"],"names":[],"mappings":"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"}
@@ -20,12 +20,24 @@ const Entropy = /*#__PURE__*/ brand("Entropy", Uint8Array);
20
20
  * @group Random bytes
21
21
  */
22
22
  export const Entropy16 = /*#__PURE__*/ length(16)(Entropy);
23
+ /**
24
+ * Cryptographic entropy of exactly 20 bytes.
25
+ *
26
+ * @group Random bytes
27
+ */
28
+ export const Entropy20 = /*#__PURE__*/ length(20)(Entropy);
23
29
  /**
24
30
  * Cryptographic entropy of exactly 24 bytes.
25
31
  *
26
32
  * @group Random bytes
27
33
  */
28
34
  export const Entropy24 = /*#__PURE__*/ length(24)(Entropy);
35
+ /**
36
+ * Cryptographic entropy of exactly 28 bytes.
37
+ *
38
+ * @group Random bytes
39
+ */
40
+ export const Entropy28 = /*#__PURE__*/ length(28)(Entropy);
29
41
  /**
30
42
  * Cryptographic entropy of exactly 32 bytes.
31
43
  *
@@ -56,9 +68,13 @@ export const testCreateRandomBytes = (deps) => ({
56
68
  create: (bytesLength) => globalThis.Uint8Array.from({ length: bytesLength }, () => deps.randomLib.int(0, 255)),
57
69
  });
58
70
  /**
59
- * SLIP21.
71
+ * Derives a 32-byte key from a seed and a path using
72
+ * [SLIP-21](https://github.com/satoshilabs/slips/blob/master/slip-0021.md).
60
73
  *
61
- * https://github.com/satoshilabs/slips/blob/master/slip-0021.md
74
+ * Derived keys are no stronger than the seed. A 16-byte seed gives 128 bits of
75
+ * security, or about 64 against a quantum computer, whatever the output length.
76
+ * Use a 32-byte random seed for keys that must stay safe against a quantum
77
+ * computer.
62
78
  *
63
79
  * @group Key derivation
64
80
  */
@@ -132,17 +132,29 @@ export type OwnerWriteKey = typeof OwnerWriteKey.Output;
132
132
  */
133
133
  export declare const createOwnerWriteKey: (deps: RandomBytesDep) => OwnerWriteKey;
134
134
  /**
135
- * 32 bytes of cryptographic entropy used to derive {@link Owner} keys.
136
- *
137
- * Can be created using {@link createOwnerSecret} or converted from a
138
- * {@link Mnemonic} using {@link mnemonicToOwnerSecret}.
135
+ * BIP-39 entropy used to derive {@link Owner} keys.
136
+ *
137
+ * A {@link Mnemonic} represents an OwnerSecret, so each valid mnemonic converts
138
+ * to exactly one secret with {@link mnemonicToOwnerSecret} and back with
139
+ * {@link ownerSecretToMnemonic}. A 24-word mnemonic holds 32 bytes, a 12-word
140
+ * mnemonic holds 16 bytes, and 15, 18, and 21 words hold 20, 24, and 28 bytes.
141
+ *
142
+ * {@link createOwnerSecret} generates 32 random bytes, which keep the owner
143
+ * post-quantum safe. The {@link OwnerId} is public and derived from the secret,
144
+ * so anyone who stores an owner's encrypted data can test guesses of the secret
145
+ * offline, and a quantum computer needs only about the square root of the
146
+ * guesses. 32 random bytes leave about 128 bits of security, while 16 bytes
147
+ * leave about 64. A secret derived from a smaller root, such as a 20-word
148
+ * SLIP-39 share, is no stronger than that root, whatever its length. Shorter
149
+ * secrets are accepted for owners created outside Evolu, typically from 12-word
150
+ * mnemonics.
139
151
  *
140
152
  * @group Core
141
153
  */
142
- export declare const OwnerSecret: import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length32", import("../Type.ts").LengthError<32>>, "OwnerSecret", never>;
154
+ export declare const OwnerSecret: import("../Type.ts").BrandType<import("../Type.ts").UnionType<readonly [import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length16", import("../Type.ts").LengthError<16>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length20", import("../Type.ts").LengthError<20>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length24", import("../Type.ts").LengthError<24>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length28", import("../Type.ts").LengthError<28>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length32", import("../Type.ts").LengthError<32>>]>, "OwnerSecret", never>;
143
155
  export type OwnerSecret = typeof OwnerSecret.Output;
144
156
  /**
145
- * Creates a cryptographically random {@link OwnerSecret}.
157
+ * Creates a cryptographically random 32-byte {@link OwnerSecret}.
146
158
  *
147
159
  * @group Core
148
160
  */
@@ -152,7 +164,7 @@ export declare const createOwnerSecret: (deps: RandomBytesDep) => OwnerSecret;
152
164
  *
153
165
  * @group Testing
154
166
  */
155
- export declare const testOwnerSecret: Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length32"> & import("../Brand.ts").Brand<"OwnerSecret">;
167
+ export declare const testOwnerSecret: ((Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length16">) | (Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length20">) | (Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length24">) | (Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length28">) | (Uint8Array<ArrayBufferLike> & import("../Brand.ts").Brand<"Entropy"> & import("../Brand.ts").Brand<"Length32">)) & import("../Brand.ts").Brand<"OwnerSecret">;
156
168
  /**
157
169
  * Converts an {@link OwnerSecret} to a {@link Mnemonic}.
158
170
  *
@@ -160,7 +172,7 @@ export declare const testOwnerSecret: Uint8Array<ArrayBufferLike> & import("../B
160
172
  */
161
173
  export declare const ownerSecretToMnemonic: (secret: OwnerSecret) => Mnemonic;
162
174
  /**
163
- * Converts a {@link Mnemonic} to an {@link OwnerSecret}.
175
+ * Converts a {@link Mnemonic} to the {@link OwnerSecret} it represents.
164
176
  *
165
177
  * @group Core
166
178
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../../src/local-first/Owner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Owner.d.ts","sourceRoot":"","sources":["../../../src/local-first/Owner.ts"],"names":[],"mappings":"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"}
@@ -41,10 +41,10 @@
41
41
  */
42
42
  import * as bip39 from "@scure/bip39";
43
43
  import { wordlist } from "@scure/bip39/wordlists/english.js";
44
- import { createSlip21, EncryptionKey, Entropy16, Entropy32, testCreateRandomBytes, } from "../Crypto.js";
44
+ import { createSlip21, EncryptionKey, Entropy16, Entropy20, Entropy24, Entropy28, Entropy32, testCreateRandomBytes, } from "../Crypto.js";
45
45
  import { testCreateRandomLib } from "../Random.js";
46
46
  import { getOrNull } from "../Result.js";
47
- import { brand, Id, IdBytes, idBytesToId, idToIdBytes, Mnemonic, NonNegativeInt, } from "../Type.js";
47
+ import { brand, Id, IdBytes, idBytesToId, idToIdBytes, Mnemonic, NonNegativeInt, union, } from "../Type.js";
48
48
  import { TimestampBytes } from "./Timestamp.js";
49
49
  /**
50
50
  * A branded {@link Id} that uniquely identifies an {@link Owner}.
@@ -99,16 +99,29 @@ export const OwnerWriteKey = /*#__PURE__*/ brand("OwnerWriteKey", Entropy16);
99
99
  */
100
100
  export const createOwnerWriteKey = (deps) => deps.randomBytes.create(16);
101
101
  /**
102
- * 32 bytes of cryptographic entropy used to derive {@link Owner} keys.
103
- *
104
- * Can be created using {@link createOwnerSecret} or converted from a
105
- * {@link Mnemonic} using {@link mnemonicToOwnerSecret}.
102
+ * BIP-39 entropy used to derive {@link Owner} keys.
103
+ *
104
+ * A {@link Mnemonic} represents an OwnerSecret, so each valid mnemonic converts
105
+ * to exactly one secret with {@link mnemonicToOwnerSecret} and back with
106
+ * {@link ownerSecretToMnemonic}. A 24-word mnemonic holds 32 bytes, a 12-word
107
+ * mnemonic holds 16 bytes, and 15, 18, and 21 words hold 20, 24, and 28 bytes.
108
+ *
109
+ * {@link createOwnerSecret} generates 32 random bytes, which keep the owner
110
+ * post-quantum safe. The {@link OwnerId} is public and derived from the secret,
111
+ * so anyone who stores an owner's encrypted data can test guesses of the secret
112
+ * offline, and a quantum computer needs only about the square root of the
113
+ * guesses. 32 random bytes leave about 128 bits of security, while 16 bytes
114
+ * leave about 64. A secret derived from a smaller root, such as a 20-word
115
+ * SLIP-39 share, is no stronger than that root, whatever its length. Shorter
116
+ * secrets are accepted for owners created outside Evolu, typically from 12-word
117
+ * mnemonics.
106
118
  *
107
119
  * @group Core
108
120
  */
109
- export const OwnerSecret = /*#__PURE__*/ brand("OwnerSecret", Entropy32);
121
+ export const OwnerSecret = /*#__PURE__*/ brand("OwnerSecret",
122
+ /*#__PURE__*/ union(Entropy16, Entropy20, Entropy24, Entropy28, Entropy32));
110
123
  /**
111
- * Creates a cryptographically random {@link OwnerSecret}.
124
+ * Creates a cryptographically random 32-byte {@link OwnerSecret}.
112
125
  *
113
126
  * @group Core
114
127
  */
@@ -130,11 +143,11 @@ export const testOwnerSecret = /*#__PURE__*/ createOwnerSecret({
130
143
  */
131
144
  export const ownerSecretToMnemonic = (secret) => bip39.entropyToMnemonic(secret, wordlist);
132
145
  /**
133
- * Converts a {@link Mnemonic} to an {@link OwnerSecret}.
146
+ * Converts a {@link Mnemonic} to the {@link OwnerSecret} it represents.
134
147
  *
135
148
  * @group Core
136
149
  */
137
- export const mnemonicToOwnerSecret = (mnemonic) => bip39.mnemonicToEntropy(mnemonic, wordlist);
150
+ export const mnemonicToOwnerSecret = (mnemonic) => OwnerSecret.orThrow(bip39.mnemonicToEntropy(mnemonic, wordlist));
138
151
  /**
139
152
  * Creates an {@link Owner} from a {@link OwnerSecret} using SLIP-21 key
140
153
  * derivation.
@@ -192,7 +192,7 @@ export declare const testLocalOnlyEvoluSchema: {
192
192
  readonly id: import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"String", string, string, import("../Type.ts").TypeOfError<"String">, null, import("../Type.ts").TypeOfError<"String">, never, string, true>, "Id", import("../Type.ts").IdError>, "OwnerId", never>;
193
193
  readonly encryptionKey: import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length32", import("../Type.ts").LengthError<32>>, "EncryptionKey", never>, "OwnerEncryptionKey", never>;
194
194
  readonly writeKey: import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length16", import("../Type.ts").LengthError<16>>, "OwnerWriteKey", never>;
195
- readonly secret: UnionType<readonly [import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length32", import("../Type.ts").LengthError<32>>, "OwnerSecret", never>, import("../Type.ts").LiteralType<null>]>;
195
+ readonly secret: UnionType<readonly [import("../Type.ts").BrandType<UnionType<readonly [import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length16", import("../Type.ts").LengthError<16>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length20", import("../Type.ts").LengthError<20>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length24", import("../Type.ts").LengthError<24>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length28", import("../Type.ts").LengthError<28>>, import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("../Type.ts").ObjectTagError<"Uint8Array">, null, import("../Type.ts").ObjectTagError<"Uint8Array">, never, Uint8Array<ArrayBufferLike>, true>, "Entropy", never>, "Length32", import("../Type.ts").LengthError<32>>]>, "OwnerSecret", never>, import("../Type.ts").LiteralType<null>]>;
196
196
  readonly name: UnionType<readonly [import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").BrandType<import("../Type.ts").Type<"String", string, string, import("../Type.ts").TypeOfError<"String">, null, import("../Type.ts").TypeOfError<"String">, never, string, true>, "Trimmed", import("../Type.ts").TrimmedError>, "MinLength1", import("../Type.ts").MinLengthError<1>>, "MaxLength100", import("../Type.ts").MaxLengthError<100>>, import("../Type.ts").LiteralType<null>]>;
197
197
  };
198
198
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolu/common",
3
- "version": "8.16.0",
3
+ "version": "8.17.0",
4
4
  "description": "TypeScript library and local-first platform",
5
5
  "keywords": [
6
6
  "evolu",
package/src/Crypto.ts CHANGED
@@ -102,6 +102,14 @@ type Entropy = typeof Entropy.Output;
102
102
  export const Entropy16 = /*#__PURE__*/ length(16)(Entropy);
103
103
  export type Entropy16 = typeof Entropy16.Output;
104
104
 
105
+ /**
106
+ * Cryptographic entropy of exactly 20 bytes.
107
+ *
108
+ * @group Random bytes
109
+ */
110
+ export const Entropy20 = /*#__PURE__*/ length(20)(Entropy);
111
+ export type Entropy20 = typeof Entropy20.Output;
112
+
105
113
  /**
106
114
  * Cryptographic entropy of exactly 24 bytes.
107
115
  *
@@ -110,6 +118,14 @@ export type Entropy16 = typeof Entropy16.Output;
110
118
  export const Entropy24 = /*#__PURE__*/ length(24)(Entropy);
111
119
  export type Entropy24 = typeof Entropy24.Output;
112
120
 
121
+ /**
122
+ * Cryptographic entropy of exactly 28 bytes.
123
+ *
124
+ * @group Random bytes
125
+ */
126
+ export const Entropy28 = /*#__PURE__*/ length(28)(Entropy);
127
+ export type Entropy28 = typeof Entropy28.Output;
128
+
113
129
  /**
114
130
  * Cryptographic entropy of exactly 32 bytes.
115
131
  *
@@ -150,14 +166,18 @@ export const testCreateRandomBytes = (deps: RandomLibDep): RandomBytes =>
150
166
  }) as RandomBytes;
151
167
 
152
168
  /**
153
- * SLIP21.
169
+ * Derives a 32-byte key from a seed and a path using
170
+ * [SLIP-21](https://github.com/satoshilabs/slips/blob/master/slip-0021.md).
154
171
  *
155
- * https://github.com/satoshilabs/slips/blob/master/slip-0021.md
172
+ * Derived keys are no stronger than the seed. A 16-byte seed gives 128 bits of
173
+ * security, or about 64 against a quantum computer, whatever the output length.
174
+ * Use a 32-byte random seed for keys that must stay safe against a quantum
175
+ * computer.
156
176
  *
157
177
  * @group Key derivation
158
178
  */
159
179
  export const createSlip21 = (
160
- seed: Entropy16 | Entropy32 | Entropy64,
180
+ seed: Entropy16 | Entropy20 | Entropy24 | Entropy28 | Entropy32 | Entropy64,
161
181
  path: ReadonlyArray<string | number>,
162
182
  ): Entropy32 => {
163
183
  let currentNode = hmac(
@@ -1,12 +1,21 @@
1
+ import { bytesToHex } from "@noble/hashes/utils.js";
2
+ import * as bip39 from "@scure/bip39";
3
+ import { wordlist } from "@scure/bip39/wordlists/english.js";
1
4
  import { eqData } from "../Eq.ts";
2
5
  import { test } from "node:test";
3
- import { assertEqual, assertFalse, assertNotUndefined } from "../Assert.ts";
6
+ import {
7
+ assertEqual,
8
+ assertFalse,
9
+ assertNotUndefined,
10
+ assertTrue,
11
+ } from "../Assert.ts";
4
12
 
5
13
  import {
6
14
  createAppOwner,
7
15
  createOwnerSecret,
8
16
  deriveShardOwner,
9
17
  mnemonicToOwnerSecret,
18
+ OwnerSecret,
10
19
  ownerIdBytesToOwnerId,
11
20
  ownerIdToOwnerIdBytes,
12
21
  ownerSecretToMnemonic,
@@ -14,6 +23,7 @@ import {
14
23
  testOwnerSecret,
15
24
  } from "./Owner.ts";
16
25
  import { testCreateDeps } from "../Task.ts";
26
+ import { Mnemonic } from "../Type.ts";
17
27
 
18
28
  const testOwnerSecret2 = createOwnerSecret(testCreateDeps({ seed: "owner-2" }));
19
29
 
@@ -31,6 +41,47 @@ test("ownerSecretToMnemonic and mnemonicToOwnerSecret are inverses", () => {
31
41
  assertEqual(backToSecret, secret);
32
42
  });
33
43
 
44
+ test("mnemonicToOwnerSecret converts every BIP-39 mnemonic length", () => {
45
+ for (const [words, bytes] of [
46
+ [12, 16],
47
+ [15, 20],
48
+ [18, 24],
49
+ [21, 28],
50
+ [24, 32],
51
+ ] as const) {
52
+ const entropy = new Uint8Array(bytes).fill(words);
53
+ const mnemonic = Mnemonic.orThrow(
54
+ bip39.entropyToMnemonic(entropy, wordlist),
55
+ );
56
+ const secret = mnemonicToOwnerSecret(mnemonic);
57
+
58
+ assertEqual(mnemonic.split(" ").length, words);
59
+ assertTrue(OwnerSecret.is(secret));
60
+ assertEqual(secret, entropy);
61
+ assertEqual(ownerSecretToMnemonic(secret), mnemonic);
62
+ }
63
+ });
64
+
65
+ test("OwnerSecret rejects lengths that no mnemonic holds", () => {
66
+ assertFalse(OwnerSecret.is(new Uint8Array(17)));
67
+ assertFalse(OwnerSecret.is(new Uint8Array(64)));
68
+ });
69
+
70
+ test("createAppOwner derives fixed keys from a 12-word mnemonic", () => {
71
+ const owner = createAppOwner(
72
+ mnemonicToOwnerSecret(
73
+ Mnemonic.orThrow("all all all all all all all all all all all all"),
74
+ ),
75
+ );
76
+
77
+ assertEqual(owner.id, "njGMKFwCtldekpIYmB-VKA");
78
+ assertEqual(
79
+ bytesToHex(owner.encryptionKey),
80
+ "d9cae8d1e141e9f4824ba9b56b9b991d242c1a37f48a146053c3d69f432c5599",
81
+ );
82
+ assertEqual(bytesToHex(owner.writeKey), "8d77d62517c4d525223647a189261ab2");
83
+ });
84
+
34
85
  test("createAppOwner is deterministic", () => {
35
86
  const owner1 = createAppOwner(testOwnerSecret);
36
87
  const owner2 = createAppOwner(testOwnerSecret);
@@ -48,6 +48,9 @@ import {
48
48
  createSlip21,
49
49
  EncryptionKey,
50
50
  Entropy16,
51
+ Entropy20,
52
+ Entropy24,
53
+ Entropy28,
51
54
  Entropy32,
52
55
  testCreateRandomBytes,
53
56
  } from "../Crypto.ts";
@@ -62,6 +65,7 @@ import {
62
65
  Mnemonic,
63
66
  NonNegativeInt,
64
67
  type Typed,
68
+ union,
65
69
  } from "../Type.ts";
66
70
  import type { EncryptedDbChange, Storage } from "./Storage.ts";
67
71
  import { TimestampBytes } from "./Timestamp.ts";
@@ -172,18 +176,33 @@ export const createOwnerWriteKey = (deps: RandomBytesDep): OwnerWriteKey =>
172
176
  deps.randomBytes.create(16) as OwnerWriteKey;
173
177
 
174
178
  /**
175
- * 32 bytes of cryptographic entropy used to derive {@link Owner} keys.
179
+ * BIP-39 entropy used to derive {@link Owner} keys.
176
180
  *
177
- * Can be created using {@link createOwnerSecret} or converted from a
178
- * {@link Mnemonic} using {@link mnemonicToOwnerSecret}.
181
+ * A {@link Mnemonic} represents an OwnerSecret, so each valid mnemonic converts
182
+ * to exactly one secret with {@link mnemonicToOwnerSecret} and back with
183
+ * {@link ownerSecretToMnemonic}. A 24-word mnemonic holds 32 bytes, a 12-word
184
+ * mnemonic holds 16 bytes, and 15, 18, and 21 words hold 20, 24, and 28 bytes.
185
+ *
186
+ * {@link createOwnerSecret} generates 32 random bytes, which keep the owner
187
+ * post-quantum safe. The {@link OwnerId} is public and derived from the secret,
188
+ * so anyone who stores an owner's encrypted data can test guesses of the secret
189
+ * offline, and a quantum computer needs only about the square root of the
190
+ * guesses. 32 random bytes leave about 128 bits of security, while 16 bytes
191
+ * leave about 64. A secret derived from a smaller root, such as a 20-word
192
+ * SLIP-39 share, is no stronger than that root, whatever its length. Shorter
193
+ * secrets are accepted for owners created outside Evolu, typically from 12-word
194
+ * mnemonics.
179
195
  *
180
196
  * @group Core
181
197
  */
182
- export const OwnerSecret = /*#__PURE__*/ brand("OwnerSecret", Entropy32);
198
+ export const OwnerSecret = /*#__PURE__*/ brand(
199
+ "OwnerSecret",
200
+ /*#__PURE__*/ union(Entropy16, Entropy20, Entropy24, Entropy28, Entropy32),
201
+ );
183
202
  export type OwnerSecret = typeof OwnerSecret.Output;
184
203
 
185
204
  /**
186
- * Creates a cryptographically random {@link OwnerSecret}.
205
+ * Creates a cryptographically random 32-byte {@link OwnerSecret}.
187
206
  *
188
207
  * @group Core
189
208
  */
@@ -210,12 +229,12 @@ export const ownerSecretToMnemonic = (secret: OwnerSecret): Mnemonic =>
210
229
  bip39.entropyToMnemonic(secret, wordlist) as Mnemonic;
211
230
 
212
231
  /**
213
- * Converts a {@link Mnemonic} to an {@link OwnerSecret}.
232
+ * Converts a {@link Mnemonic} to the {@link OwnerSecret} it represents.
214
233
  *
215
234
  * @group Core
216
235
  */
217
236
  export const mnemonicToOwnerSecret = (mnemonic: Mnemonic): OwnerSecret =>
218
- bip39.mnemonicToEntropy(mnemonic, wordlist) as OwnerSecret;
237
+ OwnerSecret.orThrow(bip39.mnemonicToEntropy(mnemonic, wordlist));
219
238
 
220
239
  /**
221
240
  * Creates an {@link Owner} from a {@link OwnerSecret} using SLIP-21 key