space-data-module-sdk 0.4.1 → 0.5.4
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 +17 -9
- package/package.json +12 -4
- package/src/browser.js +8 -0
- package/src/bundle/wasm.js +21 -4
- package/src/capabilities.js +46 -0
- package/src/compiler/compileModule.js +79 -13
- package/src/compliance/index.js +4 -2
- package/src/compliance/pluginCompliance.js +4 -47
- package/src/index.d.ts +159 -5
- package/src/index.js +1 -0
- package/src/manifest/browser.js +15 -0
- package/src/transport/index.js +19 -0
- package/src/transport/pki.js +125 -4
- package/src/transport/records.js +836 -0
- package/src/utils/wasmCrypto.js +43 -0
package/src/transport/pki.js
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
toUint8Array,
|
|
7
7
|
} from "../utils/encoding.js";
|
|
8
8
|
import {
|
|
9
|
+
aesCtrDecrypt,
|
|
10
|
+
aesCtrEncrypt,
|
|
9
11
|
aesGcmDecrypt,
|
|
10
12
|
aesGcmEncrypt,
|
|
11
13
|
hkdfBytes,
|
|
@@ -13,6 +15,13 @@ import {
|
|
|
13
15
|
x25519PublicKey,
|
|
14
16
|
x25519SharedSecret,
|
|
15
17
|
} from "../utils/wasmCrypto.js";
|
|
18
|
+
import {
|
|
19
|
+
appendPublicationRecordCollection,
|
|
20
|
+
createEncryptedEnvelopePayload,
|
|
21
|
+
decodeEncRecord,
|
|
22
|
+
encodePublicationRecordCollection,
|
|
23
|
+
extractPublicationRecordCollection,
|
|
24
|
+
} from "./records.js";
|
|
16
25
|
|
|
17
26
|
function normalizePublicKey(value) {
|
|
18
27
|
if (typeof value === "string") {
|
|
@@ -53,15 +62,12 @@ export async function generateX25519Keypair() {
|
|
|
53
62
|
};
|
|
54
63
|
}
|
|
55
64
|
|
|
56
|
-
|
|
65
|
+
async function encryptBytesLegacy({
|
|
57
66
|
plaintext,
|
|
58
67
|
recipientPublicKey,
|
|
59
68
|
context = "space-data-module-sdk/package",
|
|
60
69
|
senderKeyPair = null,
|
|
61
70
|
} = {}) {
|
|
62
|
-
if (!recipientPublicKey) {
|
|
63
|
-
throw new Error("encryptBytesForRecipient requires recipientPublicKey.");
|
|
64
|
-
}
|
|
65
71
|
const sender = senderKeyPair ?? (await generateX25519Keypair());
|
|
66
72
|
const salt = await randomBytes(32);
|
|
67
73
|
const iv = await randomBytes(12);
|
|
@@ -89,6 +95,77 @@ export async function encryptBytesForRecipient({
|
|
|
89
95
|
};
|
|
90
96
|
}
|
|
91
97
|
|
|
98
|
+
export async function decryptProtectedBytes({
|
|
99
|
+
protectedBytes,
|
|
100
|
+
recipientPrivateKey,
|
|
101
|
+
} = {}) {
|
|
102
|
+
const parsed = extractPublicationRecordCollection(protectedBytes);
|
|
103
|
+
if (!parsed?.enc) {
|
|
104
|
+
return toUint8Array(protectedBytes);
|
|
105
|
+
}
|
|
106
|
+
const sharedSecret = await deriveSharedSecret(
|
|
107
|
+
recipientPrivateKey,
|
|
108
|
+
parsed.enc.ephemeralPublicKey,
|
|
109
|
+
);
|
|
110
|
+
const aesKey = await deriveAesKey(
|
|
111
|
+
sharedSecret,
|
|
112
|
+
new Uint8Array(0),
|
|
113
|
+
parsed.enc.context ?? "",
|
|
114
|
+
);
|
|
115
|
+
return aesCtrDecrypt(aesKey, parsed.payloadBytes, parsed.enc.nonceStart);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export async function encryptBytesForRecipient({
|
|
119
|
+
plaintext,
|
|
120
|
+
recipientPublicKey,
|
|
121
|
+
context = "space-data-module-sdk/package",
|
|
122
|
+
senderKeyPair = null,
|
|
123
|
+
recipientKeyId = null,
|
|
124
|
+
schemaHash = null,
|
|
125
|
+
rootType = null,
|
|
126
|
+
} = {}) {
|
|
127
|
+
if (!recipientPublicKey) {
|
|
128
|
+
throw new Error("encryptBytesForRecipient requires recipientPublicKey.");
|
|
129
|
+
}
|
|
130
|
+
const sender = senderKeyPair ?? (await generateX25519Keypair());
|
|
131
|
+
const nonceStart = await randomBytes(12);
|
|
132
|
+
const sharedSecret = await deriveSharedSecret(
|
|
133
|
+
sender.privateKey,
|
|
134
|
+
recipientPublicKey,
|
|
135
|
+
);
|
|
136
|
+
const aesKey = await deriveAesKey(sharedSecret, new Uint8Array(0), context);
|
|
137
|
+
const ciphertext = await aesCtrEncrypt(aesKey, toUint8Array(plaintext), nonceStart);
|
|
138
|
+
const enc = {
|
|
139
|
+
version: 1,
|
|
140
|
+
keyExchange: "X25519",
|
|
141
|
+
symmetric: "AES_256_CTR",
|
|
142
|
+
keyDerivation: "HKDF_SHA256",
|
|
143
|
+
ephemeralPublicKey: sender.publicKey,
|
|
144
|
+
nonceStart,
|
|
145
|
+
recipientKeyId,
|
|
146
|
+
context,
|
|
147
|
+
schemaHash,
|
|
148
|
+
rootType,
|
|
149
|
+
timestamp: Date.now(),
|
|
150
|
+
};
|
|
151
|
+
const recordCollectionBytes = encodePublicationRecordCollection({ enc });
|
|
152
|
+
const protectedBlobBytes = appendPublicationRecordCollection(
|
|
153
|
+
ciphertext,
|
|
154
|
+
recordCollectionBytes,
|
|
155
|
+
);
|
|
156
|
+
return createEncryptedEnvelopePayload({
|
|
157
|
+
protectedBlobBytes,
|
|
158
|
+
parsedProtectedBlob: {
|
|
159
|
+
payloadBytes: ciphertext,
|
|
160
|
+
recordCollectionBytes,
|
|
161
|
+
enc,
|
|
162
|
+
pnm: null,
|
|
163
|
+
},
|
|
164
|
+
enc,
|
|
165
|
+
context,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
92
169
|
export async function decryptBytesFromEnvelope({
|
|
93
170
|
envelope,
|
|
94
171
|
recipientPrivateKey,
|
|
@@ -98,6 +175,29 @@ export async function decryptBytesFromEnvelope({
|
|
|
98
175
|
"decryptBytesFromEnvelope requires envelope and recipientPrivateKey.",
|
|
99
176
|
);
|
|
100
177
|
}
|
|
178
|
+
if (envelope.protectedBlobBase64) {
|
|
179
|
+
return decryptProtectedBytes({
|
|
180
|
+
protectedBytes: base64ToBytes(envelope.protectedBlobBase64),
|
|
181
|
+
recipientPrivateKey,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
if (envelope.ciphertextBase64 && envelope.encRecordBase64) {
|
|
185
|
+
const enc = decodeEncRecord(base64ToBytes(envelope.encRecordBase64));
|
|
186
|
+
const sharedSecret = await deriveSharedSecret(
|
|
187
|
+
recipientPrivateKey,
|
|
188
|
+
enc.ephemeralPublicKey,
|
|
189
|
+
);
|
|
190
|
+
const aesKey = await deriveAesKey(
|
|
191
|
+
sharedSecret,
|
|
192
|
+
new Uint8Array(0),
|
|
193
|
+
enc.context ?? envelope.context ?? "",
|
|
194
|
+
);
|
|
195
|
+
return aesCtrDecrypt(
|
|
196
|
+
aesKey,
|
|
197
|
+
base64ToBytes(envelope.ciphertextBase64),
|
|
198
|
+
enc.nonceStart,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
101
201
|
const sharedSecret = await deriveSharedSecret(
|
|
102
202
|
recipientPrivateKey,
|
|
103
203
|
base64ToBytes(envelope.senderPublicKeyBase64),
|
|
@@ -133,3 +233,24 @@ export async function decryptJsonFromEnvelope(options = {}) {
|
|
|
133
233
|
return JSON.parse(new TextDecoder().decode(bytes));
|
|
134
234
|
}
|
|
135
235
|
|
|
236
|
+
export async function decryptPublicationRecordCollection({
|
|
237
|
+
protectedBytes,
|
|
238
|
+
recipientPrivateKey,
|
|
239
|
+
} = {}) {
|
|
240
|
+
const parsed = extractPublicationRecordCollection(protectedBytes);
|
|
241
|
+
if (!parsed) {
|
|
242
|
+
return {
|
|
243
|
+
payloadBytes: toUint8Array(protectedBytes),
|
|
244
|
+
decryptedBytes: toUint8Array(protectedBytes),
|
|
245
|
+
publication: null,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
const decryptedBytes = parsed.enc
|
|
249
|
+
? await decryptProtectedBytes({ protectedBytes, recipientPrivateKey })
|
|
250
|
+
: parsed.payloadBytes;
|
|
251
|
+
return {
|
|
252
|
+
payloadBytes: parsed.payloadBytes,
|
|
253
|
+
decryptedBytes,
|
|
254
|
+
publication: parsed,
|
|
255
|
+
};
|
|
256
|
+
}
|