Skip to content

Commit 917f48c

Browse files
authored
Fix bug in mocked inclusion proof (#649)
Signed-off-by: Brian DeHamer <[email protected]>
1 parent b0f3da5 commit 917f48c

File tree

4 files changed

+66
-39
lines changed

4 files changed

+66
-39
lines changed

.changeset/hip-papayas-build.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sigstore/mock': patch
3+
---
4+
5+
Fix bug in inclusion proof returned with mocked transaction log enries

packages/mock/src/rekor/handler.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ describe('rekorHandler', () => {
7171
).toEqual(proposedEntry);
7272
expect(entry.integratedTime).toBeGreaterThan(0);
7373
expect(entry.logID).toBe(logID);
74-
expect(entry.logIndex).toBe(0);
74+
expect(entry.logIndex).toBeGreaterThan(0);
7575
expect(entry.verification).toBeDefined();
7676
expect(entry.verification?.signedEntryTimestamp).toBeDefined();
7777
});

packages/mock/src/rekor/tlog.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ describe('TLog', () => {
5050
);
5151
expect(entry.integratedTime).toBeGreaterThan(0);
5252
expect(entry.logID).toEqual(logID);
53-
expect(entry.logIndex).toBe(0);
53+
expect(entry.logIndex).toBeGreaterThan(0);
5454
expect(entry.verification).toBeDefined();
5555
expect(entry.verification?.signedEntryTimestamp).toBeDefined();
5656
expect(entry.verification?.inclusionProof).toBeDefined();
5757
expect(entry.verification?.inclusionProof?.logIndex).toBe(0);
5858
expect(entry.verification?.inclusionProof?.treeSize).toBe(1);
5959
expect(entry.verification?.inclusionProof?.rootHash).toBeDefined();
60-
expect(entry.verification?.inclusionProof?.hashes).toHaveLength(1);
60+
expect(entry.verification?.inclusionProof?.hashes).toHaveLength(0);
6161
expect(entry.verification?.inclusionProof?.checkpoint).toBeDefined();
6262
});
6363
});

packages/mock/src/rekor/tlog.ts

+58-36
Original file line numberDiff line numberDiff line change
@@ -53,41 +53,76 @@ class TLogImpl implements TLog {
5353
}
5454

5555
public async log(proposedEntry: object): Promise<LogEntry> {
56-
const logIndex = 0;
57-
const treeSize = 1;
58-
const treeID = crypto.randomInt(0, 2 ** 48 - 1);
59-
const uuid = crypto.randomBytes(32).toString('hex');
60-
const timestamp = Math.floor(Date.now() / 1000);
6156
const logID = crypto.createHash('sha256').update(this.publicKey).digest();
62-
const body = canonicalize(proposedEntry);
57+
const logIndex = crypto.randomInt(10_000_000);
58+
const timestamp = Math.floor(Date.now() / 1000);
59+
const body = canonicalize(proposedEntry)!;
60+
61+
const entry = { logID, logIndex, timestamp, body };
62+
const set = this.calculateSET(entry);
63+
const proof = this.calculateInclusionProof(entry);
6364

64-
// Calculate SET
65-
// https://github.com/sigstore/rekor/blob/9eb7ec628a41ffed291b605a57e716e86ef0d680/pkg/api/entries.go#L71
65+
const uuid = crypto.randomBytes(32).toString('hex');
66+
67+
return {
68+
[uuid]: {
69+
body: Buffer.from(body).toString('base64'),
70+
integratedTime: timestamp,
71+
logID: logID.toString('hex'),
72+
logIndex: logIndex,
73+
verification: {
74+
inclusionProof: proof,
75+
signedEntryTimestamp: set.toString('base64'),
76+
},
77+
},
78+
};
79+
}
80+
81+
// Compute the Signed Entry Timestamp (SET) for the given entry.
82+
// https://github.com/sigstore/rekor/blob/9eb7ec628a41ffed291b605a57e716e86ef0d680/pkg/api/entries.go#L71
83+
private calculateSET({
84+
body,
85+
timestamp,
86+
logIndex,
87+
logID,
88+
}: {
89+
body: string;
90+
timestamp: number;
91+
logIndex: number;
92+
logID: Buffer;
93+
}): Buffer {
6694
const setData = {
6795
body: body,
6896
integratedTime: timestamp,
6997
logIndex: logIndex,
7098
logID: logID.toString('hex'),
7199
};
72100
const setBuffer = Buffer.from(canonicalize(setData)!, 'utf8');
73-
const set = crypto.sign('sha256', setBuffer, this.privateKey);
101+
return crypto.sign('sha256', setBuffer, this.privateKey);
102+
}
103+
104+
// Calculate inclusion proof assuming that the entry being added is the
105+
// first and only entry in the log.
106+
// https://github.com/sigstore/rekor/blob/2bd83dacf5a302da83ab4eaf20ff7ad119cb6c11/pkg/util/signed_note.go
107+
private calculateInclusionProof({
108+
body,
109+
timestamp,
110+
logID,
111+
}: {
112+
body: string;
113+
timestamp: number;
114+
logID: Buffer;
115+
}): InclusionProof {
116+
const treeSize = 1;
117+
const treeID = crypto.randomInt(2 ** 48 - 1);
74118

75-
// Calculate inclusion proof assuming that the entry being added is the first
76-
// entry in the log.
77-
const leafHash = crypto
78-
.createHash('sha256')
79-
.update(Buffer.from([0x00]))
80-
.update(body!)
81-
.digest();
82119
const rootHash = crypto
83120
.createHash('sha256')
84-
.update(Buffer.from([0x01]))
85-
.update(leafHash)
86-
.update(leafHash)
121+
.update(Buffer.from([0x00]))
122+
.update(body)
87123
.digest();
88124

89125
// Construct checkpoint note
90-
// https://github.com/sigstore/rekor/blob/2bd83dacf5a302da83ab4eaf20ff7ad119cb6c11/pkg/util/signed_note.go
91126
const note = [
92127
`${this.host} - ${treeID}`,
93128
`${treeSize}`,
@@ -104,25 +139,12 @@ class TLogImpl implements TLog {
104139
// Assemble checkpoint from note and signature
105140
const checkpoint = [note, sigLine, ''].join('\n');
106141

107-
const proof: InclusionProof = {
108-
logIndex: logIndex,
142+
return {
143+
logIndex: 0,
109144
treeSize: treeSize,
110145
checkpoint,
111-
hashes: [leafHash.toString('hex')],
146+
hashes: [],
112147
rootHash: rootHash.toString('hex'),
113148
};
114-
115-
return {
116-
[uuid]: {
117-
body: Buffer.from(body!).toString('base64'),
118-
integratedTime: timestamp,
119-
logID: logID.toString('hex'),
120-
logIndex: logIndex,
121-
verification: {
122-
inclusionProof: proof,
123-
signedEntryTimestamp: set.toString('base64'),
124-
},
125-
},
126-
};
127149
}
128150
}

0 commit comments

Comments
 (0)