@teepin/sdk 0.2.1 → 0.3.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 +41 -36
- package/dist/cjs/client.js +42 -4
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/direct/bytes.js +50 -0
- package/dist/cjs/direct/bytes.js.map +1 -0
- package/dist/cjs/direct/common.js +167 -0
- package/dist/cjs/direct/common.js.map +1 -0
- package/dist/cjs/direct/downloads-plan.js +127 -0
- package/dist/cjs/direct/downloads-plan.js.map +1 -0
- package/dist/cjs/direct/engine.js +405 -0
- package/dist/cjs/direct/engine.js.map +1 -0
- package/dist/cjs/direct/formats.js +44 -0
- package/dist/cjs/direct/formats.js.map +1 -0
- package/dist/cjs/direct/hpke.js +275 -0
- package/dist/cjs/direct/hpke.js.map +1 -0
- package/dist/cjs/direct/journal.js +80 -0
- package/dist/cjs/direct/journal.js.map +1 -0
- package/dist/cjs/direct/large.js +850 -0
- package/dist/cjs/direct/large.js.map +1 -0
- package/dist/cjs/direct/reads.js +1314 -0
- package/dist/cjs/direct/reads.js.map +1 -0
- package/dist/cjs/direct/sha256.js +122 -0
- package/dist/cjs/direct/sha256.js.map +1 -0
- package/dist/cjs/direct/tws1.js +480 -0
- package/dist/cjs/direct/tws1.js.map +1 -0
- package/dist/cjs/direct/uploads.js +1706 -0
- package/dist/cjs/direct/uploads.js.map +1 -0
- package/dist/cjs/errors.js +70 -13
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/index.js +5 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/links.js +195 -0
- package/dist/cjs/links.js.map +1 -0
- package/dist/cjs/node/downloads.js +835 -0
- package/dist/cjs/node/downloads.js.map +1 -0
- package/dist/cjs/node/journal.js +841 -0
- package/dist/cjs/node/journal.js.map +1 -0
- package/dist/cjs/node/uploads.js +219 -0
- package/dist/cjs/node/uploads.js.map +1 -0
- package/dist/cjs/node.js +26 -39
- package/dist/cjs/node.js.map +1 -1
- package/dist/cjs/storage.js +214 -184
- package/dist/cjs/storage.js.map +1 -1
- package/dist/cjs/transfer.js +18 -351
- package/dist/cjs/transfer.js.map +1 -1
- package/dist/esm/client.js +42 -4
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/direct/bytes.js +42 -0
- package/dist/esm/direct/bytes.js.map +1 -0
- package/dist/esm/direct/common.js +155 -0
- package/dist/esm/direct/common.js.map +1 -0
- package/dist/esm/direct/downloads-plan.js +117 -0
- package/dist/esm/direct/downloads-plan.js.map +1 -0
- package/dist/esm/direct/engine.js +385 -0
- package/dist/esm/direct/engine.js.map +1 -0
- package/dist/esm/direct/formats.js +40 -0
- package/dist/esm/direct/formats.js.map +1 -0
- package/dist/esm/direct/hpke.js +262 -0
- package/dist/esm/direct/hpke.js.map +1 -0
- package/dist/esm/direct/journal.js +75 -0
- package/dist/esm/direct/journal.js.map +1 -0
- package/dist/esm/direct/large.js +816 -0
- package/dist/esm/direct/large.js.map +1 -0
- package/dist/esm/direct/reads.js +1275 -0
- package/dist/esm/direct/reads.js.map +1 -0
- package/dist/esm/direct/sha256.js +118 -0
- package/dist/esm/direct/sha256.js.map +1 -0
- package/dist/esm/direct/tws1.js +460 -0
- package/dist/esm/direct/tws1.js.map +1 -0
- package/dist/esm/direct/uploads.js +1660 -0
- package/dist/esm/direct/uploads.js.map +1 -0
- package/dist/esm/errors.js +64 -11
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/links.js +189 -0
- package/dist/esm/links.js.map +1 -0
- package/dist/esm/node/downloads.js +829 -0
- package/dist/esm/node/downloads.js.map +1 -0
- package/dist/esm/node/journal.js +824 -0
- package/dist/esm/node/journal.js.map +1 -0
- package/dist/esm/node/uploads.js +187 -0
- package/dist/esm/node/uploads.js.map +1 -0
- package/dist/esm/node.js +17 -14
- package/dist/esm/node.js.map +1 -1
- package/dist/esm/storage.js +214 -184
- package/dist/esm/storage.js.map +1 -1
- package/dist/esm/transfer.js +19 -349
- package/dist/esm/transfer.js.map +1 -1
- package/dist/types/client.d.ts +45 -4
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/direct/bytes.d.ts +11 -0
- package/dist/types/direct/bytes.d.ts.map +1 -0
- package/dist/types/direct/common.d.ts +47 -0
- package/dist/types/direct/common.d.ts.map +1 -0
- package/dist/types/direct/downloads-plan.d.ts +75 -0
- package/dist/types/direct/downloads-plan.d.ts.map +1 -0
- package/dist/types/direct/engine.d.ts +191 -0
- package/dist/types/direct/engine.d.ts.map +1 -0
- package/dist/types/direct/formats.d.ts +9 -0
- package/dist/types/direct/formats.d.ts.map +1 -0
- package/dist/types/direct/hpke.d.ts +55 -0
- package/dist/types/direct/hpke.d.ts.map +1 -0
- package/dist/types/direct/journal.d.ts +55 -0
- package/dist/types/direct/journal.d.ts.map +1 -0
- package/dist/types/direct/large.d.ts +170 -0
- package/dist/types/direct/large.d.ts.map +1 -0
- package/dist/types/direct/reads.d.ts +306 -0
- package/dist/types/direct/reads.d.ts.map +1 -0
- package/dist/types/direct/sha256.d.ts +16 -0
- package/dist/types/direct/sha256.d.ts.map +1 -0
- package/dist/types/direct/tws1.d.ts +157 -0
- package/dist/types/direct/tws1.d.ts.map +1 -0
- package/dist/types/direct/uploads.d.ts +461 -0
- package/dist/types/direct/uploads.d.ts.map +1 -0
- package/dist/types/errors.d.ts +47 -8
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/links.d.ts +86 -0
- package/dist/types/links.d.ts.map +1 -0
- package/dist/types/node/downloads.d.ts +73 -0
- package/dist/types/node/downloads.d.ts.map +1 -0
- package/dist/types/node/journal.d.ts +162 -0
- package/dist/types/node/journal.d.ts.map +1 -0
- package/dist/types/node/uploads.d.ts +86 -0
- package/dist/types/node/uploads.d.ts.map +1 -0
- package/dist/types/node.d.ts +4 -2
- package/dist/types/node.d.ts.map +1 -1
- package/dist/types/storage.d.ts +107 -64
- package/dist/types/storage.d.ts.map +1 -1
- package/dist/types/transfer.d.ts +14 -23
- package/dist/types/transfer.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
// Copyright 2026 TEEPIN Project
|
|
2
|
+
// Licensed under the Apache License, Version 2.0
|
|
3
|
+
// TWS1, the format objects are encrypted in on the device before they go to
|
|
4
|
+
// storage (TEEPIN-STORAGE-DESIGN.md section 20.1). The reference is
|
|
5
|
+
// teepin-core's pkg/tws1; this module matches it byte for byte, and the shared
|
|
6
|
+
// vectors in test/vectors/tws1.json prove it.
|
|
7
|
+
//
|
|
8
|
+
// An object is a 72-byte header, then 64 KiB plaintext segments, each sealed
|
|
9
|
+
// with AES-256-GCM:
|
|
10
|
+
//
|
|
11
|
+
// - header: "TWS1", version 1, algorithm 1, log2 of the segment size (16), a
|
|
12
|
+
// zero byte, a 32-byte random salt, and a 32-byte key commitment;
|
|
13
|
+
// - keys: PRK = HKDF-Extract(SHA-512, salt, data key); the commitment, the
|
|
14
|
+
// segment key and a 7-byte nonce prefix are expanded from it, each bound to
|
|
15
|
+
// the header's first 40 bytes;
|
|
16
|
+
// - a segment's nonce is the prefix, its index (uint32 big-endian) and a byte
|
|
17
|
+
// that is 1 only on the last segment, so segments can't be reordered, dropped
|
|
18
|
+
// or cut off; the associated data is the whole header.
|
|
19
|
+
//
|
|
20
|
+
// A large object is one stream cut into parts at segment boundaries (section
|
|
21
|
+
// 21.1, D1): Stream seals any part from its plaintext alone, and the same
|
|
22
|
+
// plaintext always seals to the same bytes, so a retried part is identical.
|
|
23
|
+
//
|
|
24
|
+
// In a pack, each object is preceded by a 64-byte needle: "TPK1", the object
|
|
25
|
+
// id, the stored size and the SHA-256 of the stored bytes.
|
|
26
|
+
//
|
|
27
|
+
// Nothing here does I/O. Crypto is WebCrypto only, so the same code runs in
|
|
28
|
+
// Node 20+ and browsers. The segment key never leaves WebCrypto (it is derived
|
|
29
|
+
// as a non-extractable key); data keys stay with the caller, who can zero them.
|
|
30
|
+
import { DataIntegrityError, TeepinError } from '../errors.js';
|
|
31
|
+
import { concat, constantTimeEqual, isInt, utf8 } from './bytes.js';
|
|
32
|
+
/**
|
|
33
|
+
* Data that failed a check (errors.ts): reason is "segment", "commitment", "needle", "truncated" or "format" here.
|
|
34
|
+
* Re-exported, as this module threw its own before the read surface landed.
|
|
35
|
+
*/
|
|
36
|
+
export { DataIntegrityError };
|
|
37
|
+
export const HEADER_SIZE = 72;
|
|
38
|
+
export const SEGMENT_SIZE = 1 << 16;
|
|
39
|
+
export const TAG_SIZE = 16;
|
|
40
|
+
export const STORED_SEGMENT_SIZE = SEGMENT_SIZE + TAG_SIZE;
|
|
41
|
+
export const KEY_SIZE = 32;
|
|
42
|
+
export const SALT_SIZE = 32;
|
|
43
|
+
/** The most segments one object may have (the index is a uint32). */
|
|
44
|
+
export const MAX_SEGMENTS = 2 ** 32 - 1;
|
|
45
|
+
export const NEEDLE_HEADER_SIZE = 64;
|
|
46
|
+
const MAGIC = utf8('TWS1');
|
|
47
|
+
const VERSION = 0x01;
|
|
48
|
+
const ALGORITHM = 0x01;
|
|
49
|
+
const SEGMENT_LOG2 = 16;
|
|
50
|
+
const PREFIX_SIZE = 7;
|
|
51
|
+
const BOUND_SIZE = 40; // the header bytes every derivation is bound to: all before the commitment
|
|
52
|
+
const NEEDLE_MAGIC = utf8('TPK1');
|
|
53
|
+
/**
|
|
54
|
+
* Where fresh salts come from. Only tests replace salt, to reproduce the shared vectors; the public functions take no
|
|
55
|
+
* salt, so callers can't choose one, and a test checks that no file under src assigns it. Shared state is safe here,
|
|
56
|
+
* unlike for HPKE's ephemeral keys (hpke.sealWith): every object has a fresh random data key, so even a fixed salt
|
|
57
|
+
* never repeats a segment key and nonce.
|
|
58
|
+
*/
|
|
59
|
+
export const testHooks = {
|
|
60
|
+
salt: () => crypto.getRandomValues(new Uint8Array(SALT_SIZE)),
|
|
61
|
+
};
|
|
62
|
+
/** A fresh 32-byte data key; the caller zeroes it (fill(0)) when done. */
|
|
63
|
+
export function newDataKey() {
|
|
64
|
+
return crypto.getRandomValues(new Uint8Array(KEY_SIZE));
|
|
65
|
+
}
|
|
66
|
+
/** How many segments an object of this size has: at least one, since an empty object is one empty last segment. */
|
|
67
|
+
export function segments(plaintextSize) {
|
|
68
|
+
if (plaintextSize <= 0)
|
|
69
|
+
return 1;
|
|
70
|
+
return Math.ceil(plaintextSize / SEGMENT_SIZE);
|
|
71
|
+
}
|
|
72
|
+
/** The size of the stored object, from the plaintext's size alone. */
|
|
73
|
+
export function storedSize(plaintextSize) {
|
|
74
|
+
return HEADER_SIZE + segments(plaintextSize) * TAG_SIZE + plaintextSize;
|
|
75
|
+
}
|
|
76
|
+
// --- keys -------------------------------------------------------------------
|
|
77
|
+
/** The keys derived from a data key and an object's header. */
|
|
78
|
+
export class Keys {
|
|
79
|
+
aad;
|
|
80
|
+
commit;
|
|
81
|
+
aead;
|
|
82
|
+
prefix;
|
|
83
|
+
constructor(header, commitment, aead, prefix) {
|
|
84
|
+
this.aad = header;
|
|
85
|
+
this.commit = commitment;
|
|
86
|
+
this.aead = aead;
|
|
87
|
+
this.prefix = prefix;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The keys for an object's header. Given only the header's first 40 bytes, the derived commitment completes it (how
|
|
91
|
+
* a new header is made); a full header's commitment is not checked here, openHeader does that.
|
|
92
|
+
*/
|
|
93
|
+
static async derive(dek, header) {
|
|
94
|
+
if (dek.length !== KEY_SIZE)
|
|
95
|
+
throw new TeepinError('tws1: a data key must be 32 bytes');
|
|
96
|
+
if (header.length !== BOUND_SIZE && header.length < HEADER_SIZE)
|
|
97
|
+
throw new TeepinError(`tws1: a header is ${HEADER_SIZE} bytes`);
|
|
98
|
+
const bound = header.slice(0, BOUND_SIZE);
|
|
99
|
+
const salt = bound.subarray(8, 8 + SALT_SIZE);
|
|
100
|
+
// WebCrypto's HKDF is Extract then Expand in one call, so each derivation
|
|
101
|
+
// extracts the same PRK again from the salt and the data key.
|
|
102
|
+
const ikm = await crypto.subtle.importKey('raw', dek, 'HKDF', false, ['deriveBits', 'deriveKey']);
|
|
103
|
+
const params = (label) => ({ name: 'HKDF', hash: 'SHA-512', salt, info: concat([utf8(label), bound]) });
|
|
104
|
+
const [commitment, aead, prefix] = await Promise.all([
|
|
105
|
+
crypto.subtle.deriveBits(params('tws1/commit'), ikm, 32 * 8),
|
|
106
|
+
crypto.subtle.deriveKey(params('tws1/key'), ikm, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']),
|
|
107
|
+
crypto.subtle.deriveBits(params('tws1/nonce'), ikm, PREFIX_SIZE * 8),
|
|
108
|
+
]);
|
|
109
|
+
const commit = new Uint8Array(commitment);
|
|
110
|
+
const full = header.length === BOUND_SIZE ? concat([bound, commit]) : header.slice(0, HEADER_SIZE);
|
|
111
|
+
return new Keys(full, commit, aead, new Uint8Array(prefix));
|
|
112
|
+
}
|
|
113
|
+
/** The object's 72-byte header (a copy). */
|
|
114
|
+
get header() {
|
|
115
|
+
return this.aad.slice();
|
|
116
|
+
}
|
|
117
|
+
/** The commitment derived from the data key (a copy); in a valid header it is the last 32 bytes. */
|
|
118
|
+
get commitment() {
|
|
119
|
+
return this.commit.slice();
|
|
120
|
+
}
|
|
121
|
+
/** Segment index's nonce: the prefix, the index (uint32 big-endian) and 1 on the last segment, else 0. */
|
|
122
|
+
nonce(index, last) {
|
|
123
|
+
if (!isInt(index) || index < 0 || index > 0xffffffff)
|
|
124
|
+
throw new TeepinError(`tws1: segment index ${index} is not a uint32`);
|
|
125
|
+
const n = new Uint8Array(12);
|
|
126
|
+
n.set(this.prefix);
|
|
127
|
+
new DataView(n.buffer).setUint32(PREFIX_SIZE, index);
|
|
128
|
+
n[11] = last ? 1 : 0;
|
|
129
|
+
return n;
|
|
130
|
+
}
|
|
131
|
+
/** One segment, sealed: its ciphertext and tag. */
|
|
132
|
+
async seal(index, last, plain) {
|
|
133
|
+
const params = { name: 'AES-GCM', iv: this.nonce(index, last), additionalData: this.aad };
|
|
134
|
+
return new Uint8Array(await crypto.subtle.encrypt(params, this.aead, plain));
|
|
135
|
+
}
|
|
136
|
+
/** One segment, opened; DataIntegrityError if it fails authentication. */
|
|
137
|
+
async open(index, last, sealed) {
|
|
138
|
+
const params = { name: 'AES-GCM', iv: this.nonce(index, last), additionalData: this.aad };
|
|
139
|
+
let plain;
|
|
140
|
+
try {
|
|
141
|
+
plain = await crypto.subtle.decrypt(params, this.aead, sealed);
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
throw new DataIntegrityError('a segment failed authentication', 'segment');
|
|
145
|
+
}
|
|
146
|
+
return new Uint8Array(plain);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/** A new object's header, with a fresh salt and its commitment, and the keys to seal its segments. */
|
|
150
|
+
export async function newHeader(dek) {
|
|
151
|
+
if (dek.length !== KEY_SIZE)
|
|
152
|
+
throw new TeepinError('tws1: a data key must be 32 bytes');
|
|
153
|
+
const salt = testHooks.salt();
|
|
154
|
+
if (salt.length !== SALT_SIZE)
|
|
155
|
+
throw new TeepinError('tws1: a salt must be 32 bytes');
|
|
156
|
+
const bound = new Uint8Array(BOUND_SIZE);
|
|
157
|
+
bound.set(MAGIC);
|
|
158
|
+
bound[4] = VERSION;
|
|
159
|
+
bound[5] = ALGORITHM;
|
|
160
|
+
bound[6] = SEGMENT_LOG2;
|
|
161
|
+
bound.set(salt, 8);
|
|
162
|
+
const keys = await Keys.derive(dek, bound);
|
|
163
|
+
return { header: keys.header, keys };
|
|
164
|
+
}
|
|
165
|
+
/** The keys for an existing object, after checking its header and, in constant time, that the data key matches its commitment. */
|
|
166
|
+
export async function openHeader(dek, header) {
|
|
167
|
+
if (header.length < HEADER_SIZE)
|
|
168
|
+
throw new DataIntegrityError('the object is truncated', 'truncated');
|
|
169
|
+
const h = header.subarray(0, HEADER_SIZE);
|
|
170
|
+
if (!constantTimeEqual(h.subarray(0, 4), MAGIC) || h[4] !== VERSION || h[5] !== ALGORITHM || h[6] !== SEGMENT_LOG2 || h[7] !== 0) {
|
|
171
|
+
throw new DataIntegrityError('not a TWS1 object, or an unsupported version', 'format');
|
|
172
|
+
}
|
|
173
|
+
const keys = await Keys.derive(dek, h);
|
|
174
|
+
if (!constantTimeEqual(keys.commitment, h.subarray(BOUND_SIZE, HEADER_SIZE))) {
|
|
175
|
+
throw new DataIntegrityError("the data key does not match the object's commitment", 'commitment');
|
|
176
|
+
}
|
|
177
|
+
return keys;
|
|
178
|
+
}
|
|
179
|
+
// --- whole objects ----------------------------------------------------------
|
|
180
|
+
/** A whole object, encrypted with a fresh salt. */
|
|
181
|
+
export async function encrypt(dek, plaintext) {
|
|
182
|
+
const n = segments(plaintext.length);
|
|
183
|
+
if (n > MAX_SEGMENTS)
|
|
184
|
+
throw new TeepinError(`tws1: an object may have at most ${MAX_SEGMENTS} segments`);
|
|
185
|
+
const { header, keys } = await newHeader(dek);
|
|
186
|
+
const out = new Uint8Array(storedSize(plaintext.length));
|
|
187
|
+
out.set(header);
|
|
188
|
+
for (let i = 0; i < n; i++) {
|
|
189
|
+
const sealed = await keys.seal(i, i === n - 1, plaintext.subarray(i * SEGMENT_SIZE, (i + 1) * SEGMENT_SIZE));
|
|
190
|
+
out.set(sealed, HEADER_SIZE + i * STORED_SEGMENT_SIZE);
|
|
191
|
+
}
|
|
192
|
+
return out;
|
|
193
|
+
}
|
|
194
|
+
/** A whole object, decrypted and verified. */
|
|
195
|
+
export async function decrypt(dek, stored) {
|
|
196
|
+
const keys = await openHeader(dek, stored);
|
|
197
|
+
const body = stored.subarray(HEADER_SIZE);
|
|
198
|
+
if (body.length < TAG_SIZE)
|
|
199
|
+
throw new DataIntegrityError('the object is truncated', 'truncated');
|
|
200
|
+
const n = Math.ceil(body.length / STORED_SEGMENT_SIZE);
|
|
201
|
+
if (body.length - (n - 1) * STORED_SEGMENT_SIZE < TAG_SIZE)
|
|
202
|
+
throw new DataIntegrityError('the object is truncated', 'truncated');
|
|
203
|
+
const out = new Uint8Array(body.length - n * TAG_SIZE);
|
|
204
|
+
for (let i = 0; i < n; i++) {
|
|
205
|
+
const plain = await keys.open(i, i === n - 1, body.subarray(i * STORED_SEGMENT_SIZE, (i + 1) * STORED_SEGMENT_SIZE));
|
|
206
|
+
out.set(plain, i * SEGMENT_SIZE);
|
|
207
|
+
}
|
|
208
|
+
return out;
|
|
209
|
+
}
|
|
210
|
+
/** The segments holding plaintext bytes [offset, offset + length). */
|
|
211
|
+
export function locate(plaintextSize, offset, length) {
|
|
212
|
+
if (!isInt(plaintextSize) || !isInt(offset) || !isInt(length) || offset < 0 || length < 0 || offset + length > plaintextSize) {
|
|
213
|
+
throw new TeepinError(`tws1: range [${offset}, ${offset + length}) is outside an object of ${plaintextSize} bytes`);
|
|
214
|
+
}
|
|
215
|
+
const n = segments(plaintextSize);
|
|
216
|
+
const first = Math.min(Math.floor(offset / SEGMENT_SIZE), n - 1);
|
|
217
|
+
const last = length === 0 ? first : Math.floor((offset + length - 1) / SEGMENT_SIZE);
|
|
218
|
+
const storedEnd = last === n - 1 ? storedSize(plaintextSize) : HEADER_SIZE + (last + 1) * STORED_SEGMENT_SIZE;
|
|
219
|
+
const start = HEADER_SIZE + first * STORED_SEGMENT_SIZE;
|
|
220
|
+
return { firstSegment: first, storedOffset: start, storedLength: storedEnd - start, skip: offset - first * SEGMENT_SIZE, length };
|
|
221
|
+
}
|
|
222
|
+
/** A located range, decrypted from exactly its stored bytes. */
|
|
223
|
+
export async function decryptRange(keys, plaintextSize, r, stored) {
|
|
224
|
+
if (stored.length !== r.storedLength)
|
|
225
|
+
throw new DataIntegrityError('the range is truncated', 'truncated');
|
|
226
|
+
const n = segments(plaintextSize);
|
|
227
|
+
const opened = [];
|
|
228
|
+
let total = 0;
|
|
229
|
+
for (let i = r.firstSegment, off = 0; off < stored.length; i++) {
|
|
230
|
+
if (i >= n)
|
|
231
|
+
throw new DataIntegrityError('the range runs past the object', 'truncated');
|
|
232
|
+
const end = Math.min(off + STORED_SEGMENT_SIZE, stored.length);
|
|
233
|
+
const plain = await keys.open(i, i === n - 1, stored.subarray(off, end));
|
|
234
|
+
opened.push(plain);
|
|
235
|
+
total += plain.length;
|
|
236
|
+
off = end;
|
|
237
|
+
}
|
|
238
|
+
if (r.skip + r.length > total)
|
|
239
|
+
throw new DataIntegrityError('the range is truncated', 'truncated');
|
|
240
|
+
return concat(opened).slice(r.skip, r.skip + r.length);
|
|
241
|
+
}
|
|
242
|
+
/** [stored offset, stored length] of segment index. */
|
|
243
|
+
export function segmentAt(plaintextSize, index) {
|
|
244
|
+
const n = segments(plaintextSize);
|
|
245
|
+
if (!isInt(index) || index < 0 || index >= n)
|
|
246
|
+
throw new TeepinError(`tws1: segment ${index} of ${n}`);
|
|
247
|
+
const start = HEADER_SIZE + index * STORED_SEGMENT_SIZE;
|
|
248
|
+
if (index === n - 1)
|
|
249
|
+
return [start, storedSize(plaintextSize) - start];
|
|
250
|
+
return [start, STORED_SEGMENT_SIZE];
|
|
251
|
+
}
|
|
252
|
+
function checkPartSize(partSize) {
|
|
253
|
+
if (!isInt(partSize) || partSize <= 0 || partSize % SEGMENT_SIZE !== 0) {
|
|
254
|
+
throw new TeepinError(`tws1: a part holds a positive multiple of ${SEGMENT_SIZE} plaintext bytes`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function checkLayout(plaintextSize, partSize) {
|
|
258
|
+
if (!isInt(plaintextSize) || plaintextSize < 1)
|
|
259
|
+
throw new TeepinError('tws1: a large object has at least one byte');
|
|
260
|
+
checkPartSize(partSize);
|
|
261
|
+
if (segments(plaintextSize) > MAX_SEGMENTS)
|
|
262
|
+
throw new TeepinError(`tws1: an object may have at most ${MAX_SEGMENTS} segments`);
|
|
263
|
+
}
|
|
264
|
+
function partAt(plaintextSize, partSize, j) {
|
|
265
|
+
const plainFirst = j * partSize;
|
|
266
|
+
const plainSize = Math.min(partSize, plaintextSize - plainFirst);
|
|
267
|
+
const size = Math.ceil(plainSize / SEGMENT_SIZE) * TAG_SIZE + plainSize;
|
|
268
|
+
if (j === 0)
|
|
269
|
+
return { number: 1, plainFirst: 0, plainSize, storedFirst: 0, storedSize: size + HEADER_SIZE };
|
|
270
|
+
const storedFirst = HEADER_SIZE + (plainFirst / SEGMENT_SIZE) * STORED_SEGMENT_SIZE;
|
|
271
|
+
return { number: j + 1, plainFirst, plainSize, storedFirst, storedSize: size };
|
|
272
|
+
}
|
|
273
|
+
/** How many parts parts() makes, without making them. */
|
|
274
|
+
export function partCount(plaintextSize, partSize) {
|
|
275
|
+
checkLayout(plaintextSize, partSize);
|
|
276
|
+
return Math.ceil(plaintextSize / partSize);
|
|
277
|
+
}
|
|
278
|
+
/** Every part of an object of plaintextSize cut into partSize plaintext bytes (a multiple of 64 KiB). */
|
|
279
|
+
export function parts(plaintextSize, partSize) {
|
|
280
|
+
const n = partCount(plaintextSize, partSize);
|
|
281
|
+
const out = [];
|
|
282
|
+
for (let j = 0; j < n; j++)
|
|
283
|
+
out.push(partAt(plaintextSize, partSize, j));
|
|
284
|
+
return out;
|
|
285
|
+
}
|
|
286
|
+
/** Part number (1-based) of the layout parts() makes. */
|
|
287
|
+
export function partOf(plaintextSize, partSize, number) {
|
|
288
|
+
const n = partCount(plaintextSize, partSize);
|
|
289
|
+
if (!isInt(number) || number < 1 || number > n)
|
|
290
|
+
throw new TeepinError(`tws1: part ${number} of ${n}`);
|
|
291
|
+
return partAt(plaintextSize, partSize, number - 1);
|
|
292
|
+
}
|
|
293
|
+
/** One large object's encryption, sealed a part at a time in any order. */
|
|
294
|
+
export class Stream {
|
|
295
|
+
size;
|
|
296
|
+
partSize;
|
|
297
|
+
partCount;
|
|
298
|
+
keys;
|
|
299
|
+
segmentCount;
|
|
300
|
+
constructor(keys, size, partSize) {
|
|
301
|
+
this.partCount = partCount(size, partSize);
|
|
302
|
+
this.keys = keys;
|
|
303
|
+
this.size = size;
|
|
304
|
+
this.partSize = partSize;
|
|
305
|
+
this.segmentCount = segments(size);
|
|
306
|
+
}
|
|
307
|
+
/** A new stream, with a fresh header. */
|
|
308
|
+
static async create(dek, size, partSize) {
|
|
309
|
+
partCount(size, partSize);
|
|
310
|
+
const { keys } = await newHeader(dek);
|
|
311
|
+
return new Stream(keys, size, partSize);
|
|
312
|
+
}
|
|
313
|
+
/** The stream an earlier header began, to seal its remaining parts. */
|
|
314
|
+
static async resume(dek, header, size, partSize) {
|
|
315
|
+
partCount(size, partSize);
|
|
316
|
+
return new Stream(await openHeader(dek, header), size, partSize);
|
|
317
|
+
}
|
|
318
|
+
/** The object's header (a copy): the start of part 1, kept to seal any part again after a restart. */
|
|
319
|
+
get header() {
|
|
320
|
+
return this.keys.header;
|
|
321
|
+
}
|
|
322
|
+
/** Part number, sealed from exactly its plaintext. */
|
|
323
|
+
async sealPart(number, plain) {
|
|
324
|
+
if (!isInt(number) || number < 1 || number > this.partCount)
|
|
325
|
+
throw new TeepinError(`tws1: part ${number} of ${this.partCount}`);
|
|
326
|
+
const p = partAt(this.size, this.partSize, number - 1);
|
|
327
|
+
if (plain.length !== p.plainSize)
|
|
328
|
+
throw new TeepinError(`tws1: part ${number} holds ${p.plainSize} plaintext bytes, not ${plain.length}`);
|
|
329
|
+
return concat(await sealSegments(this.keys, number, p.plainFirst / SEGMENT_SIZE, plain, this.segmentCount - 1));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* A stream whose size isn't known yet (section 22.1, E2 b), sealed a part at a time in any order. Every part but the
|
|
334
|
+
* last holds exactly partSize plaintext bytes; the last holds 1 to partSize and is sealed as the last, so its final
|
|
335
|
+
* segment carries the last flag. For the same key, header and plaintext it seals exactly the bytes Stream would, so
|
|
336
|
+
* storage and readers can't tell the two apart.
|
|
337
|
+
*/
|
|
338
|
+
export class OpenStream {
|
|
339
|
+
partSize;
|
|
340
|
+
keys;
|
|
341
|
+
constructor(keys, partSize) {
|
|
342
|
+
checkPartSize(partSize);
|
|
343
|
+
this.keys = keys;
|
|
344
|
+
this.partSize = partSize;
|
|
345
|
+
}
|
|
346
|
+
/** A new stream, with a fresh header. */
|
|
347
|
+
static async create(dek, partSize) {
|
|
348
|
+
checkPartSize(partSize);
|
|
349
|
+
const { keys } = await newHeader(dek);
|
|
350
|
+
return new OpenStream(keys, partSize);
|
|
351
|
+
}
|
|
352
|
+
/** The object's header (a copy): the start of part 1. */
|
|
353
|
+
get header() {
|
|
354
|
+
return this.keys.header;
|
|
355
|
+
}
|
|
356
|
+
/** Part number, sealed from exactly its plaintext; last says it ends the stream. */
|
|
357
|
+
async sealPart(number, plain, last) {
|
|
358
|
+
return concat(await this.sealSegments(number, plain, last));
|
|
359
|
+
}
|
|
360
|
+
/** sealPart as its pieces (the header first on part 1), so a caller can drop the plaintext before joining them. */
|
|
361
|
+
async sealSegments(number, plain, last) {
|
|
362
|
+
if (!isInt(number) || number < 1)
|
|
363
|
+
throw new TeepinError(`tws1: part ${number}`);
|
|
364
|
+
if (last && !(plain.length >= 1 && plain.length <= this.partSize)) {
|
|
365
|
+
throw new TeepinError(`tws1: a last part holds 1 to ${this.partSize} plaintext bytes, not ${plain.length}`);
|
|
366
|
+
}
|
|
367
|
+
if (!last && plain.length !== this.partSize)
|
|
368
|
+
throw new TeepinError(`tws1: part ${number} holds ${this.partSize} plaintext bytes, not ${plain.length}`);
|
|
369
|
+
const first = ((number - 1) * this.partSize) / SEGMENT_SIZE;
|
|
370
|
+
const count = Math.ceil(plain.length / SEGMENT_SIZE);
|
|
371
|
+
if (first + count > MAX_SEGMENTS)
|
|
372
|
+
throw new TeepinError(`tws1: an object may have at most ${MAX_SEGMENTS} segments`);
|
|
373
|
+
return sealSegments(this.keys, number, first, plain, last ? first + count - 1 : -1);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/** A part's sealed segments from first on, the one at lastIndex sealed as the stream's last; part 1 begins with the header. */
|
|
377
|
+
async function sealSegments(keys, number, first, plain, lastIndex) {
|
|
378
|
+
const out = number === 1 ? [keys.header] : [];
|
|
379
|
+
for (let off = 0; off < plain.length; off += SEGMENT_SIZE) {
|
|
380
|
+
const i = first + off / SEGMENT_SIZE;
|
|
381
|
+
out.push(await keys.seal(i, i === lastIndex, plain.subarray(off, off + SEGMENT_SIZE)));
|
|
382
|
+
}
|
|
383
|
+
return out;
|
|
384
|
+
}
|
|
385
|
+
// --- needles (objects in a pack) --------------------------------------------
|
|
386
|
+
async function sha256(data) {
|
|
387
|
+
return new Uint8Array(await crypto.subtle.digest('SHA-256', data));
|
|
388
|
+
}
|
|
389
|
+
/** The 64-byte header that precedes an object in a pack. */
|
|
390
|
+
export async function needle(objectId, stored) {
|
|
391
|
+
if (objectId.length !== 16)
|
|
392
|
+
throw new TeepinError('tws1: an object id is 16 bytes');
|
|
393
|
+
const h = new Uint8Array(NEEDLE_HEADER_SIZE);
|
|
394
|
+
h.set(NEEDLE_MAGIC);
|
|
395
|
+
h.set(objectId, 4);
|
|
396
|
+
new DataView(h.buffer).setBigUint64(20, BigInt(stored.length));
|
|
397
|
+
h.set(await sha256(stored), 28);
|
|
398
|
+
return h;
|
|
399
|
+
}
|
|
400
|
+
/** A pack being built: each object's needle, then its stored bytes. */
|
|
401
|
+
export class Pack {
|
|
402
|
+
chunks = [];
|
|
403
|
+
length = 0;
|
|
404
|
+
/** The pack's size so far, in bytes. */
|
|
405
|
+
get size() {
|
|
406
|
+
return this.length;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Appends an object's needle and a copy of its stored bytes; returns the offset of the stored bytes in the pack.
|
|
410
|
+
* Appends may overlap: each lands whole, and returns where its own bytes are.
|
|
411
|
+
*/
|
|
412
|
+
async appendNeedle(objectId, stored) {
|
|
413
|
+
const copy = stored.slice();
|
|
414
|
+
const head = await needle(objectId, copy);
|
|
415
|
+
this.chunks.push(head, copy);
|
|
416
|
+
const offset = this.length + NEEDLE_HEADER_SIZE;
|
|
417
|
+
this.length = offset + copy.length;
|
|
418
|
+
return offset;
|
|
419
|
+
}
|
|
420
|
+
/** The whole pack (await every appendNeedle first). */
|
|
421
|
+
bytes() {
|
|
422
|
+
return concat(this.chunks);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/** Checks that a needle names this object, its size and its stored bytes' SHA-256; DataIntegrityError otherwise. */
|
|
426
|
+
export async function checkNeedle(head, objectId, stored) {
|
|
427
|
+
const ok = head.length === NEEDLE_HEADER_SIZE &&
|
|
428
|
+
constantTimeEqual(head.subarray(0, 4), NEEDLE_MAGIC) &&
|
|
429
|
+
constantTimeEqual(head.subarray(4, 20), objectId) &&
|
|
430
|
+
new DataView(head.buffer, head.byteOffset, head.length).getBigUint64(20) === BigInt(stored.length) &&
|
|
431
|
+
constantTimeEqual(head.subarray(60, 64), new Uint8Array(4)) &&
|
|
432
|
+
constantTimeEqual(head.subarray(28, 60), await sha256(stored));
|
|
433
|
+
if (!ok)
|
|
434
|
+
throw new DataIntegrityError("the pack's needle does not match the object", 'needle');
|
|
435
|
+
}
|
|
436
|
+
/** The stored bytes (a copy) of the object at offset in a pack, after checking its needle. */
|
|
437
|
+
export async function readNeedle(pack, offset, objectId, size) {
|
|
438
|
+
const start = offset - NEEDLE_HEADER_SIZE;
|
|
439
|
+
if (!isInt(offset) || !isInt(size) || start < 0 || size < 0 || offset + size > pack.length) {
|
|
440
|
+
throw new DataIntegrityError("the pack's needle does not match the object", 'needle');
|
|
441
|
+
}
|
|
442
|
+
const stored = pack.subarray(offset, offset + size);
|
|
443
|
+
await checkNeedle(pack.subarray(start, offset), objectId, stored);
|
|
444
|
+
return stored.slice();
|
|
445
|
+
}
|
|
446
|
+
/** A UUID string's 16 bytes (hyphens, braces and a urn:uuid: prefix are allowed). */
|
|
447
|
+
export function objectIdBytes(objectId) {
|
|
448
|
+
const hex = objectId
|
|
449
|
+
.replace(/urn:/g, '')
|
|
450
|
+
.replace(/uuid:/g, '')
|
|
451
|
+
.replace(/^[{}]+|[{}]+$/g, '')
|
|
452
|
+
.replace(/-/g, '');
|
|
453
|
+
if (!/^[0-9a-fA-F]{32}$/.test(hex))
|
|
454
|
+
throw new TeepinError(`tws1: ${objectId} is not a UUID`);
|
|
455
|
+
const out = new Uint8Array(16);
|
|
456
|
+
for (let i = 0; i < 16; i++)
|
|
457
|
+
out[i] = parseInt(hex.slice(2 * i, 2 * i + 2), 16);
|
|
458
|
+
return out;
|
|
459
|
+
}
|
|
460
|
+
//# sourceMappingURL=tws1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tws1.js","sourceRoot":"","sources":["../../../src/direct/tws1.ts"],"names":[],"mappings":"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"}
|