1// Flags: --expose-internals --no-warnings 2'use strict'; 3 4const common = require('../common'); 5 6if (!common.hasCrypto) 7 common.skip('missing crypto'); 8 9const assert = require('assert'); 10const { subtle } = require('crypto').webcrypto; 11 12// This is only a partial test. The WebCrypto Web Platform Tests 13// will provide much greater coverage. 14 15// Test ECDH bit derivation 16{ 17 async function test(namedCurve) { 18 const [alice, bob] = await Promise.all([ 19 subtle.generateKey({ name: 'ECDH', namedCurve }, true, ['deriveBits']), 20 subtle.generateKey({ name: 'ECDH', namedCurve }, true, ['deriveBits']), 21 ]); 22 23 const [secret1, secret2] = await Promise.all([ 24 subtle.deriveBits({ 25 name: 'ECDH', namedCurve, public: alice.publicKey 26 }, bob.privateKey, 128), 27 subtle.deriveBits({ 28 name: 'ECDH', namedCurve, public: bob.publicKey 29 }, alice.privateKey, 128), 30 ]); 31 32 assert(secret1 instanceof ArrayBuffer); 33 assert(secret2 instanceof ArrayBuffer); 34 assert.deepStrictEqual(secret1, secret2); 35 } 36 37 test('P-521').then(common.mustCall()); 38} 39 40// Test HKDF bit derivation 41{ 42 async function test(pass, info, salt, hash, length, expected) { 43 const ec = new TextEncoder(); 44 const key = await subtle.importKey( 45 'raw', 46 ec.encode(pass), 47 { name: 'HKDF', hash }, 48 false, ['deriveBits']); 49 const secret = await subtle.deriveBits({ 50 name: 'HKDF', 51 hash, 52 salt: ec.encode(salt), 53 info: ec.encode(info) 54 }, key, length); 55 assert.strictEqual(Buffer.from(secret).toString('hex'), expected); 56 } 57 58 const kTests = [ 59 ['hello', 'there', 'my friend', 'SHA-256', 512, 60 '14d93b0ccd99d4f2cbd9fbfe9c830b5b8a43e3e45e329' + 61 '41ef21bdeb0fa87b6b6bfa5c54466aa5bf76cdc2685fb' + 62 'a4408ea5b94c049fe035649b46f92fdc519374'], 63 ['hello', 'there', 'my friend', 'SHA-384', 128, 64 'e36cf2cf943d8f3a88adb80f478745c3'], 65 ]; 66 67 const tests = Promise.all(kTests.map((args) => test(...args))); 68 69 tests.then(common.mustCall()); 70} 71 72// Test PBKDF2 bit derivation 73{ 74 async function test(pass, salt, iterations, hash, length, expected) { 75 const ec = new TextEncoder(); 76 const key = await subtle.importKey( 77 'raw', 78 ec.encode(pass), 79 { name: 'PBKDF2', hash }, 80 false, ['deriveBits']); 81 const secret = await subtle.deriveBits({ 82 name: 'PBKDF2', 83 hash, 84 salt: ec.encode(salt), 85 iterations, 86 }, key, length); 87 assert.strictEqual(Buffer.from(secret).toString('hex'), expected); 88 } 89 90 const kTests = [ 91 ['hello', 'there', 10, 'SHA-256', 512, 92 'f72d1cf4853fffbd16a42751765d11f8dc7939498ee7b7' + 93 'ce7678b4cb16fad88098110a83e71f4483ce73203f7a64' + 94 '719d293280f780f9fafdcf46925c5c0588b3'], 95 ['hello', 'there', 5, 'SHA-384', 128, 96 '201509b012c9cd2fbe7ea938f0c509b3'], 97 ]; 98 99 const tests = Promise.all(kTests.map((args) => test(...args))); 100 101 tests.then(common.mustCall()); 102} 103 104// Test X25519 and X448 bit derivation 105{ 106 async function test(name) { 107 const [alice, bob] = await Promise.all([ 108 subtle.generateKey({ name }, true, ['deriveBits']), 109 subtle.generateKey({ name }, true, ['deriveBits']), 110 ]); 111 112 const [secret1, secret2] = await Promise.all([ 113 subtle.deriveBits({ 114 name, public: alice.publicKey 115 }, bob.privateKey, 128), 116 subtle.deriveBits({ 117 name, public: bob.publicKey 118 }, alice.privateKey, 128), 119 ]); 120 121 assert(secret1 instanceof ArrayBuffer); 122 assert(secret2 instanceof ArrayBuffer); 123 assert.deepStrictEqual(secret1, secret2); 124 } 125 126 test('X25519').then(common.mustCall()); 127 test('X448').then(common.mustCall()); 128} 129