Skip to content

Commit fbfb315

Browse files
authoredJun 28, 2023
export new createVerifier function (#559)
* export new initBasicVerifier function Signed-off-by: Brian DeHamer <bdehamer@github.com> * basicVerifier → createVerifier Signed-off-by: Brian DeHamer <bdehamer@github.com> --------- Signed-off-by: Brian DeHamer <bdehamer@github.com>
1 parent 3a902bc commit fbfb315

File tree

5 files changed

+97
-5
lines changed

5 files changed

+97
-5
lines changed
 

‎.changeset/silly-turtles-pull.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'sigstore': minor
3+
---
4+
5+
Exports new `createVerifier` function

‎packages/client/src/__tests__/index.test.ts

+5
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,17 @@ describe('sigstore', () => {
2222
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2323
const identityProvider: IdentityProvider = {} as any;
2424
expect(identityProvider).toBeDefined();
25+
26+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
27+
const bundleVerifier: sigstore.BundleVerifier = {} as any;
28+
expect(bundleVerifier).toBeDefined();
2529
});
2630

2731
it('exports sigstore core functions', async () => {
2832
expect(sigstore.attest).toBeInstanceOf(Function);
2933
expect(sigstore.sign).toBeInstanceOf(Function);
3034
expect(sigstore.verify).toBeInstanceOf(Function);
35+
expect(sigstore.createVerifier).toBeInstanceOf(Function);
3136
});
3237

3338
it('exports sigstore utils', () => {

‎packages/client/src/__tests__/sigstore.test.ts

+58-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
1617
import {
1718
Bundle,
1819
HashAlgorithm,
@@ -22,14 +23,16 @@ import {
2223
X509CertificateChain,
2324
} from '@sigstore/protobuf-specs';
2425
import { TUFError } from '@sigstore/tuf';
26+
import { fromPartial } from '@total-typescript/shoehorn';
2527
import mocktuf, { Target } from '@tufjs/repo-mock';
2628
import { PolicyError, VerificationError } from '../error';
2729
import { Signer } from '../sign';
28-
import { attest, sign, tuf, verify } from '../sigstore';
30+
import { attest, createVerifier, sign, tuf, verify } from '../sigstore';
31+
import { SerializedBundle } from '../types/sigstore';
2932
import bundles from './__fixtures__/bundles';
3033
import { trustedRoot } from './__fixtures__/trust';
3134

32-
import type { VerifyOptions } from '../config';
35+
import type { TUFOptions, VerifyOptions } from '../config';
3336

3437
jest.mock('../sign');
3538

@@ -317,25 +320,75 @@ describe('#verify', () => {
317320
});
318321
});
319322

320-
describe('tuf', () => {
323+
describe('#createVerifier', () => {
321324
let tufRepo: ReturnType<typeof mocktuf> | undefined;
322-
let options: VerifyOptions | undefined;
325+
let tufOptions: VerifyOptions | undefined;
326+
327+
const trustedRootJSON = JSON.stringify(TrustedRoot.toJSON(trustedRoot));
328+
const target: Target = {
329+
name: 'trusted_root.json',
330+
content: Buffer.from(trustedRootJSON),
331+
};
323332

324333
beforeEach(() => {
325334
tufRepo = mocktuf(target, { metadataPathPrefix: '' });
326-
options = {
335+
tufOptions = {
327336
tufMirrorURL: tufRepo.baseURL,
328337
tufCachePath: tufRepo.cachePath,
329338
};
330339
});
331340

332341
afterEach(() => tufRepo?.teardown());
333342

343+
it('returns a object', async () => {
344+
const verifier = await createVerifier(tufOptions!);
345+
expect(verifier).toBeInstanceOf(Object);
346+
});
347+
348+
describe('when the bundle is valid', () => {
349+
const bundle: SerializedBundle = fromPartial(
350+
bundles.dsse.valid.withSigningCert
351+
);
352+
353+
it('does not throw an error when invoked', async () => {
354+
const verifier = await createVerifier(tufOptions!);
355+
expect(verifier.verify(bundle)).toBeUndefined();
356+
});
357+
});
358+
359+
describe('when the bundle is invalid', () => {
360+
const bundle: SerializedBundle = fromPartial(
361+
bundles.dsse.invalid.badSignature
362+
);
363+
364+
it('throws an error when invoked', async () => {
365+
const verifier = await createVerifier(tufOptions!);
366+
expect(() => {
367+
verifier.verify(bundle);
368+
}).toThrowError(VerificationError);
369+
});
370+
});
371+
});
372+
373+
describe('tuf', () => {
374+
let tufRepo: ReturnType<typeof mocktuf> | undefined;
375+
let options: TUFOptions | undefined;
376+
334377
const target: Target = {
335378
name: 'foo',
336379
content: 'bar',
337380
};
338381

382+
beforeEach(() => {
383+
tufRepo = mocktuf(target, { metadataPathPrefix: '' });
384+
options = {
385+
tufMirrorURL: tufRepo.baseURL,
386+
tufCachePath: tufRepo.cachePath,
387+
};
388+
});
389+
390+
afterEach(() => tufRepo?.teardown());
391+
339392
describe('getTarget', () => {
340393
describe('when the target exists', () => {
341394
it('returns the target', async () => {

‎packages/client/src/config.ts

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ export type VerifyOptions = {
6868
} & TLogOptions &
6969
TUFOptions;
7070

71+
export type CreateVerifierOptions = {
72+
keySelector?: KeySelector;
73+
} & TUFOptions;
74+
7175
export const DEFAULT_FULCIO_URL = 'https://fulcio.sigstore.dev';
7276
export const DEFAULT_REKOR_URL = 'https://rekor.sigstore.dev';
7377

‎packages/client/src/sigstore.ts

+25
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,31 @@ export async function verify(
8181
return verifier.verify(deserializedBundle, opts, payload);
8282
}
8383

84+
export interface BundleVerifier {
85+
verify(bundle: sigstore.SerializedBundle): void;
86+
}
87+
88+
export async function createVerifier(
89+
options: config.CreateVerifierOptions
90+
): Promise<BundleVerifier> {
91+
const trustedRoot = await tuf.getTrustedRoot({
92+
mirrorURL: options.tufMirrorURL,
93+
rootPath: options.tufRootPath,
94+
cachePath: options.tufCachePath,
95+
retry: options.retry ?? config.DEFAULT_RETRY,
96+
timeout: options.timeout ?? config.DEFAULT_TIMEOUT,
97+
});
98+
const verifier = new Verifier(trustedRoot, options.keySelector);
99+
const verifyOpts = config.artifactVerificationOptions(options);
100+
101+
return {
102+
verify: (bundle: sigstore.SerializedBundle): void => {
103+
const deserializedBundle = sigstore.bundleFromJSON(bundle);
104+
return verifier.verify(deserializedBundle, verifyOpts);
105+
},
106+
};
107+
}
108+
84109
const tufUtils = {
85110
client: (options: config.TUFOptions = {}): Promise<tuf.TUF> => {
86111
return tuf.initTUF({

0 commit comments

Comments
 (0)
Please sign in to comment.