@opensecret/react 1.0.1 → 1.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.
package/README.md CHANGED
@@ -94,31 +94,79 @@ The `useOpenSecret` hook provides access to the OpenSecret API. It returns an ob
94
94
  - `generateThirdPartyToken(audience?: string): Promise<{ token: string }>`: Generates a JWT token for use with third-party services. If an audience is provided, it can be any valid URL. If omitted, a token with no audience restriction will be generated.
95
95
 
96
96
  #### Cryptographic Methods
97
- - `getPrivateKey(): Promise<{ mnemonic: string }>`: Retrieves the user's private key mnemonic phrase. This is used for cryptographic operations and should be kept secure.
98
-
99
- - `getPrivateKeyBytes(derivationPath?: string): Promise<{ private_key: string }>`: Retrieves the private key bytes for a given BIP32 derivation path. If no path is provided, returns the master private key bytes.
100
- - Supports both absolute (starting with "m/") and relative paths
101
- - Supports hardened derivation using either ' or h notation
102
- Examples:
103
- - Absolute path: "m/44'/0'/0'/0/0"
104
- - Relative path: "0'/0'/0'/0/0"
105
- - Hardened notation: "44'" or "44h"
106
- - Common paths:
107
- - BIP44 (Legacy): `m/44'/0'/0'/0/0`
108
- - BIP49 (SegWit): `m/49'/0'/0'/0/0`
109
- - BIP84 (Native SegWit): `m/84'/0'/0'/0/0`
110
- - BIP86 (Taproot): `m/86'/0'/0'/0/0`
111
-
112
- - `getPublicKey(algorithm: 'schnorr' | 'ecdsa', derivationPath?: string): Promise<PublicKeyResponse>`: Retrieves the user's public key for the specified signing algorithm and optional derivation path. The derivation path determines which child key pair is used, allowing different public keys to be generated from the same master key. This is useful for:
113
- - Separating keys by purpose (e.g., different chains or applications)
114
- - Generating deterministic addresses
115
- - Supporting different address formats (Legacy, SegWit, Native SegWit, Taproot)
97
+
98
+ ##### Key Derivation Options
99
+
100
+ For cryptographic operations, the SDK supports a `KeyOptions` object with the following structure:
101
+
102
+ ```typescript
103
+ type KeyOptions = {
104
+ /**
105
+ * BIP-85 derivation path to derive a child mnemonic
106
+ * Example: "m/83696968'/39'/0'/12'/0'"
107
+ */
108
+ seed_phrase_derivation_path?: string;
109
+
110
+ /**
111
+ * BIP-32 derivation path to derive a child key from the master (or BIP-85 derived) seed
112
+ * Example: "m/44'/0'/0'/0/0"
113
+ */
114
+ private_key_derivation_path?: string;
115
+ };
116
+ ```
117
+
118
+ All cryptographic methods accept this `KeyOptions` object as a parameter to specify derivation options.
119
+
120
+ ##### Methods
121
+
122
+ - `getPrivateKey(key_options?: KeyOptions): Promise<{ mnemonic: string }>`: Retrieves the user's private key mnemonic phrase.
123
+ - If no key_options are provided, returns the master mnemonic
124
+ - If `seed_phrase_derivation_path` is provided, returns a BIP-85 derived child mnemonic
125
+ - For BIP-85, the path format is typically `m/83696968'/39'/0'/12'/0'` where:
126
+ - `83696968'` is the hardened BIP-85 application number (ASCII for "BIPS")
127
+ - `39'` is the hardened BIP-39 application (for mnemonic derivation)
128
+ - `0'` is the hardened coin type (0' for Bitcoin)
129
+ - `12'` is the hardened entropy in words (12-word mnemonic)
130
+ - `0'` is the hardened index (can be incremented to generate different phrases)
131
+
132
+ - `getPrivateKeyBytes(key_options?: KeyOptions): Promise<{ private_key: string }>`: Retrieves the private key bytes with flexible derivation options.
133
+ - Supports multiple derivation approaches:
134
+
135
+ 1. Master key only (no parameters)
136
+ - Returns the master private key bytes
137
+
138
+ 2. BIP-32 derivation only
139
+ - Uses path format like `m/44'/0'/0'/0/0`
140
+ - Supports both absolute (starting with "m/") and relative paths
141
+ - Supports hardened derivation using either ' or h notation
142
+
143
+ 3. BIP-85 derivation only
144
+ - Derives a child mnemonic from the master seed using BIP-85
145
+ - Then returns the master private key of that derived seed
146
+
147
+ 4. Combined BIP-85 and BIP-32 derivation
148
+ - First derives a child mnemonic via BIP-85
149
+ - Then applies BIP-32 derivation to that derived seed
150
+
151
+ Common BIP-32 paths:
152
+ - BIP44 (Legacy): `m/44'/0'/0'/0/0`
153
+ - BIP49 (SegWit): `m/49'/0'/0'/0/0`
154
+ - BIP84 (Native SegWit): `m/84'/0'/0'/0/0`
155
+ - BIP86 (Taproot): `m/86'/0'/0'/0/0`
156
+
157
+ - `getPublicKey(algorithm: 'schnorr' | 'ecdsa', key_options?: KeyOptions): Promise<PublicKeyResponse>`: Retrieves the user's public key for the specified signing algorithm and derivation options.
158
+
159
+ The derivation paths determine which key is used to generate the public key:
160
+ - Master key (no parameters)
161
+ - BIP-32 derived key
162
+ - BIP-85 derived key
163
+ - Combined BIP-85 + BIP-32 derived key
116
164
 
117
165
  Supports two algorithms:
118
166
  - `'schnorr'`: For Schnorr signatures
119
167
  - `'ecdsa'`: For ECDSA signatures
120
168
 
121
- - `signMessage(messageBytes: Uint8Array, algorithm: 'schnorr' | 'ecdsa', derivationPath?: string): Promise<SignatureResponse>`: Signs a message using the specified algorithm and optional derivation path. The message must be provided as a Uint8Array of bytes. Returns a signature that can be verified using the corresponding public key.
169
+ - `signMessage(messageBytes: Uint8Array, algorithm: 'schnorr' | 'ecdsa', key_options?: KeyOptions): Promise<SignatureResponse>`: Signs a message using the specified algorithm and derivation options.
122
170
 
123
171
  Example message preparation:
124
172
  ```typescript
@@ -129,36 +177,129 @@ The `useOpenSecret` hook provides access to the OpenSecret API. It returns an ob
129
177
  const messageBytes = new Uint8Array(Buffer.from("deadbeef", "hex"));
130
178
  ```
131
179
 
132
- - `encryptData(data: string, derivationPath?: string): Promise<{ encrypted_data: string }>`: Encrypts arbitrary string data using the user's private key.
133
- - Uses AES-256-GCM encryption with a random nonce for each operation
134
- - If derivation_path is provided, encryption uses the derived key at that path
135
- - If derivation_path is omitted, encryption uses the master key
136
- - Returns base64-encoded encrypted data containing the nonce, ciphertext, and authentication tag
180
+ - `encryptData(data: string, key_options?: KeyOptions): Promise<{ encrypted_data: string }>`: Encrypts arbitrary string data using the user's private key with flexible derivation options.
137
181
 
138
- Example:
182
+ Examples:
139
183
  ```typescript
140
184
  // Encrypt with master key
141
185
  const { encrypted_data } = await os.encryptData("Secret message");
142
186
 
143
- // Encrypt with derived key
144
- const { encrypted_data } = await os.encryptData("Secret message", "m/44'/0'/0'/0/0");
187
+ // Encrypt with BIP-32 derived key
188
+ const { encrypted_data } = await os.encryptData("Secret message", {
189
+ private_key_derivation_path: "m/44'/0'/0'/0/0"
190
+ });
191
+
192
+ // Encrypt with BIP-85 derived key
193
+ const { encrypted_data } = await os.encryptData("Secret message", {
194
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'"
195
+ });
196
+
197
+ // Encrypt with combined BIP-85 and BIP-32 derivation
198
+ const { encrypted_data } = await os.encryptData("Secret message", {
199
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'",
200
+ private_key_derivation_path: "m/44'/0'/0'/0/0"
201
+ });
145
202
  ```
146
203
 
147
- - `decryptData(encryptedData: string, derivationPath?: string): Promise<string>`: Decrypts data that was previously encrypted with the user's key.
148
- - Uses AES-256-GCM decryption with authentication tag verification
149
- - If derivation_path is provided, decryption uses the derived key at that path
150
- - If derivation_path is omitted, decryption uses the master key
151
- - The encrypted_data must be in the exact format returned by the encrypt endpoint
204
+ - `decryptData(encryptedData: string, key_options?: KeyOptions): Promise<string>`: Decrypts data that was previously encrypted with the user's key.
152
205
 
153
- Example:
206
+ IMPORTANT: You must use the exact same derivation options for decryption that were used for encryption.
207
+
208
+ Examples:
154
209
  ```typescript
155
210
  // Decrypt with master key
156
211
  const decrypted = await os.decryptData(encrypted_data);
157
212
 
158
- // Decrypt with derived key (must use same path as encryption)
159
- const decrypted = await os.decryptData(encrypted_data, "m/44'/0'/0'/0/0");
213
+ // Decrypt with BIP-32 derived key
214
+ const decrypted = await os.decryptData(encrypted_data, {
215
+ private_key_derivation_path: "m/44'/0'/0'/0/0"
216
+ });
217
+
218
+ // Decrypt with BIP-85 derived key
219
+ const decrypted = await os.decryptData(encrypted_data, {
220
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'"
221
+ });
222
+
223
+ // Decrypt with combined BIP-85 and BIP-32 derivation
224
+ const decrypted = await os.decryptData(encrypted_data, {
225
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'",
226
+ private_key_derivation_path: "m/44'/0'/0'/0/0"
227
+ });
160
228
  ```
161
229
 
230
+ ##### Implementation Examples
231
+
232
+ 1. Basic Usage with Default Master Key
233
+
234
+ ```typescript
235
+ // Get the master mnemonic
236
+ const { mnemonic } = await os.getPrivateKey();
237
+
238
+ // Get the master private key bytes
239
+ const { private_key } = await os.getPrivateKeyBytes();
240
+
241
+ // Sign with the master key
242
+ const signature = await os.signMessage(messageBytes, 'ecdsa');
243
+ ```
244
+
245
+ 2. Using BIP-32 Derivation Only
246
+
247
+ ```typescript
248
+ // Get private key bytes using BIP-32 derivation
249
+ const { private_key } = await os.getPrivateKeyBytes({
250
+ private_key_derivation_path: "m/44'/0'/0'/0/0"
251
+ });
252
+
253
+ // Sign with a derived key
254
+ const signature = await os.signMessage(messageBytes, 'ecdsa', {
255
+ private_key_derivation_path: "m/44'/0'/0'/0/0"
256
+ });
257
+ ```
258
+
259
+ 3. Using BIP-85 Derivation Only
260
+
261
+ ```typescript
262
+ // Get a child mnemonic phrase derived via BIP-85
263
+ const { mnemonic } = await os.getPrivateKey({
264
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'"
265
+ });
266
+
267
+ // Get master private key of a BIP-85 derived seed
268
+ const { private_key } = await os.getPrivateKeyBytes({
269
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'"
270
+ });
271
+ ```
272
+
273
+ 4. Using Both BIP-85 and BIP-32 Derivation
274
+
275
+ ```typescript
276
+ // Get private key bytes derived through BIP-85 and then BIP-32
277
+ const { private_key } = await os.getPrivateKeyBytes({
278
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'",
279
+ private_key_derivation_path: "m/44'/0'/0'/0/0"
280
+ });
281
+
282
+ // Sign a message with a key derived through both methods
283
+ const signature = await os.signMessage(messageBytes, 'schnorr', {
284
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'",
285
+ private_key_derivation_path: "m/44'/0'/0'/0/0"
286
+ });
287
+ ```
288
+
289
+ 5. Encryption/Decryption with Derived Keys
290
+
291
+ ```typescript
292
+ // Encrypt with a BIP-85 derived key
293
+ const { encrypted_data } = await os.encryptData("Secret message", {
294
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'"
295
+ });
296
+
297
+ // Decrypt using the same derivation path
298
+ const decrypted = await os.decryptData(encrypted_data, {
299
+ seed_phrase_derivation_path: "m/83696968'/39'/0'/12'/0'"
300
+ });
301
+ ```
302
+
162
303
  ### AI Integration
163
304
 
164
305
  To get encrypted-to-the-gpu AI chat we provide a special version of `fetch` (`os.aiCustomFetch`) that handles all the encryption. Because we require the user to be logged in, and do the encryption client-side, this is safe to call from the client.