diff options
Diffstat (limited to 'deps/npm/node_modules/ssri/index.js')
-rw-r--r-- | deps/npm/node_modules/ssri/index.js | 83 |
1 files changed, 63 insertions, 20 deletions
diff --git a/deps/npm/node_modules/ssri/index.js b/deps/npm/node_modules/ssri/index.js index 8ece662ba6..d4c9e49c4d 100644 --- a/deps/npm/node_modules/ssri/index.js +++ b/deps/npm/node_modules/ssri/index.js @@ -1,7 +1,5 @@ 'use strict' -const Buffer = require('safe-buffer').Buffer - const crypto = require('crypto') const Transform = require('stream').Transform @@ -9,7 +7,7 @@ const SPEC_ALGORITHMS = ['sha256', 'sha384', 'sha512'] const BASE64_REGEX = /^[a-z0-9+/]+(?:=?=?)$/i const SRI_REGEX = /^([^-]+)-([^?]+)([?\S*]*)$/ -const STRICT_SRI_REGEX = /^([^-]+)-([A-Za-z0-9+/]+(?:=?=?))([?\x21-\x7E]*)$/ +const STRICT_SRI_REGEX = /^([^-]+)-([A-Za-z0-9+/=]{44,88})(\?[\x21-\x7E]*)*$/ const VCHAR_REGEX = /^[\x21-\x7E]+$/ class Hash { @@ -93,6 +91,19 @@ class Integrity { hexDigest () { return parse(this, {single: true}).hexDigest() } + match (integrity, opts) { + const other = parse(integrity, opts) + const algo = other.pickAlgorithm(opts) + return ( + this[algo] && + other[algo] && + this[algo].find(hash => + other[algo].find(otherhash => + hash.digest === otherhash.digest + ) + ) + ) || false + } pickAlgorithm (opts) { const pickAlgorithm = (opts && opts.pickAlgorithm) || getPrioritizedHash const keys = Object.keys(this) @@ -203,11 +214,39 @@ module.exports.checkData = checkData function checkData (data, sri, opts) { opts = opts || {} sri = parse(sri, opts) - if (!Object.keys(sri).length) { return false } + if (!Object.keys(sri).length) { + if (opts.error) { + throw Object.assign( + new Error('No valid integrity hashes to check against'), { + code: 'EINTEGRITY' + } + ) + } else { + return false + } + } const algorithm = sri.pickAlgorithm(opts) - const digests = sri[algorithm] || [] const digest = crypto.createHash(algorithm).update(data).digest('base64') - return digests.find(hash => hash.digest === digest) || false + const newSri = parse({algorithm, digest}) + const match = newSri.match(sri, opts) + if (match || !opts.error) { + return match + } else if (typeof opts.size === 'number' && (data.length !== opts.size)) { + const err = new Error(`data size mismatch when checking ${sri}.\n Wanted: ${opts.size}\n Found: ${data.length}`) + err.code = 'EBADSIZE' + err.found = data.length + err.expected = opts.size + err.sri = sri + throw err + } else { + const err = new Error(`Integrity checksum failed when using ${algorithm}: Wanted ${sri}, but got ${newSri}. (${data.length} bytes)`) + err.code = 'EINTEGRITY' + err.found = newSri + err.expected = sri + err.algorithm = algorithm + err.sri = sri + throw err + } } module.exports.checkStream = checkStream @@ -237,7 +276,12 @@ function integrityStream (opts) { const algorithm = goodSri && sri.pickAlgorithm(opts) const digests = goodSri && sri[algorithm] // Calculating stream - const algorithms = opts.algorithms || [algorithm || 'sha512'] + const algorithms = Array.from( + new Set( + (opts.algorithms || ['sha512']) + .concat(algorithm ? [algorithm] : []) + ) + ) const hashes = algorithms.map(crypto.createHash) let streamSize = 0 const stream = new Transform({ @@ -253,17 +297,8 @@ function integrityStream (opts) { const newSri = parse(hashes.map((h, i) => { return `${algorithms[i]}-${h.digest('base64')}${optString}` }).join(' '), opts) - const match = ( - // Integrity verification mode - opts.integrity && - newSri[algorithm] && - digests && - digests.find(hash => { - return newSri[algorithm].find(newhash => { - return hash.digest === newhash.digest - }) - }) - ) + // Integrity verification mode + const match = goodSri && newSri.match(sri, opts) if (typeof opts.size === 'number' && streamSize !== opts.size) { const err = new Error(`stream size mismatch when checking ${sri}.\n Wanted: ${opts.size}\n Found: ${streamSize}`) err.code = 'EBADSIZE' @@ -323,10 +358,18 @@ function createIntegrity (opts) { } } +const NODE_HASHES = new Set(crypto.getHashes()) + // This is a Best Effortâ„¢ at a reasonable priority for hash algos const DEFAULT_PRIORITY = [ - 'md5', 'whirlpool', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512' -] + 'md5', 'whirlpool', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', + // TODO - it's unclear _which_ of these Node will actually use as its name + // for the algorithm, so we guesswork it based on the OpenSSL names. + 'sha3', + 'sha3-256', 'sha3-384', 'sha3-512', + 'sha3_256', 'sha3_384', 'sha3_512' +].filter(algo => NODE_HASHES.has(algo)) + function getPrioritizedHash (algo1, algo2) { return DEFAULT_PRIORITY.indexOf(algo1.toLowerCase()) >= DEFAULT_PRIORITY.indexOf(algo2.toLowerCase()) ? algo1 |