1'use strict'; 2 3const common = require('../common'); 4 5if (!common.hasCrypto) 6 common.skip('missing crypto'); 7 8const assert = require('assert'); 9const { Buffer } = require('buffer'); 10const { subtle } = require('crypto').webcrypto; 11const { createHash } = require('crypto'); 12 13const kTests = [ 14 ['SHA-1', 'sha1', 160], 15 ['SHA-256', 'sha256', 256], 16 ['SHA-384', 'sha384', 384], 17 ['SHA-512', 'sha512', 512], 18]; 19 20// Empty hash just works, not checking result 21subtle.digest('SHA-512', Buffer.alloc(0)) 22 .then(common.mustCall()); 23 24// TODO(@jasnell): Need to move this particular test to pummel 25// // Careful, this is an expensive operation because of both the memory 26// // allocation and the cost of performing the hash on such a large 27// // input. 28// subtle.digest('SHA-512', new ArrayBuffer(2 ** 31 - 1)) 29// .then(common.mustCall()); 30 31// TODO(@jasnell): Change max to 2 ** 31 - 1 32// assert.rejects(subtle.digest('SHA-512', new ArrayBuffer(kMaxLength + 1)), { 33// code: 'ERR_OUT_OF_RANGE' 34// }); 35 36const kData = (new TextEncoder()).encode('hello'); 37(async function() { 38 await Promise.all(kTests.map(async (test) => { 39 // Get the digest using the legacy crypto API 40 const checkValue = 41 createHash(test[1]).update(kData).digest().toString('hex'); 42 43 // Get the digest using the SubtleCrypto API 44 const values = Promise.all([ 45 subtle.digest({ name: test[0] }, kData), 46 subtle.digest({ name: test[0], length: test[2] }, kData), 47 subtle.digest(test[0], kData), 48 subtle.digest(test[0], kData.buffer), 49 subtle.digest(test[0], new DataView(kData.buffer)), 50 subtle.digest(test[0], Buffer.from(kData)), 51 ]); 52 53 // subtle.digest copies the input data, so changing it 54 // while we're waiting on the Promises should never 55 // cause the test to fail. 56 kData[0] = 0x1; 57 kData[2] = 0x2; 58 kData[4] = 0x3; 59 60 // Compare that the legacy crypto API and SubtleCrypto API 61 // produce the same results 62 (await values).forEach((v) => { 63 assert(v instanceof ArrayBuffer); 64 assert.strictEqual(checkValue, Buffer.from(v).toString('hex')); 65 }); 66 })); 67})().then(common.mustCall()); 68 69Promise.all([1, null, undefined].map((i) => 70 assert.rejects(subtle.digest(i, Buffer.alloc(0)), { 71 message: /Unrecognized algorithm name/, 72 name: 'NotSupportedError', 73 }) 74)).then(common.mustCall()); 75 76assert.rejects(subtle.digest('', Buffer.alloc(0)), { 77 message: /Unrecognized algorithm name/, 78 name: 'NotSupportedError', 79}).then(common.mustCall()); 80 81Promise.all([1, [], {}, null, undefined].map((i) => 82 assert.rejects(subtle.digest('SHA-256', i), { 83 code: 'ERR_INVALID_ARG_TYPE' 84 }) 85)).then(common.mustCall()); 86 87const kSourceData = { 88 empty: '', 89 short: '156eea7cc14c56cb94db030a4a9d95ff', 90 medium: 'b6c8f9df648cd088b70f38e74197b18cb81e1e435' + 91 '0d50bccb8fb5a7379c87bb2e3d6ed5461ed1e9f36' + 92 'f340a3962a446b815b794b4bd43a4403502077b22' + 93 '56cc807837f3aacd118eb4b9c2baeb897068625ab' + 94 'aca193', 95 long: null 96}; 97 98kSourceData.long = kSourceData.medium.repeat(1024); 99 100const kDigestedData = { 101 'sha-1': { 102 empty: 'da39a3ee5e6b4b0d3255bfef95601890afd80709', 103 short: 'c91318cdf2396a015e3f4e6a86a0ba65b8635944', 104 medium: 'e541060870eb16bf33b68e51f513526893986729', 105 long: '3098b50037ecd02ebd657653b2bfa01eee27a2ea' 106 }, 107 'sha-256': { 108 empty: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 109 short: 'a2831186984792c7d32d59c89740687f19addc1b959e71a1cc538a3b7ed843f2', 110 medium: '535367877ef014d7fc717e5cb7843e59b61aee62c7029cec7ec6c12fd924e0e4', 111 long: '14cdea9dc75f5a6274d9fc1e64009912f1dcd306b48fe8e9cf122de671571781' 112 }, 113 'sha-384': { 114 empty: '38b060a751ac96384cd9327eb1b1e36a21fdb71114b' + 115 'e07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2' + 116 'f14898b95b', 117 short: '6bf5ea6524d1cddc43f7cf3b56ee059227404a2f538' + 118 'f022a3db7447a782c06c1ed05e8ab4f5edc17f37114' + 119 '40dfe97731', 120 medium: 'cbc2c588fe5b25f916da28b4e47a484ae6fc1fe490' + 121 '2dd5c9939a6bfd034ab3b48b39087436011f6a9987' + 122 '9d279540e977', 123 long: '49f4fdb3981968f97d57370f85345067cd5296a97dd1' + 124 'a18e06911e756e9608492529870e1ad130998d57cbfb' + 125 'b7c1d09e' 126 }, 127 'sha-512': { 128 empty: 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5' + 129 '715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318' + 130 'd2877eec2f63b931bd47417a81a538327af927da3e', 131 short: '375248be5ff34be74cab4ff1c3bc8dc68bd5f8dff40' + 132 '23e98f87b865cff2c724292df189443a64ff4134a65' + 133 'cd4635b9d4f5dc0d3fb67528002a63acf26c9da575', 134 medium: 'b9109f839e8ea43c890f293ce11dc6e2798d1e2431' + 135 'f1e4b919e3b20c4f36303ba39c916db306c45a3b65' + 136 '761ff5be85328eeaf42c3830f1d95e7a41165b7d2d36', 137 long: '4b02caf650276030ea5617e597c5d53fd9daa68b78bfe' + 138 '60b22aab8d36a4c2a3affdb71234f49276737c575ddf7' + 139 '4d14054cbd6fdb98fd0ddcbcb46f91ad76b6ee' 140 } 141}; 142 143async function testDigest(size, name) { 144 const digest = await subtle.digest( 145 name, 146 Buffer.from(kSourceData[size], 'hex')); 147 148 assert.strictEqual( 149 Buffer.from(digest).toString('hex'), 150 kDigestedData[name.toLowerCase()][size]); 151} 152 153(async function() { 154 const variations = []; 155 Object.keys(kSourceData).forEach((size) => { 156 Object.keys(kDigestedData).forEach((alg) => { 157 const upCase = alg.toUpperCase(); 158 const downCase = alg.toLowerCase(); 159 const mixedCase = upCase.substr(0, 1) + downCase.substr(1); 160 161 variations.push(testDigest(size, upCase)); 162 variations.push(testDigest(size, downCase)); 163 variations.push(testDigest(size, mixedCase)); 164 }); 165 }); 166 167 await Promise.all(variations); 168})().then(common.mustCall()); 169 170(async () => { 171 await assert.rejects(subtle.digest('RSA-OAEP', Buffer.alloc(1)), { 172 name: 'NotSupportedError', 173 }); 174})().then(common.mustCall()); 175