1'use strict'; 2 3const common = require('../common'); 4 5if (!common.hasCrypto) 6 common.skip('missing crypto'); 7 8const assert = require('assert'); 9const { subtle } = require('crypto').webcrypto; 10 11const vectors = require('../fixtures/crypto/hmac')(); 12 13async function testVerify({ hash, 14 keyBuffer, 15 signature, 16 plaintext }) { 17 const name = 'HMAC'; 18 const [ 19 key, 20 noVerifyKey, 21 rsaKeys, 22 ] = await Promise.all([ 23 subtle.importKey( 24 'raw', 25 keyBuffer, 26 { name, hash }, 27 false, 28 ['verify']), 29 subtle.importKey( 30 'raw', 31 keyBuffer, 32 { name, hash }, 33 false, 34 ['sign']), 35 subtle.generateKey( 36 { 37 name: 'RSA-PSS', 38 modulusLength: 1024, 39 publicExponent: new Uint8Array([1, 0, 1]), 40 hash: 'SHA-256', 41 }, 42 false, 43 ['sign']), 44 ]); 45 46 assert(await subtle.verify({ name, hash }, key, signature, plaintext)); 47 48 // Test verification with altered buffers 49 const copy = Buffer.from(plaintext); 50 const sigcopy = Buffer.from(signature); 51 const p = subtle.verify({ name, hash }, key, sigcopy, copy); 52 copy[0] = 255 - copy[0]; 53 sigcopy[0] = 255 - sigcopy[0]; 54 assert(await p); 55 56 // Test failure when using wrong key 57 await assert.rejects( 58 subtle.verify({ name, hash }, noVerifyKey, signature, plaintext), { 59 message: /Unable to use this key to verify/ 60 }); 61 62 // Test failure when using the wrong algorithms 63 await assert.rejects( 64 subtle.verify({ name, hash }, rsaKeys.publicKey, signature, plaintext), { 65 message: /Unable to use this key to verify/ 66 }); 67 68 // Test failure when signature is altered 69 { 70 const copy = Buffer.from(signature); 71 copy[0] = 255 - copy[0]; 72 assert(!(await subtle.verify( 73 { name, hash }, 74 key, 75 copy, 76 plaintext))); 77 assert(!(await subtle.verify( 78 { name, hash }, 79 key, 80 copy.slice(1), 81 plaintext))); 82 } 83 84 // Test failure when data is altered 85 { 86 const copy = Buffer.from(plaintext); 87 copy[0] = 255 - copy[0]; 88 assert(!(await subtle.verify({ name, hash }, key, signature, copy))); 89 } 90 91 // Test failure when wrong hash is used 92 { 93 const otherhash = hash === 'SHA-1' ? 'SHA-256' : 'SHA-1'; 94 const keyWithOtherHash = await subtle.importKey( 95 'raw', 96 keyBuffer, 97 { name, hash: otherhash }, 98 false, 99 ['verify']); 100 assert(!(await subtle.verify({ name }, keyWithOtherHash, signature, plaintext))); 101 } 102} 103 104async function testSign({ hash, 105 keyBuffer, 106 signature, 107 plaintext }) { 108 const name = 'HMAC'; 109 const [ 110 key, 111 noSignKey, 112 rsaKeys, 113 ] = await Promise.all([ 114 subtle.importKey( 115 'raw', 116 keyBuffer, 117 { name, hash }, 118 false, 119 ['verify', 'sign']), 120 subtle.importKey( 121 'raw', 122 keyBuffer, 123 { name, hash }, 124 false, 125 [ 'verify' ]), 126 subtle.generateKey( 127 { 128 name: 'RSA-PSS', 129 modulusLength: 1024, 130 publicExponent: new Uint8Array([1, 0, 1]), 131 hash: 'SHA-256', 132 }, 133 false, 134 ['sign']), 135 ]); 136 137 { 138 const sig = await subtle.sign({ name, hash }, key, plaintext); 139 assert.strictEqual( 140 Buffer.from(sig).toString('hex'), 141 signature.toString('hex')); 142 assert(await subtle.verify({ name, hash }, key, sig, plaintext)); 143 } 144 145 { 146 const copy = Buffer.from(plaintext); 147 const p = subtle.sign({ name, hash }, key, copy); 148 copy[0] = 255 - copy[0]; 149 const sig = await p; 150 assert(await subtle.verify({ name, hash }, key, sig, plaintext)); 151 } 152 153 await assert.rejects( 154 subtle.generateKey({ name }, false, ['sign', 'verify']), { 155 name: 'TypeError', 156 code: 'ERR_MISSING_OPTION', 157 }); 158 159 // Test failure when no sign usage 160 await assert.rejects( 161 subtle.sign({ name, hash }, noSignKey, plaintext), { 162 message: /Unable to use this key to sign/ 163 }); 164 165 // Test failure when using the wrong algorithms 166 await assert.rejects( 167 subtle.sign({ name, hash }, rsaKeys.privateKey, plaintext), { 168 message: /Unable to use this key to sign/ 169 }); 170} 171 172(async function() { 173 const variations = []; 174 175 vectors.forEach((vector) => { 176 variations.push(testVerify(vector)); 177 variations.push(testSign(vector)); 178 }); 179 180 await Promise.all(variations); 181})().then(common.mustCall()); 182