Skip to content

Commit

Permalink
feat(size): calculate and update stream sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
zkat committed Apr 3, 2017
1 parent 049b89e commit 02ed1ad
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ or an error happens with `stream`, the Promise will be rejected.
If the Promise is rejected because verification failed, the returned error will
have `err.code` as `EBADCHECKSUM`.

If `opts.size` is given, it will be matched against the stream size. An error
with `err.code` `EBADSIZE` will be returned by a rejection if the expected size
and actual size fail to match.

If `opts.pickAlgorithm` is provided, it will be used by
[`Integrity#pickAlgorithm`](#integrity-pick-algorithm) when deciding which of
the available digests to match against.
Expand Down Expand Up @@ -385,6 +389,10 @@ against `sri`. `sri` can be any subresource integrity representation that
If verification fails, the returned stream will error with an `EBADCHECKSUM`
error code.

If `opts.size` is given, it will be matched against the stream size. An error
with `err.code` `EBADSIZE` will be emitted by the stream if the expected size
and actual size fail to match.

If `opts.pickAlgorithm` is provided, it will be passed two algorithms as
arguments. ssri will prioritize whichever of the two algorithms is returned by
this function. Note that the function may be called multiple times, and it
Expand Down
15 changes: 13 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,23 +229,34 @@ function createCheckerStream (sri, opts) {
const algorithm = sri.pickAlgorithm(opts)
const digests = sri[algorithm]
const hash = crypto.createHash(algorithm)
let streamSize = 0
const stream = new Transform({
transform: function (chunk, enc, cb) {
streamSize += chunk.length
hash.update(chunk, enc)
cb(null, chunk, enc)
},
flush: function (cb) {
const digest = hash.digest('base64')
const match = digests.find(meta => meta.digest === digest)
if (match) {
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
return cb(err)
} else if (match) {
stream.emit('size', streamSize)
stream.emit('verified', match)
return cb()
} else {
const err = new Error(`${algorithm} integrity checksum failed`)
const err = new Error(`${sri} integrity checksum failed when using ${algorithm}`)
err.code = 'EBADCHECKSUM'
err.found = digest
err.expected = digests
err.algorithm = algorithm
err.sri = sri
return cb(err)
}
}
Expand Down
9 changes: 9 additions & 0 deletions test/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,14 @@ test('checkStream', t => {
})['sha384'][0],
'picks the "strongest" available algorithm, by default'
)
return ssri.checkStream(
fileStream(), `sha256-${hash(TEST_DATA, 'sha256')}`, {
size: TEST_DATA.length - 1
}
).then(() => {
throw new Error('unexpected success')
}, err => {
t.equal(err.code, 'EBADSIZE', 'size check failure rejects the promise')
})
})
})

0 comments on commit 02ed1ad

Please sign in to comment.