CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ssri

Standard Subresource Integrity library that parses, serializes, generates, and verifies integrity metadata according to the SRI spec.

Pending
Overview
Eval results
Files

generation.mddocs/

Integrity Generation

Generate SRI hashes from various data sources including raw data, streams, and hex values. Supports multiple algorithms and custom options for flexible hash creation in different scenarios.

Capabilities

From Data Function

Creates integrity hashes directly from string or Buffer data using multiple algorithms simultaneously.

/**
 * Creates Integrity object from string or Buffer data
 * @param {string|Buffer} data - Data to hash
 * @param {object} opts - Optional configuration
 * @param {string[]} opts.algorithms - Algorithms to use (default: ['sha512'])
 * @param {string[]} opts.options - Option strings to add to hashes
 * @param {boolean} opts.strict - Use strict mode
 * @returns {Integrity} Generated integrity object
 */
function fromData(data, opts);

Usage Examples:

const ssri = require('ssri');
const fs = require('fs');

// Basic usage with default SHA-512
const integrity = ssri.fromData('hello world');
console.log(integrity.toString());
// -> 'sha512-MJ7MSJwS1utMxA9QyQLytNDtd+5RGnx6m808qG1M2G+YndNbxf9JlnDaNCVbRbDP2DDoH2Bdz33FVC6TrpzXbw=='

// Multiple algorithms
const multiAlgo = ssri.fromData(fs.readFileSync('./package.json'), {
  algorithms: ['sha256', 'sha384', 'sha512']
});
console.log(multiAlgo.toString());
// -> 'sha256-abc... sha384-def... sha512-ghi...'

// With custom options
const withOptions = ssri.fromData('data', {
  algorithms: ['sha256'],
  options: ['cors', 'integrity-metadata']
});
console.log(withOptions.toString());
// -> 'sha256-abc...?cors?integrity-metadata'

// From Buffer
const buffer = Buffer.from('binary data', 'utf8');
const bufferIntegrity = ssri.fromData(buffer);

From Stream Function

Asynchronously generates integrity hashes by reading from a stream, ideal for large files or network streams.

/**
 * Generates Integrity by reading from stream
 * @param {ReadableStream} stream - Stream to read data from
 * @param {object} opts - Optional configuration (same as fromData)
 * @returns {Promise<Integrity>} Promise resolving to generated integrity
 */
function fromStream(stream, opts);

Usage Examples:

const ssri = require('ssri');
const fs = require('fs');

// Generate integrity from file stream
ssri.fromStream(fs.createReadStream('./large-file.zip'))
  .then(integrity => {
    console.log('File integrity:', integrity.toString());
    // Save integrity for later verification
    fs.writeFileSync('./large-file.zip.integrity', integrity.toString());
  })
  .catch(err => console.error('Generation failed:', err));

// Multiple algorithms from stream
ssri.fromStream(fs.createReadStream('./data.json'), {
  algorithms: ['sha1', 'sha256', 'sha512']
})
  .then(integrity => {
    console.log('Multi-algorithm integrity generated');
    // Can verify with any of the algorithms
  });

// HTTP response stream
const https = require('https');
https.get('https://example.com/file.js', (response) => {
  ssri.fromStream(response, { algorithms: ['sha384'] })
    .then(integrity => {
      console.log('CDN file integrity:', integrity.toString());
    });
});

From Hex Function

Creates integrity from existing hex-formatted hash digests, useful for converting from other hash formats.

/**
 * Creates Integrity from hex-formatted hash
 * @param {string} hexDigest - Hex string of hash digest
 * @param {string} algorithm - Hash algorithm name
 * @param {object} opts - Optional configuration
 * @param {string[]} opts.options - Option strings to add
 * @param {boolean} opts.strict - Use strict mode
 * @param {boolean} opts.single - Return single Hash instead of Integrity
 * @returns {Integrity|Hash} Generated integrity or hash object
 */
function fromHex(hexDigest, algorithm, opts);

Usage Examples:

const ssri = require('ssri');
const crypto = require('crypto');

// Convert existing hex hash to SRI format
const hexHash = crypto.createHash('sha256').update('hello').digest('hex');
const integrity = ssri.fromHex(hexHash, 'sha256');
console.log(integrity.toString());
// -> 'sha256-LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ='

// With options
const withOptions = ssri.fromHex('deadbeef', 'sha1', {
  options: ['legacy-hash']
});
console.log(withOptions.toString());
// -> 'sha1-3q2+7w==?legacy-hash'

// Return single Hash instead of Integrity
const singleHash = ssri.fromHex('abcd1234', 'sha256', { single: true });
console.log(singleHash.algorithm); // 'sha256'
console.log(singleHash.hexDigest()); // 'abcd1234'

// Converting from other systems
const md5Hash = 'd41d8cd98f00b204e9800998ecf8427e'; // empty string MD5
const md5Integrity = ssri.fromHex(md5Hash, 'md5');

Create Function

Creates a hash builder object that mimics Node.js crypto.Hash interface for incremental hashing.

/**
 * Creates hash builder with update/digest pattern
 * @param {object} opts - Optional configuration (same as fromData)
 * @returns {object} Hash builder with update() and digest() methods
 */
function create(opts);

interface HashBuilder {
  /**
   * Updates hash with new data chunk
   * @param {string|Buffer} chunk - Data to add
   * @param {string} enc - Encoding for string data
   * @returns {HashBuilder} This builder for chaining
   */
  update(chunk, enc);

  /**
   * Finalizes hash and returns Integrity object
   * @returns {Integrity} Generated integrity object
   */
  digest();
}

Usage Examples:

const ssri = require('ssri');

// Incremental hashing
const hasher = ssri.create();
hasher.update('Hello, ');
hasher.update('world!');
const integrity = hasher.digest();
console.log(integrity.toString());

// Stream-like usage
const builder = ssri.create({ algorithms: ['sha256', 'sha512'] });
const chunks = ['chunk1', 'chunk2', 'chunk3'];
chunks.forEach(chunk => builder.update(chunk));
const result = builder.digest();

// Processing form data
const formHasher = ssri.create();
formHasher.update('field1=value1&');
formHasher.update('field2=value2&');
formHasher.update('field3=value3');
const formIntegrity = formHasher.digest();

// Compatible with crypto.Hash pattern
function hashData(data) {
  return ssri.create()
    .update(data)
    .digest();
}

Generation Options

Algorithm Selection

interface GenerationOptions {
  /** Algorithms to use for hash generation */
  algorithms?: string[];  // Default: ['sha512']
  
  /** Option strings to append to generated hashes */
  options?: string[];     // Default: undefined
  
  /** Use strict SRI spec compliance */
  strict?: boolean;       // Default: false
}

Available Algorithms:

// Standard SRI algorithms (recommended)
['sha256', 'sha384', 'sha512']

// Extended algorithms (when not in strict mode)
crypto.getHashes() // All Node.js supported algorithms

Custom Options

// Add custom metadata to hashes
const integrity = ssri.fromData(data, {
  algorithms: ['sha384'],
  options: ['cors', 'version=1.2.3', 'env=prod']
});
// Result: 'sha384-abc...?cors?version=1.2.3?env=prod'

Performance Considerations

// Single algorithm for performance
const fast = ssri.fromData(largeData, { algorithms: ['sha256'] });

// Multiple algorithms for security (more CPU intensive)
const secure = ssri.fromData(sensitiveData, { 
  algorithms: ['sha256', 'sha384', 'sha512'] 
});

// Stream processing for large files (memory efficient)
const streamIntegrity = await ssri.fromStream(
  fs.createReadStream('./huge-file.bin'),
  { algorithms: ['sha512'] }
);

Error Handling

Generation functions are generally robust but can encounter these scenarios:

// Stream errors propagate to Promise rejection
ssri.fromStream(badStream)
  .catch(err => {
    console.error('Stream error:', err.message);
    // Handle stream read errors, network issues, etc.
  });

// Invalid algorithm names silently ignored in permissive mode
const partial = ssri.fromData('test', { 
  algorithms: ['sha256', 'invalid-algo', 'sha512'] 
});
// Only generates sha256 and sha512 hashes

// Strict mode validation
const strict = ssri.fromData('test', { 
  algorithms: ['md5'], 
  strict: true 
});
// May not include md5 if not in SPEC_ALGORITHMS

Integration Patterns

Package Manager Integration

// Generate package integrity
const packageIntegrity = ssri.fromData(
  fs.readFileSync('./package.tgz'),
  { algorithms: ['sha512'] }
);

// Store in package-lock.json format
const lockEntry = {
  integrity: packageIntegrity.toString(),
  // ... other metadata
};

CDN Resource Verification

// Generate integrity for CDN resources
const cdnResource = await fetch('https://cdn.example.com/lib.js');
const resourceData = await cdnResource.text();
const cdnIntegrity = ssri.fromData(resourceData, {
  algorithms: ['sha384'] // Common for CDN SRI
});

// Use in HTML
console.log(`<script src="https://cdn.example.com/lib.js" 
  integrity="${cdnIntegrity.toString()}" 
  crossorigin="anonymous"></script>`);

Build System Integration

// Generate integrity hashes during build
const buildFiles = glob.sync('./dist/**/*.{js,css}');
const integrityMap = {};

buildFiles.forEach(file => {
  const content = fs.readFileSync(file);
  integrityMap[file] = ssri.fromData(content, {
    algorithms: ['sha384']
  }).toString();
});

fs.writeFileSync('./dist/integrity.json', JSON.stringify(integrityMap));

Install with Tessl CLI

npx tessl i tessl/npm-ssri

docs

generation.md

index.md

parsing-serialization.md

verification.md

tile.json