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/eddsa')(); 12 13async function testVerify({ name, 14 publicKeyBuffer, 15 privateKeyBuffer, 16 signature, 17 data }) { 18 const [ 19 publicKey, 20 noVerifyPublicKey, 21 privateKey, 22 hmacKey, 23 rsaKeys, 24 ecKeys, 25 ] = await Promise.all([ 26 subtle.importKey( 27 'spki', 28 publicKeyBuffer, 29 { name }, 30 false, 31 ['verify']), 32 subtle.importKey( 33 'spki', 34 publicKeyBuffer, 35 { name }, 36 false, 37 [ /* No usages */ ]), 38 subtle.importKey( 39 'pkcs8', 40 privateKeyBuffer, 41 { name }, 42 false, 43 ['sign']), 44 subtle.generateKey( 45 { name: 'HMAC', hash: 'SHA-256' }, 46 false, 47 ['sign']), 48 subtle.generateKey( 49 { 50 name: 'RSA-PSS', 51 modulusLength: 1024, 52 publicExponent: new Uint8Array([1, 0, 1]), 53 hash: 'SHA-256', 54 }, 55 false, 56 ['sign']), 57 subtle.generateKey( 58 { 59 name: 'ECDSA', 60 namedCurve: 'P-256' 61 }, 62 false, 63 ['sign']), 64 ]); 65 66 assert(await subtle.verify({ name }, publicKey, signature, data)); 67 68 // Test verification with altered buffers 69 const copy = Buffer.from(data); 70 const sigcopy = Buffer.from(signature); 71 const p = subtle.verify({ name }, publicKey, sigcopy, copy); 72 copy[0] = 255 - copy[0]; 73 sigcopy[0] = 255 - sigcopy[0]; 74 assert(await p); 75 76 // Test failure when using wrong key 77 await assert.rejects( 78 subtle.verify({ name }, privateKey, signature, data), { 79 message: /Unable to use this key to verify/ 80 }); 81 82 await assert.rejects( 83 subtle.verify({ name }, noVerifyPublicKey, signature, data), { 84 message: /Unable to use this key to verify/ 85 }); 86 87 // Test failure when using the wrong algorithms 88 await assert.rejects( 89 subtle.verify({ name }, hmacKey, signature, data), { 90 message: /Unable to use this key to verify/ 91 }); 92 93 await assert.rejects( 94 subtle.verify({ name }, rsaKeys.publicKey, signature, data), { 95 message: /Unable to use this key to verify/ 96 }); 97 98 await assert.rejects( 99 subtle.verify({ name }, ecKeys.publicKey, signature, data), { 100 message: /Unable to use this key to verify/ 101 }); 102 103 // Test failure when signature is altered 104 { 105 const copy = Buffer.from(signature); 106 copy[0] = 255 - copy[0]; 107 assert(!(await subtle.verify( 108 { name }, 109 publicKey, 110 copy, 111 data))); 112 assert(!(await subtle.verify( 113 { name }, 114 publicKey, 115 copy.slice(1), 116 data))); 117 } 118 119 // Test failure when data is altered 120 { 121 const copy = Buffer.from(data); 122 copy[0] = 255 - copy[0]; 123 assert(!(await subtle.verify({ name }, publicKey, signature, copy))); 124 } 125} 126 127async function testSign({ name, 128 publicKeyBuffer, 129 privateKeyBuffer, 130 signature, 131 data }) { 132 const [ 133 publicKey, 134 privateKey, 135 hmacKey, 136 rsaKeys, 137 ecKeys, 138 ] = await Promise.all([ 139 subtle.importKey( 140 'spki', 141 publicKeyBuffer, 142 { name }, 143 false, 144 ['verify']), 145 subtle.importKey( 146 'pkcs8', 147 privateKeyBuffer, 148 { name }, 149 false, 150 ['sign']), 151 subtle.generateKey( 152 { name: 'HMAC', hash: 'SHA-256' }, 153 false, 154 ['sign']), 155 subtle.generateKey( 156 { 157 name: 'RSA-PSS', 158 modulusLength: 1024, 159 publicExponent: new Uint8Array([1, 0, 1]), 160 hash: 'SHA-256', 161 }, 162 false, 163 ['sign']), 164 subtle.generateKey( 165 { 166 name: 'ECDSA', 167 namedCurve: 'P-256' 168 }, 169 false, 170 ['sign']), 171 ]); 172 173 { 174 const sig = await subtle.sign({ name }, privateKey, data); 175 assert.strictEqual(sig.byteLength, signature.byteLength); 176 assert(await subtle.verify({ name }, publicKey, sig, data)); 177 } 178 179 { 180 const copy = Buffer.from(data); 181 const p = subtle.sign({ name }, privateKey, copy); 182 copy[0] = 255 - copy[0]; 183 const sig = await p; 184 assert(await subtle.verify({ name }, publicKey, sig, data)); 185 } 186 187 // Test failure when using wrong key 188 await assert.rejects( 189 subtle.sign({ name }, publicKey, data), { 190 message: /Unable to use this key to sign/ 191 }); 192 193 // Test failure when using the wrong algorithms 194 await assert.rejects( 195 subtle.sign({ name }, hmacKey, data), { 196 message: /Unable to use this key to sign/ 197 }); 198 199 await assert.rejects( 200 subtle.sign({ name }, rsaKeys.privateKey, data), { 201 message: /Unable to use this key to sign/ 202 }); 203 204 await assert.rejects( 205 subtle.sign({ name }, ecKeys.privateKey, data), { 206 message: /Unable to use this key to sign/ 207 }); 208} 209 210(async function() { 211 const variations = []; 212 213 vectors.forEach((vector) => { 214 variations.push(testVerify(vector)); 215 variations.push(testSign(vector)); 216 }); 217 218 await Promise.all(variations); 219})().then(common.mustCall()); 220 221// Ed448 context 222{ 223 const vector = vectors.find(({ name }) => name === 'Ed448'); 224 Promise.all([ 225 subtle.importKey( 226 'pkcs8', 227 vector.privateKeyBuffer, 228 { name: 'Ed448' }, 229 false, 230 ['sign']), 231 subtle.importKey( 232 'spki', 233 vector.publicKeyBuffer, 234 { name: 'Ed448' }, 235 false, 236 ['verify']), 237 ]).then(async ([privateKey, publicKey]) => { 238 const sig = await subtle.sign({ name: 'Ed448', context: Buffer.alloc(0) }, privateKey, vector.data); 239 assert.deepStrictEqual(Buffer.from(sig), vector.signature); 240 assert.strictEqual( 241 await subtle.verify({ name: 'Ed448', context: Buffer.alloc(0) }, publicKey, sig, vector.data), true); 242 243 await assert.rejects(subtle.sign({ name: 'Ed448', context: Buffer.alloc(1) }, privateKey, vector.data), { 244 message: /Non zero-length context is not yet supported/ 245 }); 246 await assert.rejects(subtle.verify({ name: 'Ed448', context: Buffer.alloc(1) }, publicKey, sig, vector.data), { 247 message: /Non zero-length context is not yet supported/ 248 }); 249 }).then(common.mustCall()); 250} 251