@sigstore/verify
Advanced tools
+1
-0
@@ -6,1 +6,2 @@ export { toSignedEntity } from './bundle'; | ||
| export type { SignedEntity, Signer, VerificationPolicy } from './shared.types'; | ||
| export type { ObjectIdentifierValuePair } from '@sigstore/protobuf-specs'; |
@@ -59,5 +59,13 @@ "use strict"; | ||
| } | ||
| const oids = cert.extensions.map((ext) => { | ||
| const oid = ext.subs[0].toOID(); | ||
| return { | ||
| oid: { id: oid.split('.').map(Number) }, | ||
| value: ext.subs[ext.subs.length - 1].value, | ||
| }; | ||
| }); | ||
| const identity = { | ||
| extensions: { issuer }, | ||
| subjectAlternativeName: cert.subjectAltName, | ||
| oids, | ||
| }; | ||
@@ -64,0 +72,0 @@ return { |
+2
-0
| import { CertificateExtensions } from './shared.types'; | ||
| import type { ObjectIdentifierValuePair } from '@sigstore/protobuf-specs'; | ||
| export declare function verifySubjectAlternativeName(policyIdentity: string, signerIdentity: string | undefined): void; | ||
| export declare function verifyExtensions(policyExtensions: CertificateExtensions, signerExtensions?: CertificateExtensions): void; | ||
| export declare function verifyOIDs(policyOIDs: ObjectIdentifierValuePair[], signerOIDs?: ObjectIdentifierValuePair[]): void; |
+26
-0
@@ -5,3 +5,8 @@ "use strict"; | ||
| exports.verifyExtensions = verifyExtensions; | ||
| exports.verifyOIDs = verifyOIDs; | ||
| const error_1 = require("./error"); | ||
| // Verifies that the signer's SAN matches the policy identity. The | ||
| // policyIdentity is treated as a JavaScript regular expression pattern and | ||
| // tested against the full signerIdentity string. For exact matching, use | ||
| // anchored patterns (e.g. '^user@example\\.com$'). | ||
| function verifySubjectAlternativeName(policyIdentity, signerIdentity) { | ||
@@ -26,1 +31,22 @@ if (signerIdentity === undefined || !signerIdentity.match(policyIdentity)) { | ||
| } | ||
| function verifyOIDs(policyOIDs, signerOIDs = []) { | ||
| for (const policyOID of policyOIDs) { | ||
| const match = signerOIDs.find((signerOID) => oidEquals(policyOID.oid?.id, signerOID.oid?.id) && | ||
| policyOID.value.equals(signerOID.value)); | ||
| if (!match) { | ||
| /* istanbul ignore next */ | ||
| const oid = policyOID.oid?.id.join('.') ?? '<unknown>'; | ||
| throw new error_1.PolicyError({ | ||
| code: 'UNTRUSTED_SIGNER_ERROR', | ||
| message: `invalid certificate extension - missing OID ${oid}`, | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| function oidEquals(a, b) { | ||
| /* istanbul ignore if */ | ||
| if (a === undefined || b === undefined) { | ||
| return false; | ||
| } | ||
| return a.length === b.length && a.every((v, i) => v === b[i]); | ||
| } |
| import type { TransparencyLogEntry } from '@sigstore/bundle'; | ||
| import type { RFC3161Timestamp, X509Certificate, crypto } from '@sigstore/core'; | ||
| import type { ObjectIdentifierValuePair } from '@sigstore/protobuf-specs'; | ||
| export type CertificateExtensionName = 'issuer'; | ||
@@ -10,2 +11,3 @@ export type CertificateExtensions = { | ||
| extensions?: CertificateExtensions; | ||
| oids?: ObjectIdentifierValuePair[]; | ||
| }; | ||
@@ -12,0 +14,0 @@ export type VerificationPolicy = CertificateIdentity; |
@@ -11,2 +11,2 @@ import { RFC3161Timestamp } from '@sigstore/core'; | ||
| export declare function getTSATimestamp(timestamp: RFC3161Timestamp, data: Buffer, timestampAuthorities: CertAuthority[]): TimestampVerificationResult; | ||
| export declare function getTLogTimestamp(entry: TransparencyLogEntry): TimestampVerificationResult; | ||
| export declare function getTLogTimestamp(entry: TransparencyLogEntry): TimestampVerificationResult | undefined; |
@@ -15,2 +15,6 @@ "use strict"; | ||
| function getTLogTimestamp(entry) { | ||
| // Only entries with an inclusion promise provide a verifiable timestamp | ||
| if (!entry.inclusionPromise) { | ||
| return undefined; | ||
| } | ||
| return { | ||
@@ -17,0 +21,0 @@ type: 'transparency-log', |
+20
-10
@@ -49,13 +49,18 @@ "use strict"; | ||
| verifyTimestamps(entity) { | ||
| let timestampCount = 0; | ||
| const timestamps = entity.timestamps.map((timestamp) => { | ||
| const timestamps = []; | ||
| for (const timestamp of entity.timestamps) { | ||
| switch (timestamp.$case) { | ||
| case 'timestamp-authority': | ||
| timestampCount++; | ||
| return (0, timestamp_1.getTSATimestamp)(timestamp.timestamp, entity.signature.signature, this.trustMaterial.timestampAuthorities); | ||
| case 'transparency-log': | ||
| timestampCount++; | ||
| return (0, timestamp_1.getTLogTimestamp)(timestamp.tlogEntry); | ||
| timestamps.push((0, timestamp_1.getTSATimestamp)(timestamp.timestamp, entity.signature.signature, this.trustMaterial.timestampAuthorities)); | ||
| break; | ||
| case 'transparency-log': { | ||
| const result = (0, timestamp_1.getTLogTimestamp)(timestamp.tlogEntry); | ||
| /* istanbul ignore else */ | ||
| if (result) { | ||
| timestamps.push(result); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| }); | ||
| } | ||
| // Check for duplicate timestamps | ||
@@ -68,6 +73,6 @@ if (containsDupes(timestamps)) { | ||
| } | ||
| if (timestampCount < this.options.timestampThreshold) { | ||
| if (timestamps.length < this.options.timestampThreshold) { | ||
| throw new error_1.VerificationError({ | ||
| code: 'TIMESTAMP_ERROR', | ||
| message: `expected ${this.options.timestampThreshold} timestamps, got ${timestampCount}`, | ||
| message: `expected ${this.options.timestampThreshold} timestamps, got ${timestamps.length}`, | ||
| }); | ||
@@ -138,2 +143,7 @@ } | ||
| } | ||
| // Check that the OIDs of the signer match the policy | ||
| /* istanbul ignore if */ | ||
| if (policy.oids) { | ||
| (0, policy_1.verifyOIDs)(policy.oids, identity.oids); | ||
| } | ||
| } | ||
@@ -140,0 +150,0 @@ } |
+2
-2
| { | ||
| "name": "@sigstore/verify", | ||
| "version": "3.1.0", | ||
| "version": "3.1.1", | ||
| "description": "Verification of Sigstore signatures", | ||
@@ -31,3 +31,3 @@ "main": "dist/index.js", | ||
| "@sigstore/bundle": "^4.0.0", | ||
| "@sigstore/core": "^3.1.0" | ||
| "@sigstore/core": "^3.2.1" | ||
| }, | ||
@@ -34,0 +34,0 @@ "engines": { |
81339
2.83%1894
2.88%Updated