Comparing version 1.5.2 to 1.6.0
@@ -30,2 +30,3 @@ import { CA } from './ca'; | ||
export type SignOptions = { | ||
identityProvider?: Provider; | ||
tlogUpload?: boolean; | ||
@@ -32,0 +33,0 @@ } & CAOptions & TLogOptions & TSAOptions & FetchOptions & IdentityProviderOptions; |
@@ -1,15 +0,10 @@ | ||
import { Entry, EntryKind } from '../tlog'; | ||
import type { LogEntry, ProposedEntry, ProposedDSSEEntry, ProposedHashedRekordEntry, ProposedIntotoEntry, SearchIndex, SearchLogQuery } from '@sigstore/rekor-types'; | ||
import type { FetchOptions } from '../types/fetch'; | ||
export type { ProposedEntry, SearchIndex, SearchLogQuery, ProposedDSSEEntry, ProposedHashedRekordEntry, ProposedIntotoEntry, }; | ||
export type Entry = { | ||
uuid: string; | ||
} & LogEntry['x']; | ||
export type RekorOptions = { | ||
baseURL: string; | ||
} & FetchOptions; | ||
export interface SearchIndex { | ||
email?: string; | ||
hash?: string; | ||
} | ||
export interface SearchLogQuery { | ||
entries?: EntryKind[]; | ||
entryUUIDs?: string[]; | ||
logIndexes?: number[]; | ||
} | ||
/** | ||
@@ -24,6 +19,6 @@ * Rekor API client. | ||
* Create a new entry in the Rekor log. | ||
* @param propsedEntry {EntryKind} Data to create a new entry | ||
* @param propsedEntry {ProposedEntry} Data to create a new entry | ||
* @returns {Promise<Entry>} The created entry | ||
*/ | ||
createEntry(propsedEntry: EntryKind): Promise<Entry>; | ||
createEntry(propsedEntry: ProposedEntry): Promise<Entry>; | ||
/** | ||
@@ -30,0 +25,0 @@ * Get an entry from the Rekor log. |
@@ -42,3 +42,3 @@ "use strict"; | ||
* Create a new entry in the Rekor log. | ||
* @param propsedEntry {EntryKind} Data to create a new entry | ||
* @param propsedEntry {ProposedEntry} Data to create a new entry | ||
* @returns {Promise<Entry>} The created entry | ||
@@ -111,3 +111,3 @@ */ | ||
// Grab UUID and entry data from the response | ||
const [uuid, entry] = Object.entries(data)[0]; | ||
const [uuid, entry] = entries[0]; | ||
return { | ||
@@ -114,0 +114,0 @@ ...entry, |
@@ -0,1 +1,2 @@ | ||
export type { Provider as IdentityProvider } from './identity'; | ||
export * as sigstore from './sigstore'; |
@@ -27,17 +27,2 @@ "use strict"; | ||
exports.sigstore = 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.sigstore = __importStar(require("./sigstore")); |
/// <reference types="node" /> | ||
import * as tuf from '@sigstore/tuf'; | ||
import * as config from './config'; | ||
import * as tuf from './tuf'; | ||
import * as sigstore from './types/sigstore'; | ||
@@ -12,6 +12,6 @@ export declare function sign(payload: Buffer, options?: config.SignOptions): Promise<sigstore.SerializedBundle>; | ||
}; | ||
export type { TUF } from '@sigstore/tuf'; | ||
export type { SignOptions, VerifyOptions } from './config'; | ||
export { InternalError, PolicyError, ValidationError, VerificationError, } from './error'; | ||
export * as utils from './sigstore-utils'; | ||
export type { TUF } from './tuf'; | ||
export type { SerializedBundle as Bundle, SerializedEnvelope as Envelope, } from './types/sigstore'; | ||
@@ -18,0 +18,0 @@ export { tufUtils as tuf }; |
@@ -42,5 +42,5 @@ "use strict"; | ||
*/ | ||
const tuf = __importStar(require("@sigstore/tuf")); | ||
const config = __importStar(require("./config")); | ||
const sign_1 = require("./sign"); | ||
const tuf = __importStar(require("./tuf")); | ||
const sigstore = __importStar(require("./types/sigstore")); | ||
@@ -55,3 +55,5 @@ const verify_1 = require("./verify"); | ||
tlog, | ||
identityProviders: idps, | ||
identityProviders: options.identityProvider | ||
? [options.identityProvider] | ||
: idps, | ||
tlogUpload: options.tlogUpload, | ||
@@ -72,3 +74,5 @@ }); | ||
tsa, | ||
identityProviders: idps, | ||
identityProviders: options.identityProvider | ||
? [options.identityProvider] | ||
: idps, | ||
tlogUpload: options.tlogUpload, | ||
@@ -96,10 +100,9 @@ }); | ||
client: (options = {}) => { | ||
const t = new tuf.TUFClient({ | ||
return tuf.initTUF({ | ||
mirrorURL: options.tufMirrorURL, | ||
rootPath: options.tufRootPath, | ||
cachePath: options.tufCachePath, | ||
retry: options.retry ?? config.DEFAULT_RETRY, | ||
timeout: options.timeout ?? config.DEFAULT_TIMEOUT, | ||
retry: options.retry, | ||
timeout: options.timeout, | ||
}); | ||
return t.refresh().then(() => t); | ||
}, | ||
@@ -110,3 +113,11 @@ /* | ||
getTarget: (path, options = {}) => { | ||
return tufUtils.client(options).then((t) => t.getTarget(path)); | ||
return tuf | ||
.initTUF({ | ||
mirrorURL: options.tufMirrorURL, | ||
rootPath: options.tufRootPath, | ||
cachePath: options.tufCachePath, | ||
retry: options.retry, | ||
timeout: options.timeout, | ||
}) | ||
.then((t) => t.getTarget(path)); | ||
}, | ||
@@ -113,0 +124,0 @@ }; |
/// <reference types="node" /> | ||
import { SignatureMaterial } from '../types/signature'; | ||
import { Envelope } from '../types/sigstore'; | ||
import { HashedRekordKind, IntotoKind } from './types'; | ||
export declare function toProposedHashedRekordEntry(digest: Buffer, signature: SignatureMaterial): HashedRekordKind; | ||
export declare function toProposedIntotoEntry(envelope: Envelope, signature: SignatureMaterial, apiVersion?: string): IntotoKind; | ||
import type { ProposedDSSEEntry, ProposedHashedRekordEntry, ProposedIntotoEntry } from '../external/rekor'; | ||
export declare function toProposedDSSEEntry(envelope: Envelope, signature: SignatureMaterial, apiVersion?: string): ProposedDSSEEntry; | ||
export declare function toProposedHashedRekordEntry(digest: Buffer, signature: SignatureMaterial): ProposedHashedRekordEntry; | ||
export declare function toProposedIntotoEntry(envelope: Envelope, signature: SignatureMaterial, apiVersion?: string): ProposedIntotoEntry; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.toProposedIntotoEntry = exports.toProposedHashedRekordEntry = void 0; | ||
exports.toProposedIntotoEntry = exports.toProposedHashedRekordEntry = exports.toProposedDSSEEntry = void 0; | ||
const sigstore_1 = require("../types/sigstore"); | ||
const util_1 = require("../util"); | ||
const types_1 = require("./types"); | ||
const DEFAULT_DSSE_API_VERSION = '0.0.1'; | ||
const DEFAULT_HASHEDREKORD_API_VERSION = '0.0.1'; | ||
const DEFAULT_INTOTO_API_VERSION = '0.0.2'; | ||
// Returns a properly formatted Rekor "dsse" entry for the given DSSE | ||
// envelope and signature | ||
function toProposedDSSEEntry(envelope, signature, apiVersion = DEFAULT_DSSE_API_VERSION) { | ||
switch (apiVersion) { | ||
case '0.0.1': | ||
return toProposedDSSEV001Entry(envelope, signature); | ||
default: | ||
throw new Error(`Unsupported dsse kind API version: ${apiVersion}`); | ||
} | ||
} | ||
exports.toProposedDSSEEntry = toProposedDSSEEntry; | ||
// Returns a properly formatted Rekor "hashedrekord" entry for the given digest | ||
@@ -16,3 +28,3 @@ // and signature | ||
apiVersion: DEFAULT_HASHEDREKORD_API_VERSION, | ||
kind: types_1.HASHEDREKORD_KIND, | ||
kind: 'hashedrekord', | ||
spec: { | ||
@@ -46,2 +58,14 @@ data: { | ||
exports.toProposedIntotoEntry = toProposedIntotoEntry; | ||
function toProposedDSSEV001Entry(envelope, signature) { | ||
return { | ||
apiVersion: '0.0.1', | ||
kind: 'dsse', | ||
spec: { | ||
proposedContent: { | ||
envelope: JSON.stringify(sigstore_1.Envelope.toJSON(envelope)), | ||
verifiers: [util_1.encoding.base64Encode(toPublicKey(signature))], | ||
}, | ||
}, | ||
}; | ||
} | ||
function toProposedIntotoV002Entry(envelope, signature) { | ||
@@ -51,3 +75,3 @@ // Calculate the value for the payloadHash field in the Rekor entry | ||
// Calculate the value for the hash field in the Rekor entry | ||
const envelopeHash = calculateDSSEHash(envelope); | ||
const envelopeHash = calculateDSSEHash(envelope, signature); | ||
// Collect values for re-creating the DSSE envelope. | ||
@@ -62,3 +86,3 @@ // Double-encode payload and signature cause that's what Rekor expects | ||
// envelope, but is required by Rekor. | ||
const dsse = { | ||
const dsseEnv = { | ||
payloadType: envelope.payloadType, | ||
@@ -72,10 +96,10 @@ payload: payload, | ||
if (keyid.length > 0) { | ||
dsse.signatures[0].keyid = keyid; | ||
dsseEnv.signatures[0].keyid = keyid; | ||
} | ||
return { | ||
apiVersion: '0.0.2', | ||
kind: types_1.INTOTO_KIND, | ||
kind: 'intoto', | ||
spec: { | ||
content: { | ||
envelope: dsse, | ||
envelope: dsseEnv, | ||
hash: { algorithm: 'sha256', value: envelopeHash }, | ||
@@ -94,13 +118,18 @@ payloadHash: { algorithm: 'sha256', value: payloadHash }, | ||
// * The resulting JSON is canonicalized and hashed to a hex string | ||
function calculateDSSEHash(envelope) { | ||
const dsse = { | ||
function calculateDSSEHash(envelope, signature) { | ||
const dsseEnv = { | ||
payloadType: envelope.payloadType, | ||
payload: envelope.payload.toString('base64'), | ||
signatures: [{ sig: envelope.signatures[0].sig.toString('base64') }], | ||
signatures: [ | ||
{ | ||
sig: envelope.signatures[0].sig.toString('base64'), | ||
publicKey: toPublicKey(signature), | ||
}, | ||
], | ||
}; | ||
// If the keyid is an empty string, Rekor seems to remove it altogether. | ||
if (envelope.signatures[0].keyid.length > 0) { | ||
dsse.signatures[0].keyid = envelope.signatures[0].keyid; | ||
dsseEnv.signatures[0].keyid = envelope.signatures[0].keyid; | ||
} | ||
return util_1.crypto.hash(util_1.json.canonicalize(dsse)).toString('hex'); | ||
return util_1.crypto.hash(util_1.json.canonicalize(dsseEnv)).toString('hex'); | ||
} | ||
@@ -107,0 +136,0 @@ function toPublicKey(signature) { |
/// <reference types="node" /> | ||
import { SignatureMaterial } from '../types/signature'; | ||
import * as sigstore from '../types/sigstore'; | ||
import { Entry } from './types'; | ||
import type { Entry } from '../external/rekor'; | ||
import type { FetchOptions } from '../types/fetch'; | ||
@@ -9,3 +9,2 @@ interface CreateEntryOptions { | ||
} | ||
export { Entry, EntryKind, HashedRekordKind } from './types'; | ||
export interface TLog { | ||
@@ -25,1 +24,2 @@ createMessageSignatureEntry: (digest: Buffer, sigMaterial: SignatureMaterial) => Promise<Entry>; | ||
} | ||
export {}; |
@@ -31,2 +31,5 @@ "use strict"; | ||
switch (body.kind) { | ||
case 'dsse': | ||
verifyDSSETLogBody(body, bundleContent); | ||
break; | ||
case 'intoto': | ||
@@ -49,2 +52,16 @@ verifyIntotoTLogBody(body, bundleContent); | ||
// Compare the given intoto tlog entry to the given bundle | ||
function verifyDSSETLogBody(tlogEntry, content) { | ||
if (content?.$case !== 'dsseEnvelope') { | ||
throw new error_1.VerificationError(`unsupported bundle content: ${content?.$case || 'unknown'}`); | ||
} | ||
const dsse = content.dsseEnvelope; | ||
switch (tlogEntry.apiVersion) { | ||
case '0.0.1': | ||
verifyDSSE001TLogBody(tlogEntry, dsse); | ||
break; | ||
default: | ||
throw new error_1.VerificationError(`unsupported dsse version: ${tlogEntry.apiVersion}`); | ||
} | ||
} | ||
// Compare the given intoto tlog entry to the given bundle | ||
function verifyIntotoTLogBody(tlogEntry, content) { | ||
@@ -77,2 +94,24 @@ if (content?.$case !== 'dsseEnvelope') { | ||
} | ||
// Compare the given dsse v0.0.1 tlog entry to the given DSSE envelope. | ||
function verifyDSSE001TLogBody(tlogEntry, dsse) { | ||
// Collect all of the signatures from the DSSE envelope | ||
// Turns them into base64-encoded strings for comparison | ||
const dsseSigs = dsse.signatures.map((signature) => signature.sig.toString('base64')); | ||
// Collect all of the signatures from the tlog entry | ||
const tlogSigs = tlogEntry.spec.signatures?.map((signature) => signature.signature); | ||
// Ensure the bundle's DSSE and the tlog entry contain the same number of signatures | ||
if (dsseSigs.length !== tlogSigs?.length) { | ||
throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); | ||
} | ||
// Ensure that every signature in the bundle's DSSE is present in the tlog entry | ||
if (!dsseSigs.every((dsseSig) => tlogSigs.includes(dsseSig))) { | ||
throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); | ||
} | ||
// Ensure the digest of the bundle's DSSE payload matches the digest in the | ||
// tlog entry | ||
const dssePayloadHash = util_1.crypto.hash(dsse.payload).toString('hex'); | ||
if (dssePayloadHash !== tlogEntry.spec.payloadHash?.value) { | ||
throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); | ||
} | ||
} | ||
// Compare the given intoto v0.0.2 tlog entry to the given DSSE envelope. | ||
@@ -79,0 +118,0 @@ function verifyIntoto002TLogBody(tlogEntry, dsse) { |
@@ -6,3 +6,3 @@ /// <reference types="node" /> | ||
import { ValidBundle } from './validate'; | ||
import type { Entry } from '../../tlog'; | ||
import type { Entry } from '../../external/rekor'; | ||
import type { SignatureMaterial } from '../signature'; | ||
@@ -9,0 +9,0 @@ export * from '@sigstore/protobuf-specs'; |
@@ -106,3 +106,4 @@ "use strict"; | ||
function toTransparencyLogEntry(entry) { | ||
const set = Buffer.from(entry.verification.signedEntryTimestamp, 'base64'); | ||
const b64SET = entry.verification?.signedEntryTimestamp || ''; | ||
const set = Buffer.from(b64SET, 'base64'); | ||
const logID = Buffer.from(entry.logID, 'hex'); | ||
@@ -109,0 +110,0 @@ // Parse entry body so we can extract the kind and version. |
@@ -1,2 +0,2 @@ | ||
export * as appdata from './appdata'; | ||
export * as asn1 from './asn1'; | ||
export * as crypto from './crypto'; | ||
@@ -3,0 +3,0 @@ export * as dsse from './dsse'; |
@@ -26,3 +26,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ua = exports.promise = exports.pem = exports.oidc = exports.json = exports.encoding = exports.dsse = exports.crypto = exports.appdata = void 0; | ||
exports.ua = exports.promise = exports.pem = exports.oidc = exports.json = exports.encoding = exports.dsse = exports.crypto = exports.asn1 = void 0; | ||
/* | ||
@@ -43,3 +43,3 @@ Copyright 2022 The Sigstore Authors. | ||
*/ | ||
exports.appdata = __importStar(require("./appdata")); | ||
exports.asn1 = __importStar(require("./asn1")); | ||
exports.crypto = __importStar(require("./crypto")); | ||
@@ -46,0 +46,0 @@ exports.dsse = __importStar(require("./dsse")); |
@@ -115,3 +115,3 @@ "use strict"; | ||
} | ||
exports.ByteStream = ByteStream; | ||
ByteStream.BLOCK_SIZE = 1024; | ||
exports.ByteStream = ByteStream; |
/// <reference types="node" /> | ||
import * as sigstore from '../types/sigstore'; | ||
import { ASN1Obj } from './asn1/obj'; | ||
import { ASN1Obj } from '../util/asn1'; | ||
import { x509AuthorityKeyIDExtension, x509BasicConstraintsExtension, x509Extension, x509KeyUsageExtension, x509SCTExtension, x509SubjectAlternativeNameExtension, x509SubjectKeyIDExtension } from './ext'; | ||
@@ -5,0 +5,0 @@ interface SCTVerificationResult { |
@@ -5,4 +5,4 @@ "use strict"; | ||
const util_1 = require("../util"); | ||
const asn1_1 = require("../util/asn1"); | ||
const stream_1 = require("../util/stream"); | ||
const obj_1 = require("./asn1/obj"); | ||
const ext_1 = require("./ext"); | ||
@@ -37,3 +37,3 @@ const EXTENSION_OID_SUBJECT_KEY_ID = '2.5.29.14'; | ||
const der = typeof cert === 'string' ? util_1.pem.toDER(cert) : cert; | ||
const asn1 = obj_1.ASN1Obj.parseBuffer(der); | ||
const asn1 = asn1_1.ASN1Obj.parseBuffer(der); | ||
return new x509Certificate(asn1); | ||
@@ -40,0 +40,0 @@ } |
/// <reference types="node" /> | ||
import { ASN1Obj } from './asn1/obj'; | ||
import { ASN1Obj } from '../util/asn1'; | ||
import { SignedCertificateTimestamp } from './sct'; | ||
@@ -4,0 +4,0 @@ export declare class x509Extension { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.x509SCTExtension = exports.x509SubjectKeyIDExtension = exports.x509AuthorityKeyIDExtension = exports.x509SubjectAlternativeNameExtension = exports.x509KeyUsageExtension = exports.x509BasicConstraintsExtension = exports.x509Extension = void 0; | ||
/* | ||
Copyright 2023 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. | ||
*/ | ||
const stream_1 = require("../util/stream"); | ||
@@ -20,0 +5,0 @@ const sct_1 = require("./sct"); |
{ | ||
"name": "sigstore", | ||
"version": "1.5.2", | ||
"version": "1.6.0", | ||
"description": "code-signing for npm packages", | ||
@@ -8,2 +8,3 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"clean": "shx rm -rf dist *.tsbuildinfo", | ||
"build": "tsc --build", | ||
@@ -33,12 +34,16 @@ "test": "jest" | ||
"devDependencies": { | ||
"@sigstore/rekor-types": "^1.0.0", | ||
"@total-typescript/shoehorn": "^0.1.0", | ||
"@tufjs/repo-mock": "^1.1.0", | ||
"@types/make-fetch-happen": "^10.0.0", | ||
"@types/node": "^20.0.0", | ||
"@types/sigstore-jest-extended": "^0.0.0", | ||
"@types/node": "^20.2.5", | ||
"json-schema-to-typescript": "^13.0.0", | ||
"nock": "^13.2.4", | ||
"typescript": "^5.0.2" | ||
"shx": "^0.3.3", | ||
"typescript": "^5.1.3" | ||
}, | ||
"dependencies": { | ||
"@sigstore/protobuf-specs": "^0.1.0", | ||
"@sigstore/tuf": "^1.0.0", | ||
"make-fetch-happen": "^11.0.1", | ||
@@ -45,0 +50,0 @@ "tuf-js": "^1.1.3" |
@@ -45,3 +45,4 @@ # sigstore · [![npm version](https://img.shields.io/npm/v/sigstore.svg?style=flat)](https://www.npmjs.com/package/sigstore) [![CI Status](https://github.com/sigstore/sigstore-js/workflows/CI/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/ci.yml) [![Smoke Test Status](https://github.com/sigstore/sigstore-js/workflows/smoke-test/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/smoke-test.yml) | ||
* `tlogUpload` `<boolean>`: Flag indicating whether or not the signature should be recorded on the Rekor transparency log. Defaults to `true`. | ||
* `identityToken` `<string>`: The OIDC token identifying the signer. If no explicit token is supplied, an attempt will be made to retrieve one from the environment. | ||
* `identityToken` `<string>`: The OIDC token identifying the signer. If no explicit token is supplied, an attempt will be made to retrieve one from the environment. This config cannot be used with `identityProvider`. | ||
* `identityProvider` `<IdentityProvider>`: Object which implements `getToken: () => Promise<string>`. The supplied provider will be used to retrieve an OIDC token. If no provider is supplied, an attempt will be made to retrieve an OIDC token from the environment. This config cannot be used with `identityToken`. | ||
@@ -61,3 +62,4 @@ ### attest(payload, payloadType[, options]) | ||
* `tlogUpload` `<boolean>`: Flag indicating whether or not the signed statement should be recorded on the Rekor transparency log. Defaults to `true`. | ||
* `identityToken` `<string>`: The OIDC token identifying the signer. If no explicit token is supplied, an attempt will be made to retrieve one from the environment. | ||
* `identityToken` `<string>`: The OIDC token identifying the signer. If no explicit token is supplied, an attempt will be made to retrieve one from the environment. This config cannot be used with `identityProvider`. | ||
* `identityProvider` `<IdentityProvider>`: Object which implements `getToken: () => Promise<string>`. The supplied provider will be used to retrieve an OIDC token. If no provider is supplied, an attempt will be made to retrieve an OIDC token from the environment. This config cannot be used with `identityToken`. | ||
@@ -64,0 +66,0 @@ |
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
166
8
238904
4
10
125
5256
+ Added@sigstore/tuf@^1.0.0
+ Added@sigstore/protobuf-specs@0.2.1(transitive)
+ Added@sigstore/tuf@1.0.3(transitive)