From 5dd25718af6c32ce8f9881676fed3a0c5c4e15a5 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 28 Sep 2026 00:52:03 +0200 Subject: [PATCH] Read Idunn identity envelope format --- .../cultnet-ts/src/idunn-runtime-authority.ts | 18 +++++++++++++-- .../test/idunn-runtime-authority.test.ts | 23 +++++++++++++++---- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/packages/cultnet-ts/src/idunn-runtime-authority.ts b/packages/cultnet-ts/src/idunn-runtime-authority.ts index ea07ba27..c6f82c27 100644 --- a/packages/cultnet-ts/src/idunn-runtime-authority.ts +++ b/packages/cultnet-ts/src/idunn-runtime-authority.ts @@ -543,8 +543,7 @@ function decodeRoute(value: unknown): ExpectedIncarnation["route"] { } function openProviderHealthIdentity(credentialBytes: Buffer): crypto.KeyObject { - const record = readAuthorityRecordBytes(credentialBytes, "gamecult.provider_health_identity", "gamecult.provider_health_identity.private.v1"); - const fields = decodeArray(record, 10, "provider-health identity"); + const fields = decodeArray(readProviderHealthIdentityCredential(credentialBytes), 10, "provider-health identity"); const [schema, identityId, publicKeyValue, protectedSeedValue, protectorKind, binding, version, assurance, createdAt, enrollmentNonceValue] = fields; if (schema !== "gamecult.provider_health_identity.private.v1" || version !== "v1") throw new Error("Provider-health identity schema is unsupported."); string(createdAt, "Provider-health identity creation time"); @@ -573,6 +572,21 @@ function openProviderHealthIdentity(credentialBytes: Buffer): crypto.KeyObject { return key; } +function readProviderHealthIdentityCredential(bytes: Buffer): Uint8Array { + const decoded = decode(bytes); + if (!Array.isArray(decoded) || decoded.length !== 1) { + throw new Error("Provider-health identity credential must contain exactly one envelope."); + } + const envelope = array(decoded[0], 5, "Provider-health identity envelope"); + if (envelope[0] !== "gamecult-provider-health-identity" + || envelope[1] !== "gamecult.provider_health_identity.private.v1" + || envelope[4] !== "gamecult.provider_health_identity.private.v1") { + throw new Error("Provider-health identity credential belongs to a different profile or schema."); + } + string(envelope[3], "Provider-health identity stored-at time"); + return bytesValue(envelope[2], "Provider-health identity payload"); +} + function readAuthorityRecordBytes(bytes: Buffer, type: string, schemaId: string): Uint8Array { const decoded = decode(bytes); if (!Array.isArray(decoded) || decoded[0] !== CULTCACHE_STORE_FORMAT || !Array.isArray(decoded[1]) || !Array.isArray(decoded[2])) { diff --git a/packages/cultnet-ts/test/idunn-runtime-authority.test.ts b/packages/cultnet-ts/test/idunn-runtime-authority.test.ts index a2277c92..1ffeb2ba 100644 --- a/packages/cultnet-ts/test/idunn-runtime-authority.test.ts +++ b/packages/cultnet-ts/test/idunn-runtime-authority.test.ts @@ -78,14 +78,18 @@ test("opens Idunn's machine-bound identity and signs the exact Expected incarnat Buffer.from(binding, "utf8"), ])).digest(); const protectedSeed = Buffer.from(providerSeed.map((value, index) => value ^ mask[index]!)); - const providerCredential = cultCacheStore( - "gamecult.provider_health_identity", "gamecult.provider_health_identity.private.v1", - "gamecult-provider-health-identity", Buffer.from(encode([ + const providerCredential = Buffer.from(encode([[ + "gamecult-provider-health-identity", + "gamecult.provider_health_identity.private.v1", + Buffer.from(encode([ "gamecult.provider_health_identity.private.v1", providerIdentity, providerPublic, protectedSeed, "linux_file_mode_machine_id_binding", binding, "v1", "os_installation_file_bound_cloneable_baseline", "2026-01-01T00:00:00Z", new Uint8Array(32).fill(0x2a), ])), - ); + "2026-01-01T00:00:00Z", + "gamecult.provider_health_identity.private.v1", + ]])); + let descriptorProviderCredential = providerCredential; const originalEnvironment = { ...process.env }; context.after(() => { @@ -101,7 +105,7 @@ test("opens Idunn's machine-bound identity and signs the exact Expected incarnat const realReadFileSync = fs.readFileSync.bind(fs); mock.method(fs, "readFileSync", (filePath: fs.PathOrFileDescriptor, ...args: unknown[]) => { if (filePath === 3) return activationSeed; - if (filePath === 4) return providerCredential; + if (filePath === 4) return descriptorProviderCredential; if (filePath === "/etc/machine-id") return machineId; return realReadFileSync(filePath as never, ...args as never[]); }); @@ -121,6 +125,15 @@ test("opens Idunn's machine-bound identity and signs the exact Expected incarnat const signedRecord = decode(signed.payload) as unknown[]; assert.equal(crypto.verify(null, runtimePresenceProviderSigningMessage(proof), crypto.createPublicKey(providerKey), Buffer.from(signedRecord[21] as Uint8Array)), true); assert.equal(crypto.verify(null, runtimePresenceActivationSigningMessage(proof), crypto.createPublicKey(activationKey), Buffer.from(signedRecord[23] as Uint8Array)), true); + + descriptorProviderCredential = Buffer.from(encode([ + ...(decode(providerCredential) as unknown[][]), + ...(decode(providerCredential) as unknown[][]), + ])); + assert.throws( + () => loadIdunnRuntimeAuthorityFromEnvironment(target, contract, "127.0.0.1:17871"), + /exactly one envelope/, + ); }); function cultCacheStore(type: string, schemaId: string, key: string, payload: Uint8Array): Buffer {