@substrate-system/crypto-stream 0.0.34 → 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.
- package/README.md +296 -13
- package/dist/ece.cjs +87 -14
- package/dist/keychain.cjs +101 -4
- package/dist/src/ece.d.ts +76 -0
- package/dist/src/ece.d.ts.map +1 -1
- package/dist/src/ece.js +135 -7
- package/dist/src/ece.js.map +1 -1
- package/dist/src/keychain.d.ts +69 -3
- package/dist/src/keychain.d.ts.map +1 -1
- package/dist/src/keychain.js +90 -5
- package/dist/src/keychain.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,10 +18,11 @@ This uses the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/
|
|
|
18
18
|
|
|
19
19
|
<!-- toc -->
|
|
20
20
|
|
|
21
|
-
- [
|
|
22
|
-
- [
|
|
23
|
-
- [
|
|
24
|
-
* [
|
|
21
|
+
- [Install](#install)
|
|
22
|
+
- [Fork](#fork)
|
|
23
|
+
- [Example](#example)
|
|
24
|
+
* [Example With Blobs](#example-with-blobs)
|
|
25
|
+
- [Seek](#seek)
|
|
25
26
|
- [API](#api)
|
|
26
27
|
* [`new Keychain([key, [salt]])`](#new-keychainkey-salt)
|
|
27
28
|
* [`keychain.key`](#keychainkey)
|
|
@@ -32,7 +33,10 @@ This uses the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/
|
|
|
32
33
|
* [`keychain.authTokenB64()`](#keychainauthtokenb64)
|
|
33
34
|
* [`keychain.authHeader()`](#keychainauthheader)
|
|
34
35
|
* [`keychain.setAuthToken(authToken)`](#keychainsetauthtokenauthtoken)
|
|
35
|
-
* [`keychain.encryptStream(stream)`](#keychainencryptstreamstream)
|
|
36
|
+
* [`keychain.encryptStream(stream[, opts])`](#keychainencryptstreamstream-opts)
|
|
37
|
+
* [`keychain.contentDigest(content)`](#keychaincontentdigestcontent)
|
|
38
|
+
* [`keychain.header(opts)`](#keychainheaderopts)
|
|
39
|
+
* [`keychain.encryptRecord(seq, plaintext, opts)`](#keychainencryptrecordseq-plaintext-opts)
|
|
36
40
|
* [`keychain.decryptStream(encryptedStream)`](#keychaindecryptstreamencryptedstream)
|
|
37
41
|
* [`keychain.decryptStreamRange(offset, length, totalEncryptedLength)`](#keychaindecryptstreamrangeoffset-length-totalencryptedlength)
|
|
38
42
|
* [`keychain.encryptMeta(meta)`](#keychainencryptmetameta)
|
|
@@ -41,21 +45,29 @@ This uses the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/
|
|
|
41
45
|
* [`keychain.decryptBytes(bytes)`](#keychaindecryptbytesbytes)
|
|
42
46
|
* [`plaintextSize(encryptedSize)`](#plaintextsizeencryptedsize)
|
|
43
47
|
* [`encryptedSize(plaintextSize)`](#encryptedsizeplaintextsize)
|
|
48
|
+
- [Reproducible & record-addressable encryption](#reproducible--record-addressable-encryption)
|
|
49
|
+
* [Two-pass flow: hash, then encrypt](#two-pass-flow-hash-then-encrypt)
|
|
50
|
+
* [Low-level ECE building blocks](#low-level-ece-building-blocks)
|
|
44
51
|
- [credits](#credits)
|
|
45
52
|
|
|
46
53
|
<!-- tocstop -->
|
|
47
54
|
|
|
48
55
|
</details>
|
|
49
56
|
|
|
50
|
-
##
|
|
57
|
+
## Install
|
|
58
|
+
|
|
51
59
|
```sh
|
|
52
60
|
npm i -S @substrate-system/crypto-stream
|
|
53
61
|
```
|
|
54
62
|
|
|
55
|
-
##
|
|
56
|
-
|
|
63
|
+
## Fork
|
|
64
|
+
|
|
65
|
+
This is a fork of
|
|
66
|
+
[SocketDev/wormhole-crypto](https://github.com/SocketDev/wormhole-crypto).
|
|
67
|
+
Thanks [@SocketDev](https://github.com/SocketDev) team for working in the
|
|
68
|
+
world of open source.
|
|
57
69
|
|
|
58
|
-
##
|
|
70
|
+
## Example
|
|
59
71
|
|
|
60
72
|
```js
|
|
61
73
|
import { Keychain } from '@substrate-system/crypto-stream'
|
|
@@ -78,7 +90,7 @@ const plaintextStream = await keychain.decryptStream(encryptedStream)
|
|
|
78
90
|
// to if you had used `stream`.
|
|
79
91
|
```
|
|
80
92
|
|
|
81
|
-
###
|
|
93
|
+
### Example With Blobs
|
|
82
94
|
|
|
83
95
|
See [./example](./example/index.ts) for a version that uses blobs + a
|
|
84
96
|
local `vite` server.
|
|
@@ -98,6 +110,65 @@ function Component () {
|
|
|
98
110
|
}
|
|
99
111
|
```
|
|
100
112
|
|
|
113
|
+
## Seek
|
|
114
|
+
|
|
115
|
+
`crypto-stream` can seek on both sides of the cipher.
|
|
116
|
+
|
|
117
|
+
Reads use
|
|
118
|
+
[`decryptStreamRange`](#keychaindecryptstreamrangeoffset-length-totalencryptedlength),
|
|
119
|
+
which decrypts an arbitrary byte range without reading the whole
|
|
120
|
+
ciphertext.
|
|
121
|
+
|
|
122
|
+
Writes use *reproducible, record-addressable* encryption. The same plaintext
|
|
123
|
+
always encrypts to identical bytes, and you can regenerate any single record
|
|
124
|
+
on demand without re-encrypting the rest. That is what lets a peer seed a
|
|
125
|
+
large file (for example, over WebRTC) without buffering the whole ciphertext.
|
|
126
|
+
Hash the content once, then hand out individual records as they are requested.
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
import { Keychain } from '@substrate-system/crypto-stream'
|
|
130
|
+
import {
|
|
131
|
+
recordPlaintextSize,
|
|
132
|
+
recordCount
|
|
133
|
+
} from '@substrate-system/crypto-stream/src/ece'
|
|
134
|
+
|
|
135
|
+
const keychain = new Keychain()
|
|
136
|
+
const data = new TextEncoder().encode('the quick brown fox')
|
|
137
|
+
const rs = 1024 // record size; transport chunks line up with records
|
|
138
|
+
|
|
139
|
+
// 1. Hash pass. The salt is derived from this digest, so it is bound
|
|
140
|
+
// to exactly this content (no AES-GCM nonce reuse).
|
|
141
|
+
const digest = await keychain.contentDigest(data)
|
|
142
|
+
|
|
143
|
+
// 2. Reproducible whole-stream encrypt. Re-encrypting `data` with the
|
|
144
|
+
// same digest yields byte-identical output.
|
|
145
|
+
const encrypted = await keychain.encryptStream(new Response(data).body, {
|
|
146
|
+
contentDigest: digest,
|
|
147
|
+
recordSize: rs
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// 3. Record-addressable: rebuild any single record on demand. The full
|
|
151
|
+
// ciphertext is `header || rec0 || rec1 || ... || recLast`.
|
|
152
|
+
const head = await keychain.header({ contentDigest: digest, recordSize: rs })
|
|
153
|
+
|
|
154
|
+
const max = recordPlaintextSize(rs) // plaintext bytes per record
|
|
155
|
+
const count = recordCount(data.length, rs) // number of data records
|
|
156
|
+
|
|
157
|
+
const i = 0
|
|
158
|
+
const slice = data.subarray(i * max, (i + 1) * max)
|
|
159
|
+
const record = await keychain.encryptRecord(i, slice, {
|
|
160
|
+
isLast: i === count - 1,
|
|
161
|
+
contentDigest: digest,
|
|
162
|
+
recordSize: rs
|
|
163
|
+
})
|
|
164
|
+
// `head || record` equals the first record of `encrypted`, byte for byte.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
See
|
|
168
|
+
[Reproducible & record-addressable encryption](#reproducible--record-addressable-encryption)
|
|
169
|
+
for the safety model (why the salt is derived from the content) and the
|
|
170
|
+
low-level building blocks.
|
|
171
|
+
|
|
101
172
|
## API
|
|
102
173
|
|
|
103
174
|
### `new Keychain([key, [salt]])`
|
|
@@ -221,10 +292,13 @@ The authentication token. This should be 16 bytes in length. If a `string` is
|
|
|
221
292
|
given, then it should be a base64-encoded string. If this argument is `null`,
|
|
222
293
|
then an authentication token will be automatically generated.
|
|
223
294
|
|
|
224
|
-
### `keychain.encryptStream(stream)`
|
|
295
|
+
### `keychain.encryptStream(stream[, opts])`
|
|
225
296
|
|
|
226
297
|
```ts
|
|
227
|
-
encryptStream (
|
|
298
|
+
encryptStream (
|
|
299
|
+
stream:ReadableStream,
|
|
300
|
+
opts?:{ contentDigest?, recordSize? }
|
|
301
|
+
):Promise<ReadableStream>
|
|
228
302
|
```
|
|
229
303
|
|
|
230
304
|
Type: `Function`
|
|
@@ -235,12 +309,157 @@ Returns a `Promise` that resolves to a `ReadableStream` encryption stream that
|
|
|
235
309
|
consumes the data in `stream` and returns an encrypted version. Data is
|
|
236
310
|
encrypted with [Encrypted Content-Encoding for HTTP (RFC 8188)](https://tools.ietf.org/html/rfc8188).
|
|
237
311
|
|
|
312
|
+
If `opts.contentDigest` is provided, the salt is derived from the digest,
|
|
313
|
+
making the output reproducible — the same plaintext always produces
|
|
314
|
+
identical ciphertext. Without options, a fresh random salt is used
|
|
315
|
+
(default behavior; not reproducible).
|
|
316
|
+
|
|
238
317
|
#### `stream`
|
|
239
318
|
|
|
240
319
|
Type: `ReadableStream`
|
|
241
320
|
|
|
242
321
|
A WHATWG readable stream used as a data source for the encrypted stream.
|
|
243
322
|
|
|
323
|
+
#### `opts`
|
|
324
|
+
|
|
325
|
+
Type: `{ contentDigest?, recordSize? }`
|
|
326
|
+
|
|
327
|
+
Optional encryption options.
|
|
328
|
+
|
|
329
|
+
##### `contentDigest`
|
|
330
|
+
|
|
331
|
+
Type: `Uint8Array`
|
|
332
|
+
|
|
333
|
+
SHA-256 digest of the plaintext (from `keychain.contentDigest()`).
|
|
334
|
+
When provided, enables reproducible encryption by deriving the salt
|
|
335
|
+
from the digest internally.
|
|
336
|
+
|
|
337
|
+
##### `recordSize`
|
|
338
|
+
|
|
339
|
+
Type: `number`
|
|
340
|
+
|
|
341
|
+
ECE record size in bytes (default `RECORD_SIZE` = 65536). Record size
|
|
342
|
+
affects output size and encryption granularity.
|
|
343
|
+
|
|
344
|
+
### `keychain.contentDigest(content)`
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
contentDigest (
|
|
348
|
+
content:ReadableStream<Uint8Array>|Uint8Array|Blob
|
|
349
|
+
):Promise<Uint8Array>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Type: `Function`
|
|
353
|
+
|
|
354
|
+
Returns: `Promise<Uint8Array>`
|
|
355
|
+
|
|
356
|
+
Returns a 32-byte SHA-256 digest of the plaintext. Use this digest as
|
|
357
|
+
the input to `encryptStream`, `header`, and `encryptRecord` to enable
|
|
358
|
+
reproducible encryption. Accepts a stream, byte array, or Blob; streams
|
|
359
|
+
and Blobs are drained into memory before hashing.
|
|
360
|
+
|
|
361
|
+
#### `content`
|
|
362
|
+
|
|
363
|
+
Type: `ReadableStream<Uint8Array> | Uint8Array | Blob`
|
|
364
|
+
|
|
365
|
+
The plaintext to hash.
|
|
366
|
+
|
|
367
|
+
### `keychain.header(opts)`
|
|
368
|
+
|
|
369
|
+
```ts
|
|
370
|
+
header (opts:{ contentDigest, recordSize? }):Promise<Uint8Array>
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Type: `Function`
|
|
374
|
+
|
|
375
|
+
Returns: `Promise<Uint8Array>`
|
|
376
|
+
|
|
377
|
+
Returns the 21-byte ECE header for content identified by the digest.
|
|
378
|
+
The salt is derived internally from the content digest, so this never
|
|
379
|
+
exposes a raw salt. The header is byte-identical to the header that
|
|
380
|
+
`encryptStream` with the same options emits.
|
|
381
|
+
|
|
382
|
+
#### `opts`
|
|
383
|
+
|
|
384
|
+
Type: `{ contentDigest, recordSize? }`
|
|
385
|
+
|
|
386
|
+
Required options.
|
|
387
|
+
|
|
388
|
+
##### `contentDigest`
|
|
389
|
+
|
|
390
|
+
Type: `Uint8Array`
|
|
391
|
+
|
|
392
|
+
SHA-256 digest of the plaintext (from `keychain.contentDigest()`).
|
|
393
|
+
|
|
394
|
+
##### `recordSize`
|
|
395
|
+
|
|
396
|
+
Type: `number`
|
|
397
|
+
|
|
398
|
+
ECE record size in bytes (default `RECORD_SIZE` = 65536).
|
|
399
|
+
|
|
400
|
+
### `keychain.encryptRecord(seq, plaintext, opts)`
|
|
401
|
+
|
|
402
|
+
```ts
|
|
403
|
+
encryptRecord (
|
|
404
|
+
seq:number,
|
|
405
|
+
plaintext:Uint8Array,
|
|
406
|
+
opts:{
|
|
407
|
+
isLast:boolean,
|
|
408
|
+
contentDigest:Uint8Array,
|
|
409
|
+
recordSize?:number
|
|
410
|
+
}
|
|
411
|
+
):Promise<Uint8Array>
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Type: `Function`
|
|
415
|
+
|
|
416
|
+
Returns: `Promise<Uint8Array>`
|
|
417
|
+
|
|
418
|
+
Encrypts a single ECE record by index. The result is byte-identical to
|
|
419
|
+
record `seq` of `encryptStream` with the same content and options. The
|
|
420
|
+
salt is derived from the content digest internally.
|
|
421
|
+
|
|
422
|
+
Non-final records must be exactly `recordPlaintextSize(recordSize)` bytes;
|
|
423
|
+
the final record must be less than or equal to that. The low-level ECE
|
|
424
|
+
functions throw if violated.
|
|
425
|
+
|
|
426
|
+
#### `seq`
|
|
427
|
+
|
|
428
|
+
Type: `number`
|
|
429
|
+
|
|
430
|
+
Zero-based record index (0, 1, 2, ...).
|
|
431
|
+
|
|
432
|
+
#### `plaintext`
|
|
433
|
+
|
|
434
|
+
Type: `Uint8Array`
|
|
435
|
+
|
|
436
|
+
The record's plaintext data.
|
|
437
|
+
|
|
438
|
+
#### `opts`
|
|
439
|
+
|
|
440
|
+
Type: `{ isLast, contentDigest, recordSize? }`
|
|
441
|
+
|
|
442
|
+
Required options.
|
|
443
|
+
|
|
444
|
+
##### `isLast`
|
|
445
|
+
|
|
446
|
+
Type: `boolean`
|
|
447
|
+
|
|
448
|
+
Whether this is the final record of the content.
|
|
449
|
+
|
|
450
|
+
##### `contentDigest`
|
|
451
|
+
|
|
452
|
+
Type: `Uint8Array`
|
|
453
|
+
|
|
454
|
+
SHA-256 digest of the entire plaintext (from `keychain.contentDigest()`).
|
|
455
|
+
|
|
456
|
+
##### `recordSize`
|
|
457
|
+
|
|
458
|
+
Type: `number`
|
|
459
|
+
|
|
460
|
+
ECE record size in bytes (default `RECORD_SIZE` = 65536). Must match
|
|
461
|
+
the record size used for the header and other records.
|
|
462
|
+
|
|
244
463
|
### `keychain.decryptStream(encryptedStream)`
|
|
245
464
|
|
|
246
465
|
Type: `Function`
|
|
@@ -361,6 +580,70 @@ function encryptedSize (
|
|
|
361
580
|
|
|
362
581
|
Given a plaintext size, return the corresponding encrypted size.
|
|
363
582
|
|
|
583
|
+
## Reproducible & record-addressable encryption
|
|
584
|
+
|
|
585
|
+
By default, `encryptStream` uses a fresh random salt for each call.
|
|
586
|
+
This provides strong privacy (identical plaintexts don't leak through
|
|
587
|
+
repeated ciphertext), but the same input encrypted twice produces
|
|
588
|
+
different output.
|
|
589
|
+
|
|
590
|
+
For use cases like deduplication and content-addressed storage, you
|
|
591
|
+
need reproducible encryption: the same plaintext always produces
|
|
592
|
+
identical ciphertext. This is safe only if the salt is bound to the
|
|
593
|
+
plaintext, preventing a single salt from encrypting two different
|
|
594
|
+
contents (which would break AES-GCM).
|
|
595
|
+
|
|
596
|
+
The Keychain API enforces this binding automatically. The salt is
|
|
597
|
+
never chosen by the caller; it's derived from a content digest
|
|
598
|
+
(SHA-256 hash of the plaintext) via HKDF. This guarantees: a fixed
|
|
599
|
+
salt pairs with exactly one plaintext.
|
|
600
|
+
|
|
601
|
+
### Two-pass flow: hash, then encrypt
|
|
602
|
+
|
|
603
|
+
To encrypt reproducibly, first compute the content digest, then
|
|
604
|
+
pass it to the encrypt functions:
|
|
605
|
+
|
|
606
|
+
```js
|
|
607
|
+
// 1. Hash pass
|
|
608
|
+
const digest = await keychain.contentDigest(file.stream())
|
|
609
|
+
|
|
610
|
+
// 2. Encrypt pass — reproducible: same input -> identical ciphertext
|
|
611
|
+
const encrypted = await keychain.encryptStream(file.stream(), {
|
|
612
|
+
contentDigest: digest,
|
|
613
|
+
recordSize: rs
|
|
614
|
+
})
|
|
615
|
+
|
|
616
|
+
// On demand: regenerate record i byte-identically
|
|
617
|
+
const rec = await keychain.encryptRecord(i, sliceI, {
|
|
618
|
+
isLast,
|
|
619
|
+
contentDigest: digest,
|
|
620
|
+
recordSize: rs
|
|
621
|
+
})
|
|
622
|
+
// Full ciphertext = header(21) || rec0 || rec1 || ... || recLast
|
|
623
|
+
const head = await keychain.header({
|
|
624
|
+
contentDigest: digest,
|
|
625
|
+
recordSize: rs
|
|
626
|
+
})
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
Note that `encryptStream` with no options keeps the original random-salt
|
|
630
|
+
behavior and is a single pass.
|
|
631
|
+
|
|
632
|
+
### Low-level ECE building blocks
|
|
633
|
+
|
|
634
|
+
The package exports low-level ECE functions at
|
|
635
|
+
`@substrate-system/crypto-stream/src/ece`. These include `RECORD_SIZE`,
|
|
636
|
+
`HEADER_LENGTH`, `recordPlaintextSize`, `recordCount`, `header`,
|
|
637
|
+
`deriveContentSalt`, and `encryptRecord`. They take a raw salt directly
|
|
638
|
+
and are footgun-prone: passing the same raw salt with two different
|
|
639
|
+
plaintexts breaks AES-GCM (nonce-reuse catastrophe). Prefer the
|
|
640
|
+
Keychain API, which derives the salt from the content digest and is
|
|
641
|
+
nonce-reuse-safe by construction.
|
|
642
|
+
|
|
364
643
|
## credits
|
|
365
644
|
|
|
366
|
-
Thank you
|
|
645
|
+
Thank you
|
|
646
|
+
[Feross](https://github.com/feross) and
|
|
647
|
+
[SocketDev](https://github.com/SocketDev)
|
|
648
|
+
team for writing and publishing the original,
|
|
649
|
+
[wormhole-crypto](https://github.com/SocketDev/wormhole-crypto).
|
package/dist/ece.cjs
CHANGED
|
@@ -19,13 +19,20 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
19
19
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
20
|
var ece_exports = {};
|
|
21
21
|
__export(ece_exports, {
|
|
22
|
+
HEADER_LENGTH: () => HEADER_LENGTH,
|
|
22
23
|
KEY_LENGTH: () => KEY_LENGTH,
|
|
24
|
+
RECORD_SIZE: () => RECORD_SIZE,
|
|
23
25
|
TAG_LENGTH: () => TAG_LENGTH,
|
|
24
26
|
decryptStream: () => decryptStream,
|
|
25
27
|
decryptStreamRange: () => decryptStreamRange,
|
|
28
|
+
deriveContentSalt: () => deriveContentSalt,
|
|
29
|
+
encryptRecord: () => encryptRecord,
|
|
26
30
|
encryptStream: () => encryptStream,
|
|
27
31
|
encryptedSize: () => encryptedSize,
|
|
28
|
-
|
|
32
|
+
header: () => header,
|
|
33
|
+
plaintextSize: () => plaintextSize,
|
|
34
|
+
recordCount: () => recordCount,
|
|
35
|
+
recordPlaintextSize: () => recordPlaintextSize
|
|
29
36
|
});
|
|
30
37
|
module.exports = __toCommonJS(ece_exports);
|
|
31
38
|
var import_concat_streams = require("./concat-streams.js");
|
|
@@ -42,6 +49,7 @@ const NONCE_LENGTH = 12;
|
|
|
42
49
|
const RECORD_SIZE = 64 * 1024;
|
|
43
50
|
const HEADER_LENGTH = KEY_LENGTH + 4 + 1;
|
|
44
51
|
const encoder = new TextEncoder();
|
|
52
|
+
const SALT_INFO = encoder.encode("Content-Encoding: salt\0");
|
|
45
53
|
class ECETransformer {
|
|
46
54
|
static {
|
|
47
55
|
__name(this, "ECETransformer");
|
|
@@ -151,25 +159,21 @@ class ECETransformer {
|
|
|
151
159
|
}
|
|
152
160
|
createHeader() {
|
|
153
161
|
if (!this.salt) throw new Error("Not salt");
|
|
154
|
-
|
|
155
|
-
header.set(this.salt);
|
|
156
|
-
const dv = new DataView(header.buffer, header.byteOffset, header.byteLength);
|
|
157
|
-
dv.setUint32(KEY_LENGTH, this.rs);
|
|
158
|
-
return header;
|
|
162
|
+
return header(this.salt, this.rs);
|
|
159
163
|
}
|
|
160
164
|
readHeader(buffer) {
|
|
161
165
|
if (buffer.byteLength !== HEADER_LENGTH) {
|
|
162
166
|
throw new Error("chunk is not expected header length");
|
|
163
167
|
}
|
|
164
|
-
const
|
|
168
|
+
const header2 = { salt: null, rs: null };
|
|
165
169
|
const dv = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
166
|
-
|
|
167
|
-
|
|
170
|
+
header2.salt = buffer.slice(0, KEY_LENGTH);
|
|
171
|
+
header2.rs = dv.getUint32(KEY_LENGTH);
|
|
168
172
|
const idlen = dv.getUint8(KEY_LENGTH + 4);
|
|
169
173
|
if (idlen !== 0) {
|
|
170
174
|
throw new Error("Implementation does not support non-zero idlen");
|
|
171
175
|
}
|
|
172
|
-
return
|
|
176
|
+
return header2;
|
|
173
177
|
}
|
|
174
178
|
async encryptRecord(record, seq, isLast) {
|
|
175
179
|
const nonce = this.generateNonce(seq);
|
|
@@ -218,14 +222,14 @@ class ECETransformer {
|
|
|
218
222
|
} else {
|
|
219
223
|
if (this.seq === -1) {
|
|
220
224
|
if (!this.prevChunk) throw new Error("not this.prevChunk");
|
|
221
|
-
const
|
|
222
|
-
this.salt = (0, import_util.asBufferSource)(
|
|
223
|
-
if (this.rs !== null && this.rs !==
|
|
225
|
+
const header2 = this.readHeader(this.prevChunk);
|
|
226
|
+
this.salt = (0, import_util.asBufferSource)(header2.salt);
|
|
227
|
+
if (this.rs !== null && this.rs !== header2.rs) {
|
|
224
228
|
throw new Error(
|
|
225
229
|
"Record size declared in constructor does not match record size in encrypted stream"
|
|
226
230
|
);
|
|
227
231
|
}
|
|
228
|
-
this.rs =
|
|
232
|
+
this.rs = header2.rs;
|
|
229
233
|
this.key = await this.generateKey();
|
|
230
234
|
this.nonceBase = await this.generateNonceBase();
|
|
231
235
|
const startSeq = this.seekOpts.startSeq;
|
|
@@ -287,6 +291,75 @@ function plaintextSize(encryptedSize2, rs = RECORD_SIZE) {
|
|
|
287
291
|
return encryptedRecordsSize - chunkMetaLength * Math.ceil(encryptedRecordsSize / rs);
|
|
288
292
|
}
|
|
289
293
|
__name(plaintextSize, "plaintextSize");
|
|
294
|
+
function recordPlaintextSize(rs = RECORD_SIZE) {
|
|
295
|
+
if (!Number.isInteger(rs)) {
|
|
296
|
+
throw new TypeError("rs");
|
|
297
|
+
}
|
|
298
|
+
return rs - TAG_LENGTH - 1;
|
|
299
|
+
}
|
|
300
|
+
__name(recordPlaintextSize, "recordPlaintextSize");
|
|
301
|
+
function recordCount(plaintextSize2, rs = RECORD_SIZE) {
|
|
302
|
+
if (!Number.isInteger(plaintextSize2)) {
|
|
303
|
+
throw new TypeError("plaintextSize");
|
|
304
|
+
}
|
|
305
|
+
if (!Number.isInteger(rs)) {
|
|
306
|
+
throw new TypeError("rs");
|
|
307
|
+
}
|
|
308
|
+
return Math.ceil(plaintextSize2 / recordPlaintextSize(rs));
|
|
309
|
+
}
|
|
310
|
+
__name(recordCount, "recordCount");
|
|
311
|
+
function header(salt, rs = RECORD_SIZE) {
|
|
312
|
+
if (salt.byteLength !== KEY_LENGTH) {
|
|
313
|
+
throw new Error("Invalid salt length");
|
|
314
|
+
}
|
|
315
|
+
if (!Number.isInteger(rs)) {
|
|
316
|
+
throw new TypeError("rs");
|
|
317
|
+
}
|
|
318
|
+
const buf = new Uint8Array(HEADER_LENGTH);
|
|
319
|
+
buf.set(salt);
|
|
320
|
+
const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
321
|
+
dv.setUint32(KEY_LENGTH, rs);
|
|
322
|
+
return buf;
|
|
323
|
+
}
|
|
324
|
+
__name(header, "header");
|
|
325
|
+
async function deriveContentSalt(secretKey, contentDigest) {
|
|
326
|
+
if (contentDigest.byteLength === 0) {
|
|
327
|
+
throw new Error("empty content digest");
|
|
328
|
+
}
|
|
329
|
+
const infoLen = SALT_INFO.byteLength + contentDigest.byteLength;
|
|
330
|
+
const info = new Uint8Array(infoLen);
|
|
331
|
+
info.set(SALT_INFO, 0);
|
|
332
|
+
info.set(contentDigest, SALT_INFO.byteLength);
|
|
333
|
+
const bits = await import_one_webcrypto.webcrypto.subtle.deriveBits(
|
|
334
|
+
{
|
|
335
|
+
name: "HKDF",
|
|
336
|
+
hash: "SHA-256",
|
|
337
|
+
salt: new Uint8Array(0),
|
|
338
|
+
info
|
|
339
|
+
},
|
|
340
|
+
secretKey,
|
|
341
|
+
KEY_LENGTH * 8
|
|
342
|
+
);
|
|
343
|
+
return new Uint8Array(bits);
|
|
344
|
+
}
|
|
345
|
+
__name(deriveContentSalt, "deriveContentSalt");
|
|
346
|
+
async function encryptRecord(secretKey, seq, plaintext, isLast, salt, rs = RECORD_SIZE) {
|
|
347
|
+
const transformer = new ECETransformer(MODE_ENCRYPT, secretKey, rs, salt);
|
|
348
|
+
const max = recordPlaintextSize(rs);
|
|
349
|
+
if (isLast) {
|
|
350
|
+
if (plaintext.byteLength > max) {
|
|
351
|
+
throw new Error("final record exceeds recordPlaintextSize");
|
|
352
|
+
}
|
|
353
|
+
} else {
|
|
354
|
+
if (plaintext.byteLength !== max) {
|
|
355
|
+
throw new Error("non-final record must equal recordPlaintextSize");
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
transformer.key = await transformer.generateKey();
|
|
359
|
+
transformer.nonceBase = await transformer.generateNonceBase();
|
|
360
|
+
return transformer.encryptRecord(plaintext, seq, isLast);
|
|
361
|
+
}
|
|
362
|
+
__name(encryptRecord, "encryptRecord");
|
|
290
363
|
function encryptStream(input, secretKey, rs = RECORD_SIZE, salt = (0, import_util.generateSalt)(KEY_LENGTH)) {
|
|
291
364
|
const stream = (0, import_transform_stream.transformStream)(
|
|
292
365
|
input,
|
package/dist/keychain.cjs
CHANGED
|
@@ -162,17 +162,114 @@ class Keychain {
|
|
|
162
162
|
setAuthToken(authToken) {
|
|
163
163
|
this.authTokenPromise = Promise.resolve(decodeBits(authToken));
|
|
164
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* SHA-256 digest of the plaintext, used as the input to content-bound
|
|
167
|
+
* salt derivation. Accepts a stream, a byte array, or a Blob;
|
|
168
|
+
* equivalent content yields the same digest.
|
|
169
|
+
*
|
|
170
|
+
* Pass the result to `encryptStream`/`header`/`encryptRecord` as
|
|
171
|
+
* `contentDigest`. The salt is derived from this digest internally,
|
|
172
|
+
* so the Keychain API never exposes a raw salt — a fixed salt can
|
|
173
|
+
* never pair with two different plaintexts.
|
|
174
|
+
*
|
|
175
|
+
* NOTE: WebCrypto has no incremental hash, so a stream/Blob is
|
|
176
|
+
* drained into memory before hashing.
|
|
177
|
+
*
|
|
178
|
+
* @param content Plaintext as a ReadableStream, Uint8Array, or Blob.
|
|
179
|
+
* @returns 32-byte SHA-256 digest.
|
|
180
|
+
*/
|
|
181
|
+
async contentDigest(content) {
|
|
182
|
+
let bytes;
|
|
183
|
+
if (content instanceof Uint8Array) {
|
|
184
|
+
bytes = content;
|
|
185
|
+
} else if (content instanceof ReadableStream) {
|
|
186
|
+
bytes = new Uint8Array(await new Response(content).arrayBuffer());
|
|
187
|
+
} else if (typeof Blob !== "undefined" && content instanceof Blob) {
|
|
188
|
+
bytes = new Uint8Array(await content.arrayBuffer());
|
|
189
|
+
} else {
|
|
190
|
+
throw new TypeError(
|
|
191
|
+
"content must be a ReadableStream, Uint8Array, or Blob"
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
const digest = await import_one_webcrypto.webcrypto.subtle.digest(
|
|
195
|
+
"SHA-256",
|
|
196
|
+
(0, import_util.asBufferSource)(bytes)
|
|
197
|
+
);
|
|
198
|
+
return new Uint8Array(digest);
|
|
199
|
+
}
|
|
165
200
|
/**
|
|
166
201
|
* Take a stream, return an encrypted stream.
|
|
167
|
-
*
|
|
168
|
-
*
|
|
202
|
+
*
|
|
203
|
+
* With `opts.contentDigest`, the ECE salt is derived from the digest
|
|
204
|
+
* internally (`deriveContentSalt`), so two calls over identical input
|
|
205
|
+
* produce byte-identical ciphertext (reproducible encryption). With no
|
|
206
|
+
* opts, a fresh random salt is used (today's behavior).
|
|
207
|
+
*
|
|
208
|
+
* The salt is never accepted directly: because it is bound to the
|
|
209
|
+
* content digest, a fixed salt can never encrypt two different
|
|
210
|
+
* plaintexts (AES-GCM nonce-reuse is structurally unreachable from
|
|
211
|
+
* this API).
|
|
212
|
+
*
|
|
213
|
+
* @param stream Input plaintext stream.
|
|
214
|
+
* @param opts Optional `{ contentDigest?, recordSize? }`.
|
|
215
|
+
* @returns Encrypted stream.
|
|
169
216
|
*/
|
|
170
|
-
async encryptStream(stream) {
|
|
217
|
+
async encryptStream(stream, opts) {
|
|
171
218
|
if (!(stream instanceof ReadableStream)) {
|
|
172
219
|
throw new TypeError("This is not a readable stream");
|
|
173
220
|
}
|
|
174
221
|
const mainKey = await this.mainKeyPromise;
|
|
175
|
-
|
|
222
|
+
const rs = opts?.recordSize ?? import_ece.RECORD_SIZE;
|
|
223
|
+
if (opts?.contentDigest) {
|
|
224
|
+
const salt = await (0, import_ece.deriveContentSalt)(mainKey, opts.contentDigest);
|
|
225
|
+
return (0, import_ece.encryptStream)(stream, mainKey, rs, salt);
|
|
226
|
+
}
|
|
227
|
+
return (0, import_ece.encryptStream)(stream, mainKey, rs);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Build the 21-byte ECE header for content identified by
|
|
231
|
+
* `contentDigest`. The salt is derived internally from the digest,
|
|
232
|
+
* so this never exposes a raw salt. The header is byte-identical to
|
|
233
|
+
* the header that `encryptStream({ contentDigest, recordSize })`
|
|
234
|
+
* emits for the same input.
|
|
235
|
+
*
|
|
236
|
+
* @param opts `{ contentDigest, recordSize? }`.
|
|
237
|
+
* @returns The 21-byte header.
|
|
238
|
+
*/
|
|
239
|
+
async header(opts) {
|
|
240
|
+
const mainKey = await this.mainKeyPromise;
|
|
241
|
+
const salt = await (0, import_ece.deriveContentSalt)(mainKey, opts.contentDigest);
|
|
242
|
+
return (0, import_ece.header)(salt, opts.recordSize ?? import_ece.RECORD_SIZE);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Encrypt a single ECE record by index, byte-identical to record
|
|
246
|
+
* `seq` of `encryptStream({ contentDigest, recordSize })`. The salt
|
|
247
|
+
* is derived from `contentDigest` internally; no raw salt is
|
|
248
|
+
* accepted.
|
|
249
|
+
*
|
|
250
|
+
* Non-final records must be exactly `recordPlaintextSize(recordSize)`
|
|
251
|
+
* bytes; the final record must be `<=` that. The low-level function
|
|
252
|
+
* throws otherwise.
|
|
253
|
+
*
|
|
254
|
+
* @param seq Zero-based record index.
|
|
255
|
+
* @param plaintext The record's plaintext slice.
|
|
256
|
+
* @param opts `{ isLast, contentDigest, recordSize? }`.
|
|
257
|
+
* @returns The encrypted record bytes.
|
|
258
|
+
*/
|
|
259
|
+
async encryptRecord(seq, plaintext, opts) {
|
|
260
|
+
const mainKey = await this.mainKeyPromise;
|
|
261
|
+
const salt = await (0, import_ece.deriveContentSalt)(
|
|
262
|
+
mainKey,
|
|
263
|
+
opts.contentDigest
|
|
264
|
+
);
|
|
265
|
+
return (0, import_ece.encryptRecord)(
|
|
266
|
+
mainKey,
|
|
267
|
+
seq,
|
|
268
|
+
plaintext,
|
|
269
|
+
opts.isLast,
|
|
270
|
+
salt,
|
|
271
|
+
opts.recordSize ?? import_ece.RECORD_SIZE
|
|
272
|
+
);
|
|
176
273
|
}
|
|
177
274
|
/**
|
|
178
275
|
* Encrypt and return some data; don't stream.
|
package/dist/src/ece.d.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare const KEY_LENGTH = 16;
|
|
6
6
|
export declare const TAG_LENGTH = 16;
|
|
7
|
+
export declare const RECORD_SIZE: number;
|
|
8
|
+
export declare const HEADER_LENGTH: number;
|
|
7
9
|
/**
|
|
8
10
|
* Given a plaintext size, return the corresponding encrypted size.
|
|
9
11
|
*
|
|
@@ -18,6 +20,80 @@ export declare function encryptedSize(plaintextSize: number, rs?: number): numbe
|
|
|
18
20
|
* rs: int containing record size, optional
|
|
19
21
|
*/
|
|
20
22
|
export declare function plaintextSize(encryptedSize: number, rs?: number): number;
|
|
23
|
+
/**
|
|
24
|
+
* Plaintext bytes that fit in one ECE record for the given record size.
|
|
25
|
+
* Equals `rs - TAG_LENGTH - 1` (the 16-byte AES-GCM tag plus the 1-byte
|
|
26
|
+
* padding delimiter).
|
|
27
|
+
*
|
|
28
|
+
* @param rs Record size in bytes (default RECORD_SIZE).
|
|
29
|
+
* @returns Plaintext bytes per record.
|
|
30
|
+
*/
|
|
31
|
+
export declare function recordPlaintextSize(rs?: number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Number of ECE data records needed to hold `plaintextSize` bytes. Returns 0
|
|
34
|
+
* for empty input — an empty stream encrypts to a header with no
|
|
35
|
+
* data records.
|
|
36
|
+
*
|
|
37
|
+
* @param plaintextSize Total plaintext length in bytes.
|
|
38
|
+
* @param rs Record size in bytes (default RECORD_SIZE).
|
|
39
|
+
* @returns Record count (0 when plaintextSize is 0).
|
|
40
|
+
*/
|
|
41
|
+
export declare function recordCount(plaintextSize: number, rs?: number): number;
|
|
42
|
+
/**
|
|
43
|
+
* Build the canonical 21-byte ECE header:
|
|
44
|
+
* `salt(16) || recordSize(uint32 BE) || idlen(0)`.
|
|
45
|
+
*
|
|
46
|
+
* This is the single source of truth for the header; the streaming encoder
|
|
47
|
+
* delegates to it, so a standalone header is byte-identical to the stream's
|
|
48
|
+
* header.
|
|
49
|
+
*
|
|
50
|
+
* SAFETY: a fixed salt must never encrypt two different plaintexts under the
|
|
51
|
+
* same key (AES-GCM nonce reuse). Prefer deriving the salt from the content
|
|
52
|
+
* (see `deriveContentSalt`) over choosing it directly. This is a low-level
|
|
53
|
+
* building block; the Keychain API does not accept a raw salt.
|
|
54
|
+
*
|
|
55
|
+
* @param salt 16-byte content salt.
|
|
56
|
+
* @param rs Record size in bytes (default RECORD_SIZE).
|
|
57
|
+
* @returns The 21-byte header.
|
|
58
|
+
*/
|
|
59
|
+
export declare function header(salt: Uint8Array<ArrayBuffer>, rs?: number): Uint8Array<ArrayBuffer>;
|
|
60
|
+
/**
|
|
61
|
+
* Derive a deterministic 16-byte content salt from the secret key and a
|
|
62
|
+
* content digest, via HKDF-SHA256 with info
|
|
63
|
+
* `"Content-Encoding: salt\0" || contentDigest`.
|
|
64
|
+
*
|
|
65
|
+
* Because the digest is collision-resistant over the plaintext, a salt is
|
|
66
|
+
* cryptographically bound to exactly one content — so a fixed salt can never
|
|
67
|
+
* pair with two different plaintexts. This is what makes reproducible
|
|
68
|
+
* encryption safe under AES-GCM (no nonce reuse across distinct plaintexts).
|
|
69
|
+
*
|
|
70
|
+
* @param secretKey HKDF CryptoKey (the main secret key).
|
|
71
|
+
* @param contentDigest Digest of the plaintext (e.g. 32-byte SHA-256).
|
|
72
|
+
* @returns 16-byte content salt.
|
|
73
|
+
*/
|
|
74
|
+
export declare function deriveContentSalt(secretKey: CryptoKey, contentDigest: Uint8Array): Promise<Uint8Array<ArrayBuffer>>;
|
|
75
|
+
/**
|
|
76
|
+
* Encrypt a single ECE record in isolation, byte-identical to record `seq` of
|
|
77
|
+
* the corresponding `encryptStream` output. Drives an `ECETransformer` through
|
|
78
|
+
* its existing key/nonce/record methods, so no new crypto is introduced.
|
|
79
|
+
*
|
|
80
|
+
* Non-final records must be exactly `recordPlaintextSize(rs)` bytes; the final
|
|
81
|
+
* record must be `<= recordPlaintextSize(rs)` bytes.
|
|
82
|
+
*
|
|
83
|
+
* SAFETY: the same `(secretKey, salt)` must never encrypt two different
|
|
84
|
+
* plaintexts (AES-GCM nonce reuse). This low-level function takes a raw salt;
|
|
85
|
+
* derive it from the content via `deriveContentSalt`, or use the Keychain API,
|
|
86
|
+
* which never exposes a raw salt.
|
|
87
|
+
*
|
|
88
|
+
* @param secretKey HKDF CryptoKey (the main secret key).
|
|
89
|
+
* @param seq Zero-based record index.
|
|
90
|
+
* @param plaintext The record's plaintext slice.
|
|
91
|
+
* @param isLast Whether this is the final record.
|
|
92
|
+
* @param salt 16-byte content salt (same salt as the stream's header).
|
|
93
|
+
* @param rs Record size in bytes (default RECORD_SIZE).
|
|
94
|
+
* @returns The encrypted record bytes.
|
|
95
|
+
*/
|
|
96
|
+
export declare function encryptRecord(secretKey: CryptoKey, seq: number, plaintext: Uint8Array, isLast: boolean, salt: Uint8Array<ArrayBuffer>, rs?: number): Promise<Uint8Array>;
|
|
21
97
|
/**
|
|
22
98
|
* Given a plaintext stream `input`, return an encrypted stream.
|
|
23
99
|
*
|
package/dist/src/ece.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ece.d.ts","sourceRoot":"","sources":["../../src/ece.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,eAAO,MAAM,UAAU,KAAK,CAAA;AAC5B,eAAO,MAAM,UAAU,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"ece.d.ts","sourceRoot":"","sources":["../../src/ece.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,eAAO,MAAM,UAAU,KAAK,CAAA;AAC5B,eAAO,MAAM,UAAU,KAAK,CAAA;AAE5B,eAAO,MAAM,WAAW,QAAY,CAAA;AACpC,eAAO,MAAM,aAAa,QAAqB,CAAA;AA6R/C;;;;;GAKG;AACH,wBAAgB,aAAa,CACzB,aAAa,EAAC,MAAM,EACpB,EAAE,GAAC,MAAoB,GACzB,MAAM,CAcP;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CACzB,aAAa,EAAC,MAAM,EACpB,EAAE,GAAC,MAAoB,GACzB,MAAM,CAeP;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAE,EAAE,GAAC,MAAoB,GAAE,MAAM,CAKnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACvB,aAAa,EAAC,MAAM,EACpB,EAAE,GAAC,MAAoB,GACzB,MAAM,CAQP;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,MAAM,CAClB,IAAI,EAAC,UAAU,CAAC,WAAW,CAAC,EAC5B,EAAE,GAAC,MAAoB,GACzB,UAAU,CAAC,WAAW,CAAC,CAYxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACnC,SAAS,EAAC,SAAS,EACnB,aAAa,EAAC,UAAU,GAC1B,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAsBjC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,aAAa,CAC/B,SAAS,EAAC,SAAS,EACnB,GAAG,EAAC,MAAM,EACV,SAAS,EAAC,UAAU,EACpB,MAAM,EAAC,OAAO,EACd,IAAI,EAAC,UAAU,CAAC,WAAW,CAAC,EAC5B,EAAE,GAAC,MAAoB,GACzB,OAAO,CAAC,UAAU,CAAC,CAmBpB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAC,cAAc,EACpB,SAAS,EAAC,SAAS,EACnB,EAAE,GAAC,MAAoB,EACvB,IAAI,GAAC,UAAU,CAAC,WAAW,CAA4B,GACzD,cAAc,CAUf;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAC,cAAc,EACpB,SAAS,EAAC,SAAS,EACnB,EAAE,SAAc,GAClB,cAAc,CAUf;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAC9B,SAAS,EAAC,SAAS,EACnB,MAAM,EAAC,MAAM,EACb,MAAM,EAAC,MAAM,EACb,oBAAoB,EAAC,MAAM,EAC3B,EAAE,GAAC,MAAoB,GACzB;IACE,MAAM,EAAC;QAAE,MAAM,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,OAAO,EAAC,CAAC,OAAO,EAAC,cAAc,EAAE,KAAG,cAAc,CAAA;CACrD,CAiEA"}
|
package/dist/src/ece.js
CHANGED
|
@@ -13,9 +13,10 @@ const MODE_DECRYPT = 'decrypt';
|
|
|
13
13
|
export const KEY_LENGTH = 16;
|
|
14
14
|
export const TAG_LENGTH = 16;
|
|
15
15
|
const NONCE_LENGTH = 12;
|
|
16
|
-
const RECORD_SIZE = 64 * 1024;
|
|
17
|
-
const HEADER_LENGTH = KEY_LENGTH + 4 + 1; // salt + record size + idlen
|
|
16
|
+
export const RECORD_SIZE = 64 * 1024;
|
|
17
|
+
export const HEADER_LENGTH = KEY_LENGTH + 4 + 1; // salt + record size + idlen
|
|
18
18
|
const encoder = new TextEncoder();
|
|
19
|
+
const SALT_INFO = encoder.encode('Content-Encoding: salt\0');
|
|
19
20
|
class ECETransformer {
|
|
20
21
|
mode;
|
|
21
22
|
secretKey;
|
|
@@ -121,11 +122,7 @@ class ECETransformer {
|
|
|
121
122
|
createHeader() {
|
|
122
123
|
if (!this.salt)
|
|
123
124
|
throw new Error('Not salt');
|
|
124
|
-
|
|
125
|
-
header.set(this.salt);
|
|
126
|
-
const dv = new DataView(header.buffer, header.byteOffset, header.byteLength);
|
|
127
|
-
dv.setUint32(KEY_LENGTH, this.rs);
|
|
128
|
-
return header;
|
|
125
|
+
return header(this.salt, this.rs);
|
|
129
126
|
}
|
|
130
127
|
readHeader(buffer) {
|
|
131
128
|
if (buffer.byteLength !== HEADER_LENGTH) {
|
|
@@ -264,6 +261,137 @@ export function plaintextSize(encryptedSize, rs = RECORD_SIZE) {
|
|
|
264
261
|
chunkMetaLength *
|
|
265
262
|
Math.ceil(encryptedRecordsSize / rs));
|
|
266
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Plaintext bytes that fit in one ECE record for the given record size.
|
|
266
|
+
* Equals `rs - TAG_LENGTH - 1` (the 16-byte AES-GCM tag plus the 1-byte
|
|
267
|
+
* padding delimiter).
|
|
268
|
+
*
|
|
269
|
+
* @param rs Record size in bytes (default RECORD_SIZE).
|
|
270
|
+
* @returns Plaintext bytes per record.
|
|
271
|
+
*/
|
|
272
|
+
export function recordPlaintextSize(rs = RECORD_SIZE) {
|
|
273
|
+
if (!Number.isInteger(rs)) {
|
|
274
|
+
throw new TypeError('rs');
|
|
275
|
+
}
|
|
276
|
+
return rs - TAG_LENGTH - 1;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Number of ECE data records needed to hold `plaintextSize` bytes. Returns 0
|
|
280
|
+
* for empty input — an empty stream encrypts to a header with no
|
|
281
|
+
* data records.
|
|
282
|
+
*
|
|
283
|
+
* @param plaintextSize Total plaintext length in bytes.
|
|
284
|
+
* @param rs Record size in bytes (default RECORD_SIZE).
|
|
285
|
+
* @returns Record count (0 when plaintextSize is 0).
|
|
286
|
+
*/
|
|
287
|
+
export function recordCount(plaintextSize, rs = RECORD_SIZE) {
|
|
288
|
+
if (!Number.isInteger(plaintextSize)) {
|
|
289
|
+
throw new TypeError('plaintextSize');
|
|
290
|
+
}
|
|
291
|
+
if (!Number.isInteger(rs)) {
|
|
292
|
+
throw new TypeError('rs');
|
|
293
|
+
}
|
|
294
|
+
return Math.ceil(plaintextSize / recordPlaintextSize(rs));
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Build the canonical 21-byte ECE header:
|
|
298
|
+
* `salt(16) || recordSize(uint32 BE) || idlen(0)`.
|
|
299
|
+
*
|
|
300
|
+
* This is the single source of truth for the header; the streaming encoder
|
|
301
|
+
* delegates to it, so a standalone header is byte-identical to the stream's
|
|
302
|
+
* header.
|
|
303
|
+
*
|
|
304
|
+
* SAFETY: a fixed salt must never encrypt two different plaintexts under the
|
|
305
|
+
* same key (AES-GCM nonce reuse). Prefer deriving the salt from the content
|
|
306
|
+
* (see `deriveContentSalt`) over choosing it directly. This is a low-level
|
|
307
|
+
* building block; the Keychain API does not accept a raw salt.
|
|
308
|
+
*
|
|
309
|
+
* @param salt 16-byte content salt.
|
|
310
|
+
* @param rs Record size in bytes (default RECORD_SIZE).
|
|
311
|
+
* @returns The 21-byte header.
|
|
312
|
+
*/
|
|
313
|
+
export function header(salt, rs = RECORD_SIZE) {
|
|
314
|
+
if (salt.byteLength !== KEY_LENGTH) {
|
|
315
|
+
throw new Error('Invalid salt length');
|
|
316
|
+
}
|
|
317
|
+
if (!Number.isInteger(rs)) {
|
|
318
|
+
throw new TypeError('rs');
|
|
319
|
+
}
|
|
320
|
+
const buf = new Uint8Array(HEADER_LENGTH);
|
|
321
|
+
buf.set(salt);
|
|
322
|
+
const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
323
|
+
dv.setUint32(KEY_LENGTH, rs);
|
|
324
|
+
return buf;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Derive a deterministic 16-byte content salt from the secret key and a
|
|
328
|
+
* content digest, via HKDF-SHA256 with info
|
|
329
|
+
* `"Content-Encoding: salt\0" || contentDigest`.
|
|
330
|
+
*
|
|
331
|
+
* Because the digest is collision-resistant over the plaintext, a salt is
|
|
332
|
+
* cryptographically bound to exactly one content — so a fixed salt can never
|
|
333
|
+
* pair with two different plaintexts. This is what makes reproducible
|
|
334
|
+
* encryption safe under AES-GCM (no nonce reuse across distinct plaintexts).
|
|
335
|
+
*
|
|
336
|
+
* @param secretKey HKDF CryptoKey (the main secret key).
|
|
337
|
+
* @param contentDigest Digest of the plaintext (e.g. 32-byte SHA-256).
|
|
338
|
+
* @returns 16-byte content salt.
|
|
339
|
+
*/
|
|
340
|
+
export async function deriveContentSalt(secretKey, contentDigest) {
|
|
341
|
+
if (contentDigest.byteLength === 0) {
|
|
342
|
+
throw new Error('empty content digest');
|
|
343
|
+
}
|
|
344
|
+
const infoLen = SALT_INFO.byteLength + contentDigest.byteLength;
|
|
345
|
+
const info = new Uint8Array(infoLen);
|
|
346
|
+
info.set(SALT_INFO, 0);
|
|
347
|
+
info.set(contentDigest, SALT_INFO.byteLength);
|
|
348
|
+
const bits = await webcrypto.subtle.deriveBits({
|
|
349
|
+
name: 'HKDF',
|
|
350
|
+
hash: 'SHA-256',
|
|
351
|
+
salt: new Uint8Array(0),
|
|
352
|
+
info
|
|
353
|
+
}, secretKey, KEY_LENGTH * 8);
|
|
354
|
+
return new Uint8Array(bits);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Encrypt a single ECE record in isolation, byte-identical to record `seq` of
|
|
358
|
+
* the corresponding `encryptStream` output. Drives an `ECETransformer` through
|
|
359
|
+
* its existing key/nonce/record methods, so no new crypto is introduced.
|
|
360
|
+
*
|
|
361
|
+
* Non-final records must be exactly `recordPlaintextSize(rs)` bytes; the final
|
|
362
|
+
* record must be `<= recordPlaintextSize(rs)` bytes.
|
|
363
|
+
*
|
|
364
|
+
* SAFETY: the same `(secretKey, salt)` must never encrypt two different
|
|
365
|
+
* plaintexts (AES-GCM nonce reuse). This low-level function takes a raw salt;
|
|
366
|
+
* derive it from the content via `deriveContentSalt`, or use the Keychain API,
|
|
367
|
+
* which never exposes a raw salt.
|
|
368
|
+
*
|
|
369
|
+
* @param secretKey HKDF CryptoKey (the main secret key).
|
|
370
|
+
* @param seq Zero-based record index.
|
|
371
|
+
* @param plaintext The record's plaintext slice.
|
|
372
|
+
* @param isLast Whether this is the final record.
|
|
373
|
+
* @param salt 16-byte content salt (same salt as the stream's header).
|
|
374
|
+
* @param rs Record size in bytes (default RECORD_SIZE).
|
|
375
|
+
* @returns The encrypted record bytes.
|
|
376
|
+
*/
|
|
377
|
+
export async function encryptRecord(secretKey, seq, plaintext, isLast, salt, rs = RECORD_SIZE) {
|
|
378
|
+
// Validates the key and the salt length (throws 'Invalid salt length').
|
|
379
|
+
const transformer = new ECETransformer(MODE_ENCRYPT, secretKey, rs, salt);
|
|
380
|
+
const max = recordPlaintextSize(rs);
|
|
381
|
+
if (isLast) {
|
|
382
|
+
if (plaintext.byteLength > max) {
|
|
383
|
+
throw new Error('final record exceeds recordPlaintextSize');
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
if (plaintext.byteLength !== max) {
|
|
388
|
+
throw new Error('non-final record must equal recordPlaintextSize');
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
transformer.key = await transformer.generateKey();
|
|
392
|
+
transformer.nonceBase = await transformer.generateNonceBase();
|
|
393
|
+
return transformer.encryptRecord(plaintext, seq, isLast);
|
|
394
|
+
}
|
|
267
395
|
/**
|
|
268
396
|
* Given a plaintext stream `input`, return an encrypted stream.
|
|
269
397
|
*
|
package/dist/src/ece.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ece.js","sourceRoot":"","sources":["../../src/ece.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ece.js","sourceRoot":"","sources":["../../src/ece.ts"],"names":[],"mappings":"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"}
|
package/dist/src/keychain.d.ts
CHANGED
|
@@ -39,12 +39,78 @@ export declare class Keychain {
|
|
|
39
39
|
* @param authToken The new token
|
|
40
40
|
*/
|
|
41
41
|
setAuthToken(authToken?: string | Uint8Array): void;
|
|
42
|
+
/**
|
|
43
|
+
* SHA-256 digest of the plaintext, used as the input to content-bound
|
|
44
|
+
* salt derivation. Accepts a stream, a byte array, or a Blob;
|
|
45
|
+
* equivalent content yields the same digest.
|
|
46
|
+
*
|
|
47
|
+
* Pass the result to `encryptStream`/`header`/`encryptRecord` as
|
|
48
|
+
* `contentDigest`. The salt is derived from this digest internally,
|
|
49
|
+
* so the Keychain API never exposes a raw salt — a fixed salt can
|
|
50
|
+
* never pair with two different plaintexts.
|
|
51
|
+
*
|
|
52
|
+
* NOTE: WebCrypto has no incremental hash, so a stream/Blob is
|
|
53
|
+
* drained into memory before hashing.
|
|
54
|
+
*
|
|
55
|
+
* @param content Plaintext as a ReadableStream, Uint8Array, or Blob.
|
|
56
|
+
* @returns 32-byte SHA-256 digest.
|
|
57
|
+
*/
|
|
58
|
+
contentDigest(content: ReadableStream<Uint8Array> | Uint8Array | Blob): Promise<Uint8Array<ArrayBuffer>>;
|
|
42
59
|
/**
|
|
43
60
|
* Take a stream, return an encrypted stream.
|
|
44
|
-
*
|
|
45
|
-
*
|
|
61
|
+
*
|
|
62
|
+
* With `opts.contentDigest`, the ECE salt is derived from the digest
|
|
63
|
+
* internally (`deriveContentSalt`), so two calls over identical input
|
|
64
|
+
* produce byte-identical ciphertext (reproducible encryption). With no
|
|
65
|
+
* opts, a fresh random salt is used (today's behavior).
|
|
66
|
+
*
|
|
67
|
+
* The salt is never accepted directly: because it is bound to the
|
|
68
|
+
* content digest, a fixed salt can never encrypt two different
|
|
69
|
+
* plaintexts (AES-GCM nonce-reuse is structurally unreachable from
|
|
70
|
+
* this API).
|
|
71
|
+
*
|
|
72
|
+
* @param stream Input plaintext stream.
|
|
73
|
+
* @param opts Optional `{ contentDigest?, recordSize? }`.
|
|
74
|
+
* @returns Encrypted stream.
|
|
46
75
|
*/
|
|
47
|
-
encryptStream(stream: ReadableStream<Uint8Array
|
|
76
|
+
encryptStream(stream: ReadableStream<Uint8Array>, opts?: {
|
|
77
|
+
contentDigest?: Uint8Array;
|
|
78
|
+
recordSize?: number;
|
|
79
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
80
|
+
/**
|
|
81
|
+
* Build the 21-byte ECE header for content identified by
|
|
82
|
+
* `contentDigest`. The salt is derived internally from the digest,
|
|
83
|
+
* so this never exposes a raw salt. The header is byte-identical to
|
|
84
|
+
* the header that `encryptStream({ contentDigest, recordSize })`
|
|
85
|
+
* emits for the same input.
|
|
86
|
+
*
|
|
87
|
+
* @param opts `{ contentDigest, recordSize? }`.
|
|
88
|
+
* @returns The 21-byte header.
|
|
89
|
+
*/
|
|
90
|
+
header(opts: {
|
|
91
|
+
contentDigest: Uint8Array;
|
|
92
|
+
recordSize?: number;
|
|
93
|
+
}): Promise<Uint8Array<ArrayBuffer>>;
|
|
94
|
+
/**
|
|
95
|
+
* Encrypt a single ECE record by index, byte-identical to record
|
|
96
|
+
* `seq` of `encryptStream({ contentDigest, recordSize })`. The salt
|
|
97
|
+
* is derived from `contentDigest` internally; no raw salt is
|
|
98
|
+
* accepted.
|
|
99
|
+
*
|
|
100
|
+
* Non-final records must be exactly `recordPlaintextSize(recordSize)`
|
|
101
|
+
* bytes; the final record must be `<=` that. The low-level function
|
|
102
|
+
* throws otherwise.
|
|
103
|
+
*
|
|
104
|
+
* @param seq Zero-based record index.
|
|
105
|
+
* @param plaintext The record's plaintext slice.
|
|
106
|
+
* @param opts `{ isLast, contentDigest, recordSize? }`.
|
|
107
|
+
* @returns The encrypted record bytes.
|
|
108
|
+
*/
|
|
109
|
+
encryptRecord(seq: number, plaintext: Uint8Array, opts: {
|
|
110
|
+
isLast: boolean;
|
|
111
|
+
contentDigest: Uint8Array;
|
|
112
|
+
recordSize?: number;
|
|
113
|
+
}): Promise<Uint8Array>;
|
|
48
114
|
/**
|
|
49
115
|
* Encrypt and return some data; don't stream.
|
|
50
116
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keychain.d.ts","sourceRoot":"","sources":["../../src/keychain.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"keychain.d.ts","sourceRoot":"","sources":["../../src/keychain.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAKvD,qBAAa,QAAQ;IACjB,GAAG,EAAC,UAAU,CAAC,WAAW,CAAC,CAAA;IAC3B,IAAI,EAAC,UAAU,CAAC,WAAW,CAAC,CAAA;IAC5B,cAAc,EAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACjC,cAAc,EAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACjC,gBAAgB,EAAC,OAAO,CAAC,UAAU,CAAC,CAAA;gBAEvB,GAAG,CAAC,EAAC,MAAM,GAAC,UAAU,EAAE,IAAI,CAAC,EAAC,MAAM,GAAC,UAAU;IA+C5D;;OAEG;WACU,UAAU,CAAE,SAAS,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM,GAAC,UAAU;IAwBjE,MAAM,CAAC,MAAM,CAAE,UAAU,EAAC,MAAM;IAIhC;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IAItC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAKrC;;;;OAIG;IACG,UAAU,CAAE,WAAW,CAAC,EAAC,MAAM,GAAE,OAAO,CAAC,MAAM,CAAC;IAQtD;;;OAGG;IACH,YAAY,CAAE,SAAS,CAAC,EAAC,MAAM,GAAC,UAAU,GAAE,IAAI;IAIhD;;;;;;;;;;;;;;;OAeG;IACG,aAAa,CACf,OAAO,EAAC,cAAc,CAAC,UAAU,CAAC,GAAC,UAAU,GAAC,IAAI,GACpD,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAqBlC;;;;;;;;;;;;;;;;OAgBG;IACG,aAAa,CACf,MAAM,EAAC,cAAc,CAAC,UAAU,CAAC,EACjC,IAAI,CAAC,EAAC;QACF,aAAa,CAAC,EAAC,UAAU,CAAC;QAC1B,UAAU,CAAC,EAAC,MAAM,CAAA;KACrB,GACH,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAerC;;;;;;;;;OASG;IACG,MAAM,CACR,IAAI,EAAC;QAAC,aAAa,EAAC,UAAU,CAAC;QAAC,UAAU,CAAC,EAAC,MAAM,CAAA;KAAC,GACrD,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAMlC;;;;;;;;;;;;;;OAcG;IACG,aAAa,CACf,GAAG,EAAC,MAAM,EACV,SAAS,EAAC,UAAU,EACpB,IAAI,EAAC;QACD,MAAM,EAAC,OAAO,CAAC;QACf,aAAa,EAAC,UAAU,CAAC;QACzB,UAAU,CAAC,EAAC,MAAM,CAAA;KACrB,GACH,OAAO,CAAC,UAAU,CAAC;IAgBrB;;;;;;;;;;;OAWG;IACG,YAAY,CACd,KAAK,EAAC,WAAW,GAAC,UAAU,EAC5B,IAAI,CAAC,EAAC;QAAE,EAAE,CAAC,EAAC,UAAU,CAAC;QAAC,IAAI,CAAC,EAAC,MAAM,CAAA;KAAE,GACxC,OAAO,CAAC,UAAU,CAAC;IAcrB;;OAEG;IACG,YAAY,CACd,KAAK,EAAC,UAAU,GAClB,OAAO,CAAC,WAAW,CAAC;IAatB;;;;;;OAMG;IACG,WAAW,CAAE,SAAS,CAAC,EAAC,MAAM,GAAE,OAAO,CAAC,SAAS,CAAC;IAoBxD;;;;OAIG;IACG,aAAa,CACf,eAAe,EAAC,cAAc,CAAC,UAAU,CAAC,GAC5C,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAQrC;;;;;;;;;;OAUG;IACG,kBAAkB,CACpB,MAAM,EAAC,MAAM,EACb,MAAM,EAAC,MAAM,EACb,oBAAoB,EAAC,MAAM,GAC7B,OAAO,CAAC;QACN,MAAM,EAAC;YAAE,MAAM,EAAC,MAAM,CAAC;YAAC,MAAM,EAAC,MAAM,CAAA;SAAE,EAAE,CAAC;QAC1C,OAAO,EAAC,CAAC,OAAO,EAAC,cAAc,EAAE,KAAG,cAAc,CAAA;KACrD,CAAC;IAeI,WAAW,CAAE,IAAI,EAAC,UAAU,GAAE,OAAO,CAAC,UAAU,CAAC;IA2BjD,WAAW,CAAE,eAAe,EAAC,UAAU,GAAE,OAAO,CAAC,UAAU,CAAC;CAqBrE"}
|
package/dist/src/keychain.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { webcrypto } from '@substrate-system/one-webcrypto';
|
|
2
2
|
import * as u from 'uint8arrays';
|
|
3
|
-
import { decryptStream, decryptStreamRange, encryptStream, KEY_LENGTH, } from './ece.js';
|
|
3
|
+
import { decryptStream, decryptStreamRange, deriveContentSalt, encryptStream, header as eceHeader, encryptRecord as eceEncryptRecord, KEY_LENGTH, RECORD_SIZE, } from './ece.js';
|
|
4
4
|
import { randomBuf, joinBufs, asBufferSource } from './util.js';
|
|
5
5
|
export { encryptedSize, plaintextSize } from './ece.js';
|
|
6
6
|
const IV_LENGTH = 12;
|
|
@@ -96,17 +96,102 @@ export class Keychain {
|
|
|
96
96
|
setAuthToken(authToken) {
|
|
97
97
|
this.authTokenPromise = Promise.resolve(decodeBits(authToken));
|
|
98
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* SHA-256 digest of the plaintext, used as the input to content-bound
|
|
101
|
+
* salt derivation. Accepts a stream, a byte array, or a Blob;
|
|
102
|
+
* equivalent content yields the same digest.
|
|
103
|
+
*
|
|
104
|
+
* Pass the result to `encryptStream`/`header`/`encryptRecord` as
|
|
105
|
+
* `contentDigest`. The salt is derived from this digest internally,
|
|
106
|
+
* so the Keychain API never exposes a raw salt — a fixed salt can
|
|
107
|
+
* never pair with two different plaintexts.
|
|
108
|
+
*
|
|
109
|
+
* NOTE: WebCrypto has no incremental hash, so a stream/Blob is
|
|
110
|
+
* drained into memory before hashing.
|
|
111
|
+
*
|
|
112
|
+
* @param content Plaintext as a ReadableStream, Uint8Array, or Blob.
|
|
113
|
+
* @returns 32-byte SHA-256 digest.
|
|
114
|
+
*/
|
|
115
|
+
async contentDigest(content) {
|
|
116
|
+
let bytes;
|
|
117
|
+
if (content instanceof Uint8Array) {
|
|
118
|
+
bytes = content;
|
|
119
|
+
}
|
|
120
|
+
else if (content instanceof ReadableStream) {
|
|
121
|
+
bytes = new Uint8Array(await new Response(content).arrayBuffer());
|
|
122
|
+
}
|
|
123
|
+
else if (typeof Blob !== 'undefined' && content instanceof Blob) {
|
|
124
|
+
bytes = new Uint8Array(await content.arrayBuffer());
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
throw new TypeError('content must be a ReadableStream, Uint8Array, or Blob');
|
|
128
|
+
}
|
|
129
|
+
const digest = await webcrypto.subtle.digest('SHA-256', asBufferSource(bytes));
|
|
130
|
+
return new Uint8Array(digest);
|
|
131
|
+
}
|
|
99
132
|
/**
|
|
100
133
|
* Take a stream, return an encrypted stream.
|
|
101
|
-
*
|
|
102
|
-
*
|
|
134
|
+
*
|
|
135
|
+
* With `opts.contentDigest`, the ECE salt is derived from the digest
|
|
136
|
+
* internally (`deriveContentSalt`), so two calls over identical input
|
|
137
|
+
* produce byte-identical ciphertext (reproducible encryption). With no
|
|
138
|
+
* opts, a fresh random salt is used (today's behavior).
|
|
139
|
+
*
|
|
140
|
+
* The salt is never accepted directly: because it is bound to the
|
|
141
|
+
* content digest, a fixed salt can never encrypt two different
|
|
142
|
+
* plaintexts (AES-GCM nonce-reuse is structurally unreachable from
|
|
143
|
+
* this API).
|
|
144
|
+
*
|
|
145
|
+
* @param stream Input plaintext stream.
|
|
146
|
+
* @param opts Optional `{ contentDigest?, recordSize? }`.
|
|
147
|
+
* @returns Encrypted stream.
|
|
103
148
|
*/
|
|
104
|
-
async encryptStream(stream) {
|
|
149
|
+
async encryptStream(stream, opts) {
|
|
105
150
|
if (!(stream instanceof ReadableStream)) {
|
|
106
151
|
throw new TypeError('This is not a readable stream');
|
|
107
152
|
}
|
|
108
153
|
const mainKey = await this.mainKeyPromise;
|
|
109
|
-
|
|
154
|
+
const rs = opts?.recordSize ?? RECORD_SIZE;
|
|
155
|
+
if (opts?.contentDigest) {
|
|
156
|
+
const salt = await deriveContentSalt(mainKey, opts.contentDigest);
|
|
157
|
+
return encryptStream(stream, mainKey, rs, salt);
|
|
158
|
+
}
|
|
159
|
+
return encryptStream(stream, mainKey, rs);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Build the 21-byte ECE header for content identified by
|
|
163
|
+
* `contentDigest`. The salt is derived internally from the digest,
|
|
164
|
+
* so this never exposes a raw salt. The header is byte-identical to
|
|
165
|
+
* the header that `encryptStream({ contentDigest, recordSize })`
|
|
166
|
+
* emits for the same input.
|
|
167
|
+
*
|
|
168
|
+
* @param opts `{ contentDigest, recordSize? }`.
|
|
169
|
+
* @returns The 21-byte header.
|
|
170
|
+
*/
|
|
171
|
+
async header(opts) {
|
|
172
|
+
const mainKey = await this.mainKeyPromise;
|
|
173
|
+
const salt = await deriveContentSalt(mainKey, opts.contentDigest);
|
|
174
|
+
return eceHeader(salt, opts.recordSize ?? RECORD_SIZE);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Encrypt a single ECE record by index, byte-identical to record
|
|
178
|
+
* `seq` of `encryptStream({ contentDigest, recordSize })`. The salt
|
|
179
|
+
* is derived from `contentDigest` internally; no raw salt is
|
|
180
|
+
* accepted.
|
|
181
|
+
*
|
|
182
|
+
* Non-final records must be exactly `recordPlaintextSize(recordSize)`
|
|
183
|
+
* bytes; the final record must be `<=` that. The low-level function
|
|
184
|
+
* throws otherwise.
|
|
185
|
+
*
|
|
186
|
+
* @param seq Zero-based record index.
|
|
187
|
+
* @param plaintext The record's plaintext slice.
|
|
188
|
+
* @param opts `{ isLast, contentDigest, recordSize? }`.
|
|
189
|
+
* @returns The encrypted record bytes.
|
|
190
|
+
*/
|
|
191
|
+
async encryptRecord(seq, plaintext, opts) {
|
|
192
|
+
const mainKey = await this.mainKeyPromise;
|
|
193
|
+
const salt = await deriveContentSalt(mainKey, opts.contentDigest);
|
|
194
|
+
return eceEncryptRecord(mainKey, seq, plaintext, opts.isLast, salt, opts.recordSize ?? RECORD_SIZE);
|
|
110
195
|
}
|
|
111
196
|
/**
|
|
112
197
|
* Encrypt and return some data; don't stream.
|
package/dist/src/keychain.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../src/keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAC3D,OAAO,KAAK,CAAC,MAAM,aAAa,CAAA;AAChC,OAAO,EACH,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,UAAU,
|
|
1
|
+
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../src/keychain.ts"],"names":[],"mappings":"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"}
|