1'use strict'; 2const common = require('../common'); 3if (!common.hasCrypto) 4 common.skip('missing crypto'); 5 6const assert = require('assert'); 7 8const crypto = require('crypto'); 9 10// Tests for CVE-2022-21449 11// https://neilmadden.blog/2022/04/19/psychic-signatures-in-java/ 12// Dubbed "Psychic Signatures", these signatures bypassed the ECDSA signature 13// verification implementation in Java in 15, 16, 17, and 18. OpenSSL is not 14// (and was not) vulnerable so these are a precaution. 15 16const vectors = { 17 'ieee-p1363': [ 18 Buffer.from('0000000000000000000000000000000000000000000000000000000000000000' + 19 '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), 20 Buffer.from('ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551' + 21 'ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551', 'hex'), 22 ], 23 'der': [ 24 Buffer.from('3046022100' + 25 '0000000000000000000000000000000000000000000000000000000000000000' + 26 '022100' + 27 '0000000000000000000000000000000000000000000000000000000000000000', 'hex'), 28 Buffer.from('3046022100' + 29 'ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551' + 30 '022100' + 31 'ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551', 'hex'), 32 ], 33}; 34 35const keyPair = crypto.generateKeyPairSync('ec', { 36 namedCurve: 'P-256', 37 publicKeyEncoding: { 38 format: 'der', 39 type: 'spki' 40 }, 41}); 42 43const data = Buffer.from('Hello!'); 44 45for (const [encoding, signatures] of Object.entries(vectors)) { 46 for (const signature of signatures) { 47 const key = { 48 key: keyPair.publicKey, 49 format: 'der', 50 type: 'spki', 51 dsaEncoding: encoding, 52 }; 53 54 // one-shot sync 55 assert.strictEqual( 56 crypto.verify( 57 'sha256', 58 data, 59 key, 60 signature, 61 ), 62 false, 63 ); 64 65 // one-shot async 66 crypto.verify( 67 'sha256', 68 data, 69 key, 70 signature, 71 common.mustSucceed((verified) => assert.strictEqual(verified, false)), 72 ); 73 74 // stream 75 assert.strictEqual( 76 crypto.createVerify('sha256') 77 .update(data) 78 .verify(key, signature), 79 false, 80 ); 81 82 // webcrypto 83 crypto.webcrypto.subtle.importKey( 84 'spki', 85 keyPair.publicKey, 86 { name: 'ECDSA', namedCurve: 'P-256' }, 87 false, 88 ['verify'], 89 ).then((publicKey) => { 90 return crypto.webcrypto.subtle.verify( 91 { name: 'ECDSA', hash: 'SHA-256' }, 92 publicKey, 93 signature, 94 data, 95 ); 96 }).then(common.mustCall((verified) => { 97 assert.strictEqual(verified, false); 98 })); 99 } 100} 101