Comparing version 6.0.1 to 7.0.0
145
CHANGELOG.md
@@ -1,7 +0,30 @@ | ||
# Change Log | ||
# Changelog | ||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. | ||
## [7.0.0](https://github.com/npm/ssri/compare/v6.0.1...v7.0.0) (2019-09-18) | ||
### ⚠ BREAKING CHANGES | ||
* ssri no longer accepts a Promise option, and does not | ||
use, return, or rely on Bluebird promises. | ||
* drop support for Node.js v6. | ||
We knew this was coming, and the Stream changes are breaking anyway. | ||
May as well do this now. | ||
* **streams:** this replaces the Node.js stream with a Minipass | ||
stream. See http://npm.im/minipass for documentation. | ||
### Bug Fixes | ||
* return super.write() return value ([55b055d](https://github.com/npm/ssri/commit/55b055d)) | ||
* Use native promises only ([6d13165](https://github.com/npm/ssri/commit/6d13165)) | ||
* update tap, standard, standard-version, travis ([2e54956](https://github.com/npm/ssri/commit/2e54956)) | ||
* **streams:** replace transform streams with minipass ([363995e](https://github.com/npm/ssri/commit/363995e)) | ||
<a name="6.0.1"></a> | ||
## [6.0.1](https://github.com/zkat/ssri/compare/v6.0.0...v6.0.1) (2018-08-27) | ||
## [6.0.1](https://github.com/npm/ssri/compare/v6.0.0...v6.0.1) (2018-08-27) | ||
@@ -11,3 +34,3 @@ | ||
* **opts:** use figgy-pudding to specify consumed opts ([cf86553](https://github.com/zkat/ssri/commit/cf86553)) | ||
* **opts:** use figgy-pudding to specify consumed opts ([cf86553](https://github.com/npm/ssri/commit/cf86553)) | ||
@@ -17,3 +40,3 @@ | ||
<a name="6.0.0"></a> | ||
# [6.0.0](https://github.com/zkat/ssri/compare/v5.3.0...v6.0.0) (2018-04-09) | ||
# [6.0.0](https://github.com/npm/ssri/compare/v5.3.0...v6.0.0) (2018-04-09) | ||
@@ -23,3 +46,3 @@ | ||
* **docs:** minor typo ([b71ef17](https://github.com/zkat/ssri/commit/b71ef17)) | ||
* **docs:** minor typo ([b71ef17](https://github.com/npm/ssri/commit/b71ef17)) | ||
@@ -29,3 +52,3 @@ | ||
* drop support for node@4 ([d9bf359](https://github.com/zkat/ssri/commit/d9bf359)) | ||
* drop support for node@4 ([d9bf359](https://github.com/npm/ssri/commit/d9bf359)) | ||
@@ -40,3 +63,3 @@ | ||
<a name="5.3.0"></a> | ||
# [5.3.0](https://github.com/zkat/ssri/compare/v5.2.4...v5.3.0) (2018-03-13) | ||
# [5.3.0](https://github.com/npm/ssri/compare/v5.2.4...v5.3.0) (2018-03-13) | ||
@@ -46,3 +69,3 @@ | ||
* **checkData:** optionally throw when checkData fails ([bf26b84](https://github.com/zkat/ssri/commit/bf26b84)) | ||
* **checkData:** optionally throw when checkData fails ([bf26b84](https://github.com/npm/ssri/commit/bf26b84)) | ||
@@ -52,3 +75,3 @@ | ||
<a name="5.2.4"></a> | ||
## [5.2.4](https://github.com/zkat/ssri/compare/v5.2.3...v5.2.4) (2018-02-16) | ||
## [5.2.4](https://github.com/npm/ssri/compare/v5.2.3...v5.2.4) (2018-02-16) | ||
@@ -58,3 +81,3 @@ | ||
<a name="5.2.3"></a> | ||
## [5.2.3](https://github.com/zkat/ssri/compare/v5.2.2...v5.2.3) (2018-02-16) | ||
## [5.2.3](https://github.com/npm/ssri/compare/v5.2.2...v5.2.3) (2018-02-16) | ||
@@ -64,4 +87,4 @@ | ||
* **hashes:** filter hash priority list by available hashes ([2fa30b8](https://github.com/zkat/ssri/commit/2fa30b8)) | ||
* **integrityStream:** dedupe algorithms to generate ([d56c654](https://github.com/zkat/ssri/commit/d56c654)) | ||
* **hashes:** filter hash priority list by available hashes ([2fa30b8](https://github.com/npm/ssri/commit/2fa30b8)) | ||
* **integrityStream:** dedupe algorithms to generate ([d56c654](https://github.com/npm/ssri/commit/d56c654)) | ||
@@ -71,3 +94,3 @@ | ||
<a name="5.2.2"></a> | ||
## [5.2.2](https://github.com/zkat/ssri/compare/v5.2.1...v5.2.2) (2018-02-14) | ||
## [5.2.2](https://github.com/npm/ssri/compare/v5.2.1...v5.2.2) (2018-02-14) | ||
@@ -77,3 +100,3 @@ | ||
* **security:** tweak strict SRI regex ([#10](https://github.com/zkat/ssri/issues/10)) ([d0ebcdc](https://github.com/zkat/ssri/commit/d0ebcdc)) | ||
* **security:** tweak strict SRI regex ([#10](https://github.com/npm/ssri/issues/10)) ([d0ebcdc](https://github.com/npm/ssri/commit/d0ebcdc)) | ||
@@ -83,3 +106,3 @@ | ||
<a name="5.2.1"></a> | ||
## [5.2.1](https://github.com/zkat/ssri/compare/v5.2.0...v5.2.1) (2018-02-06) | ||
## [5.2.1](https://github.com/npm/ssri/compare/v5.2.0...v5.2.1) (2018-02-06) | ||
@@ -89,3 +112,3 @@ | ||
<a name="5.2.0"></a> | ||
# [5.2.0](https://github.com/zkat/ssri/compare/v5.1.0...v5.2.0) (2018-02-06) | ||
# [5.2.0](https://github.com/npm/ssri/compare/v5.1.0...v5.2.0) (2018-02-06) | ||
@@ -95,3 +118,3 @@ | ||
* **match:** add integrity.match() ([3c49cc4](https://github.com/zkat/ssri/commit/3c49cc4)) | ||
* **match:** add integrity.match() ([3c49cc4](https://github.com/npm/ssri/commit/3c49cc4)) | ||
@@ -101,3 +124,3 @@ | ||
<a name="5.1.0"></a> | ||
# [5.1.0](https://github.com/zkat/ssri/compare/v5.0.0...v5.1.0) (2018-01-18) | ||
# [5.1.0](https://github.com/npm/ssri/compare/v5.0.0...v5.1.0) (2018-01-18) | ||
@@ -107,3 +130,3 @@ | ||
* **checkStream:** integrityStream now takes opts.integrity algos into account ([d262910](https://github.com/zkat/ssri/commit/d262910)) | ||
* **checkStream:** integrityStream now takes opts.integrity algos into account ([d262910](https://github.com/npm/ssri/commit/d262910)) | ||
@@ -113,3 +136,3 @@ | ||
* **sha3:** do some guesswork about upcoming sha3 ([7fdd9df](https://github.com/zkat/ssri/commit/7fdd9df)) | ||
* **sha3:** do some guesswork about upcoming sha3 ([7fdd9df](https://github.com/npm/ssri/commit/7fdd9df)) | ||
@@ -119,3 +142,3 @@ | ||
<a name="5.0.0"></a> | ||
# [5.0.0](https://github.com/zkat/ssri/compare/v4.1.6...v5.0.0) (2017-10-23) | ||
# [5.0.0](https://github.com/npm/ssri/compare/v4.1.6...v5.0.0) (2017-10-23) | ||
@@ -125,3 +148,3 @@ | ||
* **license:** relicense to ISC (#9) ([c82983a](https://github.com/zkat/ssri/commit/c82983a)) | ||
* **license:** relicense to ISC (#9) ([c82983a](https://github.com/npm/ssri/commit/c82983a)) | ||
@@ -136,3 +159,3 @@ | ||
<a name="4.1.6"></a> | ||
## [4.1.6](https://github.com/zkat/ssri/compare/v4.1.5...v4.1.6) (2017-06-07) | ||
## [4.1.6](https://github.com/npm/ssri/compare/v4.1.5...v4.1.6) (2017-06-07) | ||
@@ -142,3 +165,3 @@ | ||
* **checkStream:** make sure to pass all opts through ([0b1bcbe](https://github.com/zkat/ssri/commit/0b1bcbe)) | ||
* **checkStream:** make sure to pass all opts through ([0b1bcbe](https://github.com/npm/ssri/commit/0b1bcbe)) | ||
@@ -148,3 +171,3 @@ | ||
<a name="4.1.5"></a> | ||
## [4.1.5](https://github.com/zkat/ssri/compare/v4.1.4...v4.1.5) (2017-06-05) | ||
## [4.1.5](https://github.com/npm/ssri/compare/v4.1.4...v4.1.5) (2017-06-05) | ||
@@ -154,3 +177,3 @@ | ||
* **integrityStream:** stop crashing if opts.algorithms and opts.integrity have an algo mismatch ([fb1293e](https://github.com/zkat/ssri/commit/fb1293e)) | ||
* **integrityStream:** stop crashing if opts.algorithms and opts.integrity have an algo mismatch ([fb1293e](https://github.com/npm/ssri/commit/fb1293e)) | ||
@@ -160,3 +183,3 @@ | ||
<a name="4.1.4"></a> | ||
## [4.1.4](https://github.com/zkat/ssri/compare/v4.1.3...v4.1.4) (2017-05-31) | ||
## [4.1.4](https://github.com/npm/ssri/compare/v4.1.3...v4.1.4) (2017-05-31) | ||
@@ -166,3 +189,3 @@ | ||
* **node:** older versions of node[@4](https://github.com/4) do not support base64buffer string parsing ([513df4e](https://github.com/zkat/ssri/commit/513df4e)) | ||
* **node:** older versions of node[@4](https://github.com/4) do not support base64buffer string parsing ([513df4e](https://github.com/npm/ssri/commit/513df4e)) | ||
@@ -172,3 +195,3 @@ | ||
<a name="4.1.3"></a> | ||
## [4.1.3](https://github.com/zkat/ssri/compare/v4.1.2...v4.1.3) (2017-05-24) | ||
## [4.1.3](https://github.com/npm/ssri/compare/v4.1.2...v4.1.3) (2017-05-24) | ||
@@ -178,3 +201,3 @@ | ||
* **check:** handle various bad hash corner cases better ([c2c262b](https://github.com/zkat/ssri/commit/c2c262b)) | ||
* **check:** handle various bad hash corner cases better ([c2c262b](https://github.com/npm/ssri/commit/c2c262b)) | ||
@@ -184,3 +207,3 @@ | ||
<a name="4.1.2"></a> | ||
## [4.1.2](https://github.com/zkat/ssri/compare/v4.1.1...v4.1.2) (2017-04-18) | ||
## [4.1.2](https://github.com/npm/ssri/compare/v4.1.1...v4.1.2) (2017-04-18) | ||
@@ -190,3 +213,3 @@ | ||
* **stream:** _flush can be called multiple times. use on("end") ([b1c4805](https://github.com/zkat/ssri/commit/b1c4805)) | ||
* **stream:** _flush can be called multiple times. use on("end") ([b1c4805](https://github.com/npm/ssri/commit/b1c4805)) | ||
@@ -196,3 +219,3 @@ | ||
<a name="4.1.1"></a> | ||
## [4.1.1](https://github.com/zkat/ssri/compare/v4.1.0...v4.1.1) (2017-04-12) | ||
## [4.1.1](https://github.com/npm/ssri/compare/v4.1.0...v4.1.1) (2017-04-12) | ||
@@ -202,3 +225,3 @@ | ||
* **pickAlgorithm:** error if pickAlgorithm() is used in an empty Integrity ([fab470e](https://github.com/zkat/ssri/commit/fab470e)) | ||
* **pickAlgorithm:** error if pickAlgorithm() is used in an empty Integrity ([fab470e](https://github.com/npm/ssri/commit/fab470e)) | ||
@@ -208,3 +231,3 @@ | ||
<a name="4.1.0"></a> | ||
# [4.1.0](https://github.com/zkat/ssri/compare/v4.0.0...v4.1.0) (2017-04-07) | ||
# [4.1.0](https://github.com/npm/ssri/compare/v4.0.0...v4.1.0) (2017-04-07) | ||
@@ -214,3 +237,3 @@ | ||
* adding ssri.create for a crypto style interface (#2) ([96f52ad](https://github.com/zkat/ssri/commit/96f52ad)) | ||
* adding ssri.create for a crypto style interface (#2) ([96f52ad](https://github.com/npm/ssri/commit/96f52ad)) | ||
@@ -220,3 +243,3 @@ | ||
<a name="4.0.0"></a> | ||
# [4.0.0](https://github.com/zkat/ssri/compare/v3.0.2...v4.0.0) (2017-04-03) | ||
# [4.0.0](https://github.com/npm/ssri/compare/v3.0.2...v4.0.0) (2017-04-03) | ||
@@ -226,3 +249,3 @@ | ||
* **integrity:** should have changed the error code before. oops ([8381afa](https://github.com/zkat/ssri/commit/8381afa)) | ||
* **integrity:** should have changed the error code before. oops ([8381afa](https://github.com/npm/ssri/commit/8381afa)) | ||
@@ -237,3 +260,3 @@ | ||
<a name="3.0.2"></a> | ||
## [3.0.2](https://github.com/zkat/ssri/compare/v3.0.1...v3.0.2) (2017-04-03) | ||
## [3.0.2](https://github.com/npm/ssri/compare/v3.0.1...v3.0.2) (2017-04-03) | ||
@@ -243,3 +266,3 @@ | ||
<a name="3.0.1"></a> | ||
## [3.0.1](https://github.com/zkat/ssri/compare/v3.0.0...v3.0.1) (2017-04-03) | ||
## [3.0.1](https://github.com/npm/ssri/compare/v3.0.0...v3.0.1) (2017-04-03) | ||
@@ -249,3 +272,3 @@ | ||
* **package.json:** really should have these in the keywords because search ([a6ac6d0](https://github.com/zkat/ssri/commit/a6ac6d0)) | ||
* **package.json:** really should have these in the keywords because search ([a6ac6d0](https://github.com/npm/ssri/commit/a6ac6d0)) | ||
@@ -255,3 +278,3 @@ | ||
<a name="3.0.0"></a> | ||
# [3.0.0](https://github.com/zkat/ssri/compare/v2.0.0...v3.0.0) (2017-04-03) | ||
# [3.0.0](https://github.com/npm/ssri/compare/v2.0.0...v3.0.0) (2017-04-03) | ||
@@ -261,3 +284,3 @@ | ||
* **hashes:** IntegrityMetadata -> Hash ([d04aa1f](https://github.com/zkat/ssri/commit/d04aa1f)) | ||
* **hashes:** IntegrityMetadata -> Hash ([d04aa1f](https://github.com/npm/ssri/commit/d04aa1f)) | ||
@@ -267,11 +290,11 @@ | ||
* **check:** return IntegrityMetadata on check success ([2301e74](https://github.com/zkat/ssri/commit/2301e74)) | ||
* **fromHex:** ssri.fromHex to make it easier to generate them from hex valus ([049b89e](https://github.com/zkat/ssri/commit/049b89e)) | ||
* **hex:** utility function for getting hex version of digest ([a9f021c](https://github.com/zkat/ssri/commit/a9f021c)) | ||
* **hexDigest:** added hexDigest method to Integrity objects too ([85208ba](https://github.com/zkat/ssri/commit/85208ba)) | ||
* **integrity:** add .isIntegrity and .isIntegrityMetadata ([1b29e6f](https://github.com/zkat/ssri/commit/1b29e6f)) | ||
* **integrityStream:** new stream that can both generate and check streamed data ([fd23e1b](https://github.com/zkat/ssri/commit/fd23e1b)) | ||
* **parse:** allow parsing straight into a single IntegrityMetadata object ([c8ddf48](https://github.com/zkat/ssri/commit/c8ddf48)) | ||
* **pickAlgorithm:** Intergrity#pickAlgorithm() added ([b97a796](https://github.com/zkat/ssri/commit/b97a796)) | ||
* **size:** calculate and update stream sizes ([02ed1ad](https://github.com/zkat/ssri/commit/02ed1ad)) | ||
* **check:** return IntegrityMetadata on check success ([2301e74](https://github.com/npm/ssri/commit/2301e74)) | ||
* **fromHex:** ssri.fromHex to make it easier to generate them from hex valus ([049b89e](https://github.com/npm/ssri/commit/049b89e)) | ||
* **hex:** utility function for getting hex version of digest ([a9f021c](https://github.com/npm/ssri/commit/a9f021c)) | ||
* **hexDigest:** added hexDigest method to Integrity objects too ([85208ba](https://github.com/npm/ssri/commit/85208ba)) | ||
* **integrity:** add .isIntegrity and .isIntegrityMetadata ([1b29e6f](https://github.com/npm/ssri/commit/1b29e6f)) | ||
* **integrityStream:** new stream that can both generate and check streamed data ([fd23e1b](https://github.com/npm/ssri/commit/fd23e1b)) | ||
* **parse:** allow parsing straight into a single IntegrityMetadata object ([c8ddf48](https://github.com/npm/ssri/commit/c8ddf48)) | ||
* **pickAlgorithm:** Intergrity#pickAlgorithm() added ([b97a796](https://github.com/npm/ssri/commit/b97a796)) | ||
* **size:** calculate and update stream sizes ([02ed1ad](https://github.com/npm/ssri/commit/02ed1ad)) | ||
@@ -290,3 +313,3 @@ | ||
<a name="2.0.0"></a> | ||
# [2.0.0](https://github.com/zkat/ssri/compare/v1.0.0...v2.0.0) (2017-03-24) | ||
# [2.0.0](https://github.com/npm/ssri/compare/v1.0.0...v2.0.0) (2017-03-24) | ||
@@ -296,3 +319,3 @@ | ||
* **strict-mode:** make regexes more rigid ([122a32c](https://github.com/zkat/ssri/commit/122a32c)) | ||
* **strict-mode:** make regexes more rigid ([122a32c](https://github.com/npm/ssri/commit/122a32c)) | ||
@@ -302,8 +325,8 @@ | ||
* **api:** added serialize alias for unparse ([999b421](https://github.com/zkat/ssri/commit/999b421)) | ||
* **concat:** add Integrity#concat() ([cae12c7](https://github.com/zkat/ssri/commit/cae12c7)) | ||
* **pickAlgo:** pick the strongest algorithm provided, by default ([58c18f7](https://github.com/zkat/ssri/commit/58c18f7)) | ||
* **strict-mode:** strict SRI support ([3f0b64c](https://github.com/zkat/ssri/commit/3f0b64c)) | ||
* **stringify:** replaced unparse/serialize with stringify ([4acad30](https://github.com/zkat/ssri/commit/4acad30)) | ||
* **verification:** add opts.pickAlgorithm ([f72e658](https://github.com/zkat/ssri/commit/f72e658)) | ||
* **api:** added serialize alias for unparse ([999b421](https://github.com/npm/ssri/commit/999b421)) | ||
* **concat:** add Integrity#concat() ([cae12c7](https://github.com/npm/ssri/commit/cae12c7)) | ||
* **pickAlgo:** pick the strongest algorithm provided, by default ([58c18f7](https://github.com/npm/ssri/commit/58c18f7)) | ||
* **strict-mode:** strict SRI support ([3f0b64c](https://github.com/npm/ssri/commit/3f0b64c)) | ||
* **stringify:** replaced unparse/serialize with stringify ([4acad30](https://github.com/npm/ssri/commit/4acad30)) | ||
* **verification:** add opts.pickAlgorithm ([f72e658](https://github.com/npm/ssri/commit/f72e658)) | ||
@@ -325,3 +348,3 @@ | ||
* **api:** implemented initial api ([4fbb16b](https://github.com/zkat/ssri/commit/4fbb16b)) | ||
* **api:** implemented initial api ([4fbb16b](https://github.com/npm/ssri/commit/4fbb16b)) | ||
@@ -328,0 +351,0 @@ |
195
index.js
@@ -5,3 +5,3 @@ 'use strict' | ||
const figgyPudding = require('figgy-pudding') | ||
const Transform = require('stream').Transform | ||
const MiniPass = require('minipass') | ||
@@ -16,14 +16,74 @@ const SPEC_ALGORITHMS = ['sha256', 'sha384', 'sha512'] | ||
const SsriOpts = figgyPudding({ | ||
algorithms: {default: ['sha512']}, | ||
error: {default: false}, | ||
algorithms: { default: ['sha512'] }, | ||
error: { default: false }, | ||
integrity: {}, | ||
options: {default: []}, | ||
pickAlgorithm: {default: () => getPrioritizedHash}, | ||
Promise: {default: () => Promise}, | ||
sep: {default: ' '}, | ||
single: {default: false}, | ||
options: { default: [] }, | ||
pickAlgorithm: { default: () => getPrioritizedHash }, | ||
sep: { default: ' ' }, | ||
single: { default: false }, | ||
size: {}, | ||
strict: {default: false} | ||
strict: { default: false } | ||
}) | ||
class IntegrityStream extends MiniPass { | ||
constructor (opts) { | ||
super() | ||
this.size = 0 | ||
this.opts = opts | ||
// For verification | ||
this.sri = opts.integrity && parse(opts.integrity, opts) | ||
this.goodSri = this.sri && Object.keys(this.sri).length | ||
this.algorithm = this.goodSri && this.sri.pickAlgorithm(opts) | ||
this.digests = this.goodSri && this.sri[this.algorithm] | ||
// Calculating stream | ||
this.algorithms = Array.from( | ||
new Set(opts.algorithms.concat(this.algorithm ? [this.algorithm] : [])) | ||
) | ||
this.hashes = this.algorithms.map(crypto.createHash) | ||
this.onEnd = this.onEnd.bind(this) | ||
} | ||
emit (ev, data) { | ||
if (ev === 'end') this.onEnd() | ||
return super.emit(ev, data) | ||
} | ||
write (data) { | ||
this.size += data.length | ||
this.hashes.forEach(h => h.update(data)) | ||
return super.write(data) | ||
} | ||
onEnd () { | ||
const optString = (this.opts.options && this.opts.options.length) | ||
? `?${this.opts.options.join('?')}` | ||
: '' | ||
const newSri = parse(this.hashes.map((h, i) => { | ||
return `${this.algorithms[i]}-${h.digest('base64')}${optString}` | ||
}).join(' '), this.opts) | ||
// Integrity verification mode | ||
const match = this.goodSri && newSri.match(this.sri, this.opts) | ||
if (typeof this.opts.size === 'number' && this.size !== this.opts.size) { | ||
const err = new Error(`stream size mismatch when checking ${this.sri}.\n Wanted: ${this.opts.size}\n Found: ${this.size}`) | ||
err.code = 'EBADSIZE' | ||
err.found = this.size | ||
err.expected = this.opts.size | ||
err.sri = this.sri | ||
this.emit('error', err) | ||
} else if (this.opts.integrity && !match) { | ||
const err = new Error(`${this.sri} integrity checksum failed when using ${this.algorithm}: wanted ${this.digests} but got ${newSri}. (${this.size} bytes)`) | ||
err.code = 'EINTEGRITY' | ||
err.found = newSri | ||
err.expected = this.digests | ||
err.algorithm = this.algorithm | ||
err.sri = this.sri | ||
this.emit('error', err) | ||
} else { | ||
this.emit('size', this.size) | ||
this.emit('integrity', newSri) | ||
match && this.emit('verified', match) | ||
} | ||
} | ||
} | ||
class Hash { | ||
@@ -35,2 +95,9 @@ get isHash () { return true } | ||
this.source = hash.trim() | ||
// set default values so that we make V8 happy to | ||
// always see a familiar object template. | ||
this.digest = '' | ||
this.algorithm = '' | ||
this.options = [] | ||
// 3.1. Integrity metadata (called "Hash" by ssri) | ||
@@ -40,4 +107,4 @@ // https://w3c.github.io/webappsec-subresource-integrity/#integrity-metadata-description | ||
strict | ||
? STRICT_SRI_REGEX | ||
: SRI_REGEX | ||
? STRICT_SRI_REGEX | ||
: SRI_REGEX | ||
) | ||
@@ -50,10 +117,15 @@ if (!match) { return } | ||
const rawOpts = match[3] | ||
this.options = rawOpts ? rawOpts.slice(1).split('?') : [] | ||
if (rawOpts) { | ||
this.options = rawOpts.slice(1).split('?') | ||
} | ||
} | ||
hexDigest () { | ||
return this.digest && Buffer.from(this.digest, 'base64').toString('hex') | ||
} | ||
toJSON () { | ||
return this.toString() | ||
} | ||
toString (opts) { | ||
@@ -76,3 +148,3 @@ opts = SsriOpts(opts) | ||
// https://tools.ietf.org/html/rfc5234#appendix-B.1 | ||
(this.options || []).every(opt => opt.match(VCHAR_REGEX)) | ||
this.options.every(opt => opt.match(VCHAR_REGEX)) | ||
)) { | ||
@@ -83,4 +155,4 @@ return '' | ||
const options = this.options && this.options.length | ||
? `?${this.options.join('?')}` | ||
: '' | ||
? `?${this.options.join('?')}` | ||
: '' | ||
return `${this.algorithm}-${this.digest}${options}` | ||
@@ -95,2 +167,3 @@ } | ||
} | ||
toString (opts) { | ||
@@ -109,12 +182,15 @@ opts = SsriOpts(opts) | ||
} | ||
concat (integrity, opts) { | ||
opts = SsriOpts(opts) | ||
const other = typeof integrity === 'string' | ||
? integrity | ||
: stringify(integrity, opts) | ||
? integrity | ||
: stringify(integrity, opts) | ||
return parse(`${this.toString(opts)} ${other}`, opts) | ||
} | ||
hexDigest () { | ||
return parse(this, {single: true}).hexDigest() | ||
return parse(this, { single: true }).hexDigest() | ||
} | ||
match (integrity, opts) { | ||
@@ -134,2 +210,3 @@ opts = SsriOpts(opts) | ||
} | ||
pickAlgorithm (opts) { | ||
@@ -197,4 +274,4 @@ opts = SsriOpts(opts) | ||
const optString = opts.options && opts.options.length | ||
? `?${opts.options.join('?')}` | ||
: '' | ||
? `?${opts.options.join('?')}` | ||
: '' | ||
return parse( | ||
@@ -212,4 +289,4 @@ `${algorithm}-${ | ||
const optString = opts.options && opts.options.length | ||
? `?${opts.options.join('?')}` | ||
: '' | ||
? `?${opts.options.join('?')}` | ||
: '' | ||
return algorithms.reduce((acc, algo) => { | ||
@@ -219,4 +296,7 @@ const digest = crypto.createHash(algo).update(data).digest('base64') | ||
`${algo}-${digest}${optString}`, | ||
opts | ||
opts | ||
) | ||
/* istanbul ignore else - it would be VERY strange if the string we | ||
* just calculated with an algo did not have an algo or digest. | ||
*/ | ||
if (hash.algorithm && hash.digest) { | ||
@@ -234,5 +314,4 @@ const algo = hash.algorithm | ||
opts = SsriOpts(opts) | ||
const P = opts.Promise || Promise | ||
const istream = integrityStream(opts) | ||
return new P((resolve, reject) => { | ||
return new Promise((resolve, reject) => { | ||
stream.pipe(istream) | ||
@@ -265,3 +344,3 @@ stream.on('error', reject) | ||
const digest = crypto.createHash(algorithm).update(data).digest('base64') | ||
const newSri = parse({algorithm, digest}) | ||
const newSri = parse({ algorithm, digest }) | ||
const match = newSri.match(sri, opts) | ||
@@ -291,7 +370,6 @@ if (match || !opts.error) { | ||
opts = SsriOpts(opts) | ||
const P = opts.Promise || Promise | ||
const checker = integrityStream(opts.concat({ | ||
integrity: sri | ||
})) | ||
return new P((resolve, reject) => { | ||
return new Promise((resolve, reject) => { | ||
stream.pipe(checker) | ||
@@ -309,51 +387,3 @@ stream.on('error', reject) | ||
function integrityStream (opts) { | ||
opts = SsriOpts(opts) | ||
// For verification | ||
const sri = opts.integrity && parse(opts.integrity, opts) | ||
const goodSri = sri && Object.keys(sri).length | ||
const algorithm = goodSri && sri.pickAlgorithm(opts) | ||
const digests = goodSri && sri[algorithm] | ||
// Calculating stream | ||
const algorithms = Array.from( | ||
new Set(opts.algorithms.concat(algorithm ? [algorithm] : [])) | ||
) | ||
const hashes = algorithms.map(crypto.createHash) | ||
let streamSize = 0 | ||
const stream = new Transform({ | ||
transform (chunk, enc, cb) { | ||
streamSize += chunk.length | ||
hashes.forEach(h => h.update(chunk, enc)) | ||
cb(null, chunk, enc) | ||
} | ||
}).on('end', () => { | ||
const optString = (opts.options && opts.options.length) | ||
? `?${opts.options.join('?')}` | ||
: '' | ||
const newSri = parse(hashes.map((h, i) => { | ||
return `${algorithms[i]}-${h.digest('base64')}${optString}` | ||
}).join(' '), opts) | ||
// 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' | ||
err.found = streamSize | ||
err.expected = opts.size | ||
err.sri = sri | ||
stream.emit('error', err) | ||
} else if (opts.integrity && !match) { | ||
const err = new Error(`${sri} integrity checksum failed when using ${algorithm}: wanted ${digests} but got ${newSri}. (${streamSize} bytes)`) | ||
err.code = 'EINTEGRITY' | ||
err.found = newSri | ||
err.expected = digests | ||
err.algorithm = algorithm | ||
err.sri = sri | ||
stream.emit('error', err) | ||
} else { | ||
stream.emit('size', streamSize) | ||
stream.emit('integrity', newSri) | ||
match && stream.emit('verified', match) | ||
} | ||
}) | ||
return stream | ||
return new IntegrityStream(SsriOpts(opts)) | ||
} | ||
@@ -366,4 +396,4 @@ | ||
const optString = opts.options.length | ||
? `?${opts.options.join('?')}` | ||
: '' | ||
? `?${opts.options.join('?')}` | ||
: '' | ||
@@ -384,2 +414,5 @@ const hashes = algorithms.map(crypto.createHash) | ||
) | ||
/* istanbul ignore else - it would be VERY strange if the hash we | ||
* just calculated with an algo did not have an algo or digest. | ||
*/ | ||
if (hash.algorithm && hash.digest) { | ||
@@ -412,4 +445,4 @@ const algo = hash.algorithm | ||
return DEFAULT_PRIORITY.indexOf(algo1.toLowerCase()) >= DEFAULT_PRIORITY.indexOf(algo2.toLowerCase()) | ||
? algo1 | ||
: algo2 | ||
? algo1 | ||
: algo2 | ||
} |
{ | ||
"name": "ssri", | ||
"version": "6.0.1", | ||
"description": "Standard Subresource Integrity library -- parses, serializes, generates, and verifies integrity metadata according to the SRI spec.", | ||
"version": "7.0.0", | ||
"description": "Standard Subresource Integrity library -- parses, serializes, generates, and verifies integrity metadata according to the SRI spec.", | ||
"main": "index.js", | ||
@@ -18,3 +18,3 @@ "files": [ | ||
}, | ||
"repository": "https://github.com/zkat/ssri", | ||
"repository": "https://github.com/npm/ssri", | ||
"keywords": [ | ||
@@ -41,20 +41,15 @@ "w3c", | ||
"dependencies": { | ||
"figgy-pudding": "^3.5.1" | ||
"figgy-pudding": "^3.5.1", | ||
"minipass": "^2.5.1" | ||
}, | ||
"devDependencies": { | ||
"nyc": "^11.4.1", | ||
"standard": "^10.0.3", | ||
"standard-version": "^4.3.0", | ||
"tap": "^11.1.0", | ||
"standard": "^14.3.0", | ||
"standard-version": "^7.0.0", | ||
"tap": "^14.6.4", | ||
"weallbehave": "^1.2.0", | ||
"weallcontribute": "^1.0.8" | ||
}, | ||
"config": { | ||
"nyc": { | ||
"exclude": [ | ||
"node_modules/**", | ||
"test/**" | ||
] | ||
} | ||
"tap": { | ||
"check-coverage": true | ||
} | ||
} |
@@ -1,4 +0,4 @@ | ||
# ssri [![npm version](https://img.shields.io/npm/v/ssri.svg)](https://npm.im/ssri) [![license](https://img.shields.io/npm/l/ssri.svg)](https://npm.im/ssri) [![Travis](https://img.shields.io/travis/zkat/ssri.svg)](https://travis-ci.org/zkat/ssri) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/zkat/ssri?svg=true)](https://ci.appveyor.com/project/zkat/ssri) [![Coverage Status](https://coveralls.io/repos/github/zkat/ssri/badge.svg?branch=latest)](https://coveralls.io/github/zkat/ssri?branch=latest) | ||
# ssri [![npm version](https://img.shields.io/npm/v/ssri.svg)](https://npm.im/ssri) [![license](https://img.shields.io/npm/l/ssri.svg)](https://npm.im/ssri) [![Travis](https://img.shields.io/travis/npm/ssri.svg)](https://travis-ci.org/npm/ssri) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/npm/ssri?svg=true)](https://ci.appveyor.com/project/npm/ssri) [![Coverage Status](https://coveralls.io/repos/github/npm/ssri/badge.svg?branch=latest)](https://coveralls.io/github/npm/ssri?branch=latest) | ||
[`ssri`](https://github.com/zkat/ssri), short for Standard Subresource | ||
[`ssri`](https://github.com/npm/ssri), short for Standard Subresource | ||
Integrity, is a Node.js utility for parsing, manipulating, serializing, | ||
@@ -5,0 +5,0 @@ generating, and verifying [Subresource |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
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
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
42951
5
391
2
1
+ Addedminipass@^2.5.1
+ Addedminipass@2.9.0(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedyallist@3.1.1(transitive)