Comparing version 0.0.1-alpha.2 to 0.0.1-alpha.3
export declare function processArgv(): Promise<void>; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -68,2 +68,3 @@ "use strict"; | ||
oidcIssuer: 'https://oauth2.sigstore.dev/auth', | ||
rekorBaseURL: index_1.sigstore.DEFAULT_REKOR_BASE_URL, | ||
}; | ||
@@ -74,3 +75,3 @@ async function sign(artifactPath) { | ||
const bundle = await index_1.sigstore.sign(buffer, signOptions); | ||
const url = `${index_1.sigstore.getRekorBaseUrl(signOptions)}/api/v1/log/entries`; | ||
const url = `${signOptions.rekorBaseURL}/api/v1/log/entries`; | ||
const logIndex = (_a = bundle.verificationData) === null || _a === void 0 ? void 0 : _a.tlogEntries[0].logIndex; | ||
@@ -93,8 +94,12 @@ console.error(`Created entry at index ${logIndex}, available at`); | ||
const bundle = JSON.parse(bundleFile.toString('utf-8')); | ||
const result = await index_1.sigstore.verify(bundle, payload); | ||
if (result) { | ||
try { | ||
await index_1.sigstore.verify(bundle, payload); | ||
console.error('Verified OK'); | ||
} | ||
else { | ||
throw 'Signature verification failed'; | ||
catch (e) { | ||
console.error('Verification failed'); | ||
if (e instanceof Error) { | ||
console.error('Error: ' + e.message); | ||
} | ||
process.exit(1); | ||
} | ||
@@ -101,0 +106,0 @@ } |
@@ -9,2 +9,1 @@ import fetch from 'make-fetch-happen'; | ||
export {}; | ||
//# sourceMappingURL=error.d.ts.map |
@@ -14,2 +14,1 @@ import { CertificateRequest } from '../types/fulcio'; | ||
} | ||
//# sourceMappingURL=fulcio.d.ts.map |
export { Fulcio } from './fulcio'; | ||
export { Rekor } from './rekor'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,4 +0,4 @@ | ||
import { Entry, EntryKind } from '../types/rekor'; | ||
import { Entry, EntryKind } from '../tlog'; | ||
export interface RekorOptions { | ||
baseURL?: string; | ||
baseURL: string; | ||
} | ||
@@ -21,3 +21,2 @@ export interface SearchIndex { | ||
constructor(options: RekorOptions); | ||
static getBaseUrl(baseURL?: string): string; | ||
/** | ||
@@ -48,2 +47,1 @@ * Create a new entry in the Rekor log. | ||
} | ||
//# sourceMappingURL=rekor.d.ts.map |
@@ -25,3 +25,2 @@ "use strict"; | ||
const error_1 = require("./error"); | ||
const DEFAULT_BASE_URL = 'https://rekor.sigstore.dev'; | ||
/** | ||
@@ -40,7 +39,4 @@ * Rekor API client. | ||
}); | ||
this.baseUrl = Rekor.getBaseUrl(options.baseURL); | ||
this.baseUrl = options.baseURL; | ||
} | ||
static getBaseUrl(baseURL) { | ||
return baseURL !== null && baseURL !== void 0 ? baseURL : DEFAULT_BASE_URL; | ||
} | ||
/** | ||
@@ -47,0 +43,0 @@ * Create a new entry in the Rekor log. |
@@ -12,2 +12,1 @@ import { Provider } from './provider'; | ||
} | ||
//# sourceMappingURL=ci.d.ts.map |
@@ -26,2 +26,1 @@ import { Provider } from './provider'; | ||
export { Provider } from './provider'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -16,2 +16,1 @@ /** | ||
} | ||
//# sourceMappingURL=issuer.d.ts.map |
@@ -20,2 +20,1 @@ import { Issuer } from './issuer'; | ||
} | ||
//# sourceMappingURL=oauth.d.ts.map |
export interface Provider { | ||
getToken: () => Promise<string>; | ||
} | ||
//# sourceMappingURL=provider.d.ts.map |
export * as sigstore from './sigstore'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -9,2 +9,1 @@ /// <reference types="node" /> | ||
} | ||
//# sourceMappingURL=digest.d.ts.map |
export { Hasher } from './digest'; | ||
export { verifyInclusion } from './verify'; | ||
//# sourceMappingURL=index.d.ts.map |
/// <reference types="node" /> | ||
import { Hasher } from './digest'; | ||
export declare function verifyInclusion(hasher: Hasher, index: bigint, size: bigint, leafHash: Buffer, proof: Buffer[], root: Buffer): boolean; | ||
//# sourceMappingURL=verify.d.ts.map |
/// <reference types="node" /> | ||
import { Fulcio, Rekor } from './client'; | ||
import { Fulcio } from './client'; | ||
import { Provider } from './identity'; | ||
import { TLog } from './tlog'; | ||
import { Bundle } from './types/bundle'; | ||
import { SignerFunc } from './types/signature'; | ||
export interface SignOptions { | ||
fulcio: Fulcio; | ||
rekor: Rekor; | ||
tlog: TLog; | ||
identityProviders: Provider[]; | ||
signer?: SignerFunc; | ||
} | ||
export declare class Signer { | ||
private fulcio; | ||
private rekor; | ||
private tlog; | ||
private signer; | ||
private identityProviders; | ||
@@ -17,5 +21,4 @@ constructor(options: SignOptions); | ||
signAttestation(payload: Buffer, payloadType: string): Promise<Bundle>; | ||
private sign; | ||
private signWithEphemeralKey; | ||
private getIdentityToken; | ||
} | ||
//# sourceMappingURL=sign.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Signer = void 0; | ||
const bundle_1 = require("./types/bundle"); | ||
const fulcio_1 = require("./types/fulcio"); | ||
const rekor_1 = require("./types/rekor"); | ||
const util_1 = require("./util"); | ||
@@ -12,21 +10,20 @@ class Signer { | ||
this.fulcio = options.fulcio; | ||
this.rekor = options.rekor; | ||
this.tlog = options.tlog; | ||
this.identityProviders = options.identityProviders; | ||
this.signer = options.signer || this.signWithEphemeralKey.bind(this); | ||
} | ||
async signBlob(payload) { | ||
// Get signature and signing certificate for payload | ||
const { signature, certificates } = await this.sign(payload); | ||
// Get signature and verification material for payload | ||
const sigMaterial = await this.signer(payload); | ||
// Calculate artifact digest | ||
const digest = util_1.crypto.hash(payload); | ||
const leafCertificate = certificates[0]; | ||
// Create Rekor entry | ||
const proposedEntry = rekor_1.rekor.toProposedHashedRekordEntry(digest, signature, leafCertificate); | ||
const entry = await this.rekor.createEntry(proposedEntry); | ||
return bundle_1.bundle.toMessageSignatureBundle(digest, signature, certificates, entry); | ||
return this.tlog.createMessageSignatureEntry(digest, sigMaterial); | ||
} | ||
async signAttestation(payload, payloadType) { | ||
var _a; | ||
// Pre-authentication encoding to be signed | ||
const paeBuffer = util_1.dsse.preAuthEncoding(payloadType, payload); | ||
// Get signature and signing certificate for pae | ||
const { signature, certificates } = await this.sign(paeBuffer); | ||
// Get signature and verification material for pae | ||
const sigMaterial = await this.signer(paeBuffer); | ||
const envelope = { | ||
@@ -37,13 +34,10 @@ payloadType, | ||
{ | ||
keyid: '', | ||
sig: signature, | ||
keyid: ((_a = sigMaterial.key) === null || _a === void 0 ? void 0 : _a.id) || '', | ||
sig: sigMaterial.signature, | ||
}, | ||
], | ||
}; | ||
const signingCertificate = certificates[0]; | ||
const proposedEntry = rekor_1.rekor.toProposedIntotoEntry(envelope, signingCertificate); | ||
const entry = await this.rekor.createEntry(proposedEntry); | ||
return bundle_1.bundle.toDSSEBundle(envelope, certificates, entry); | ||
return this.tlog.createDSSEEntry(envelope, sigMaterial); | ||
} | ||
async sign(payload) { | ||
async signWithEphemeralKey(payload) { | ||
// Create emphemeral key pair | ||
@@ -64,2 +58,3 @@ const keypair = util_1.crypto.generateKeyPair(); | ||
certificates: util_1.pem.split(certificate), | ||
key: undefined, | ||
}; | ||
@@ -66,0 +61,0 @@ } |
/// <reference types="node" /> | ||
import { SerializedBundle } from './types/bundle'; | ||
export interface SignOptions { | ||
import { SerializedEnvelope, SerializedBundle } from './types/bundle'; | ||
export * as utils from './sigstore-utils'; | ||
export declare const DEFAULT_REKOR_BASE_URL = "https://rekor.sigstore.dev"; | ||
interface TLogOptions { | ||
rekorBaseURL?: string; | ||
} | ||
export declare type SignOptions = { | ||
fulcioBaseURL?: string; | ||
@@ -10,11 +15,8 @@ rekorBaseURL?: string; | ||
oidcClientSecret?: string; | ||
} | ||
export interface VerifierOptions { | ||
rekorBaseURL?: string; | ||
} | ||
export declare function getRekorBaseUrl(options?: SignOptions): string; | ||
} & TLogOptions; | ||
export declare type VerifierOptions = TLogOptions; | ||
export declare type Bundle = SerializedBundle; | ||
export declare type Envelope = SerializedEnvelope; | ||
export declare function sign(payload: Buffer, options?: SignOptions): Promise<Bundle>; | ||
export declare function signAttestation(payload: Buffer, payloadType: string, options?: SignOptions): Promise<Bundle>; | ||
export declare function verify(bundle: Bundle, data?: Buffer, options?: VerifierOptions): Promise<boolean>; | ||
//# sourceMappingURL=sigstore.d.ts.map | ||
export declare function verify(bundle: Bundle, data?: Buffer, options?: VerifierOptions): Promise<void>; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -6,3 +29,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.verify = exports.signAttestation = exports.sign = exports.getRekorBaseUrl = void 0; | ||
exports.verify = exports.signAttestation = exports.sign = exports.DEFAULT_REKOR_BASE_URL = exports.utils = void 0; | ||
/* | ||
@@ -26,19 +49,24 @@ Copyright 2022 The Sigstore Authors. | ||
const sign_1 = require("./sign"); | ||
const tlog_1 = require("./tlog"); | ||
const keys_1 = require("./tlog/keys"); | ||
const bundle_1 = require("./types/bundle"); | ||
const verify_1 = require("./verify"); | ||
function getRekorBaseUrl(options) { | ||
return client_1.Rekor.getBaseUrl(options === null || options === void 0 ? void 0 : options.rekorBaseURL); | ||
exports.utils = __importStar(require("./sigstore-utils")); | ||
exports.DEFAULT_REKOR_BASE_URL = 'https://rekor.sigstore.dev'; | ||
function createTLogClient(options) { | ||
return new tlog_1.TLogClient({ | ||
rekorBaseURL: options.rekorBaseURL || exports.DEFAULT_REKOR_BASE_URL, | ||
}); | ||
} | ||
exports.getRekorBaseUrl = getRekorBaseUrl; | ||
async function sign(payload, options = {}) { | ||
const fulcio = new client_1.Fulcio({ baseURL: options.fulcioBaseURL }); | ||
const rekor = new client_1.Rekor({ baseURL: options.rekorBaseURL }); | ||
const tlog = createTLogClient(options); | ||
const idps = configureIdentityProviders(options); | ||
const signer = new sign_1.Signer({ | ||
fulcio, | ||
rekor, | ||
tlog, | ||
identityProviders: idps, | ||
}); | ||
const bundle = await signer.signBlob(payload); | ||
return bundle_1.Bundle.toJSON(bundle); | ||
return (0, bundle_1.bundleToJSON)(bundle); | ||
} | ||
@@ -48,18 +76,19 @@ exports.sign = sign; | ||
const fulcio = new client_1.Fulcio({ baseURL: options.fulcioBaseURL }); | ||
const rekor = new client_1.Rekor({ baseURL: options.rekorBaseURL }); | ||
const tlog = createTLogClient(options); | ||
const idps = configureIdentityProviders(options); | ||
const signer = new sign_1.Signer({ | ||
fulcio, | ||
rekor, | ||
tlog, | ||
identityProviders: idps, | ||
}); | ||
const bundle = await signer.signAttestation(payload, payloadType); | ||
return bundle_1.Bundle.toJSON(bundle); | ||
return (0, bundle_1.bundleToJSON)(bundle); | ||
} | ||
exports.signAttestation = signAttestation; | ||
async function verify(bundle, data, options = {}) { | ||
const rekor = new client_1.Rekor({ baseURL: options.rekorBaseURL }); | ||
const verifier = new verify_1.Verifier({ rekor }); | ||
const b = bundle_1.Bundle.fromJSON(bundle); | ||
return verifier.verify(b, data); | ||
const tlog = createTLogClient(options); | ||
const tlogKeys = (0, keys_1.getKeys)(); | ||
const verifier = new verify_1.Verifier({ tlog, tlogKeys }); | ||
const b = (0, bundle_1.bundleFromJSON)(bundle); | ||
return verifier.verifyOffline(b, data); | ||
} | ||
@@ -66,0 +95,0 @@ exports.verify = verify; |
/// <reference types="node" /> | ||
/** https://raw.githubusercontent.com/secure-systems-lab/dsse/9c813476bd36de70a5738c72e784f123ecea16af/envelope.proto */ | ||
/** An authenticated message of arbitrary type. */ | ||
@@ -48,2 +47,1 @@ export interface Envelope { | ||
}; | ||
//# sourceMappingURL=envelope.d.ts.map |
@@ -22,3 +22,3 @@ import { Envelope } from "./envelope"; | ||
* such as transparency and timestamp of the signature creation. | ||
* As this message can be either empty (no timestamps), or a combination of | ||
* As this message can be either empty (no inclusion proof or timestamps), or a combination of | ||
* an arbitrarily number of transparency log entries and signed timestamps, | ||
@@ -30,7 +30,7 @@ * it is the client's responsibility to implement any required verification | ||
/** | ||
* This is the regular inclusion promise and proof, where | ||
* This is the inclusion promise and/or proof, where | ||
* the timestamp is coming from the transparency log. | ||
*/ | ||
tlogEntries: TransparencyLogEntry[]; | ||
/** Timestamp verirication data, over the artifact's signature. */ | ||
/** Timestamp verification data, over the artifact's signature. */ | ||
timestampVerificationData: TimestampVerificationData | undefined; | ||
@@ -66,2 +66,1 @@ } | ||
}; | ||
//# sourceMappingURL=sigstore_bundle.d.ts.map |
@@ -12,3 +12,3 @@ /// <reference types="node" /> | ||
export declare enum HashAlgorithm { | ||
UNSPECIFIED = 0, | ||
HASH_ALGORITHM_UNSPECIFIED = 0, | ||
SHA2_256 = 1, | ||
@@ -50,6 +50,4 @@ SHA2_512 = 2 | ||
/** | ||
* Signed timestamp is the DER encoded TimeStampToken | ||
* Signed timestamp is the DER encoded TimeStampResponse. | ||
* See https://www.rfc-editor.org/rfc/rfc3161.html#section-2.4.2 | ||
* For verification, the TimeStampToken MUST contain TSA's | ||
* certificate chain. | ||
*/ | ||
@@ -68,2 +66,6 @@ signedTimestamp: Buffer; | ||
* specification. | ||
* Example use-case is to specify the public key to use, from a | ||
* trusted key-ring. | ||
* Implementors are RECOMMENDED derive the value from the public | ||
* key as described in https://www.rfc-editor.org/rfc/rfc3280#section-4.2.1.1 | ||
*/ | ||
@@ -73,10 +75,10 @@ hint: string; | ||
export interface X509Certificate { | ||
/** DER encoded X509 certificate. */ | ||
derBytes: Buffer; | ||
/** DER-encoded X.509 certificate. */ | ||
rawBytes: Buffer; | ||
} | ||
/** A chain of X509 certificates. */ | ||
/** A chain of X.509 certificates. */ | ||
export interface X509CertificateChain { | ||
/** | ||
* The chain of certificates, with indices 0 to n. | ||
* The first certificate in the array must be the leaf | ||
* The first certificate in the array must be the leaf | ||
* certificate used for signing. Any intermediate certificates | ||
@@ -129,2 +131,1 @@ * must be stored as offset 1 to n-1, and the root certificate at | ||
}; | ||
//# sourceMappingURL=sigstore_common.d.ts.map |
@@ -16,3 +16,3 @@ "use strict"; | ||
(function (HashAlgorithm) { | ||
HashAlgorithm[HashAlgorithm["UNSPECIFIED"] = 0] = "UNSPECIFIED"; | ||
HashAlgorithm[HashAlgorithm["HASH_ALGORITHM_UNSPECIFIED"] = 0] = "HASH_ALGORITHM_UNSPECIFIED"; | ||
HashAlgorithm[HashAlgorithm["SHA2_256"] = 1] = "SHA2_256"; | ||
@@ -24,4 +24,4 @@ HashAlgorithm[HashAlgorithm["SHA2_512"] = 2] = "SHA2_512"; | ||
case 0: | ||
case "UNSPECIFIED": | ||
return HashAlgorithm.UNSPECIFIED; | ||
case "HASH_ALGORITHM_UNSPECIFIED": | ||
return HashAlgorithm.HASH_ALGORITHM_UNSPECIFIED; | ||
case 1: | ||
@@ -40,4 +40,4 @@ case "SHA2_256": | ||
switch (object) { | ||
case HashAlgorithm.UNSPECIFIED: | ||
return "UNSPECIFIED"; | ||
case HashAlgorithm.HASH_ALGORITHM_UNSPECIFIED: | ||
return "HASH_ALGORITHM_UNSPECIFIED"; | ||
case HashAlgorithm.SHA2_256: | ||
@@ -121,12 +121,12 @@ return "SHA2_256"; | ||
function createBaseX509Certificate() { | ||
return { derBytes: Buffer.alloc(0) }; | ||
return { rawBytes: Buffer.alloc(0) }; | ||
} | ||
exports.X509Certificate = { | ||
fromJSON(object) { | ||
return { derBytes: isSet(object.derBytes) ? Buffer.from(bytesFromBase64(object.derBytes)) : Buffer.alloc(0) }; | ||
return { rawBytes: isSet(object.rawBytes) ? Buffer.from(bytesFromBase64(object.rawBytes)) : Buffer.alloc(0) }; | ||
}, | ||
toJSON(message) { | ||
const obj = {}; | ||
message.derBytes !== undefined && | ||
(obj.derBytes = base64FromBytes(message.derBytes !== undefined ? message.derBytes : Buffer.alloc(0))); | ||
message.rawBytes !== undefined && | ||
(obj.rawBytes = base64FromBytes(message.rawBytes !== undefined ? message.rawBytes : Buffer.alloc(0))); | ||
return obj; | ||
@@ -133,0 +133,0 @@ }, |
@@ -18,5 +18,5 @@ /// <reference types="node" /> | ||
* https://github.com/transparency-dev/formats/blob/main/log/README.md | ||
* The details are here https://github.com/sigstore/rekor/blob/main/pkg/util/signed_note.go#L114. | ||
* The details are here https://github.com/sigstore/rekor/blob/a6e58f72b6b18cc06cefe61808efd562b9726330/pkg/util/signed_note.go#L114 | ||
* The signature has the same format as | ||
* TransparencyLogEntry.inclusion_proof. See below for more details. | ||
* InclusionPromise.signed_entry_timestamp. See below for more details. | ||
*/ | ||
@@ -43,5 +43,11 @@ export interface Checkpoint { | ||
* in order from leaf to root. | ||
* Not that leaf and root hashes are not included. | ||
* The root has is available separately in this message, and the | ||
* leaf hash should be calculated by the client. | ||
*/ | ||
hashes: Buffer[]; | ||
/** Signature of the current tree head. See above for more details. */ | ||
/** | ||
* Signature of the tree head, as of the time of this proof was | ||
* generated. See above info on 'Checkpoint' for more details. | ||
*/ | ||
checkpoint: Checkpoint | undefined; | ||
@@ -53,3 +59,3 @@ } | ||
* log ID, log index and the integration timestamp. | ||
* See https://github.com/sigstore/rekor/blob/main/pkg/api/entries.go#L54 | ||
* See https://github.com/sigstore/rekor/blob/a6e58f72b6b18cc06cefe61808efd562b9726330/pkg/api/entries.go#L54 | ||
* The format of the signature depends on the transparency log's public key. | ||
@@ -59,3 +65,4 @@ * If the signature algorithm requires a hash function and/or a signature | ||
* operators, together with the public key. | ||
* This is primarily used to verify the integration timestamp's value. | ||
* This is used to verify the integration timestamp's value and that the log | ||
* has promised to include the entry. | ||
*/ | ||
@@ -65,3 +72,3 @@ export interface InclusionPromise { | ||
} | ||
/** LogId captures the identity of a transparceny log. */ | ||
/** LogId captures the identity of a transparency log. */ | ||
export interface LogId { | ||
@@ -106,3 +113,3 @@ /** | ||
*/ | ||
inclusionProof?: InclusionProof | undefined; | ||
inclusionProof: InclusionProof | undefined; | ||
} | ||
@@ -133,2 +140,1 @@ export declare const KindVersion: { | ||
}; | ||
//# sourceMappingURL=sigstore_rekor.d.ts.map |
/// <reference types="node" /> | ||
import { Entry } from '../rekor'; | ||
import { Entry } from '../../tlog'; | ||
import { SignatureMaterial } from '../signature'; | ||
import { Envelope } from './__generated__/envelope'; | ||
@@ -9,6 +10,9 @@ import { Bundle } from './__generated__/sigstore_bundle'; | ||
export * from './__generated__/sigstore_common'; | ||
export declare const bundleToJSON: (message: Bundle) => unknown; | ||
export declare const bundleFromJSON: (object: any) => Bundle; | ||
export declare const envelopeToJSON: (message: Envelope) => unknown; | ||
export declare const envelopeFromJSON: (object: any) => Envelope; | ||
export declare const bundle: { | ||
toDSSEBundle: (envelope: Envelope, certificate: string[], rekorEntry: Entry) => Bundle; | ||
toMessageSignatureBundle: (digest: Buffer, signature: Buffer, certificate: string[], rekorEntry: Entry) => Bundle; | ||
toDSSEBundle: (envelope: Envelope, signature: SignatureMaterial, rekorEntry: Entry) => Bundle; | ||
toMessageSignatureBundle: (digest: Buffer, signature: SignatureMaterial, rekorEntry: Entry) => Bundle; | ||
}; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -17,19 +17,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.bundle = void 0; | ||
/* | ||
Copyright 2022 The Sigstore Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
exports.bundle = exports.envelopeFromJSON = exports.envelopeToJSON = exports.bundleFromJSON = exports.bundleToJSON = void 0; | ||
const util_1 = require("../../util"); | ||
const envelope_1 = require("./__generated__/envelope"); | ||
const sigstore_bundle_1 = require("./__generated__/sigstore_bundle"); | ||
const sigstore_common_1 = require("./__generated__/sigstore_common"); | ||
@@ -40,5 +27,9 @@ __exportStar(require("./serialized"), exports); | ||
__exportStar(require("./__generated__/sigstore_common"), exports); | ||
exports.bundleToJSON = sigstore_bundle_1.Bundle.toJSON; | ||
exports.bundleFromJSON = sigstore_bundle_1.Bundle.fromJSON; | ||
exports.envelopeToJSON = envelope_1.Envelope.toJSON; | ||
exports.envelopeFromJSON = envelope_1.Envelope.fromJSON; | ||
const BUNDLE_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.1'; | ||
exports.bundle = { | ||
toDSSEBundle: (envelope, certificate, rekorEntry) => ({ | ||
toDSSEBundle: (envelope, signature, rekorEntry) => ({ | ||
mediaType: BUNDLE_MEDIA_TYPE, | ||
@@ -55,5 +46,5 @@ content: { | ||
}, | ||
verificationMaterial: toVerificationMaterial(certificate), | ||
verificationMaterial: toVerificationMaterial(signature), | ||
}), | ||
toMessageSignatureBundle: (digest, signature, certificate, rekorEntry) => ({ | ||
toMessageSignatureBundle: (digest, signature, rekorEntry) => ({ | ||
mediaType: BUNDLE_MEDIA_TYPE, | ||
@@ -67,3 +58,3 @@ content: { | ||
}, | ||
signature: signature, | ||
signature: signature.signature, | ||
}, | ||
@@ -77,3 +68,3 @@ }, | ||
}, | ||
verificationMaterial: toVerificationMaterial(certificate), | ||
verificationMaterial: toVerificationMaterial(signature), | ||
}), | ||
@@ -103,3 +94,8 @@ }; | ||
} | ||
function toVerificationMaterial(certificates) { | ||
function toVerificationMaterial(signature) { | ||
return signature.certificates | ||
? toVerificationMaterialx509CertificateChain(signature.certificates) | ||
: toVerificationMaterialPublicKey(signature.key.id || ''); | ||
} | ||
function toVerificationMaterialx509CertificateChain(certificates) { | ||
return { | ||
@@ -110,3 +106,3 @@ content: { | ||
certificates: certificates.map((c) => ({ | ||
derBytes: util_1.pem.toDER(c), | ||
rawBytes: util_1.pem.toDER(c), | ||
})), | ||
@@ -117,1 +113,9 @@ }, | ||
} | ||
function toVerificationMaterialPublicKey(hint) { | ||
return { | ||
content: { | ||
$case: 'publicKey', | ||
publicKey: { hint }, | ||
}, | ||
}; | ||
} |
@@ -53,3 +53,3 @@ import { OneOf } from '../utility'; | ||
certificates: { | ||
derBytes: string; | ||
rawBytes: string; | ||
}[]; | ||
@@ -65,3 +65,11 @@ }; | ||
}>; | ||
interface SerializedSignature { | ||
sig: string; | ||
keyid: string; | ||
} | ||
export declare type SerializedEnvelope = { | ||
payload: string; | ||
payloadType: string; | ||
signatures: SerializedSignature[]; | ||
}; | ||
export {}; | ||
//# sourceMappingURL=serialized.d.ts.map |
@@ -12,2 +12,1 @@ /// <reference types="node" /> | ||
}; | ||
//# sourceMappingURL=fulcio.d.ts.map |
@@ -12,2 +12,1 @@ declare type ValueOf<Obj> = Obj[keyof Obj]; | ||
export {}; | ||
//# sourceMappingURL=utility.d.ts.map |
@@ -10,2 +10,1 @@ /// <reference types="node" /> | ||
export declare function randomBytes(count: number): Buffer; | ||
//# sourceMappingURL=crypto.d.ts.map |
@@ -37,3 +37,10 @@ "use strict"; | ||
function verifyBlob(data, key, signature) { | ||
return crypto_1.default.verify(null, data, key, signature); | ||
// The try/catch is to work around an issue in Node 14.x where verify throws | ||
// an error in some scenarios if the signature is invalid. | ||
try { | ||
return crypto_1.default.verify(null, data, key, signature); | ||
} | ||
catch (e) { | ||
return false; | ||
} | ||
} | ||
@@ -40,0 +47,0 @@ exports.verifyBlob = verifyBlob; |
/// <reference types="node" /> | ||
export declare function preAuthEncoding(payloadType: string, payload: Buffer): Buffer; | ||
//# sourceMappingURL=dsse.d.ts.map |
@@ -7,2 +7,1 @@ export declare function base64Encode(str: string): string; | ||
export declare function base64URLUnescape(str: string): string; | ||
//# sourceMappingURL=encoding.d.ts.map |
@@ -9,2 +9,1 @@ export * as crypto from './crypto'; | ||
export * as json from './json'; | ||
//# sourceMappingURL=index.d.ts.map |
export declare function canonicalize(object: any): string; | ||
//# sourceMappingURL=json.d.ts.map |
export declare function extractJWTSubject(jwt: string): string; | ||
//# sourceMappingURL=oidc.d.ts.map |
@@ -5,2 +5,1 @@ /// <reference types="node" /> | ||
export declare function fromDER(certificate: Buffer): string; | ||
//# sourceMappingURL=pem.d.ts.map |
@@ -22,3 +22,4 @@ "use strict"; | ||
// Given a set of PEM-encoded certificates bundled in a single string, returns | ||
// an array of certificates. | ||
// an array of certificates. Standard PEM encoding dictates that each certificate | ||
// should have a trailing newline after the footer. | ||
function split(certificate) { | ||
@@ -36,3 +37,3 @@ const certs = []; | ||
if (line === PEM_FOOTER) { | ||
certs.push(cert.join('\n')); | ||
certs.push(cert.join('\n').concat('\n')); | ||
} | ||
@@ -54,2 +55,5 @@ }); | ||
exports.toDER = toDER; | ||
// Translates a DER-encoded buffer into a PEM-encoded string. Standard PEM | ||
// encoding dictates that each certificate should have a trailing newline after | ||
// the footer. | ||
function fromDER(certificate) { | ||
@@ -60,4 +64,4 @@ // Base64-encode the certificate. | ||
const lines = der.match(/.{1,64}/g) || ''; | ||
return [PEM_HEADER, ...lines, PEM_FOOTER].join('\n') + '\n'; | ||
return [PEM_HEADER, ...lines, PEM_FOOTER].join('\n').concat('\n'); | ||
} | ||
exports.fromDER = fromDER; |
export declare const promiseAny: <T>(values: Iterable<PromiseLike<T>>) => Promise<T>; | ||
//# sourceMappingURL=promise.d.ts.map |
export declare const getUserAgent: () => string; | ||
//# sourceMappingURL=ua.d.ts.map |
/// <reference types="node" /> | ||
import { Rekor } from './client'; | ||
/// <reference types="node" /> | ||
import { KeyObject } from 'crypto'; | ||
import { TLog } from './tlog'; | ||
import { Bundle } from './types/bundle'; | ||
export interface VerifyOptions { | ||
rekor: Rekor; | ||
tlog: TLog; | ||
tlogKeys: Record<string, KeyObject>; | ||
} | ||
export declare class Verifier { | ||
private rekor; | ||
private tlog; | ||
private tlogKeys; | ||
constructor(options: VerifyOptions); | ||
verify(bundle: Bundle, data?: Buffer): Promise<boolean>; | ||
verifyOffline(bundle: Bundle, data?: Buffer): void; | ||
} | ||
//# sourceMappingURL=verify.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Verifier = void 0; | ||
const error_1 = require("./error"); | ||
const verify_1 = require("./tlog/verify"); | ||
const util_1 = require("./util"); | ||
class Verifier { | ||
constructor(options) { | ||
this.rekor = options.rekor; | ||
this.tlog = options.tlog; | ||
this.tlogKeys = options.tlogKeys; | ||
} | ||
async verify(bundle, data) { | ||
var _a, _b, _c; | ||
let signature; | ||
switch ((_a = bundle.content) === null || _a === void 0 ? void 0 : _a.$case) { | ||
case 'dsseEnvelope': { | ||
const payloadType = bundle.content.dsseEnvelope.payloadType; | ||
const payload = bundle.content.dsseEnvelope.payload; | ||
data = util_1.dsse.preAuthEncoding(payloadType, payload); | ||
if (bundle.content.dsseEnvelope.signatures.length !== 1) { | ||
throw new Error('No signatures found in bundle'); | ||
} | ||
signature = bundle.content.dsseEnvelope.signatures[0].sig; | ||
break; | ||
verifyOffline(bundle, data) { | ||
verifyArtifactSignature(bundle, data); | ||
(0, verify_1.verifyTLogSET)(bundle, this.tlogKeys); | ||
} | ||
} | ||
exports.Verifier = Verifier; | ||
// Performs bundle signature verification. Determines the type of the bundle | ||
// content and delegates to the appropriate signature verification function. | ||
function verifyArtifactSignature(bundle, data) { | ||
var _a; | ||
switch ((_a = bundle.content) === null || _a === void 0 ? void 0 : _a.$case) { | ||
case 'messageSignature': | ||
if (!data) { | ||
throw new error_1.VerificationError('No data provided for message signature verification'); | ||
} | ||
case 'messageSignature': | ||
signature = bundle.content.messageSignature.signature; | ||
break; | ||
default: | ||
throw new Error('Bundle is invalid'); | ||
} | ||
if (((_c = (_b = bundle.verificationMaterial) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.$case) !== 'x509CertificateChain') { | ||
throw new Error('No certificate found in bundle'); | ||
} | ||
const certificate = bundle.verificationMaterial.content.x509CertificateChain.certificates[0]; | ||
const cert = util_1.pem.fromDER(certificate.derBytes); | ||
if (!data) { | ||
throw new Error('No data to verify'); | ||
} | ||
return util_1.crypto.verifyBlob(data, cert, signature); | ||
verifyMessageSignature(bundle, data); | ||
break; | ||
case 'dsseEnvelope': | ||
verifyDSSESignature(bundle); | ||
break; | ||
default: | ||
throw new error_1.VerificationError('Bundle is invalid'); | ||
} | ||
} | ||
exports.Verifier = Verifier; | ||
// Performs signature verification for bundle containing a message signature. | ||
// Verifies the signature found in the bundle against the provided data. | ||
function verifyMessageSignature(bundle, data) { | ||
var _a; | ||
if (((_a = bundle.content) === null || _a === void 0 ? void 0 : _a.$case) !== 'messageSignature') { | ||
throw new error_1.VerificationError('No message signature found in bundle'); | ||
} | ||
// Extract signature for message | ||
const signature = bundle.content.messageSignature.signature; | ||
// Get signing certificate containing public key | ||
const publicKey = getSigningCertificate(bundle); | ||
if (!util_1.crypto.verifyBlob(data, publicKey, signature)) { | ||
throw new error_1.VerificationError('Artifact signature verification failed'); | ||
} | ||
} | ||
// Performs signature verification for bundle containing a DSSE envelope. | ||
// Calculates the PAE for the DSSE envelope and verifies it against the | ||
// signature in the envelope. | ||
function verifyDSSESignature(bundle) { | ||
var _a; | ||
if (((_a = bundle.content) === null || _a === void 0 ? void 0 : _a.$case) !== 'dsseEnvelope') { | ||
throw new error_1.VerificationError('Bundle is not a DSSE envelope'); | ||
} | ||
// Construct payload over which the signature was originally created | ||
const payloadType = bundle.content.dsseEnvelope.payloadType; | ||
const payload = bundle.content.dsseEnvelope.payload; | ||
const data = util_1.dsse.preAuthEncoding(payloadType, payload); | ||
// Extract signature from DSSE envelope | ||
if (bundle.content.dsseEnvelope.signatures.length < 1) { | ||
throw new error_1.VerificationError('No signatures found in DSSE envelope'); | ||
} | ||
// TODO: Support multiple signatures | ||
const signature = bundle.content.dsseEnvelope.signatures[0].sig; | ||
// Get signing certificate containing public key | ||
const publicKey = getSigningCertificate(bundle); | ||
if (!util_1.crypto.verifyBlob(data, publicKey, signature)) { | ||
throw new error_1.VerificationError('Artifact signature verification failed'); | ||
} | ||
} | ||
// Extracts the signing certificate from the bundle and formats it as a | ||
// PEM-encoded string. | ||
function getSigningCertificate(bundle) { | ||
var _a, _b; | ||
if (((_b = (_a = bundle.verificationMaterial) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.$case) !== 'x509CertificateChain') { | ||
throw new error_1.VerificationError('No certificate found in bundle'); | ||
} | ||
const signingCert = bundle.verificationMaterial.content.x509CertificateChain.certificates[0]; | ||
if (!signingCert) { | ||
throw new error_1.VerificationError('No certificate found in bundle'); | ||
} | ||
return util_1.pem.fromDER(signingCert.rawBytes); | ||
} |
{ | ||
"name": "sigstore", | ||
"version": "0.0.1-alpha.2", | ||
"version": "0.0.1-alpha.3", | ||
"description": "code-signing for npm packages", | ||
@@ -26,3 +26,4 @@ "main": "dist/index.js", | ||
"files": [ | ||
"dist" | ||
"dist", | ||
"store" | ||
], | ||
@@ -29,0 +30,0 @@ "author": "bdehamer@github.com", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
160763
3395
2
89
6