1'use strict'; 2 3const common = require('../common.js'); 4const crypto = require('crypto'); 5const fs = require('fs'); 6const path = require('path'); 7const fixtures_keydir = path.resolve(__dirname, '../../test/fixtures/keys/'); 8 9const keyFixtures = { 10 ec: fs.readFileSync(`${fixtures_keydir}/ec_p256_private.pem`, 'utf-8'), 11 rsa: fs.readFileSync(`${fixtures_keydir}/rsa_private_2048.pem`, 'utf-8'), 12 ed25519: fs.readFileSync(`${fixtures_keydir}/ed25519_private.pem`, 'utf-8'), 13}; 14 15const data = crypto.randomBytes(256); 16 17let pems; 18let keyObjects; 19 20const bench = common.createBenchmark(main, { 21 keyType: ['rsa', 'ec', 'ed25519'], 22 mode: ['sync', 'async', 'async-parallel'], 23 keyFormat: ['pem', 'der', 'jwk', 'keyObject', 'keyObject.unique'], 24 n: [1e3], 25}, { 26 combinationFilter(p) { 27 // "keyObject.unique" allows to compare the result with "keyObject" to 28 // assess whether mutexes over the key material impact the operation 29 return p.keyFormat !== 'keyObject.unique' || 30 (p.keyFormat === 'keyObject.unique' && p.mode === 'async-parallel'); 31 }, 32}); 33 34function measureSync(n, digest, privateKey, keys) { 35 bench.start(); 36 for (let i = 0; i < n; ++i) { 37 crypto.sign( 38 digest, 39 data, 40 privateKey || keys[i]); 41 } 42 bench.end(n); 43} 44 45function measureAsync(n, digest, privateKey, keys) { 46 let remaining = n; 47 function done() { 48 if (--remaining === 0) 49 bench.end(n); 50 else 51 one(); 52 } 53 54 function one() { 55 crypto.sign( 56 digest, 57 data, 58 privateKey || keys[n - remaining], 59 done); 60 } 61 bench.start(); 62 one(); 63} 64 65function measureAsyncParallel(n, digest, privateKey, keys) { 66 let remaining = n; 67 function done() { 68 if (--remaining === 0) 69 bench.end(n); 70 } 71 bench.start(); 72 for (let i = 0; i < n; ++i) { 73 crypto.sign( 74 digest, 75 data, 76 privateKey || keys[i], 77 done); 78 } 79} 80 81function main({ n, mode, keyFormat, keyType }) { 82 pems ||= [...Buffer.alloc(n)].map(() => keyFixtures[keyType]); 83 keyObjects ||= pems.map(crypto.createPrivateKey); 84 85 let privateKey, keys, digest; 86 87 switch (keyType) { 88 case 'rsa': 89 case 'ec': 90 digest = 'sha256'; 91 break; 92 case 'ed25519': 93 break; 94 default: 95 throw new Error('not implemented'); 96 } 97 98 switch (keyFormat) { 99 case 'keyObject': 100 privateKey = keyObjects[0]; 101 break; 102 case 'pem': 103 privateKey = pems[0]; 104 break; 105 case 'jwk': { 106 privateKey = { key: keyObjects[0].export({ format: 'jwk' }), format: 'jwk' }; 107 break; 108 } 109 case 'der': { 110 privateKey = { key: keyObjects[0].export({ format: 'der', type: 'pkcs8' }), format: 'der', type: 'pkcs8' }; 111 break; 112 } 113 case 'keyObject.unique': 114 keys = keyObjects; 115 break; 116 default: 117 throw new Error('not implemented'); 118 } 119 120 switch (mode) { 121 case 'sync': 122 measureSync(n, digest, privateKey, keys); 123 break; 124 case 'async': 125 measureAsync(n, digest, privateKey, keys); 126 break; 127 case 'async-parallel': 128 measureAsyncParallel(n, digest, privateKey, keys); 129 break; 130 } 131} 132