This commit is contained in:
2025-08-18 23:06:34 +08:00
parent 0bc04fb659
commit ed18af0cad
1926 changed files with 275098 additions and 0 deletions

21
package/node_modules/@tufjs/models/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 GitHub and the TUF Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

83
package/node_modules/@tufjs/models/dist/base.js generated vendored Normal file
View File

@@ -0,0 +1,83 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Signed = exports.isMetadataKind = exports.MetadataKind = void 0;
const util_1 = __importDefault(require("util"));
const error_1 = require("./error");
const utils_1 = require("./utils");
const SPECIFICATION_VERSION = ['1', '0', '31'];
var MetadataKind;
(function (MetadataKind) {
MetadataKind["Root"] = "root";
MetadataKind["Timestamp"] = "timestamp";
MetadataKind["Snapshot"] = "snapshot";
MetadataKind["Targets"] = "targets";
})(MetadataKind || (exports.MetadataKind = MetadataKind = {}));
function isMetadataKind(value) {
return (typeof value === 'string' &&
Object.values(MetadataKind).includes(value));
}
exports.isMetadataKind = isMetadataKind;
/***
* A base class for the signed part of TUF metadata.
*
* Objects with base class Signed are usually included in a ``Metadata`` object
* on the signed attribute. This class provides attributes and methods that
* are common for all TUF metadata types (roles).
*/
class Signed {
constructor(options) {
this.specVersion = options.specVersion || SPECIFICATION_VERSION.join('.');
const specList = this.specVersion.split('.');
if (!(specList.length === 2 || specList.length === 3) ||
!specList.every((item) => isNumeric(item))) {
throw new error_1.ValueError('Failed to parse specVersion');
}
// major version must match
if (specList[0] != SPECIFICATION_VERSION[0]) {
throw new error_1.ValueError('Unsupported specVersion');
}
this.expires = options.expires || new Date().toISOString();
this.version = options.version || 1;
this.unrecognizedFields = options.unrecognizedFields || {};
}
equals(other) {
if (!(other instanceof Signed)) {
return false;
}
return (this.specVersion === other.specVersion &&
this.expires === other.expires &&
this.version === other.version &&
util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields));
}
isExpired(referenceTime) {
if (!referenceTime) {
referenceTime = new Date();
}
return referenceTime >= new Date(this.expires);
}
static commonFieldsFromJSON(data) {
const { spec_version, expires, version, ...rest } = data;
if (utils_1.guard.isDefined(spec_version) && !(typeof spec_version === 'string')) {
throw new TypeError('spec_version must be a string');
}
if (utils_1.guard.isDefined(expires) && !(typeof expires === 'string')) {
throw new TypeError('expires must be a string');
}
if (utils_1.guard.isDefined(version) && !(typeof version === 'number')) {
throw new TypeError('version must be a number');
}
return {
specVersion: spec_version,
expires,
version,
unrecognizedFields: rest,
};
}
}
exports.Signed = Signed;
function isNumeric(str) {
return !isNaN(Number(str));
}

115
package/node_modules/@tufjs/models/dist/delegations.js generated vendored Normal file
View File

@@ -0,0 +1,115 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Delegations = void 0;
const util_1 = __importDefault(require("util"));
const error_1 = require("./error");
const key_1 = require("./key");
const role_1 = require("./role");
const utils_1 = require("./utils");
/**
* A container object storing information about all delegations.
*
* Targets roles that are trusted to provide signed metadata files
* describing targets with designated pathnames and/or further delegations.
*/
class Delegations {
constructor(options) {
this.keys = options.keys;
this.unrecognizedFields = options.unrecognizedFields || {};
if (options.roles) {
if (Object.keys(options.roles).some((roleName) => role_1.TOP_LEVEL_ROLE_NAMES.includes(roleName))) {
throw new error_1.ValueError('Delegated role name conflicts with top-level role name');
}
}
this.succinctRoles = options.succinctRoles;
this.roles = options.roles;
}
equals(other) {
if (!(other instanceof Delegations)) {
return false;
}
return (util_1.default.isDeepStrictEqual(this.keys, other.keys) &&
util_1.default.isDeepStrictEqual(this.roles, other.roles) &&
util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields) &&
util_1.default.isDeepStrictEqual(this.succinctRoles, other.succinctRoles));
}
*rolesForTarget(targetPath) {
if (this.roles) {
for (const role of Object.values(this.roles)) {
if (role.isDelegatedPath(targetPath)) {
yield { role: role.name, terminating: role.terminating };
}
}
}
else if (this.succinctRoles) {
yield {
role: this.succinctRoles.getRoleForTarget(targetPath),
terminating: true,
};
}
}
toJSON() {
const json = {
keys: keysToJSON(this.keys),
...this.unrecognizedFields,
};
if (this.roles) {
json.roles = rolesToJSON(this.roles);
}
else if (this.succinctRoles) {
json.succinct_roles = this.succinctRoles.toJSON();
}
return json;
}
static fromJSON(data) {
const { keys, roles, succinct_roles, ...unrecognizedFields } = data;
let succinctRoles;
if (utils_1.guard.isObject(succinct_roles)) {
succinctRoles = role_1.SuccinctRoles.fromJSON(succinct_roles);
}
return new Delegations({
keys: keysFromJSON(keys),
roles: rolesFromJSON(roles),
unrecognizedFields,
succinctRoles,
});
}
}
exports.Delegations = Delegations;
function keysToJSON(keys) {
return Object.entries(keys).reduce((acc, [keyId, key]) => ({
...acc,
[keyId]: key.toJSON(),
}), {});
}
function rolesToJSON(roles) {
return Object.values(roles).map((role) => role.toJSON());
}
function keysFromJSON(data) {
if (!utils_1.guard.isObjectRecord(data)) {
throw new TypeError('keys is malformed');
}
return Object.entries(data).reduce((acc, [keyID, keyData]) => ({
...acc,
[keyID]: key_1.Key.fromJSON(keyID, keyData),
}), {});
}
function rolesFromJSON(data) {
let roleMap;
if (utils_1.guard.isDefined(data)) {
if (!utils_1.guard.isObjectArray(data)) {
throw new TypeError('roles is malformed');
}
roleMap = data.reduce((acc, role) => {
const delegatedRole = role_1.DelegatedRole.fromJSON(role);
return {
...acc,
[delegatedRole.name]: delegatedRole,
};
}, {});
}
return roleMap;
}

27
package/node_modules/@tufjs/models/dist/error.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UnsupportedAlgorithmError = exports.CryptoError = exports.LengthOrHashMismatchError = exports.UnsignedMetadataError = exports.RepositoryError = exports.ValueError = void 0;
// An error about insufficient values
class ValueError extends Error {
}
exports.ValueError = ValueError;
// An error with a repository's state, such as a missing file.
// It covers all exceptions that come from the repository side when
// looking from the perspective of users of metadata API or ngclient.
class RepositoryError extends Error {
}
exports.RepositoryError = RepositoryError;
// An error about metadata object with insufficient threshold of signatures.
class UnsignedMetadataError extends RepositoryError {
}
exports.UnsignedMetadataError = UnsignedMetadataError;
// An error while checking the length and hash values of an object.
class LengthOrHashMismatchError extends RepositoryError {
}
exports.LengthOrHashMismatchError = LengthOrHashMismatchError;
class CryptoError extends Error {
}
exports.CryptoError = CryptoError;
class UnsupportedAlgorithmError extends CryptoError {
}
exports.UnsupportedAlgorithmError = UnsupportedAlgorithmError;

183
package/node_modules/@tufjs/models/dist/file.js generated vendored Normal file
View File

@@ -0,0 +1,183 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TargetFile = exports.MetaFile = void 0;
const crypto_1 = __importDefault(require("crypto"));
const util_1 = __importDefault(require("util"));
const error_1 = require("./error");
const utils_1 = require("./utils");
// A container with information about a particular metadata file.
//
// This class is used for Timestamp and Snapshot metadata.
class MetaFile {
constructor(opts) {
if (opts.version <= 0) {
throw new error_1.ValueError('Metafile version must be at least 1');
}
if (opts.length !== undefined) {
validateLength(opts.length);
}
this.version = opts.version;
this.length = opts.length;
this.hashes = opts.hashes;
this.unrecognizedFields = opts.unrecognizedFields || {};
}
equals(other) {
if (!(other instanceof MetaFile)) {
return false;
}
return (this.version === other.version &&
this.length === other.length &&
util_1.default.isDeepStrictEqual(this.hashes, other.hashes) &&
util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields));
}
verify(data) {
// Verifies that the given data matches the expected length.
if (this.length !== undefined) {
if (data.length !== this.length) {
throw new error_1.LengthOrHashMismatchError(`Expected length ${this.length} but got ${data.length}`);
}
}
// Verifies that the given data matches the supplied hashes.
if (this.hashes) {
Object.entries(this.hashes).forEach(([key, value]) => {
let hash;
try {
hash = crypto_1.default.createHash(key);
}
catch (e) {
throw new error_1.LengthOrHashMismatchError(`Hash algorithm ${key} not supported`);
}
const observedHash = hash.update(data).digest('hex');
if (observedHash !== value) {
throw new error_1.LengthOrHashMismatchError(`Expected hash ${value} but got ${observedHash}`);
}
});
}
}
toJSON() {
const json = {
version: this.version,
...this.unrecognizedFields,
};
if (this.length !== undefined) {
json.length = this.length;
}
if (this.hashes) {
json.hashes = this.hashes;
}
return json;
}
static fromJSON(data) {
const { version, length, hashes, ...rest } = data;
if (typeof version !== 'number') {
throw new TypeError('version must be a number');
}
if (utils_1.guard.isDefined(length) && typeof length !== 'number') {
throw new TypeError('length must be a number');
}
if (utils_1.guard.isDefined(hashes) && !utils_1.guard.isStringRecord(hashes)) {
throw new TypeError('hashes must be string keys and values');
}
return new MetaFile({
version,
length,
hashes,
unrecognizedFields: rest,
});
}
}
exports.MetaFile = MetaFile;
// Container for info about a particular target file.
//
// This class is used for Target metadata.
class TargetFile {
constructor(opts) {
validateLength(opts.length);
this.length = opts.length;
this.path = opts.path;
this.hashes = opts.hashes;
this.unrecognizedFields = opts.unrecognizedFields || {};
}
get custom() {
const custom = this.unrecognizedFields['custom'];
if (!custom || Array.isArray(custom) || !(typeof custom === 'object')) {
return {};
}
return custom;
}
equals(other) {
if (!(other instanceof TargetFile)) {
return false;
}
return (this.length === other.length &&
this.path === other.path &&
util_1.default.isDeepStrictEqual(this.hashes, other.hashes) &&
util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields));
}
async verify(stream) {
let observedLength = 0;
// Create a digest for each hash algorithm
const digests = Object.keys(this.hashes).reduce((acc, key) => {
try {
acc[key] = crypto_1.default.createHash(key);
}
catch (e) {
throw new error_1.LengthOrHashMismatchError(`Hash algorithm ${key} not supported`);
}
return acc;
}, {});
// Read stream chunk by chunk
for await (const chunk of stream) {
// Keep running tally of stream length
observedLength += chunk.length;
// Append chunk to each digest
Object.values(digests).forEach((digest) => {
digest.update(chunk);
});
}
// Verify length matches expected value
if (observedLength !== this.length) {
throw new error_1.LengthOrHashMismatchError(`Expected length ${this.length} but got ${observedLength}`);
}
// Verify each digest matches expected value
Object.entries(digests).forEach(([key, value]) => {
const expected = this.hashes[key];
const actual = value.digest('hex');
if (actual !== expected) {
throw new error_1.LengthOrHashMismatchError(`Expected hash ${expected} but got ${actual}`);
}
});
}
toJSON() {
return {
length: this.length,
hashes: this.hashes,
...this.unrecognizedFields,
};
}
static fromJSON(path, data) {
const { length, hashes, ...rest } = data;
if (typeof length !== 'number') {
throw new TypeError('length must be a number');
}
if (!utils_1.guard.isStringRecord(hashes)) {
throw new TypeError('hashes must have string keys and values');
}
return new TargetFile({
length,
path,
hashes,
unrecognizedFields: rest,
});
}
}
exports.TargetFile = TargetFile;
// Check that supplied length if valid
function validateLength(length) {
if (length < 0) {
throw new error_1.ValueError('Length must be at least 0');
}
}

24
package/node_modules/@tufjs/models/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Timestamp = exports.Targets = exports.Snapshot = exports.Signature = exports.Root = exports.Metadata = exports.Key = exports.TargetFile = exports.MetaFile = exports.ValueError = exports.MetadataKind = void 0;
var base_1 = require("./base");
Object.defineProperty(exports, "MetadataKind", { enumerable: true, get: function () { return base_1.MetadataKind; } });
var error_1 = require("./error");
Object.defineProperty(exports, "ValueError", { enumerable: true, get: function () { return error_1.ValueError; } });
var file_1 = require("./file");
Object.defineProperty(exports, "MetaFile", { enumerable: true, get: function () { return file_1.MetaFile; } });
Object.defineProperty(exports, "TargetFile", { enumerable: true, get: function () { return file_1.TargetFile; } });
var key_1 = require("./key");
Object.defineProperty(exports, "Key", { enumerable: true, get: function () { return key_1.Key; } });
var metadata_1 = require("./metadata");
Object.defineProperty(exports, "Metadata", { enumerable: true, get: function () { return metadata_1.Metadata; } });
var root_1 = require("./root");
Object.defineProperty(exports, "Root", { enumerable: true, get: function () { return root_1.Root; } });
var signature_1 = require("./signature");
Object.defineProperty(exports, "Signature", { enumerable: true, get: function () { return signature_1.Signature; } });
var snapshot_1 = require("./snapshot");
Object.defineProperty(exports, "Snapshot", { enumerable: true, get: function () { return snapshot_1.Snapshot; } });
var targets_1 = require("./targets");
Object.defineProperty(exports, "Targets", { enumerable: true, get: function () { return targets_1.Targets; } });
var timestamp_1 = require("./timestamp");
Object.defineProperty(exports, "Timestamp", { enumerable: true, get: function () { return timestamp_1.Timestamp; } });

85
package/node_modules/@tufjs/models/dist/key.js generated vendored Normal file
View File

@@ -0,0 +1,85 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Key = void 0;
const util_1 = __importDefault(require("util"));
const error_1 = require("./error");
const utils_1 = require("./utils");
const key_1 = require("./utils/key");
// A container class representing the public portion of a Key.
class Key {
constructor(options) {
const { keyID, keyType, scheme, keyVal, unrecognizedFields } = options;
this.keyID = keyID;
this.keyType = keyType;
this.scheme = scheme;
this.keyVal = keyVal;
this.unrecognizedFields = unrecognizedFields || {};
}
// Verifies the that the metadata.signatures contains a signature made with
// this key and is correctly signed.
verifySignature(metadata) {
const signature = metadata.signatures[this.keyID];
if (!signature)
throw new error_1.UnsignedMetadataError('no signature for key found in metadata');
if (!this.keyVal.public)
throw new error_1.UnsignedMetadataError('no public key found');
const publicKey = (0, key_1.getPublicKey)({
keyType: this.keyType,
scheme: this.scheme,
keyVal: this.keyVal.public,
});
const signedData = metadata.signed.toJSON();
try {
if (!utils_1.crypto.verifySignature(signedData, publicKey, signature.sig)) {
throw new error_1.UnsignedMetadataError(`failed to verify ${this.keyID} signature`);
}
}
catch (error) {
if (error instanceof error_1.UnsignedMetadataError) {
throw error;
}
throw new error_1.UnsignedMetadataError(`failed to verify ${this.keyID} signature`);
}
}
equals(other) {
if (!(other instanceof Key)) {
return false;
}
return (this.keyID === other.keyID &&
this.keyType === other.keyType &&
this.scheme === other.scheme &&
util_1.default.isDeepStrictEqual(this.keyVal, other.keyVal) &&
util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields));
}
toJSON() {
return {
keytype: this.keyType,
scheme: this.scheme,
keyval: this.keyVal,
...this.unrecognizedFields,
};
}
static fromJSON(keyID, data) {
const { keytype, scheme, keyval, ...rest } = data;
if (typeof keytype !== 'string') {
throw new TypeError('keytype must be a string');
}
if (typeof scheme !== 'string') {
throw new TypeError('scheme must be a string');
}
if (!utils_1.guard.isStringRecord(keyval)) {
throw new TypeError('keyval must be a string record');
}
return new Key({
keyID,
keyType: keytype,
scheme,
keyVal: keyval,
unrecognizedFields: rest,
});
}
}
exports.Key = Key;

158
package/node_modules/@tufjs/models/dist/metadata.js generated vendored Normal file
View File

@@ -0,0 +1,158 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Metadata = void 0;
const canonical_json_1 = require("@tufjs/canonical-json");
const util_1 = __importDefault(require("util"));
const base_1 = require("./base");
const error_1 = require("./error");
const root_1 = require("./root");
const signature_1 = require("./signature");
const snapshot_1 = require("./snapshot");
const targets_1 = require("./targets");
const timestamp_1 = require("./timestamp");
const utils_1 = require("./utils");
/***
* A container for signed TUF metadata.
*
* Provides methods to convert to and from json, read and write to and
* from JSON and to create and verify metadata signatures.
*
* ``Metadata[T]`` is a generic container type where T can be any one type of
* [``Root``, ``Timestamp``, ``Snapshot``, ``Targets``]. The purpose of this
* is to allow static type checking of the signed attribute in code using
* Metadata::
*
* root_md = Metadata[Root].fromJSON("root.json")
* # root_md type is now Metadata[Root]. This means signed and its
* # attributes like consistent_snapshot are now statically typed and the
* # types can be verified by static type checkers and shown by IDEs
*
* Using a type constraint is not required but not doing so means T is not a
* specific type so static typing cannot happen. Note that the type constraint
* ``[Root]`` is not validated at runtime (as pure annotations are not available
* then).
*
* Apart from ``expires`` all of the arguments to the inner constructors have
* reasonable default values for new metadata.
*/
class Metadata {
constructor(signed, signatures, unrecognizedFields) {
this.signed = signed;
this.signatures = signatures || {};
this.unrecognizedFields = unrecognizedFields || {};
}
sign(signer, append = true) {
const bytes = Buffer.from((0, canonical_json_1.canonicalize)(this.signed.toJSON()));
const signature = signer(bytes);
if (!append) {
this.signatures = {};
}
this.signatures[signature.keyID] = signature;
}
verifyDelegate(delegatedRole, delegatedMetadata) {
let role;
let keys = {};
switch (this.signed.type) {
case base_1.MetadataKind.Root:
keys = this.signed.keys;
role = this.signed.roles[delegatedRole];
break;
case base_1.MetadataKind.Targets:
if (!this.signed.delegations) {
throw new error_1.ValueError(`No delegations found for ${delegatedRole}`);
}
keys = this.signed.delegations.keys;
if (this.signed.delegations.roles) {
role = this.signed.delegations.roles[delegatedRole];
}
else if (this.signed.delegations.succinctRoles) {
if (this.signed.delegations.succinctRoles.isDelegatedRole(delegatedRole)) {
role = this.signed.delegations.succinctRoles;
}
}
break;
default:
throw new TypeError('invalid metadata type');
}
if (!role) {
throw new error_1.ValueError(`no delegation found for ${delegatedRole}`);
}
const signingKeys = new Set();
role.keyIDs.forEach((keyID) => {
const key = keys[keyID];
// If we dont' have the key, continue checking other keys
if (!key) {
return;
}
try {
key.verifySignature(delegatedMetadata);
signingKeys.add(key.keyID);
}
catch (error) {
// continue
}
});
if (signingKeys.size < role.threshold) {
throw new error_1.UnsignedMetadataError(`${delegatedRole} was signed by ${signingKeys.size}/${role.threshold} keys`);
}
}
equals(other) {
if (!(other instanceof Metadata)) {
return false;
}
return (this.signed.equals(other.signed) &&
util_1.default.isDeepStrictEqual(this.signatures, other.signatures) &&
util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields));
}
toJSON() {
const signatures = Object.values(this.signatures).map((signature) => {
return signature.toJSON();
});
return {
signatures,
signed: this.signed.toJSON(),
...this.unrecognizedFields,
};
}
static fromJSON(type, data) {
const { signed, signatures, ...rest } = data;
if (!utils_1.guard.isDefined(signed) || !utils_1.guard.isObject(signed)) {
throw new TypeError('signed is not defined');
}
if (type !== signed._type) {
throw new error_1.ValueError(`expected '${type}', got ${signed['_type']}`);
}
let signedObj;
switch (type) {
case base_1.MetadataKind.Root:
signedObj = root_1.Root.fromJSON(signed);
break;
case base_1.MetadataKind.Timestamp:
signedObj = timestamp_1.Timestamp.fromJSON(signed);
break;
case base_1.MetadataKind.Snapshot:
signedObj = snapshot_1.Snapshot.fromJSON(signed);
break;
case base_1.MetadataKind.Targets:
signedObj = targets_1.Targets.fromJSON(signed);
break;
default:
throw new TypeError('invalid metadata type');
}
const sigMap = signaturesFromJSON(signatures);
return new Metadata(signedObj, sigMap, rest);
}
}
exports.Metadata = Metadata;
function signaturesFromJSON(data) {
if (!utils_1.guard.isObjectArray(data)) {
throw new TypeError('signatures is not an array');
}
return data.reduce((acc, sigData) => {
const signature = signature_1.Signature.fromJSON(sigData);
return { ...acc, [signature.keyID]: signature };
}, {});
}

299
package/node_modules/@tufjs/models/dist/role.js generated vendored Normal file
View File

@@ -0,0 +1,299 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SuccinctRoles = exports.DelegatedRole = exports.Role = exports.TOP_LEVEL_ROLE_NAMES = void 0;
const crypto_1 = __importDefault(require("crypto"));
const minimatch_1 = require("minimatch");
const util_1 = __importDefault(require("util"));
const error_1 = require("./error");
const utils_1 = require("./utils");
exports.TOP_LEVEL_ROLE_NAMES = [
'root',
'targets',
'snapshot',
'timestamp',
];
/**
* Container that defines which keys are required to sign roles metadata.
*
* Role defines how many keys are required to successfully sign the roles
* metadata, and which keys are accepted.
*/
class Role {
constructor(options) {
const { keyIDs, threshold, unrecognizedFields } = options;
if (hasDuplicates(keyIDs)) {
throw new error_1.ValueError('duplicate key IDs found');
}
if (threshold < 1) {
throw new error_1.ValueError('threshold must be at least 1');
}
this.keyIDs = keyIDs;
this.threshold = threshold;
this.unrecognizedFields = unrecognizedFields || {};
}
equals(other) {
if (!(other instanceof Role)) {
return false;
}
return (this.threshold === other.threshold &&
util_1.default.isDeepStrictEqual(this.keyIDs, other.keyIDs) &&
util_1.default.isDeepStrictEqual(this.unrecognizedFields, other.unrecognizedFields));
}
toJSON() {
return {
keyids: this.keyIDs,
threshold: this.threshold,
...this.unrecognizedFields,
};
}
static fromJSON(data) {
const { keyids, threshold, ...rest } = data;
if (!utils_1.guard.isStringArray(keyids)) {
throw new TypeError('keyids must be an array');
}
if (typeof threshold !== 'number') {
throw new TypeError('threshold must be a number');
}
return new Role({
keyIDs: keyids,
threshold,
unrecognizedFields: rest,
});
}
}
exports.Role = Role;
function hasDuplicates(array) {
return new Set(array).size !== array.length;
}
/**
* A container with information about a delegated role.
*
* A delegation can happen in two ways:
* - ``paths`` is set: delegates targets matching any path pattern in ``paths``
* - ``pathHashPrefixes`` is set: delegates targets whose target path hash
* starts with any of the prefixes in ``pathHashPrefixes``
*
* ``paths`` and ``pathHashPrefixes`` are mutually exclusive: both cannot be
* set, at least one of them must be set.
*/
class DelegatedRole extends Role {
constructor(opts) {
super(opts);
const { name, terminating, paths, pathHashPrefixes } = opts;
this.name = name;
this.terminating = terminating;
if (opts.paths && opts.pathHashPrefixes) {
throw new error_1.ValueError('paths and pathHashPrefixes are mutually exclusive');
}
this.paths = paths;
this.pathHashPrefixes = pathHashPrefixes;
}
equals(other) {
if (!(other instanceof DelegatedRole)) {
return false;
}
return (super.equals(other) &&
this.name === other.name &&
this.terminating === other.terminating &&
util_1.default.isDeepStrictEqual(this.paths, other.paths) &&
util_1.default.isDeepStrictEqual(this.pathHashPrefixes, other.pathHashPrefixes));
}
isDelegatedPath(targetFilepath) {
if (this.paths) {
return this.paths.some((pathPattern) => isTargetInPathPattern(targetFilepath, pathPattern));
}
if (this.pathHashPrefixes) {
const hasher = crypto_1.default.createHash('sha256');
const pathHash = hasher.update(targetFilepath).digest('hex');
return this.pathHashPrefixes.some((pathHashPrefix) => pathHash.startsWith(pathHashPrefix));
}
return false;
}
toJSON() {
const json = {
...super.toJSON(),
name: this.name,
terminating: this.terminating,
};
if (this.paths) {
json.paths = this.paths;
}
if (this.pathHashPrefixes) {
json.path_hash_prefixes = this.pathHashPrefixes;
}
return json;
}
static fromJSON(data) {
const { keyids, threshold, name, terminating, paths, path_hash_prefixes, ...rest } = data;
if (!utils_1.guard.isStringArray(keyids)) {
throw new TypeError('keyids must be an array of strings');
}
if (typeof threshold !== 'number') {
throw new TypeError('threshold must be a number');
}
if (typeof name !== 'string') {
throw new TypeError('name must be a string');
}
if (typeof terminating !== 'boolean') {
throw new TypeError('terminating must be a boolean');
}
if (utils_1.guard.isDefined(paths) && !utils_1.guard.isStringArray(paths)) {
throw new TypeError('paths must be an array of strings');
}
if (utils_1.guard.isDefined(path_hash_prefixes) &&
!utils_1.guard.isStringArray(path_hash_prefixes)) {
throw new TypeError('path_hash_prefixes must be an array of strings');
}
return new DelegatedRole({
keyIDs: keyids,
threshold,
name,
terminating,
paths,
pathHashPrefixes: path_hash_prefixes,
unrecognizedFields: rest,
});
}
}
exports.DelegatedRole = DelegatedRole;
// JS version of Ruby's Array#zip
const zip = (a, b) => a.map((k, i) => [k, b[i]]);
function isTargetInPathPattern(target, pattern) {
const targetParts = target.split('/');
const patternParts = pattern.split('/');
if (patternParts.length != targetParts.length) {
return false;
}
return zip(targetParts, patternParts).every(([targetPart, patternPart]) => (0, minimatch_1.minimatch)(targetPart, patternPart));
}
/**
* Succinctly defines a hash bin delegation graph.
*
* A ``SuccinctRoles`` object describes a delegation graph that covers all
* targets, distributing them uniformly over the delegated roles (i.e. bins)
* in the graph.
*
* The total number of bins is 2 to the power of the passed ``bit_length``.
*
* Bin names are the concatenation of the passed ``name_prefix`` and a
* zero-padded hex representation of the bin index separated by a hyphen.
*
* The passed ``keyids`` and ``threshold`` is used for each bin, and each bin
* is 'terminating'.
*
* For details: https://github.com/theupdateframework/taps/blob/master/tap15.md
*/
class SuccinctRoles extends Role {
constructor(opts) {
super(opts);
const { bitLength, namePrefix } = opts;
if (bitLength <= 0 || bitLength > 32) {
throw new error_1.ValueError('bitLength must be between 1 and 32');
}
this.bitLength = bitLength;
this.namePrefix = namePrefix;
// Calculate the suffix_len value based on the total number of bins in
// hex. If bit_length = 10 then number_of_bins = 1024 or bin names will
// have a suffix between "000" and "3ff" in hex and suffix_len will be 3
// meaning the third bin will have a suffix of "003".
this.numberOfBins = Math.pow(2, bitLength);
// suffix_len is calculated based on "number_of_bins - 1" as the name
// of the last bin contains the number "number_of_bins -1" as a suffix.
this.suffixLen = (this.numberOfBins - 1).toString(16).length;
}
equals(other) {
if (!(other instanceof SuccinctRoles)) {
return false;
}
return (super.equals(other) &&
this.bitLength === other.bitLength &&
this.namePrefix === other.namePrefix);
}
/***
* Calculates the name of the delegated role responsible for 'target_filepath'.
*
* The target at path ''target_filepath' is assigned to a bin by casting
* the left-most 'bit_length' of bits of the file path hash digest to
* int, using it as bin index between 0 and '2**bit_length - 1'.
*
* Args:
* target_filepath: URL path to a target file, relative to a base
* targets URL.
*/
getRoleForTarget(targetFilepath) {
const hasher = crypto_1.default.createHash('sha256');
const hasherBuffer = hasher.update(targetFilepath).digest();
// can't ever need more than 4 bytes (32 bits).
const hashBytes = hasherBuffer.subarray(0, 4);
// Right shift hash bytes, so that we only have the leftmost
// bit_length bits that we care about.
const shiftValue = 32 - this.bitLength;
const binNumber = hashBytes.readUInt32BE() >>> shiftValue;
// Add zero padding if necessary and cast to hex the suffix.
const suffix = binNumber.toString(16).padStart(this.suffixLen, '0');
return `${this.namePrefix}-${suffix}`;
}
*getRoles() {
for (let i = 0; i < this.numberOfBins; i++) {
const suffix = i.toString(16).padStart(this.suffixLen, '0');
yield `${this.namePrefix}-${suffix}`;
}
}
/***
* Determines whether the given ``role_name`` is in one of
* the delegated roles that ``SuccinctRoles`` represents.
*
* Args:
* role_name: The name of the role to check against.
*/
isDelegatedRole(roleName) {
const desiredPrefix = this.namePrefix + '-';
if (!roleName.startsWith(desiredPrefix)) {
return false;
}
const suffix = roleName.slice(desiredPrefix.length, roleName.length);
if (suffix.length != this.suffixLen) {
return false;
}
// make sure the suffix is a hex string
if (!suffix.match(/^[0-9a-fA-F]+$/)) {
return false;
}
const num = parseInt(suffix, 16);
return 0 <= num && num < this.numberOfBins;
}
toJSON() {
const json = {
...super.toJSON(),
bit_length: this.bitLength,
name_prefix: this.namePrefix,
};
return json;
}
static fromJSON(data) {
const { keyids, threshold, bit_length, name_prefix, ...rest } = data;
if (!utils_1.guard.isStringArray(keyids)) {
throw new TypeError('keyids must be an array of strings');
}
if (typeof threshold !== 'number') {
throw new TypeError('threshold must be a number');
}
if (typeof bit_length !== 'number') {
throw new TypeError('bit_length must be a number');
}
if (typeof name_prefix !== 'string') {
throw new TypeError('name_prefix must be a string');
}
return new SuccinctRoles({
keyIDs: keyids,
threshold,
bitLength: bit_length,
namePrefix: name_prefix,
unrecognizedFields: rest,
});
}
}
exports.SuccinctRoles = SuccinctRoles;

116
package/node_modules/@tufjs/models/dist/root.js generated vendored Normal file
View File

@@ -0,0 +1,116 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Root = void 0;
const util_1 = __importDefault(require("util"));
const base_1 = require("./base");
const error_1 = require("./error");
const key_1 = require("./key");
const role_1 = require("./role");
const utils_1 = require("./utils");
/**
* A container for the signed part of root metadata.
*
* The top-level role and metadata file signed by the root keys.
* This role specifies trusted keys for all other top-level roles, which may further delegate trust.
*/
class Root extends base_1.Signed {
constructor(options) {
super(options);
this.type = base_1.MetadataKind.Root;
this.keys = options.keys || {};
this.consistentSnapshot = options.consistentSnapshot ?? true;
if (!options.roles) {
this.roles = role_1.TOP_LEVEL_ROLE_NAMES.reduce((acc, role) => ({
...acc,
[role]: new role_1.Role({ keyIDs: [], threshold: 1 }),
}), {});
}
else {
const roleNames = new Set(Object.keys(options.roles));
if (!role_1.TOP_LEVEL_ROLE_NAMES.every((role) => roleNames.has(role))) {
throw new error_1.ValueError('missing top-level role');
}
this.roles = options.roles;
}
}
addKey(key, role) {
if (!this.roles[role]) {
throw new error_1.ValueError(`role ${role} does not exist`);
}
if (!this.roles[role].keyIDs.includes(key.keyID)) {
this.roles[role].keyIDs.push(key.keyID);
}
this.keys[key.keyID] = key;
}
equals(other) {
if (!(other instanceof Root)) {
return false;
}
return (super.equals(other) &&
this.consistentSnapshot === other.consistentSnapshot &&
util_1.default.isDeepStrictEqual(this.keys, other.keys) &&
util_1.default.isDeepStrictEqual(this.roles, other.roles));
}
toJSON() {
return {
_type: this.type,
spec_version: this.specVersion,
version: this.version,
expires: this.expires,
keys: keysToJSON(this.keys),
roles: rolesToJSON(this.roles),
consistent_snapshot: this.consistentSnapshot,
...this.unrecognizedFields,
};
}
static fromJSON(data) {
const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data);
const { keys, roles, consistent_snapshot, ...rest } = unrecognizedFields;
if (typeof consistent_snapshot !== 'boolean') {
throw new TypeError('consistent_snapshot must be a boolean');
}
return new Root({
...commonFields,
keys: keysFromJSON(keys),
roles: rolesFromJSON(roles),
consistentSnapshot: consistent_snapshot,
unrecognizedFields: rest,
});
}
}
exports.Root = Root;
function keysToJSON(keys) {
return Object.entries(keys).reduce((acc, [keyID, key]) => ({ ...acc, [keyID]: key.toJSON() }), {});
}
function rolesToJSON(roles) {
return Object.entries(roles).reduce((acc, [roleName, role]) => ({ ...acc, [roleName]: role.toJSON() }), {});
}
function keysFromJSON(data) {
let keys;
if (utils_1.guard.isDefined(data)) {
if (!utils_1.guard.isObjectRecord(data)) {
throw new TypeError('keys must be an object');
}
keys = Object.entries(data).reduce((acc, [keyID, keyData]) => ({
...acc,
[keyID]: key_1.Key.fromJSON(keyID, keyData),
}), {});
}
return keys;
}
function rolesFromJSON(data) {
let roles;
if (utils_1.guard.isDefined(data)) {
if (!utils_1.guard.isObjectRecord(data)) {
throw new TypeError('roles must be an object');
}
roles = Object.entries(data).reduce((acc, [roleName, roleData]) => ({
...acc,
[roleName]: role_1.Role.fromJSON(roleData),
}), {});
}
return roles;
}

38
package/node_modules/@tufjs/models/dist/signature.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Signature = void 0;
/**
* A container class containing information about a signature.
*
* Contains a signature and the keyid uniquely identifying the key used
* to generate the signature.
*
* Provide a `fromJSON` method to create a Signature from a JSON object.
*/
class Signature {
constructor(options) {
const { keyID, sig } = options;
this.keyID = keyID;
this.sig = sig;
}
toJSON() {
return {
keyid: this.keyID,
sig: this.sig,
};
}
static fromJSON(data) {
const { keyid, sig } = data;
if (typeof keyid !== 'string') {
throw new TypeError('keyid must be a string');
}
if (typeof sig !== 'string') {
throw new TypeError('sig must be a string');
}
return new Signature({
keyID: keyid,
sig: sig,
});
}
}
exports.Signature = Signature;

71
package/node_modules/@tufjs/models/dist/snapshot.js generated vendored Normal file
View File

@@ -0,0 +1,71 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Snapshot = void 0;
const util_1 = __importDefault(require("util"));
const base_1 = require("./base");
const file_1 = require("./file");
const utils_1 = require("./utils");
/**
* A container for the signed part of snapshot metadata.
*
* Snapshot contains information about all target Metadata files.
* A top-level role that specifies the latest versions of all targets metadata files,
* and hence the latest versions of all targets (including any dependencies between them) on the repository.
*/
class Snapshot extends base_1.Signed {
constructor(opts) {
super(opts);
this.type = base_1.MetadataKind.Snapshot;
this.meta = opts.meta || { 'targets.json': new file_1.MetaFile({ version: 1 }) };
}
equals(other) {
if (!(other instanceof Snapshot)) {
return false;
}
return super.equals(other) && util_1.default.isDeepStrictEqual(this.meta, other.meta);
}
toJSON() {
return {
_type: this.type,
meta: metaToJSON(this.meta),
spec_version: this.specVersion,
version: this.version,
expires: this.expires,
...this.unrecognizedFields,
};
}
static fromJSON(data) {
const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data);
const { meta, ...rest } = unrecognizedFields;
return new Snapshot({
...commonFields,
meta: metaFromJSON(meta),
unrecognizedFields: rest,
});
}
}
exports.Snapshot = Snapshot;
function metaToJSON(meta) {
return Object.entries(meta).reduce((acc, [path, metadata]) => ({
...acc,
[path]: metadata.toJSON(),
}), {});
}
function metaFromJSON(data) {
let meta;
if (utils_1.guard.isDefined(data)) {
if (!utils_1.guard.isObjectRecord(data)) {
throw new TypeError('meta field is malformed');
}
else {
meta = Object.entries(data).reduce((acc, [path, metadata]) => ({
...acc,
[path]: file_1.MetaFile.fromJSON(metadata),
}), {});
}
}
return meta;
}

92
package/node_modules/@tufjs/models/dist/targets.js generated vendored Normal file
View File

@@ -0,0 +1,92 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Targets = void 0;
const util_1 = __importDefault(require("util"));
const base_1 = require("./base");
const delegations_1 = require("./delegations");
const file_1 = require("./file");
const utils_1 = require("./utils");
// Container for the signed part of targets metadata.
//
// Targets contains verifying information about target files and also delegates
// responsible to other Targets roles.
class Targets extends base_1.Signed {
constructor(options) {
super(options);
this.type = base_1.MetadataKind.Targets;
this.targets = options.targets || {};
this.delegations = options.delegations;
}
addTarget(target) {
this.targets[target.path] = target;
}
equals(other) {
if (!(other instanceof Targets)) {
return false;
}
return (super.equals(other) &&
util_1.default.isDeepStrictEqual(this.targets, other.targets) &&
util_1.default.isDeepStrictEqual(this.delegations, other.delegations));
}
toJSON() {
const json = {
_type: this.type,
spec_version: this.specVersion,
version: this.version,
expires: this.expires,
targets: targetsToJSON(this.targets),
...this.unrecognizedFields,
};
if (this.delegations) {
json.delegations = this.delegations.toJSON();
}
return json;
}
static fromJSON(data) {
const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data);
const { targets, delegations, ...rest } = unrecognizedFields;
return new Targets({
...commonFields,
targets: targetsFromJSON(targets),
delegations: delegationsFromJSON(delegations),
unrecognizedFields: rest,
});
}
}
exports.Targets = Targets;
function targetsToJSON(targets) {
return Object.entries(targets).reduce((acc, [path, target]) => ({
...acc,
[path]: target.toJSON(),
}), {});
}
function targetsFromJSON(data) {
let targets;
if (utils_1.guard.isDefined(data)) {
if (!utils_1.guard.isObjectRecord(data)) {
throw new TypeError('targets must be an object');
}
else {
targets = Object.entries(data).reduce((acc, [path, target]) => ({
...acc,
[path]: file_1.TargetFile.fromJSON(path, target),
}), {});
}
}
return targets;
}
function delegationsFromJSON(data) {
let delegations;
if (utils_1.guard.isDefined(data)) {
if (!utils_1.guard.isObject(data)) {
throw new TypeError('delegations must be an object');
}
else {
delegations = delegations_1.Delegations.fromJSON(data);
}
}
return delegations;
}

58
package/node_modules/@tufjs/models/dist/timestamp.js generated vendored Normal file
View File

@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Timestamp = void 0;
const base_1 = require("./base");
const file_1 = require("./file");
const utils_1 = require("./utils");
/**
* A container for the signed part of timestamp metadata.
*
* A top-level that specifies the latest version of the snapshot role metadata file,
* and hence the latest versions of all metadata and targets on the repository.
*/
class Timestamp extends base_1.Signed {
constructor(options) {
super(options);
this.type = base_1.MetadataKind.Timestamp;
this.snapshotMeta = options.snapshotMeta || new file_1.MetaFile({ version: 1 });
}
equals(other) {
if (!(other instanceof Timestamp)) {
return false;
}
return super.equals(other) && this.snapshotMeta.equals(other.snapshotMeta);
}
toJSON() {
return {
_type: this.type,
spec_version: this.specVersion,
version: this.version,
expires: this.expires,
meta: { 'snapshot.json': this.snapshotMeta.toJSON() },
...this.unrecognizedFields,
};
}
static fromJSON(data) {
const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data);
const { meta, ...rest } = unrecognizedFields;
return new Timestamp({
...commonFields,
snapshotMeta: snapshotMetaFromJSON(meta),
unrecognizedFields: rest,
});
}
}
exports.Timestamp = Timestamp;
function snapshotMetaFromJSON(data) {
let snapshotMeta;
if (utils_1.guard.isDefined(data)) {
const snapshotData = data['snapshot.json'];
if (!utils_1.guard.isDefined(snapshotData) || !utils_1.guard.isObject(snapshotData)) {
throw new TypeError('missing snapshot.json in meta');
}
else {
snapshotMeta = file_1.MetaFile.fromJSON(snapshotData);
}
}
return snapshotMeta;
}

33
package/node_modules/@tufjs/models/dist/utils/guard.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isObjectRecord = exports.isStringRecord = exports.isObjectArray = exports.isStringArray = exports.isObject = exports.isDefined = void 0;
function isDefined(val) {
return val !== undefined;
}
exports.isDefined = isDefined;
function isObject(value) {
return typeof value === 'object' && value !== null;
}
exports.isObject = isObject;
function isStringArray(value) {
return Array.isArray(value) && value.every((v) => typeof v === 'string');
}
exports.isStringArray = isStringArray;
function isObjectArray(value) {
return Array.isArray(value) && value.every(isObject);
}
exports.isObjectArray = isObjectArray;
function isStringRecord(value) {
return (typeof value === 'object' &&
value !== null &&
Object.keys(value).every((k) => typeof k === 'string') &&
Object.values(value).every((v) => typeof v === 'string'));
}
exports.isStringRecord = isStringRecord;
function isObjectRecord(value) {
return (typeof value === 'object' &&
value !== null &&
Object.keys(value).every((k) => typeof k === 'string') &&
Object.values(value).every((v) => typeof v === 'object' && v !== null));
}
exports.isObjectRecord = isObjectRecord;

28
package/node_modules/@tufjs/models/dist/utils/index.js generated vendored Normal file
View File

@@ -0,0 +1,28 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.crypto = exports.guard = void 0;
exports.guard = __importStar(require("./guard"));
exports.crypto = __importStar(require("./verify"));

143
package/node_modules/@tufjs/models/dist/utils/key.js generated vendored Normal file
View File

@@ -0,0 +1,143 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPublicKey = void 0;
const crypto_1 = __importDefault(require("crypto"));
const error_1 = require("../error");
const oid_1 = require("./oid");
const ASN1_TAG_SEQUENCE = 0x30;
const ANS1_TAG_BIT_STRING = 0x03;
const NULL_BYTE = 0x00;
const OID_EDDSA = '1.3.101.112';
const OID_EC_PUBLIC_KEY = '1.2.840.10045.2.1';
const OID_EC_CURVE_P256V1 = '1.2.840.10045.3.1.7';
const PEM_HEADER = '-----BEGIN PUBLIC KEY-----';
function getPublicKey(keyInfo) {
switch (keyInfo.keyType) {
case 'rsa':
return getRSAPublicKey(keyInfo);
case 'ed25519':
return getED25519PublicKey(keyInfo);
case 'ecdsa':
case 'ecdsa-sha2-nistp256':
case 'ecdsa-sha2-nistp384':
return getECDCSAPublicKey(keyInfo);
default:
throw new error_1.UnsupportedAlgorithmError(`Unsupported key type: ${keyInfo.keyType}`);
}
}
exports.getPublicKey = getPublicKey;
function getRSAPublicKey(keyInfo) {
// Only support PEM-encoded RSA keys
if (!keyInfo.keyVal.startsWith(PEM_HEADER)) {
throw new error_1.CryptoError('Invalid key format');
}
const key = crypto_1.default.createPublicKey(keyInfo.keyVal);
switch (keyInfo.scheme) {
case 'rsassa-pss-sha256':
return {
key: key,
padding: crypto_1.default.constants.RSA_PKCS1_PSS_PADDING,
};
default:
throw new error_1.UnsupportedAlgorithmError(`Unsupported RSA scheme: ${keyInfo.scheme}`);
}
}
function getED25519PublicKey(keyInfo) {
let key;
// If key is already PEM-encoded we can just parse it
if (keyInfo.keyVal.startsWith(PEM_HEADER)) {
key = crypto_1.default.createPublicKey(keyInfo.keyVal);
}
else {
// If key is not PEM-encoded it had better be hex
if (!isHex(keyInfo.keyVal)) {
throw new error_1.CryptoError('Invalid key format');
}
key = crypto_1.default.createPublicKey({
key: ed25519.hexToDER(keyInfo.keyVal),
format: 'der',
type: 'spki',
});
}
return { key };
}
function getECDCSAPublicKey(keyInfo) {
let key;
// If key is already PEM-encoded we can just parse it
if (keyInfo.keyVal.startsWith(PEM_HEADER)) {
key = crypto_1.default.createPublicKey(keyInfo.keyVal);
}
else {
// If key is not PEM-encoded it had better be hex
if (!isHex(keyInfo.keyVal)) {
throw new error_1.CryptoError('Invalid key format');
}
key = crypto_1.default.createPublicKey({
key: ecdsa.hexToDER(keyInfo.keyVal),
format: 'der',
type: 'spki',
});
}
return { key };
}
const ed25519 = {
// Translates a hex key into a crypto KeyObject
// https://keygen.sh/blog/how-to-use-hexadecimal-ed25519-keys-in-node/
hexToDER: (hex) => {
const key = Buffer.from(hex, 'hex');
const oid = (0, oid_1.encodeOIDString)(OID_EDDSA);
// Create a byte sequence containing the OID and key
const elements = Buffer.concat([
Buffer.concat([
Buffer.from([ASN1_TAG_SEQUENCE]),
Buffer.from([oid.length]),
oid,
]),
Buffer.concat([
Buffer.from([ANS1_TAG_BIT_STRING]),
Buffer.from([key.length + 1]),
Buffer.from([NULL_BYTE]),
key,
]),
]);
// Wrap up by creating a sequence of elements
const der = Buffer.concat([
Buffer.from([ASN1_TAG_SEQUENCE]),
Buffer.from([elements.length]),
elements,
]);
return der;
},
};
const ecdsa = {
hexToDER: (hex) => {
const key = Buffer.from(hex, 'hex');
const bitString = Buffer.concat([
Buffer.from([ANS1_TAG_BIT_STRING]),
Buffer.from([key.length + 1]),
Buffer.from([NULL_BYTE]),
key,
]);
const oids = Buffer.concat([
(0, oid_1.encodeOIDString)(OID_EC_PUBLIC_KEY),
(0, oid_1.encodeOIDString)(OID_EC_CURVE_P256V1),
]);
const oidSequence = Buffer.concat([
Buffer.from([ASN1_TAG_SEQUENCE]),
Buffer.from([oids.length]),
oids,
]);
// Wrap up by creating a sequence of elements
const der = Buffer.concat([
Buffer.from([ASN1_TAG_SEQUENCE]),
Buffer.from([oidSequence.length + bitString.length]),
oidSequence,
bitString,
]);
return der;
},
};
const isHex = (key) => /^[0-9a-fA-F]+$/.test(key);

27
package/node_modules/@tufjs/models/dist/utils/oid.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeOIDString = void 0;
const ANS1_TAG_OID = 0x06;
function encodeOIDString(oid) {
const parts = oid.split('.');
// The first two subidentifiers are encoded into the first byte
const first = parseInt(parts[0], 10) * 40 + parseInt(parts[1], 10);
const rest = [];
parts.slice(2).forEach((part) => {
const bytes = encodeVariableLengthInteger(parseInt(part, 10));
rest.push(...bytes);
});
const der = Buffer.from([first, ...rest]);
return Buffer.from([ANS1_TAG_OID, der.length, ...der]);
}
exports.encodeOIDString = encodeOIDString;
function encodeVariableLengthInteger(value) {
const bytes = [];
let mask = 0x00;
while (value > 0) {
bytes.unshift((value & 0x7f) | mask);
value >>= 7;
mask = 0x80;
}
return bytes;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,13 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifySignature = void 0;
const canonical_json_1 = require("@tufjs/canonical-json");
const crypto_1 = __importDefault(require("crypto"));
const verifySignature = (metaDataSignedData, key, signature) => {
const canonicalData = Buffer.from((0, canonical_json_1.canonicalize)(metaDataSignedData));
return crypto_1.default.verify(undefined, canonicalData, key, Buffer.from(signature, 'hex'));
};
exports.verifySignature = verifySignature;

37
package/node_modules/@tufjs/models/package.json generated vendored Normal file
View File

@@ -0,0 +1,37 @@
{
"name": "@tufjs/models",
"version": "2.0.1",
"description": "TUF metadata models",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc --build",
"clean": "rm -rf dist && rm tsconfig.tsbuildinfo",
"test": "jest"
},
"repository": {
"type": "git",
"url": "git+https://github.com/theupdateframework/tuf-js.git"
},
"keywords": [
"tuf",
"security",
"update"
],
"author": "bdehamer@github.com",
"license": "MIT",
"bugs": {
"url": "https://github.com/theupdateframework/tuf-js/issues"
},
"homepage": "https://github.com/theupdateframework/tuf-js/tree/main/packages/models#readme",
"dependencies": {
"@tufjs/canonical-json": "2.0.0",
"minimatch": "^9.0.4"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
}