@substrate-system/crypto-stream 0.0.33
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/LICENSE +99 -0
- package/README.md +366 -0
- package/dist/concat-streams.cjs +59 -0
- package/dist/ece.cjs +375 -0
- package/dist/extract-transformer.cjs +55 -0
- package/dist/index.cjs +28 -0
- package/dist/keychain.cjs +344 -0
- package/dist/slice-transformer.cjs +75 -0
- package/dist/src/concat-streams.d.ts +9 -0
- package/dist/src/concat-streams.d.ts.map +1 -0
- package/dist/src/concat-streams.js +46 -0
- package/dist/src/concat-streams.js.map +1 -0
- package/dist/src/ece.d.ts +66 -0
- package/dist/src/ece.d.ts.map +1 -0
- package/dist/src/ece.js +373 -0
- package/dist/src/ece.js.map +1 -0
- package/dist/src/extract-transformer.d.ts +18 -0
- package/dist/src/extract-transformer.d.ts.map +1 -0
- package/dist/src/extract-transformer.js +40 -0
- package/dist/src/extract-transformer.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/keychain.d.ts +103 -0
- package/dist/src/keychain.d.ts.map +1 -0
- package/dist/src/keychain.js +267 -0
- package/dist/src/keychain.js.map +1 -0
- package/dist/src/slice-transformer.d.ts +19 -0
- package/dist/src/slice-transformer.d.ts.map +1 -0
- package/dist/src/slice-transformer.js +58 -0
- package/dist/src/slice-transformer.js.map +1 -0
- package/dist/src/transform-stream.d.ts +11 -0
- package/dist/src/transform-stream.d.ts.map +1 -0
- package/dist/src/transform-stream.js +136 -0
- package/dist/src/transform-stream.js.map +1 -0
- package/dist/src/util.d.ts +27 -0
- package/dist/src/util.d.ts.map +1 -0
- package/dist/src/util.js +49 -0
- package/dist/src/util.js.map +1 -0
- package/dist/transform-stream.cjs +159 -0
- package/dist/util.cjs +57 -0
- package/package.json +86 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var keychain_exports = {};
|
|
31
|
+
__export(keychain_exports, {
|
|
32
|
+
Keychain: () => Keychain,
|
|
33
|
+
encryptedSize: () => import_ece2.encryptedSize,
|
|
34
|
+
plaintextSize: () => import_ece2.plaintextSize
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(keychain_exports);
|
|
37
|
+
var import_one_webcrypto = require("@substrate-system/one-webcrypto");
|
|
38
|
+
var u = __toESM(require("uint8arrays"), 1);
|
|
39
|
+
var import_ece = require("./ece.js");
|
|
40
|
+
var import_util = require("./util.js");
|
|
41
|
+
var import_ece2 = require("./ece.js");
|
|
42
|
+
const IV_LENGTH = 12;
|
|
43
|
+
const encoder = new TextEncoder();
|
|
44
|
+
class Keychain {
|
|
45
|
+
static {
|
|
46
|
+
__name(this, "Keychain");
|
|
47
|
+
}
|
|
48
|
+
key;
|
|
49
|
+
salt;
|
|
50
|
+
mainKeyPromise;
|
|
51
|
+
metaKeyPromise;
|
|
52
|
+
authTokenPromise;
|
|
53
|
+
constructor(key, salt) {
|
|
54
|
+
this.key = decodeBits(key);
|
|
55
|
+
this.salt = decodeBits(salt);
|
|
56
|
+
this.mainKeyPromise = import_one_webcrypto.webcrypto.subtle.importKey(
|
|
57
|
+
"raw",
|
|
58
|
+
this.key,
|
|
59
|
+
"HKDF",
|
|
60
|
+
false,
|
|
61
|
+
["deriveBits", "deriveKey"]
|
|
62
|
+
);
|
|
63
|
+
this.metaKeyPromise = this.mainKeyPromise.then(
|
|
64
|
+
(mainKey) => import_one_webcrypto.webcrypto.subtle.deriveKey(
|
|
65
|
+
{
|
|
66
|
+
name: "HKDF",
|
|
67
|
+
hash: "SHA-256",
|
|
68
|
+
salt: this.salt,
|
|
69
|
+
info: encoder.encode("metadata")
|
|
70
|
+
},
|
|
71
|
+
mainKey,
|
|
72
|
+
{
|
|
73
|
+
name: "AES-GCM",
|
|
74
|
+
length: 128
|
|
75
|
+
},
|
|
76
|
+
false,
|
|
77
|
+
["encrypt", "decrypt"]
|
|
78
|
+
)
|
|
79
|
+
);
|
|
80
|
+
this.authTokenPromise = this.mainKeyPromise.then(
|
|
81
|
+
(mainKey) => import_one_webcrypto.webcrypto.subtle.deriveBits(
|
|
82
|
+
{
|
|
83
|
+
name: "HKDF",
|
|
84
|
+
hash: "SHA-256",
|
|
85
|
+
salt: this.salt,
|
|
86
|
+
info: encoder.encode("authentication")
|
|
87
|
+
},
|
|
88
|
+
mainKey,
|
|
89
|
+
128
|
|
90
|
+
)
|
|
91
|
+
).then((authTokenBuf) => new Uint8Array(authTokenBuf));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get an authentication header as a static method.
|
|
95
|
+
*/
|
|
96
|
+
static async AuthHeader(secretKey, salt) {
|
|
97
|
+
const key = decodeBits(secretKey);
|
|
98
|
+
const mainKey = await import_one_webcrypto.webcrypto.subtle.importKey(
|
|
99
|
+
"raw",
|
|
100
|
+
key,
|
|
101
|
+
"HKDF",
|
|
102
|
+
false,
|
|
103
|
+
["deriveBits", "deriveKey"]
|
|
104
|
+
);
|
|
105
|
+
const token = await import_one_webcrypto.webcrypto.subtle.deriveBits(
|
|
106
|
+
{
|
|
107
|
+
name: "HKDF",
|
|
108
|
+
hash: "SHA-256",
|
|
109
|
+
salt: decodeBits(salt),
|
|
110
|
+
info: encoder.encode("authentication")
|
|
111
|
+
},
|
|
112
|
+
mainKey,
|
|
113
|
+
128
|
|
114
|
+
);
|
|
115
|
+
return Keychain.Header(arrayToB64(new Uint8Array(token)));
|
|
116
|
+
}
|
|
117
|
+
static Header(writeToken) {
|
|
118
|
+
return `Bearer sync-v1 ${writeToken}`;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get the main key as a `base64url` encoded string
|
|
122
|
+
*/
|
|
123
|
+
get keyB64() {
|
|
124
|
+
return arrayToB64Url(this.key);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get the salt as base64 string
|
|
128
|
+
*/
|
|
129
|
+
get saltB64() {
|
|
130
|
+
return arrayToB64(this.salt);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* get a promise for the auth token.
|
|
134
|
+
* @returns {Promise<Uint8Array>}
|
|
135
|
+
*/
|
|
136
|
+
async authToken() {
|
|
137
|
+
return await this.authTokenPromise;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get the auth token as a base64 string
|
|
141
|
+
*/
|
|
142
|
+
async authTokenB64() {
|
|
143
|
+
const authToken = await this.authToken();
|
|
144
|
+
return arrayToB64(authToken);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get a header string: `Bearer sync-v1 ${authTokenB64}`.
|
|
148
|
+
* Pass in a token, or else this will use the `authToken` derived from
|
|
149
|
+
* the main key.
|
|
150
|
+
*/
|
|
151
|
+
async authHeader(tokenString) {
|
|
152
|
+
if (tokenString) {
|
|
153
|
+
return `Bearer sync-v1 ${tokenString}`;
|
|
154
|
+
}
|
|
155
|
+
const authTokenB64 = await this.authTokenB64();
|
|
156
|
+
return `Bearer sync-v1 ${authTokenB64}`;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Set the auth token
|
|
160
|
+
* @param authToken The new token
|
|
161
|
+
*/
|
|
162
|
+
setAuthToken(authToken) {
|
|
163
|
+
this.authTokenPromise = Promise.resolve(decodeBits(authToken));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Take a stream, return an encrypted stream.
|
|
167
|
+
* @param stream Input stream
|
|
168
|
+
* @returns {Promise<ReadableStream>}
|
|
169
|
+
*/
|
|
170
|
+
async encryptStream(stream) {
|
|
171
|
+
if (!(stream instanceof ReadableStream)) {
|
|
172
|
+
throw new TypeError("This is not a readable stream");
|
|
173
|
+
}
|
|
174
|
+
const mainKey = await this.mainKeyPromise;
|
|
175
|
+
return (0, import_ece.encryptStream)(stream, mainKey);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Encrypt and return some data; don't stream.
|
|
179
|
+
*
|
|
180
|
+
* NOTE: This generates a new key each time it is called, via
|
|
181
|
+
* `this.generateKey`.
|
|
182
|
+
*
|
|
183
|
+
* @param bytes
|
|
184
|
+
* @param {{ iv?:Uint8Array, size?:number }} [opts] Optional params,
|
|
185
|
+
* `iv` and `size`. If `size` is omitted, default is 16 bytes. `iv` is
|
|
186
|
+
* a random 12 bits, will be generated if not passed in.
|
|
187
|
+
* @returns {Promise<Uint8Array>}
|
|
188
|
+
*/
|
|
189
|
+
async encryptBytes(bytes, opts) {
|
|
190
|
+
const iv = opts?.iv || (0, import_util.randomBuf)(12);
|
|
191
|
+
const encryptedRecordBuf = await import_one_webcrypto.webcrypto.subtle.encrypt(
|
|
192
|
+
{
|
|
193
|
+
name: "AES-GCM",
|
|
194
|
+
iv: (0, import_util.asBufferSource)(iv)
|
|
195
|
+
},
|
|
196
|
+
await this.generateKey(opts?.size),
|
|
197
|
+
(0, import_util.asBufferSource)(bytes)
|
|
198
|
+
);
|
|
199
|
+
return (0, import_util.joinBufs)(iv, encryptedRecordBuf);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Decrypt in memory, not streaming.
|
|
203
|
+
*/
|
|
204
|
+
async decryptBytes(bytes) {
|
|
205
|
+
const key = await this.generateKey();
|
|
206
|
+
const iv = bytes.slice(0, 12);
|
|
207
|
+
const cipherBytes = bytes.slice(12);
|
|
208
|
+
const msgBuf = await import_one_webcrypto.webcrypto.subtle.decrypt({
|
|
209
|
+
name: "AES-GCM",
|
|
210
|
+
iv
|
|
211
|
+
}, key, cipherBytes);
|
|
212
|
+
return msgBuf;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Derive a new AES-GCM key from the main key.
|
|
216
|
+
*
|
|
217
|
+
* @param {number} [keyLength] Optional size for the key, in bytes, eg,
|
|
218
|
+
* `16` or `32`.
|
|
219
|
+
* @returns {Promise<CryptoKey>}
|
|
220
|
+
*/
|
|
221
|
+
async generateKey(keyLength) {
|
|
222
|
+
const keySize = (keyLength || import_ece.KEY_LENGTH) * 8;
|
|
223
|
+
return import_one_webcrypto.webcrypto.subtle.deriveKey(
|
|
224
|
+
{
|
|
225
|
+
name: "HKDF",
|
|
226
|
+
hash: "SHA-256",
|
|
227
|
+
salt: this.salt,
|
|
228
|
+
info: encoder.encode("Content-Encoding: aes128gcm\0")
|
|
229
|
+
},
|
|
230
|
+
await this.mainKeyPromise,
|
|
231
|
+
{
|
|
232
|
+
name: "AES-GCM",
|
|
233
|
+
length: keySize
|
|
234
|
+
},
|
|
235
|
+
false,
|
|
236
|
+
["encrypt", "decrypt"]
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Take an encrypted stream, return a decrypted stream.
|
|
241
|
+
* @param encryptedStream The input (encrypted) stream
|
|
242
|
+
* @returns The decrypted stream
|
|
243
|
+
*/
|
|
244
|
+
async decryptStream(encryptedStream) {
|
|
245
|
+
if (!(encryptedStream instanceof ReadableStream)) {
|
|
246
|
+
throw new TypeError("encryptedStream is not a ReadableStream");
|
|
247
|
+
}
|
|
248
|
+
const mainKey = await this.mainKeyPromise;
|
|
249
|
+
return (0, import_ece.decryptStream)(encryptedStream, mainKey);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Returns an object containing `ranges`, an array of objects
|
|
253
|
+
* containing `offset` and `length` integers specifying the encrypted byte
|
|
254
|
+
* ranges that are needed to decrypt the client's specified range, and a
|
|
255
|
+
* `decrypt` function.
|
|
256
|
+
*
|
|
257
|
+
* @param {number} offset Integer
|
|
258
|
+
* @param {number} length Integer
|
|
259
|
+
* @param {number} totalEncryptedLength Integer
|
|
260
|
+
* @returns {Promise<{ ranges, decrypt }>}
|
|
261
|
+
*/
|
|
262
|
+
async decryptStreamRange(offset, length, totalEncryptedLength) {
|
|
263
|
+
if (!Number.isInteger(offset)) {
|
|
264
|
+
throw new TypeError("offset");
|
|
265
|
+
}
|
|
266
|
+
if (!Number.isInteger(length)) {
|
|
267
|
+
throw new TypeError("length");
|
|
268
|
+
}
|
|
269
|
+
if (!Number.isInteger(totalEncryptedLength)) {
|
|
270
|
+
throw new TypeError("totalEncryptedLength");
|
|
271
|
+
}
|
|
272
|
+
const mainKey = await this.mainKeyPromise;
|
|
273
|
+
return (0, import_ece.decryptStreamRange)(mainKey, offset, length, totalEncryptedLength);
|
|
274
|
+
}
|
|
275
|
+
async encryptMeta(meta) {
|
|
276
|
+
if (!(meta instanceof Uint8Array)) {
|
|
277
|
+
throw new TypeError("`meta` should be Uint8Array");
|
|
278
|
+
}
|
|
279
|
+
const iv = import_one_webcrypto.webcrypto.getRandomValues(new Uint8Array(IV_LENGTH));
|
|
280
|
+
const metaKey = await this.metaKeyPromise;
|
|
281
|
+
const encryptedMetaBuf = await import_one_webcrypto.webcrypto.subtle.encrypt(
|
|
282
|
+
{
|
|
283
|
+
name: "AES-GCM",
|
|
284
|
+
iv,
|
|
285
|
+
tagLength: 128
|
|
286
|
+
},
|
|
287
|
+
metaKey,
|
|
288
|
+
(0, import_util.asBufferSource)(meta)
|
|
289
|
+
);
|
|
290
|
+
const encryptedMeta = new Uint8Array(encryptedMetaBuf);
|
|
291
|
+
const ivEncryptedMeta = new Uint8Array(IV_LENGTH + encryptedMeta.byteLength);
|
|
292
|
+
ivEncryptedMeta.set(iv, 0);
|
|
293
|
+
ivEncryptedMeta.set(encryptedMeta, IV_LENGTH);
|
|
294
|
+
return ivEncryptedMeta;
|
|
295
|
+
}
|
|
296
|
+
async decryptMeta(ivEncryptedMeta) {
|
|
297
|
+
if (!(ivEncryptedMeta instanceof Uint8Array)) {
|
|
298
|
+
throw new Error("ivEncryptedMeta");
|
|
299
|
+
}
|
|
300
|
+
const iv = ivEncryptedMeta.slice(0, IV_LENGTH);
|
|
301
|
+
const encryptedMeta = ivEncryptedMeta.slice(IV_LENGTH);
|
|
302
|
+
const metaKey = await this.metaKeyPromise;
|
|
303
|
+
const metaBuf = await import_one_webcrypto.webcrypto.subtle.decrypt(
|
|
304
|
+
{
|
|
305
|
+
name: "AES-GCM",
|
|
306
|
+
iv,
|
|
307
|
+
tagLength: 128
|
|
308
|
+
},
|
|
309
|
+
metaKey,
|
|
310
|
+
encryptedMeta
|
|
311
|
+
);
|
|
312
|
+
const meta = new Uint8Array(metaBuf);
|
|
313
|
+
return meta;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function arrayToB64(array) {
|
|
317
|
+
return u.toString(array, "base64pad");
|
|
318
|
+
}
|
|
319
|
+
__name(arrayToB64, "arrayToB64");
|
|
320
|
+
function arrayToB64Url(array) {
|
|
321
|
+
return u.toString(array, "base64url");
|
|
322
|
+
}
|
|
323
|
+
__name(arrayToB64Url, "arrayToB64Url");
|
|
324
|
+
function b64ToArray(str) {
|
|
325
|
+
return u.fromString(str.replace(/-/g, "+").replace(/_/g, "/"), "base64");
|
|
326
|
+
}
|
|
327
|
+
__name(b64ToArray, "b64ToArray");
|
|
328
|
+
function decodeBits(bitsB64) {
|
|
329
|
+
let result;
|
|
330
|
+
if (bitsB64 instanceof Uint8Array) {
|
|
331
|
+
result = (0, import_util.asBufferSource)(bitsB64);
|
|
332
|
+
} else if (typeof bitsB64 === "string") {
|
|
333
|
+
result = b64ToArray(bitsB64);
|
|
334
|
+
} else if (bitsB64 == null) {
|
|
335
|
+
result = import_one_webcrypto.webcrypto.getRandomValues(new Uint8Array(16));
|
|
336
|
+
} else {
|
|
337
|
+
throw new Error("Must be Uint8Array, string, or nullish");
|
|
338
|
+
}
|
|
339
|
+
if (result.byteLength !== 16) {
|
|
340
|
+
throw new Error("Invalid byteLength: must be 16 bytes");
|
|
341
|
+
}
|
|
342
|
+
return result;
|
|
343
|
+
}
|
|
344
|
+
__name(decodeBits, "decodeBits");
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var slice_transformer_exports = {};
|
|
21
|
+
__export(slice_transformer_exports, {
|
|
22
|
+
SliceTransformer: () => SliceTransformer
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(slice_transformer_exports);
|
|
25
|
+
class SliceTransformer {
|
|
26
|
+
static {
|
|
27
|
+
__name(this, "SliceTransformer");
|
|
28
|
+
}
|
|
29
|
+
chunkSize;
|
|
30
|
+
restChunkSize;
|
|
31
|
+
partialChunk;
|
|
32
|
+
offset;
|
|
33
|
+
constructor(firstChunkSize, restChunkSize) {
|
|
34
|
+
this.chunkSize = firstChunkSize;
|
|
35
|
+
this.restChunkSize = restChunkSize || firstChunkSize;
|
|
36
|
+
this.partialChunk = new Uint8Array(this.chunkSize);
|
|
37
|
+
this.offset = 0;
|
|
38
|
+
}
|
|
39
|
+
send(record, controller) {
|
|
40
|
+
controller.enqueue(record);
|
|
41
|
+
this.chunkSize = this.restChunkSize;
|
|
42
|
+
this.partialChunk = new Uint8Array(this.chunkSize);
|
|
43
|
+
this.offset = 0;
|
|
44
|
+
}
|
|
45
|
+
transform(chunk, controller) {
|
|
46
|
+
let i = 0;
|
|
47
|
+
if (this.offset > 0) {
|
|
48
|
+
const len = Math.min(chunk.byteLength, this.chunkSize - this.offset);
|
|
49
|
+
this.partialChunk.set(chunk.subarray(0, len), this.offset);
|
|
50
|
+
this.offset += len;
|
|
51
|
+
i += len;
|
|
52
|
+
if (this.offset === this.chunkSize) {
|
|
53
|
+
this.send(this.partialChunk, controller);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
while (i < chunk.byteLength) {
|
|
57
|
+
const remainingBytes = chunk.byteLength - i;
|
|
58
|
+
if (remainingBytes >= this.chunkSize) {
|
|
59
|
+
const record = chunk.slice(i, i + this.chunkSize);
|
|
60
|
+
i += this.chunkSize;
|
|
61
|
+
this.send(record, controller);
|
|
62
|
+
} else {
|
|
63
|
+
const end = chunk.slice(i, i + remainingBytes);
|
|
64
|
+
i += end.byteLength;
|
|
65
|
+
this.partialChunk.set(end);
|
|
66
|
+
this.offset = end.byteLength;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
flush(controller) {
|
|
71
|
+
if (this.offset > 0) {
|
|
72
|
+
controller.enqueue(this.partialChunk.subarray(0, this.offset));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concatenates the array of ReadableStreams passed in `inputStreams`
|
|
3
|
+
* into a single ReadableStream.
|
|
4
|
+
*
|
|
5
|
+
* @param {ReadableStream[]} inputStreams
|
|
6
|
+
* @returns {ReadableStream}
|
|
7
|
+
*/
|
|
8
|
+
export declare function concatStreams(inputStreams: ReadableStream[]): ReadableStream;
|
|
9
|
+
//# sourceMappingURL=concat-streams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concat-streams.d.ts","sourceRoot":"","sources":["../../src/concat-streams.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAE,YAAY,EAAC,cAAc,EAAE,GAAE,cAAc,CAwC3E"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concatenates the array of ReadableStreams passed in `inputStreams`
|
|
3
|
+
* into a single ReadableStream.
|
|
4
|
+
*
|
|
5
|
+
* @param {ReadableStream[]} inputStreams
|
|
6
|
+
* @returns {ReadableStream}
|
|
7
|
+
*/
|
|
8
|
+
export function concatStreams(inputStreams) {
|
|
9
|
+
let currentReader = null;
|
|
10
|
+
// Move to the next stream
|
|
11
|
+
const nextStream = (controller) => {
|
|
12
|
+
const stream = inputStreams.shift();
|
|
13
|
+
if (stream !== undefined) {
|
|
14
|
+
currentReader = stream.getReader();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
currentReader = null;
|
|
18
|
+
controller.close();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
return new ReadableStream({
|
|
22
|
+
start(controller) {
|
|
23
|
+
nextStream(controller);
|
|
24
|
+
},
|
|
25
|
+
async pull(controller) {
|
|
26
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
27
|
+
while (currentReader !== null) {
|
|
28
|
+
const { value, done } = await currentReader.read();
|
|
29
|
+
if (done) {
|
|
30
|
+
nextStream(controller);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
controller.enqueue(value);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
async cancel(reason) {
|
|
39
|
+
await Promise.all([
|
|
40
|
+
currentReader && currentReader.cancel(reason),
|
|
41
|
+
...inputStreams.map(stream => stream.cancel(reason))
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=concat-streams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concat-streams.js","sourceRoot":"","sources":["../../src/concat-streams.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAE,YAA6B;IACxD,IAAI,aAAa,GAAoC,IAAI,CAAA;IAEzD,0BAA0B;IAC1B,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,EAAE;QAC9B,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,CAAA;QACnC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACvB,aAAa,GAAG,MAAM,CAAC,SAAS,EAAE,CAAA;QACtC,CAAC;aAAM,CAAC;YACJ,aAAa,GAAG,IAAI,CAAA;YACpB,UAAU,CAAC,KAAK,EAAE,CAAA;QACtB,CAAC;IACL,CAAC,CAAA;IAED,OAAO,IAAI,cAAc,CAAC;QACtB,KAAK,CAAE,UAAU;YACb,UAAU,CAAC,UAAU,CAAC,CAAA;QAC1B,CAAC;QAED,KAAK,CAAC,IAAI,CAAE,UAAU;YAClB,wDAAwD;YACxD,OAAO,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC5B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAA;gBAElD,IAAI,IAAI,EAAE,CAAC;oBACP,UAAU,CAAC,UAAU,CAAC,CAAA;gBAC1B,CAAC;qBAAM,CAAC;oBACJ,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;oBACzB,MAAK;gBACT,CAAC;YACL,CAAC;QACL,CAAC;QAED,KAAK,CAAC,MAAM,CAAE,MAAM;YAChB,MAAM,OAAO,CAAC,GAAG,CAAC;gBACd,aAAa,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC;gBAC7C,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;aACvD,CAAC,CAAA;QACN,CAAC;KACJ,CAAC,CAAA;AACN,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encryption and decryption streams for "Encrypted Content-Encoding for HTTP"
|
|
3
|
+
* specification. See: https://tools.ietf.org/html/rfc8188
|
|
4
|
+
*/
|
|
5
|
+
export declare const KEY_LENGTH = 16;
|
|
6
|
+
export declare const TAG_LENGTH = 16;
|
|
7
|
+
/**
|
|
8
|
+
* Given a plaintext size, return the corresponding encrypted size.
|
|
9
|
+
*
|
|
10
|
+
* plaintextSize: int containing plaintext size
|
|
11
|
+
* rs: int containing record size, optional
|
|
12
|
+
*/
|
|
13
|
+
export declare function encryptedSize(plaintextSize: number, rs?: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* Given an encrypted size, return the corresponding plaintext size.
|
|
16
|
+
*
|
|
17
|
+
* encryptedSize: int containing encrypted size
|
|
18
|
+
* rs: int containing record size, optional
|
|
19
|
+
*/
|
|
20
|
+
export declare function plaintextSize(encryptedSize: number, rs?: number): number;
|
|
21
|
+
/**
|
|
22
|
+
* Given a plaintext stream `input`, return an encrypted stream.
|
|
23
|
+
*
|
|
24
|
+
* input: a ReadableStream containing data to be transformed
|
|
25
|
+
* secretKey: CryptoKey containing secret key of size KEY_LENGTH
|
|
26
|
+
* rs: int containing record size, optional
|
|
27
|
+
* salt: Uint8Array containing salt of KEY_LENGTH length, optional
|
|
28
|
+
*/
|
|
29
|
+
export declare function encryptStream(input: ReadableStream, secretKey: CryptoKey, rs?: number, salt?: Uint8Array<ArrayBuffer>): ReadableStream;
|
|
30
|
+
/**
|
|
31
|
+
* Given an encrypted stream `input`, return a plaintext stream.
|
|
32
|
+
*
|
|
33
|
+
* input: a ReadableStream containing data to be transformed
|
|
34
|
+
* secretKey: CryptoKey containing secret key of size KEY_LENGTH
|
|
35
|
+
* rs: int containing record size, optional
|
|
36
|
+
*/
|
|
37
|
+
export declare function decryptStream(input: ReadableStream, secretKey: CryptoKey, rs?: number): ReadableStream;
|
|
38
|
+
/**
|
|
39
|
+
* Given a desired plaintext byte range specified by `offset` and `length`,
|
|
40
|
+
* and the total size of the encrypted stream in `totalEncryptedLength`,
|
|
41
|
+
* provides a mechanism to decrypt that range.
|
|
42
|
+
*
|
|
43
|
+
* To decrypt an arbitrary plaintext range, the client will need to supply
|
|
44
|
+
* multiple (currently always two) ranges of encrypted data.
|
|
45
|
+
* `decryptStreamRange` returns a promise that resolves to an object containing
|
|
46
|
+
* `ranges`, which is an array of { offset, length } entries specifying the
|
|
47
|
+
* needed encrypted byte ranges, and `encrypt`, a callback function.
|
|
48
|
+
*
|
|
49
|
+
* Once the client has gathered an array `streams` of encrypted ReadableStreams,
|
|
50
|
+
* one for each of these ranges, it should call `decrypt(streams)`. This will
|
|
51
|
+
* then return the final plaintext ReadableStream.
|
|
52
|
+
*
|
|
53
|
+
* secretKey: CryptoKey containing secret key of size KEY_LENGTH
|
|
54
|
+
* offset: int containing plaintext byte offset at which to start decryption
|
|
55
|
+
* length: int containing the number of plaintext bytes to decrypt
|
|
56
|
+
* totalEncryptedLength: The total number of bytes in the encrypted stream
|
|
57
|
+
* rs: int containing record size, optional
|
|
58
|
+
*/
|
|
59
|
+
export declare function decryptStreamRange(secretKey: CryptoKey, offset: number, length: number, totalEncryptedLength: number, rs?: number): {
|
|
60
|
+
ranges: {
|
|
61
|
+
offset: number;
|
|
62
|
+
length: number;
|
|
63
|
+
}[];
|
|
64
|
+
decrypt: (streams: ReadableStream[]) => ReadableStream;
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=ece.d.ts.map
|
|
@@ -0,0 +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;AAmS5B;;;;;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,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"}
|