From c0a43d5a114bec416a27f10406c13f608b4a764f Mon Sep 17 00:00:00 2001 From: Brian DeHamer Date: Fri, 20 Oct 2023 13:54:00 -0700 Subject: [PATCH] expose rekor option to choose 'intoto' or 'dsse' (#820) Signed-off-by: Brian DeHamer --- .changeset/cyan-impalas-look.md | 5 + package-lock.json | 12 +- .../src/__tests__/witness/tlog/index.test.ts | 189 ++++++++++++------ packages/sign/src/witness/tlog/index.ts | 8 +- 4 files changed, 149 insertions(+), 65 deletions(-) create mode 100644 .changeset/cyan-impalas-look.md diff --git a/.changeset/cyan-impalas-look.md b/.changeset/cyan-impalas-look.md new file mode 100644 index 00000000..9715e7a4 --- /dev/null +++ b/.changeset/cyan-impalas-look.md @@ -0,0 +1,5 @@ +--- +'@sigstore/sign': minor +--- + +Expose `entryType` option on `RekorWitness` constructor diff --git a/package-lock.json b/package-lock.json index 8c1a82b6..5aa670a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13903,7 +13903,7 @@ }, "packages/cli": { "name": "@sigstore/cli", - "version": "0.4.0", + "version": "0.5.0", "license": "Apache-2.0", "dependencies": { "@oclif/color": "^1.0.13", @@ -13948,7 +13948,7 @@ }, "packages/conformance": { "name": "@sigstore/conformance", - "version": "0.0.2", + "version": "0.1.0", "dependencies": { "@oclif/core": "^3", "sigstore": "^2.0.0" @@ -13982,7 +13982,7 @@ }, "packages/mock": { "name": "@sigstore/mock", - "version": "0.6.0", + "version": "0.6.1", "license": "Apache-2.0", "dependencies": { "@peculiar/webcrypto": "^1.4.3", @@ -14006,11 +14006,11 @@ }, "packages/mock-server": { "name": "@sigstore/mock-server", - "version": "0.0.5", + "version": "0.1.0", "dependencies": { "@oclif/color": "^1.0.13", "@oclif/core": "^3", - "@sigstore/mock": "^0.6.0", + "@sigstore/mock": "^0.6.1", "@tufjs/repo-mock": "^2.0.0", "express": "4.18.2" }, @@ -16469,7 +16469,7 @@ "requires": { "@oclif/color": "^1.0.13", "@oclif/core": "^3", - "@sigstore/mock": "^0.6.0", + "@sigstore/mock": "^0.6.1", "@tufjs/repo-mock": "^2.0.0", "@types/express": "^4.17.20", "express": "4.18.2", diff --git a/packages/sign/src/__tests__/witness/tlog/index.test.ts b/packages/sign/src/__tests__/witness/tlog/index.test.ts index fc09675f..2e6ba2df 100644 --- a/packages/sign/src/__tests__/witness/tlog/index.test.ts +++ b/packages/sign/src/__tests__/witness/tlog/index.test.ts @@ -158,65 +158,140 @@ describe('RekorWitness', () => { }, }; - it('returns the tlog entry', async () => { - const vm = await subject.testify(sigBundle, publicKey); + describe('when the Rekor entry type is "intoto"', () => { + const subject = new RekorWitness({ + rekorBaseURL, + entryType: 'intoto', + }); - expect(vm).toBeDefined(); - assert(vm.tlogEntries); - expect(vm.tlogEntries).toHaveLength(1); + it('returns the tlog entry', async () => { + const vm = await subject.testify(sigBundle, publicKey); - const tlogEntry = vm.tlogEntries[0]; - expect(tlogEntry).toBeDefined(); - expect(tlogEntry.logIndex).toEqual( - rekorEntry[uuid].logIndex.toString() - ); - expect(tlogEntry.logId?.keyId).toEqual( - Buffer.from(rekorEntry[uuid].logID, 'hex') - ); - expect(tlogEntry.kindVersion?.kind).toEqual(proposedEntry.kind); - expect(tlogEntry.kindVersion?.version).toEqual( - proposedEntry.apiVersion - ); - expect(tlogEntry.integratedTime).toEqual( - rekorEntry[uuid].integratedTime.toString() - ); - expect(tlogEntry.inclusionPromise?.signedEntryTimestamp).toEqual( - Buffer.from( - rekorEntry[uuid].verification.signedEntryTimestamp, - 'base64' - ) - ); - expect(tlogEntry.inclusionProof?.checkpoint?.envelope).toEqual( - rekorEntry[uuid].verification.inclusionProof.checkpoint - ); - expect(tlogEntry.inclusionProof?.hashes).toHaveLength(2); - expect(tlogEntry.inclusionProof?.hashes[0]).toEqual( - Buffer.from( - rekorEntry[uuid].verification.inclusionProof.hashes[0], - 'hex' - ) - ); - expect(tlogEntry.inclusionProof?.hashes[1]).toEqual( - Buffer.from( - rekorEntry[uuid].verification.inclusionProof.hashes[1], - 'hex' - ) - ); - expect(tlogEntry.inclusionProof?.logIndex).toEqual( - rekorEntry[uuid].verification.inclusionProof.logIndex.toString() - ); - expect(tlogEntry.inclusionProof?.rootHash).toEqual( - Buffer.from( - rekorEntry[uuid].verification.inclusionProof.rootHash, - 'hex' - ) - ); - expect(tlogEntry.inclusionProof?.treeSize).toEqual( - rekorEntry[uuid].verification.inclusionProof.treeSize.toString() - ); - expect(tlogEntry.canonicalizedBody).toEqual( - Buffer.from(rekorEntry[uuid].body, 'base64') - ); + expect(vm).toBeDefined(); + assert(vm.tlogEntries); + expect(vm.tlogEntries).toHaveLength(1); + + const tlogEntry = vm.tlogEntries[0]; + expect(tlogEntry).toBeDefined(); + expect(tlogEntry.logIndex).toEqual( + rekorEntry[uuid].logIndex.toString() + ); + expect(tlogEntry.logId?.keyId).toEqual( + Buffer.from(rekorEntry[uuid].logID, 'hex') + ); + expect(tlogEntry.kindVersion?.kind).toEqual(proposedEntry.kind); + expect(tlogEntry.kindVersion?.version).toEqual( + proposedEntry.apiVersion + ); + expect(tlogEntry.integratedTime).toEqual( + rekorEntry[uuid].integratedTime.toString() + ); + expect(tlogEntry.inclusionPromise?.signedEntryTimestamp).toEqual( + Buffer.from( + rekorEntry[uuid].verification.signedEntryTimestamp, + 'base64' + ) + ); + expect(tlogEntry.inclusionProof?.checkpoint?.envelope).toEqual( + rekorEntry[uuid].verification.inclusionProof.checkpoint + ); + expect(tlogEntry.inclusionProof?.hashes).toHaveLength(2); + expect(tlogEntry.inclusionProof?.hashes[0]).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.hashes[0], + 'hex' + ) + ); + expect(tlogEntry.inclusionProof?.hashes[1]).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.hashes[1], + 'hex' + ) + ); + expect(tlogEntry.inclusionProof?.logIndex).toEqual( + rekorEntry[uuid].verification.inclusionProof.logIndex.toString() + ); + expect(tlogEntry.inclusionProof?.rootHash).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.rootHash, + 'hex' + ) + ); + expect(tlogEntry.inclusionProof?.treeSize).toEqual( + rekorEntry[uuid].verification.inclusionProof.treeSize.toString() + ); + expect(tlogEntry.canonicalizedBody).toEqual( + Buffer.from(rekorEntry[uuid].body, 'base64') + ); + }); + }); + + describe('when the Rekor entry type is "dsse"', () => { + const subject = new RekorWitness({ + rekorBaseURL, + entryType: 'dsse', + }); + + it('returns the tlog entry', async () => { + const vm = await subject.testify(sigBundle, publicKey); + + expect(vm).toBeDefined(); + assert(vm.tlogEntries); + expect(vm.tlogEntries).toHaveLength(1); + + const tlogEntry = vm.tlogEntries[0]; + expect(tlogEntry).toBeDefined(); + expect(tlogEntry.logIndex).toEqual( + rekorEntry[uuid].logIndex.toString() + ); + expect(tlogEntry.logId?.keyId).toEqual( + Buffer.from(rekorEntry[uuid].logID, 'hex') + ); + expect(tlogEntry.kindVersion?.kind).toEqual(proposedEntry.kind); + expect(tlogEntry.kindVersion?.version).toEqual( + proposedEntry.apiVersion + ); + expect(tlogEntry.integratedTime).toEqual( + rekorEntry[uuid].integratedTime.toString() + ); + expect(tlogEntry.inclusionPromise?.signedEntryTimestamp).toEqual( + Buffer.from( + rekorEntry[uuid].verification.signedEntryTimestamp, + 'base64' + ) + ); + expect(tlogEntry.inclusionProof?.checkpoint?.envelope).toEqual( + rekorEntry[uuid].verification.inclusionProof.checkpoint + ); + expect(tlogEntry.inclusionProof?.hashes).toHaveLength(2); + expect(tlogEntry.inclusionProof?.hashes[0]).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.hashes[0], + 'hex' + ) + ); + expect(tlogEntry.inclusionProof?.hashes[1]).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.hashes[1], + 'hex' + ) + ); + expect(tlogEntry.inclusionProof?.logIndex).toEqual( + rekorEntry[uuid].verification.inclusionProof.logIndex.toString() + ); + expect(tlogEntry.inclusionProof?.rootHash).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.rootHash, + 'hex' + ) + ); + expect(tlogEntry.inclusionProof?.treeSize).toEqual( + rekorEntry[uuid].verification.inclusionProof.treeSize.toString() + ); + expect(tlogEntry.canonicalizedBody).toEqual( + Buffer.from(rekorEntry[uuid].body, 'base64') + ); + }); }); }); }); diff --git a/packages/sign/src/witness/tlog/index.ts b/packages/sign/src/witness/tlog/index.ts index 730be1fb..5bf00f42 100644 --- a/packages/sign/src/witness/tlog/index.ts +++ b/packages/sign/src/witness/tlog/index.ts @@ -30,12 +30,16 @@ export const DEFAULT_REKOR_URL = 'https://rekor.sigstore.dev'; type TransparencyLogEntries = { tlogEntries: TransparencyLogEntry[] }; -export type RekorWitnessOptions = Partial; +export type RekorWitnessOptions = Partial & { + entryType?: 'dsse' | 'intoto'; +}; export class RekorWitness implements Witness { private tlog: TLog; + private entryType?: 'dsse' | 'intoto'; constructor(options: RekorWitnessOptions) { + this.entryType = options.entryType; this.tlog = new TLogClient({ ...options, rekorBaseURL: @@ -47,7 +51,7 @@ export class RekorWitness implements Witness { content: SignatureBundle, publicKey: string ): Promise { - const proposedEntry = toProposedEntry(content, publicKey); + const proposedEntry = toProposedEntry(content, publicKey, this.entryType); const entry = await this.tlog.createEntry(proposedEntry); return toTransparencyLogEntry(entry); }