Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 1x 3051x 3051x 1450x 1449x 1448x 1447x 1446x 1446x 1446x 804x 803x 802x 801x 800x 800x 800x 3051x 3051x 3051x 3051x 60x 60x 60x 60x 60x 60x 1x | const crypto = require('crypto') /* Encrypts a 32-byte buffer using AES-256-ECB with the given 32-byte key */ // Internal use only function getWebCrypto () { const globalWebCrypto = typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle // Fallback for Node 16, which does not expose WebCrypto as a global /* istanbul ignore next */ const webCrypto = globalWebCrypto || crypto.webcrypto.subtle return webCrypto } /* Encrypts a 32-byte buffer using AES-256-ECB with the given 32-byte key */ // Internal use only function encrypt (data, key) { if (!Buffer.isBuffer(data)) throw new TypeError('data must be a buffer') if (data.length !== 32) throw new RangeError('data must be 32 bytes') if (!Buffer.isBuffer(key)) throw new TypeError('key must be a buffer') if (key.length !== 32) throw new RangeError('key must be 32 bytes') const cipher = crypto.createCipheriv('AES-256-ECB', key, '') cipher.setAutoPadding(false) return Buffer.concat([cipher.update(data), cipher.final()]) } /* Decrypts a 32-byte buffer using AES-256-ECB with the given 32-byte key */ // Internal use only function decrypt (data, key) { if (!Buffer.isBuffer(data)) throw new TypeError('data must be a buffer') if (data.length !== 32) throw new RangeError('data must be 32 bytes') if (!Buffer.isBuffer(key)) throw new TypeError('key must be a buffer') if (key.length !== 32) throw new RangeError('key must be 32 bytes') const decipher = crypto.createDecipheriv('AES-256-ECB', key, '') decipher.setAutoPadding(false) return Buffer.concat([decipher.update(data), decipher.final()]) } /* Derives a key using HKDF with the given parameters */ // Internal use only async function hkdf (hash, key, salt, purpose, size) { const webCrypto = getWebCrypto() const importedKey = await webCrypto.importKey('raw', key, 'HKDF', false, [ 'deriveBits' ]) const bits = await webCrypto.deriveBits( { name: 'HKDF', hash: 'SHA-256', salt: Buffer.from(salt), info: Buffer.from(purpose) }, importedKey, size * 8 ) return Buffer.from(bits) } /* Get a cryptographically secure random integer in range */ /* Inclusive of min, exclusive of max */ // Internal use only async function random (min, max) { // Calculate the range size const range = max - min // Generate random bytes until we get a value in our desired range while (true) { // Generate random bytes const randomArray = new Uint32Array(1) globalThis.crypto.getRandomValues(randomArray) const randomValue = randomArray[0] // Calculate the number of complete sets of 'range' in our random value space const sets = Math.floor(2 ** 32 / range) // If the value is within our valid range, return it /* istanbul ignore next */ if (randomValue < sets * range) { return min + (randomValue % range) } // Otherwise, try again to avoid bias } } module.exports = { encrypt, decrypt, hkdf, random } |