0
# Integrity Verification
1
2
Verify data integrity against existing SRI hashes with comprehensive error reporting. Supports both synchronous data verification and asynchronous stream verification with detailed error handling and algorithm selection.
3
4
## Capabilities
5
6
### Check Data Function
7
8
Synchronously verifies string or Buffer data against integrity hashes with optional error throwing.
9
10
```javascript { .api }
11
/**
12
* Verifies data against integrity string or object
13
* @param {string|Buffer} data - Data to verify
14
* @param {string|object} sri - Integrity string/object to verify against
15
* @param {object} opts - Optional configuration
16
* @param {boolean} opts.error - Throw error on mismatch instead of returning false
17
* @param {number} opts.size - Expected data size in bytes
18
* @param {function} opts.pickAlgorithm - Custom algorithm selection function
19
* @returns {Hash|false} Matching hash on success, false on failure
20
* @throws {Error} When opts.error is true and verification fails
21
*/
22
function checkData(data, sri, opts);
23
```
24
25
**Usage Examples:**
26
27
```javascript
28
const ssri = require('ssri');
29
const fs = require('fs');
30
31
// Basic verification
32
const data = fs.readFileSync('./package.json');
33
const integrity = 'sha512-abc123...';
34
const result = ssri.checkData(data, integrity);
35
36
if (result) {
37
console.log('Data verified with algorithm:', result.algorithm);
38
} else {
39
console.log('Verification failed!');
40
}
41
42
// Verification with error throwing
43
try {
44
const verified = ssri.checkData(data, integrity, { error: true });
45
console.log('Success:', verified.algorithm);
46
} catch (err) {
47
if (err.code === 'EINTEGRITY') {
48
console.error('Integrity check failed:', err.message);
49
console.error('Expected:', err.expected);
50
console.error('Found:', err.found);
51
} else if (err.code === 'EBADSIZE') {
52
console.error('Size mismatch:', err.message);
53
console.error('Expected size:', err.expected);
54
console.error('Actual size:', err.found);
55
}
56
}
57
58
// Size verification
59
const withSize = ssri.checkData(data, integrity, {
60
size: 1024,
61
error: true
62
});
63
64
// Multiple algorithm support
65
const multiIntegrity = 'sha256-def456 sha512-abc123';
66
const match = ssri.checkData(data, multiIntegrity);
67
// Returns the hash that matched (highest priority algorithm)
68
69
// Custom algorithm picker
70
const customMatch = ssri.checkData(data, multiIntegrity, {
71
pickAlgorithm: (alg1, alg2) => alg1 === 'sha256' ? alg1 : alg2
72
});
73
```
74
75
### Check Stream Function
76
77
Asynchronously verifies stream data against integrity hashes, consuming the entire stream.
78
79
```javascript { .api }
80
/**
81
* Verifies stream contents against integrity string or object
82
* @param {ReadableStream} stream - Stream to verify (will be consumed)
83
* @param {string|object} sri - Integrity string/object to verify against
84
* @param {object} opts - Optional configuration (same as checkData)
85
* @returns {Promise<Hash>} Promise resolving to matching hash on success
86
* @throws {Error} Promise rejected with detailed error on failure
87
*/
88
function checkStream(stream, sri, opts);
89
```
90
91
**Usage Examples:**
92
93
```javascript
94
const ssri = require('ssri');
95
const fs = require('fs');
96
const https = require('https');
97
98
// File stream verification
99
const fileStream = fs.createReadStream('./download.zip');
100
const expectedIntegrity = 'sha384-def789...';
101
102
ssri.checkStream(fileStream, expectedIntegrity)
103
.then(hash => {
104
console.log('File verified successfully:', hash.algorithm);
105
})
106
.catch(err => {
107
if (err.code === 'EINTEGRITY') {
108
console.error('File corruption detected!');
109
console.error('Expected:', err.expected.toString());
110
console.error('Actual:', err.found.toString());
111
}
112
});
113
114
// HTTP stream verification
115
https.get('https://cdn.example.com/library.js', (response) => {
116
const cdnIntegrity = 'sha384-abc123...';
117
118
ssri.checkStream(response, cdnIntegrity, {
119
size: parseInt(response.headers['content-length'])
120
})
121
.then(result => {
122
console.log('CDN resource verified:', result.algorithm);
123
})
124
.catch(err => {
125
console.error('CDN verification failed:', err.message);
126
// Handle compromised or corrupted CDN resource
127
});
128
});
129
130
// Pipe and verify pattern
131
const input = fs.createReadStream('./input.dat');
132
const output = fs.createWriteStream('./output.dat');
133
134
input.pipe(output);
135
136
ssri.checkStream(input, knownIntegrity)
137
.then(() => console.log('Stream processed and verified'))
138
.catch(err => {
139
// Clean up output file on verification failure
140
fs.unlinkSync('./output.dat');
141
throw err;
142
});
143
```
144
145
### Integrity Stream Function
146
147
Creates a transform stream for real-time integrity generation and optional verification during data processing.
148
149
```javascript { .api }
150
/**
151
* Creates IntegrityStream for generation and verification
152
* @param {object} opts - Optional configuration
153
* @param {string[]} opts.algorithms - Algorithms for generation (default: ['sha512'])
154
* @param {string|object} opts.integrity - Integrity to verify against
155
* @param {number} opts.size - Expected stream size
156
* @param {boolean} opts.single - Return single Hash instead of Integrity
157
* @param {function} opts.pickAlgorithm - Custom algorithm selection
158
* @returns {IntegrityStream} Transform stream instance
159
*/
160
function integrityStream(opts);
161
162
class IntegrityStream extends Minipass {
163
// Events:
164
// - 'size': Emitted with total byte count
165
// - 'integrity': Emitted with calculated Integrity object
166
// - 'verified': Emitted with matching hash if verification succeeds
167
// - 'error': Emitted on verification failure or size mismatch
168
}
169
```
170
171
**Usage Examples:**
172
173
```javascript
174
const ssri = require('ssri');
175
const fs = require('fs');
176
177
// Generate integrity while processing
178
const input = fs.createReadStream('./source.txt');
179
const output = fs.createWriteStream('./dest.txt');
180
const integrityStream = ssri.integrityStream({
181
algorithms: ['sha256', 'sha512']
182
});
183
184
input.pipe(integrityStream).pipe(output);
185
186
integrityStream.on('integrity', (integrity) => {
187
console.log('Generated integrity:', integrity.toString());
188
// Save integrity for later verification
189
fs.writeFileSync('./dest.txt.integrity', integrity.toString());
190
});
191
192
integrityStream.on('size', (size) => {
193
console.log('Processed bytes:', size);
194
});
195
196
// Verify while processing
197
const verifyingStream = ssri.integrityStream({
198
integrity: 'sha512-expected...',
199
size: 1024
200
});
201
202
input.pipe(verifyingStream).pipe(output);
203
204
verifyingStream.on('verified', (hash) => {
205
console.log('Stream verified:', hash.algorithm);
206
});
207
208
verifyingStream.on('error', (err) => {
209
if (err.code === 'EINTEGRITY') {
210
console.error('Stream integrity failure:', err.message);
211
} else if (err.code === 'EBADSIZE') {
212
console.error('Stream size mismatch:', err.message);
213
}
214
// Stop processing and clean up
215
output.destroy();
216
});
217
218
// Concurrent generation and verification
219
const dualStream = ssri.integrityStream({
220
algorithms: ['sha384'], // Generate new integrity
221
integrity: knownIntegrity, // Verify against existing
222
});
223
224
input.pipe(dualStream).pipe(output);
225
226
dualStream.on('integrity', (generated) => {
227
console.log('Generated:', generated.toString());
228
});
229
230
dualStream.on('verified', (verified) => {
231
console.log('Verified against existing integrity');
232
});
233
```
234
235
## Verification Options
236
237
### Error Handling Configuration
238
239
```javascript { .api }
240
interface VerificationOptions {
241
/** Throw detailed errors instead of returning false/rejected promises */
242
error?: boolean;
243
244
/** Expected data size in bytes for additional validation */
245
size?: number;
246
247
/** Custom function to select algorithm from multiple options */
248
pickAlgorithm?: (algorithm1: string, algorithm2: string) => string;
249
}
250
```
251
252
### Algorithm Selection
253
254
```javascript
255
// Default algorithm priority (strongest to weakest)
256
// Note: Higher index = stronger algorithm
257
const DEFAULT_PRIORITY = [
258
'md5', 'whirlpool', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
259
'sha3', 'sha3-256', 'sha3-384', 'sha3-512', 'sha3_256', 'sha3_384', 'sha3_512'
260
// Filtered to algorithms available in current Node.js via crypto.getHashes()
261
];
262
263
// Custom algorithm picker
264
const customPicker = (alg1, alg2) => {
265
// Always prefer SHA-512 if available
266
if (alg1 === 'sha512') return alg1;
267
if (alg2 === 'sha512') return alg2;
268
// Fall back to default priority
269
return DEFAULT_PRIORITY.indexOf(alg1) >= DEFAULT_PRIORITY.indexOf(alg2)
270
? alg1 : alg2;
271
};
272
273
ssri.checkData(data, multiIntegrity, { pickAlgorithm: customPicker });
274
```
275
276
## Error Types and Handling
277
278
### EINTEGRITY Errors
279
280
```javascript
281
// Integrity verification failure
282
try {
283
ssri.checkData(data, integrity, { error: true });
284
} catch (err) {
285
if (err.code === 'EINTEGRITY') {
286
console.error('Integrity check failed');
287
console.error('Algorithm used:', err.algorithm);
288
console.error('Expected integrity:', err.expected.toString());
289
console.error('Actual integrity:', err.found.toString());
290
console.error('Data size:', err.sri ? 'included' : 'not included');
291
}
292
}
293
```
294
295
### EBADSIZE Errors
296
297
```javascript
298
// Size verification failure
299
try {
300
ssri.checkData(data, integrity, { size: 1000, error: true });
301
} catch (err) {
302
if (err.code === 'EBADSIZE') {
303
console.error('Size mismatch detected');
304
console.error('Expected size:', err.expected);
305
console.error('Actual size:', err.found);
306
console.error('Integrity used:', err.sri.toString());
307
}
308
}
309
```
310
311
### Stream Error Handling
312
313
```javascript
314
// Comprehensive stream error handling
315
ssri.checkStream(stream, integrity, { size: 2048 })
316
.then(hash => {
317
console.log('Stream verification successful:', hash);
318
})
319
.catch(err => {
320
switch (err.code) {
321
case 'EINTEGRITY':
322
console.error('Stream data corrupted or modified');
323
// Notify monitoring systems, retry download, etc.
324
break;
325
case 'EBADSIZE':
326
console.error('Stream size unexpected, possible incomplete download');
327
// Retry with resume capability if supported
328
break;
329
default:
330
console.error('Stream error:', err.message);
331
// Handle network errors, file system errors, etc.
332
}
333
});
334
```
335
336
## Verification Patterns
337
338
### Package Manager Verification
339
340
```javascript
341
// npm package verification pattern
342
async function verifyPackage(packagePath, packageLock) {
343
const packageData = fs.readFileSync(packagePath);
344
const expectedIntegrity = packageLock.packages[packageName].integrity;
345
346
try {
347
const result = ssri.checkData(packageData, expectedIntegrity, {
348
error: true
349
});
350
console.log(`Package ${packageName} verified with ${result.algorithm}`);
351
return true;
352
} catch (err) {
353
console.error(`Package ${packageName} failed verification:`, err.message);
354
return false;
355
}
356
}
357
```
358
359
### CDN Resource Verification
360
361
```javascript
362
// Browser-style CDN verification
363
async function verifyCDNResource(url, expectedIntegrity) {
364
const response = await fetch(url);
365
const data = await response.text();
366
367
const result = ssri.checkData(data, expectedIntegrity);
368
if (!result) {
369
throw new Error(`CDN resource ${url} failed integrity check`);
370
}
371
372
return { data, algorithm: result.algorithm };
373
}
374
```
375
376
### Build Artifact Verification
377
378
```javascript
379
// CI/CD build verification
380
function verifyBuildArtifacts(artifactDir, integrityManifest) {
381
const results = {};
382
383
Object.entries(integrityManifest).forEach(([file, expectedIntegrity]) => {
384
const filePath = path.join(artifactDir, file);
385
if (!fs.existsSync(filePath)) {
386
results[file] = { status: 'missing' };
387
return;
388
}
389
390
try {
391
const data = fs.readFileSync(filePath);
392
const verified = ssri.checkData(data, expectedIntegrity, { error: true });
393
results[file] = {
394
status: 'verified',
395
algorithm: verified.algorithm
396
};
397
} catch (err) {
398
results[file] = {
399
status: 'failed',
400
error: err.message,
401
code: err.code
402
};
403
}
404
});
405
406
return results;
407
}
408
```
409
410
### Streaming Pipeline Verification
411
412
```javascript
413
// Real-time processing with verification
414
function createVerifiedPipeline(input, output, expectedIntegrity) {
415
const verifier = ssri.integrityStream({
416
integrity: expectedIntegrity,
417
algorithms: ['sha256'] // Also generate new integrity
418
});
419
420
const pipeline = input.pipe(verifier).pipe(output);
421
422
verifier.on('verified', (hash) => {
423
console.log('Pipeline data verified:', hash.algorithm);
424
});
425
426
verifier.on('integrity', (newIntegrity) => {
427
console.log('New integrity generated:', newIntegrity.toString());
428
});
429
430
verifier.on('error', (err) => {
431
console.error('Pipeline verification failed:', err.message);
432
// Cleanup and abort pipeline
433
pipeline.destroy();
434
output.destroy();
435
});
436
437
return pipeline;
438
}
439
```