@@ -169,31 +169,16 @@ function fromData (data, opts) {
169
169
module . exports . fromStream = fromStream
170
170
function fromStream ( stream , opts ) {
171
171
opts = opts || { }
172
- const algorithms = opts . algorithms || [ 'sha512' ]
173
- const optString = opts . options && opts . options . length
174
- ? `?${ opts . options . join ( '?' ) } `
175
- : ''
176
- const P = opts . promise || Promise
172
+ const P = opts . Promise || Promise
173
+ const istream = integrityStream ( opts )
177
174
return new P ( ( resolve , reject ) => {
178
- const hashes = algorithms . map ( algo => crypto . createHash ( algo ) )
179
- stream . on ( 'data' , d => hashes . forEach ( hash => hash . update ( d ) ) )
175
+ stream . pipe ( istream )
180
176
stream . on ( 'error' , reject )
181
- stream . on ( 'end' , ( ) => {
182
- resolve ( algorithms . reduce ( ( acc , algo , i ) => {
183
- const hash = hashes [ i ]
184
- const digest = hash . digest ( 'base64' )
185
- const meta = new IntegrityMetadata (
186
- `${ algo } -${ digest } ${ optString } ` ,
187
- opts
188
- )
189
- if ( meta . algorithm && meta . digest ) {
190
- const algo = meta . algorithm
191
- if ( ! acc [ algo ] ) { acc [ algo ] = [ ] }
192
- acc [ algo ] . push ( meta )
193
- }
194
- return acc
195
- } , new Integrity ( ) ) )
196
- } )
177
+ istream . on ( 'error' , reject )
178
+ let sri
179
+ istream . on ( 'integrity' , s => { sri = s } )
180
+ istream . on ( 'end' , ( ) => resolve ( sri ) )
181
+ istream . on ( 'data' , ( ) => { } )
197
182
} )
198
183
}
199
184
@@ -211,54 +196,77 @@ module.exports.checkStream = checkStream
211
196
function checkStream ( stream , sri , opts ) {
212
197
opts = opts || { }
213
198
const P = opts . Promise || Promise
214
- const checker = createCheckerStream ( sri , opts )
199
+ const checker = integrityStream ( {
200
+ integrity : sri ,
201
+ size : opts . size ,
202
+ strict : opts . strict ,
203
+ pickAlgorithm : opts . pickAlgorithm
204
+ } )
215
205
return new P ( ( resolve , reject ) => {
216
206
stream . pipe ( checker )
217
207
stream . on ( 'error' , reject )
218
208
checker . on ( 'error' , reject )
219
- checker . on ( 'verified' , meta => {
220
- resolve ( meta )
221
- } )
209
+ let sri
210
+ checker . on ( 'verified' , s => { sri = s } )
211
+ checker . on ( 'end' , ( ) => resolve ( sri ) )
212
+ checker . on ( 'data' , ( ) => { } )
222
213
} )
223
214
}
224
215
225
- module . exports . createCheckerStream = createCheckerStream
226
- function createCheckerStream ( sri , opts ) {
216
+ module . exports . integrityStream = integrityStream
217
+ function integrityStream ( opts ) {
227
218
opts = opts || { }
228
- sri = parse ( sri , opts )
229
- const algorithm = sri . pickAlgorithm ( opts )
230
- const digests = sri [ algorithm ]
231
- const hash = crypto . createHash ( algorithm )
219
+ // For verification
220
+ const sri = opts . integrity && parse ( opts . integrity , opts )
221
+ const algorithm = sri && sri . pickAlgorithm ( opts )
222
+ const digests = sri && sri [ algorithm ]
223
+ // Calculating stream
224
+ const algorithms = opts . algorithms || [ algorithm || 'sha512' ]
225
+ const hashes = algorithms . map ( crypto . createHash )
232
226
let streamSize = 0
233
227
const stream = new Transform ( {
234
- transform : function ( chunk , enc , cb ) {
228
+ transform ( chunk , enc , cb ) {
235
229
streamSize += chunk . length
236
- hash . update ( chunk , enc )
230
+ hashes . forEach ( h => h . update ( chunk , enc ) )
237
231
cb ( null , chunk , enc )
238
232
} ,
239
- flush : function ( cb ) {
240
- const digest = hash . digest ( 'base64' )
241
- const match = digests . find ( meta => meta . digest === digest )
233
+ flush ( done ) {
234
+ const optString = ( opts . options && opts . options . length )
235
+ ? `?${ opts . options . join ( '?' ) } `
236
+ : ''
237
+ const newSri = parse ( hashes . map ( ( h , i ) => {
238
+ return `${ algorithms [ i ] } -${ h . digest ( 'base64' ) } ${ optString } `
239
+ } ) . join ( ' ' ) , opts )
240
+ const match = (
241
+ // Integrity verification mode
242
+ opts . integrity &&
243
+ digests . find ( meta => {
244
+ return newSri [ algorithm ] . find ( newmeta => {
245
+ return meta . digest === newmeta . digest
246
+ } )
247
+ } )
248
+ )
242
249
if ( typeof opts . size === 'number' && streamSize !== opts . size ) {
243
250
const err = new Error ( `stream size mismatch when checking ${ sri } .\n Wanted: ${ opts . size } \n Found: ${ streamSize } ` )
244
251
err . code = 'EBADSIZE'
245
252
err . found = streamSize
246
253
err . expected = opts . size
247
254
err . sri = sri
248
- return cb ( err )
249
- } else if ( match ) {
250
- stream . emit ( 'size' , streamSize )
251
- stream . emit ( 'verified' , match )
252
- return cb ( )
253
- } else {
255
+ stream . emit ( 'error' , err )
256
+ } else if ( opts . integrity && ! match ) {
254
257
const err = new Error ( `${ sri } integrity checksum failed when using ${ algorithm } ` )
255
258
err . code = 'EBADCHECKSUM'
256
- err . found = digest
259
+ err . found = newSri
257
260
err . expected = digests
258
261
err . algorithm = algorithm
259
262
err . sri = sri
260
- return cb ( err )
263
+ stream . emit ( 'error' , err )
264
+ } else {
265
+ stream . emit ( 'size' , streamSize )
266
+ stream . emit ( 'integrity' , newSri )
267
+ match && stream . emit ( 'verified' , match )
261
268
}
269
+ done ( )
262
270
}
263
271
} )
264
272
return stream
0 commit comments