space-data-module-sdk 0.3.1 → 0.5.3
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/constants.js +5 -0
- package/src/bundle/wasm.js +21 -4
- package/src/capabilities.js +46 -0
- package/src/compiler/compileModule.js +346 -17
- package/src/compliance/index.js +4 -2
- package/src/compliance/pluginCompliance.js +4 -47
- package/src/index.d.ts +174 -6
- 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 +493 -0
- package/src/utils/wasmCrypto.js +43 -0
package/src/compliance/index.js
CHANGED
|
@@ -4,12 +4,14 @@ import {
|
|
|
4
4
|
getWasmExportNamesFromFile,
|
|
5
5
|
loadManifestFromFile,
|
|
6
6
|
loadComplianceConfig,
|
|
7
|
-
RecommendedCapabilityIds,
|
|
8
|
-
StandaloneWasiCapabilityIds,
|
|
9
7
|
resolveManifestFiles,
|
|
10
8
|
validatePluginArtifact,
|
|
11
9
|
validatePluginManifest,
|
|
12
10
|
} from "./pluginCompliance.js";
|
|
11
|
+
import {
|
|
12
|
+
RecommendedCapabilityIds,
|
|
13
|
+
StandaloneWasiCapabilityIds,
|
|
14
|
+
} from "../capabilities.js";
|
|
13
15
|
import { validateManifestAgainstStandardsCatalog } from "../standards/index.js";
|
|
14
16
|
|
|
15
17
|
function mergeReport(baseReport, issues) {
|
|
@@ -12,53 +12,10 @@ import {
|
|
|
12
12
|
ProtocolTransportKind,
|
|
13
13
|
RuntimeTarget,
|
|
14
14
|
} from "../runtime/constants.js";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"logging",
|
|
20
|
-
"timers",
|
|
21
|
-
"schedule_cron",
|
|
22
|
-
"http",
|
|
23
|
-
"tls",
|
|
24
|
-
"websocket",
|
|
25
|
-
"mqtt",
|
|
26
|
-
"tcp",
|
|
27
|
-
"udp",
|
|
28
|
-
"network",
|
|
29
|
-
"filesystem",
|
|
30
|
-
"pipe",
|
|
31
|
-
"pubsub",
|
|
32
|
-
"protocol_handle",
|
|
33
|
-
"protocol_dial",
|
|
34
|
-
"database",
|
|
35
|
-
"storage_adapter",
|
|
36
|
-
"storage_query",
|
|
37
|
-
"storage_write",
|
|
38
|
-
"context_read",
|
|
39
|
-
"context_write",
|
|
40
|
-
"process_exec",
|
|
41
|
-
"crypto_hash",
|
|
42
|
-
"crypto_sign",
|
|
43
|
-
"crypto_verify",
|
|
44
|
-
"crypto_encrypt",
|
|
45
|
-
"crypto_decrypt",
|
|
46
|
-
"crypto_key_agreement",
|
|
47
|
-
"crypto_kdf",
|
|
48
|
-
"wallet_sign",
|
|
49
|
-
"ipfs",
|
|
50
|
-
"scene_access",
|
|
51
|
-
"entity_access",
|
|
52
|
-
"render_hooks",
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
export const StandaloneWasiCapabilityIds = Object.freeze([
|
|
56
|
-
"logging",
|
|
57
|
-
"clock",
|
|
58
|
-
"random",
|
|
59
|
-
"filesystem",
|
|
60
|
-
"pipe",
|
|
61
|
-
]);
|
|
15
|
+
import {
|
|
16
|
+
RecommendedCapabilityIds,
|
|
17
|
+
StandaloneWasiCapabilityIds,
|
|
18
|
+
} from "../capabilities.js";
|
|
62
19
|
|
|
63
20
|
const RecommendedCapabilitySet = new Set(RecommendedCapabilityIds);
|
|
64
21
|
const StandaloneWasiCapabilitySet = new Set(StandaloneWasiCapabilityIds);
|
package/src/index.d.ts
CHANGED
|
@@ -380,14 +380,69 @@ export interface X25519Keypair {
|
|
|
380
380
|
privateKey: Uint8Array;
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
+
export interface EncRecord {
|
|
384
|
+
version: number;
|
|
385
|
+
keyExchange: string;
|
|
386
|
+
symmetric: string;
|
|
387
|
+
keyDerivation: string;
|
|
388
|
+
ephemeralPublicKey: Uint8Array | null;
|
|
389
|
+
nonceStart: Uint8Array | null;
|
|
390
|
+
recipientKeyId: Uint8Array | null;
|
|
391
|
+
context: string | null;
|
|
392
|
+
schemaHash: Uint8Array | null;
|
|
393
|
+
rootType: string | null;
|
|
394
|
+
timestamp: number;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export interface PublicationNotice {
|
|
398
|
+
multiformatAddress: string | null;
|
|
399
|
+
publishTimestamp: string | null;
|
|
400
|
+
cid: string | null;
|
|
401
|
+
fileName: string | null;
|
|
402
|
+
fileId: string | null;
|
|
403
|
+
signature: string | null;
|
|
404
|
+
timestampSignature: string | null;
|
|
405
|
+
signatureType: string | null;
|
|
406
|
+
timestampSignatureType: string | null;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface PublicationRecordEntry {
|
|
410
|
+
standard: string | null;
|
|
411
|
+
recordType: number;
|
|
412
|
+
value: EncRecord | PublicationNotice | unknown;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export interface PublicationRecordCollection {
|
|
416
|
+
version: string;
|
|
417
|
+
records: PublicationRecordEntry[];
|
|
418
|
+
enc: EncRecord | null;
|
|
419
|
+
pnm: PublicationNotice | null;
|
|
420
|
+
recordCollectionBytes: Uint8Array;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export interface ExtractedPublicationRecordCollection
|
|
424
|
+
extends PublicationRecordCollection {
|
|
425
|
+
payloadBytes: Uint8Array;
|
|
426
|
+
protectedBytes: Uint8Array;
|
|
427
|
+
footerBytes: Uint8Array;
|
|
428
|
+
footerMagic: string;
|
|
429
|
+
recordCollectionLength: number;
|
|
430
|
+
}
|
|
431
|
+
|
|
383
432
|
export interface EncryptedEnvelope {
|
|
384
433
|
version: number;
|
|
385
434
|
scheme: string;
|
|
386
435
|
context: string;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
436
|
+
protectedBlobBase64?: string | null;
|
|
437
|
+
recordCollectionBase64?: string | null;
|
|
438
|
+
ciphertextBase64?: string | null;
|
|
439
|
+
senderPublicKeyBase64?: string | null;
|
|
440
|
+
nonceStartBase64?: string | null;
|
|
441
|
+
recipientKeyIdBase64?: string | null;
|
|
442
|
+
encRecordBase64?: string | null;
|
|
443
|
+
pnmRecordBase64?: string | null;
|
|
444
|
+
saltBase64?: string | null;
|
|
445
|
+
ivBase64?: string | null;
|
|
391
446
|
}
|
|
392
447
|
|
|
393
448
|
export function generateX25519Keypair(): Promise<X25519Keypair>;
|
|
@@ -397,8 +452,16 @@ export function encryptBytesForRecipient(options: {
|
|
|
397
452
|
recipientPublicKey: Uint8Array | string;
|
|
398
453
|
context?: string;
|
|
399
454
|
senderKeyPair?: X25519Keypair;
|
|
455
|
+
recipientKeyId?: Uint8Array | ArrayBuffer | string | null;
|
|
456
|
+
schemaHash?: Uint8Array | ArrayBuffer | string | null;
|
|
457
|
+
rootType?: string | null;
|
|
400
458
|
}): Promise<EncryptedEnvelope>;
|
|
401
459
|
|
|
460
|
+
export function decryptProtectedBytes(options: {
|
|
461
|
+
protectedBytes: Uint8Array | ArrayBuffer;
|
|
462
|
+
recipientPrivateKey: Uint8Array | string;
|
|
463
|
+
}): Promise<Uint8Array>;
|
|
464
|
+
|
|
402
465
|
export function decryptBytesFromEnvelope(options: {
|
|
403
466
|
envelope: EncryptedEnvelope;
|
|
404
467
|
recipientPrivateKey: Uint8Array | string;
|
|
@@ -416,6 +479,78 @@ export function decryptJsonFromEnvelope(options: {
|
|
|
416
479
|
recipientPrivateKey: Uint8Array | string;
|
|
417
480
|
}): Promise<unknown>;
|
|
418
481
|
|
|
482
|
+
export function decryptPublicationRecordCollection(options: {
|
|
483
|
+
protectedBytes: Uint8Array | ArrayBuffer;
|
|
484
|
+
recipientPrivateKey: Uint8Array | string;
|
|
485
|
+
}): Promise<{
|
|
486
|
+
payloadBytes: Uint8Array;
|
|
487
|
+
decryptedBytes: Uint8Array;
|
|
488
|
+
publication: ExtractedPublicationRecordCollection | null;
|
|
489
|
+
}>;
|
|
490
|
+
|
|
491
|
+
export const TRAILER_MAGIC_TEXT: string;
|
|
492
|
+
export const TRAILER_FOOTER_LENGTH: number;
|
|
493
|
+
|
|
494
|
+
export function createCidV1Raw(
|
|
495
|
+
payloadBytes: Uint8Array | ArrayBuffer,
|
|
496
|
+
): Promise<string>;
|
|
497
|
+
|
|
498
|
+
export function encodeEncRecord(record?: Partial<EncRecord>): Uint8Array;
|
|
499
|
+
export function decodeEncRecord(
|
|
500
|
+
bytes: Uint8Array | ArrayBuffer | ArrayBufferView,
|
|
501
|
+
): EncRecord;
|
|
502
|
+
export function encodePnmRecord(
|
|
503
|
+
record?: Partial<PublicationNotice>,
|
|
504
|
+
): Uint8Array;
|
|
505
|
+
export function decodePnmRecord(
|
|
506
|
+
bytes: Uint8Array | ArrayBuffer | ArrayBufferView,
|
|
507
|
+
): PublicationNotice;
|
|
508
|
+
export function encodePublicationRecordCollection(options: {
|
|
509
|
+
version?: string;
|
|
510
|
+
enc?: Partial<EncRecord> | null;
|
|
511
|
+
pnm?: Partial<PublicationNotice> | null;
|
|
512
|
+
}): Uint8Array;
|
|
513
|
+
export function decodePublicationRecordCollection(
|
|
514
|
+
bytes: Uint8Array | ArrayBuffer | ArrayBufferView,
|
|
515
|
+
): PublicationRecordCollection;
|
|
516
|
+
export function appendPublicationRecordCollection(
|
|
517
|
+
payloadBytes: Uint8Array | ArrayBuffer,
|
|
518
|
+
recordCollectionBytes: Uint8Array | ArrayBuffer,
|
|
519
|
+
): Uint8Array;
|
|
520
|
+
export function extractPublicationRecordCollection(
|
|
521
|
+
bytes: Uint8Array | ArrayBuffer | ArrayBufferView,
|
|
522
|
+
): ExtractedPublicationRecordCollection | null;
|
|
523
|
+
export function stripPublicationRecordCollection(
|
|
524
|
+
bytes: Uint8Array | ArrayBuffer | ArrayBufferView,
|
|
525
|
+
): Uint8Array;
|
|
526
|
+
export function createPublicationNotice(options: {
|
|
527
|
+
payloadBytes: Uint8Array | ArrayBuffer;
|
|
528
|
+
cid?: string | null;
|
|
529
|
+
publishTimestamp?: string | null;
|
|
530
|
+
publishTimestampMs?: number;
|
|
531
|
+
fileName?: string | null;
|
|
532
|
+
fileId?: string | null;
|
|
533
|
+
artifactId?: string | null;
|
|
534
|
+
programId?: string | null;
|
|
535
|
+
multiformatAddress?: string | null;
|
|
536
|
+
signature?: string | null;
|
|
537
|
+
timestampSignature?: string | null;
|
|
538
|
+
signatureType?: string | null;
|
|
539
|
+
timestampSignatureType?: string | null;
|
|
540
|
+
signer?: Signer | null;
|
|
541
|
+
}): Promise<PublicationNotice>;
|
|
542
|
+
export function createEncryptedEnvelopePayload(options: {
|
|
543
|
+
protectedBlobBytes: Uint8Array | ArrayBuffer;
|
|
544
|
+
parsedProtectedBlob?: ExtractedPublicationRecordCollection | null;
|
|
545
|
+
enc?: EncRecord | null;
|
|
546
|
+
context?: string | null;
|
|
547
|
+
scheme?: string | null;
|
|
548
|
+
version?: number;
|
|
549
|
+
}): EncryptedEnvelope;
|
|
550
|
+
export function decodeProtectedBlobBase64(
|
|
551
|
+
base64: string,
|
|
552
|
+
): ExtractedPublicationRecordCollection | null;
|
|
553
|
+
|
|
419
554
|
// --- Compiler ---
|
|
420
555
|
|
|
421
556
|
export interface CompilationResult {
|
|
@@ -424,10 +559,19 @@ export interface CompilationResult {
|
|
|
424
559
|
outputPath: string | null;
|
|
425
560
|
tempDir: string | null;
|
|
426
561
|
wasmBytes: Uint8Array;
|
|
562
|
+
guestLink: GuestLinkArtifact | null;
|
|
427
563
|
manifestWarnings: string[];
|
|
428
564
|
report: ComplianceReport;
|
|
429
565
|
}
|
|
430
566
|
|
|
567
|
+
export interface GuestLinkArtifact {
|
|
568
|
+
format: "wasm-object";
|
|
569
|
+
language: string;
|
|
570
|
+
symbolPrefix: string;
|
|
571
|
+
methodSymbols: Record<string, string>;
|
|
572
|
+
objectBytes: Uint8Array;
|
|
573
|
+
}
|
|
574
|
+
|
|
431
575
|
export interface ProtectedArtifact {
|
|
432
576
|
mnemonic: string;
|
|
433
577
|
signingPublicKeyHex: string;
|
|
@@ -444,6 +588,10 @@ export interface ProtectedArtifact {
|
|
|
444
588
|
manifestHashHex: string;
|
|
445
589
|
authorization: SignedEnvelope;
|
|
446
590
|
};
|
|
591
|
+
publicationNotice: PublicationNotice | null;
|
|
592
|
+
publicationRecordsBytes: Uint8Array | null;
|
|
593
|
+
protectedArtifactBytes: Uint8Array;
|
|
594
|
+
protectedArtifactBase64: string;
|
|
447
595
|
encrypted: boolean;
|
|
448
596
|
encryptedEnvelope: EncryptedEnvelope | null;
|
|
449
597
|
singleFileBundle: { wasmBytes: Uint8Array } | null;
|
|
@@ -473,7 +621,8 @@ export function protectModuleArtifact(options: {
|
|
|
473
621
|
targetUrl?: string;
|
|
474
622
|
capabilities?: string[];
|
|
475
623
|
singleFileBundle?: boolean;
|
|
476
|
-
bundleEntries?: Record<string, unknown
|
|
624
|
+
bundleEntries?: Array<Record<string, unknown>>;
|
|
625
|
+
guestLink?: GuestLinkArtifact | null;
|
|
477
626
|
}): Promise<ProtectedArtifact>;
|
|
478
627
|
|
|
479
628
|
export function createRecipientKeypairHex(): Promise<{
|
|
@@ -567,6 +716,10 @@ export function validateManifestAgainstStandardsCatalog(
|
|
|
567
716
|
|
|
568
717
|
export const SDS_BUNDLE_SECTION_NAME: string;
|
|
569
718
|
export const DEFAULT_HASH_ALGORITHM: string;
|
|
719
|
+
export const SDS_GUEST_LINK_OBJECT_ENTRY_ID: string;
|
|
720
|
+
export const SDS_GUEST_LINK_METADATA_ENTRY_ID: string;
|
|
721
|
+
export const SDS_GUEST_LINK_SECTION_NAME: string;
|
|
722
|
+
export const SDS_GUEST_LINK_MEDIA_TYPE: string;
|
|
570
723
|
|
|
571
724
|
export function createSingleFileBundle(options: {
|
|
572
725
|
wasmBytes: Uint8Array;
|
|
@@ -577,9 +730,24 @@ export function createSingleFileBundle(options: {
|
|
|
577
730
|
entries?: Array<Record<string, unknown>>;
|
|
578
731
|
}): Promise<{ wasmBytes: Uint8Array }>;
|
|
579
732
|
|
|
733
|
+
export interface ParsedSingleFileBundle {
|
|
734
|
+
wasmBytes: Uint8Array;
|
|
735
|
+
protectedArtifactBytes: Uint8Array | null;
|
|
736
|
+
publicationRecords: ExtractedPublicationRecordCollection | null;
|
|
737
|
+
bundleBytes: Uint8Array;
|
|
738
|
+
bundle: unknown;
|
|
739
|
+
entries: Array<Record<string, unknown>>;
|
|
740
|
+
manifest: PluginManifest | null;
|
|
741
|
+
deploymentPlan: ModuleDeploymentPlan | null;
|
|
742
|
+
customSections: Array<Record<string, unknown>>;
|
|
743
|
+
canonicalWasmBytes: Uint8Array;
|
|
744
|
+
canonicalModuleHash: Uint8Array;
|
|
745
|
+
canonicalModuleHashHex: string;
|
|
746
|
+
}
|
|
747
|
+
|
|
580
748
|
export function parseSingleFileBundle(
|
|
581
749
|
wasmBytes: Uint8Array,
|
|
582
|
-
):
|
|
750
|
+
): Promise<ParsedSingleFileBundle>;
|
|
583
751
|
|
|
584
752
|
export function parseWasmModuleSections(
|
|
585
753
|
bytes: Uint8Array,
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./auth/index.js";
|
|
|
4
4
|
export * from "./transport/index.js";
|
|
5
5
|
export * from "./compiler/index.js";
|
|
6
6
|
export * from "./bundle/index.js";
|
|
7
|
+
export * from "./capabilities.js";
|
|
7
8
|
export * from "./standards/index.js";
|
|
8
9
|
export * from "./host/index.js";
|
|
9
10
|
export * from "./invoke/index.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "../generated/orbpro/manifest.js";
|
|
2
|
+
export { PayloadWireFormat } from "../generated/orbpro/stream/payload-wire-format.js";
|
|
3
|
+
export {
|
|
4
|
+
FlatBufferTypeRefT,
|
|
5
|
+
FlatBufferTypeRefT as PayloadTypeRef,
|
|
6
|
+
} from "../generated/orbpro/stream/flat-buffer-type-ref.js";
|
|
7
|
+
export { decodePluginManifest, encodePluginManifest } from "./codec.js";
|
|
8
|
+
export { toEmbeddedPluginManifest } from "./normalize.js";
|
|
9
|
+
export {
|
|
10
|
+
clonePayloadTypeRef,
|
|
11
|
+
getPayloadTypeWireFormat,
|
|
12
|
+
normalizePayloadWireFormatName,
|
|
13
|
+
payloadTypeRefsMatch,
|
|
14
|
+
selectPreferredPayloadTypeRef,
|
|
15
|
+
} from "./typeRefs.js";
|
package/src/transport/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export {
|
|
2
|
+
decryptProtectedBytes,
|
|
3
|
+
decryptPublicationRecordCollection,
|
|
2
4
|
decryptBytesFromEnvelope,
|
|
3
5
|
decryptJsonFromEnvelope,
|
|
4
6
|
encryptBytesForRecipient,
|
|
@@ -6,3 +8,20 @@ export {
|
|
|
6
8
|
generateX25519Keypair,
|
|
7
9
|
} from "./pki.js";
|
|
8
10
|
|
|
11
|
+
export {
|
|
12
|
+
appendPublicationRecordCollection,
|
|
13
|
+
createCidV1Raw,
|
|
14
|
+
createEncryptedEnvelopePayload,
|
|
15
|
+
createPublicationNotice,
|
|
16
|
+
decodeEncRecord,
|
|
17
|
+
decodePnmRecord,
|
|
18
|
+
decodeProtectedBlobBase64,
|
|
19
|
+
decodePublicationRecordCollection,
|
|
20
|
+
encodeEncRecord,
|
|
21
|
+
encodePnmRecord,
|
|
22
|
+
encodePublicationRecordCollection,
|
|
23
|
+
extractPublicationRecordCollection,
|
|
24
|
+
stripPublicationRecordCollection,
|
|
25
|
+
TRAILER_FOOTER_LENGTH,
|
|
26
|
+
TRAILER_MAGIC_TEXT,
|
|
27
|
+
} from "./records.js";
|
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
|
+
}
|