11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciif (!common.hasCrypto) 61cb0ef41Sopenharmony_ci common.skip('missing crypto'); 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ciconst assert = require('assert'); 91cb0ef41Sopenharmony_ciconst { webcrypto } = require('crypto'); 101cb0ef41Sopenharmony_ciconst { subtle } = webcrypto; 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciconst kTests = [ 131cb0ef41Sopenharmony_ci { 141cb0ef41Sopenharmony_ci name: 'X25519', 151cb0ef41Sopenharmony_ci size: 32, 161cb0ef41Sopenharmony_ci pkcs8: '302e020100300506032b656e04220420c8838e76d057dfb7d8c95a69e138160ad' + 171cb0ef41Sopenharmony_ci 'd6373fd71a4d276bb56e3a81b64ff61', 181cb0ef41Sopenharmony_ci spki: '302a300506032b656e0321001cf2b1e6022ec537371ed7f53e54fa1154d83e98eb' + 191cb0ef41Sopenharmony_ci '64ea51fae5b3307cfe9706', 201cb0ef41Sopenharmony_ci result: '2768409dfab99ec23b8c89b93ff5880295f76176088f89e43dfebe7ea1950008' 211cb0ef41Sopenharmony_ci }, 221cb0ef41Sopenharmony_ci { 231cb0ef41Sopenharmony_ci name: 'X448', 241cb0ef41Sopenharmony_ci size: 56, 251cb0ef41Sopenharmony_ci pkcs8: '3046020100300506032b656f043a043858c7d29a3eb519b29d00cfb191bb64fc6' + 261cb0ef41Sopenharmony_ci 'd8a42d8f17176272b89f2272d1819295c6525c0829671b052ef0727530f188e31' + 271cb0ef41Sopenharmony_ci 'd0cc53bf26929e', 281cb0ef41Sopenharmony_ci spki: '3042300506032b656f033900b604a1d1a5cd1d9426d561ef630a9eb16cbe69d5b9' + 291cb0ef41Sopenharmony_ci 'ca615edc53633efb52ea31e6e6a0a1dbacc6e76cbce6482d7e4ba3d55d9e802765' + 301cb0ef41Sopenharmony_ci 'ce6f', 311cb0ef41Sopenharmony_ci result: 'f0f6c5f17f94f4291eab7178866d37ec8906dd6c514143dc85be7cf28deff39b' + 321cb0ef41Sopenharmony_ci '726e0f6dcf810eb594dca97b4882bd44c43ea7dc67f49a4e', 331cb0ef41Sopenharmony_ci }, 341cb0ef41Sopenharmony_ci]; 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ciasync function prepareKeys() { 371cb0ef41Sopenharmony_ci const keys = {}; 381cb0ef41Sopenharmony_ci await Promise.all( 391cb0ef41Sopenharmony_ci kTests.map(async ({ name, size, pkcs8, spki, result }) => { 401cb0ef41Sopenharmony_ci const [ 411cb0ef41Sopenharmony_ci privateKey, 421cb0ef41Sopenharmony_ci publicKey, 431cb0ef41Sopenharmony_ci ] = await Promise.all([ 441cb0ef41Sopenharmony_ci subtle.importKey( 451cb0ef41Sopenharmony_ci 'pkcs8', 461cb0ef41Sopenharmony_ci Buffer.from(pkcs8, 'hex'), 471cb0ef41Sopenharmony_ci { name }, 481cb0ef41Sopenharmony_ci true, 491cb0ef41Sopenharmony_ci ['deriveKey', 'deriveBits']), 501cb0ef41Sopenharmony_ci subtle.importKey( 511cb0ef41Sopenharmony_ci 'spki', 521cb0ef41Sopenharmony_ci Buffer.from(spki, 'hex'), 531cb0ef41Sopenharmony_ci { name }, 541cb0ef41Sopenharmony_ci true, 551cb0ef41Sopenharmony_ci []), 561cb0ef41Sopenharmony_ci ]); 571cb0ef41Sopenharmony_ci keys[name] = { 581cb0ef41Sopenharmony_ci privateKey, 591cb0ef41Sopenharmony_ci publicKey, 601cb0ef41Sopenharmony_ci size, 611cb0ef41Sopenharmony_ci result, 621cb0ef41Sopenharmony_ci }; 631cb0ef41Sopenharmony_ci })); 641cb0ef41Sopenharmony_ci return keys; 651cb0ef41Sopenharmony_ci} 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci(async function() { 681cb0ef41Sopenharmony_ci const keys = await prepareKeys(); 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci await Promise.all( 711cb0ef41Sopenharmony_ci Object.keys(keys).map(async (name) => { 721cb0ef41Sopenharmony_ci const { size, result, privateKey, publicKey } = keys[name]; 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci { 751cb0ef41Sopenharmony_ci // Good parameters 761cb0ef41Sopenharmony_ci const bits = await subtle.deriveBits({ 771cb0ef41Sopenharmony_ci name, 781cb0ef41Sopenharmony_ci public: publicKey 791cb0ef41Sopenharmony_ci }, privateKey, 8 * size); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci assert(bits instanceof ArrayBuffer); 821cb0ef41Sopenharmony_ci assert.strictEqual(Buffer.from(bits).toString('hex'), result); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci { 861cb0ef41Sopenharmony_ci // Case insensitivity 871cb0ef41Sopenharmony_ci const bits = await subtle.deriveBits({ 881cb0ef41Sopenharmony_ci name: name.toLowerCase(), 891cb0ef41Sopenharmony_ci public: publicKey 901cb0ef41Sopenharmony_ci }, privateKey, 8 * size); 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci assert.strictEqual(Buffer.from(bits).toString('hex'), result); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci { 961cb0ef41Sopenharmony_ci // Null length 971cb0ef41Sopenharmony_ci const bits = await subtle.deriveBits({ 981cb0ef41Sopenharmony_ci name, 991cb0ef41Sopenharmony_ci public: publicKey 1001cb0ef41Sopenharmony_ci }, privateKey, null); 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci assert.strictEqual(Buffer.from(bits).toString('hex'), result); 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci { 1061cb0ef41Sopenharmony_ci // Short Result 1071cb0ef41Sopenharmony_ci const bits = await subtle.deriveBits({ 1081cb0ef41Sopenharmony_ci name, 1091cb0ef41Sopenharmony_ci public: publicKey 1101cb0ef41Sopenharmony_ci }, privateKey, 8 * size - 32); 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci assert.strictEqual( 1131cb0ef41Sopenharmony_ci Buffer.from(bits).toString('hex'), 1141cb0ef41Sopenharmony_ci result.slice(0, -8)); 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci { 1181cb0ef41Sopenharmony_ci // Too long result 1191cb0ef41Sopenharmony_ci await assert.rejects(subtle.deriveBits({ 1201cb0ef41Sopenharmony_ci name, 1211cb0ef41Sopenharmony_ci public: publicKey 1221cb0ef41Sopenharmony_ci }, privateKey, 8 * size + 8), { 1231cb0ef41Sopenharmony_ci message: /derived bit length is too small/ 1241cb0ef41Sopenharmony_ci }); 1251cb0ef41Sopenharmony_ci } 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci { 1281cb0ef41Sopenharmony_ci // Non-multiple of 8 1291cb0ef41Sopenharmony_ci const bits = await subtle.deriveBits({ 1301cb0ef41Sopenharmony_ci name, 1311cb0ef41Sopenharmony_ci public: publicKey 1321cb0ef41Sopenharmony_ci }, privateKey, 8 * size - 11); 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci assert.strictEqual( 1351cb0ef41Sopenharmony_ci Buffer.from(bits).toString('hex'), 1361cb0ef41Sopenharmony_ci result.slice(0, -2)); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci })); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci // Error tests 1411cb0ef41Sopenharmony_ci { 1421cb0ef41Sopenharmony_ci // Missing public property 1431cb0ef41Sopenharmony_ci await assert.rejects( 1441cb0ef41Sopenharmony_ci subtle.deriveBits( 1451cb0ef41Sopenharmony_ci { name: 'X448' }, 1461cb0ef41Sopenharmony_ci keys.X448.privateKey, 1471cb0ef41Sopenharmony_ci 8 * keys.X448.size), 1481cb0ef41Sopenharmony_ci { code: 'ERR_MISSING_OPTION' }); 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci { 1521cb0ef41Sopenharmony_ci // The public property is not a CryptoKey 1531cb0ef41Sopenharmony_ci await assert.rejects( 1541cb0ef41Sopenharmony_ci subtle.deriveBits( 1551cb0ef41Sopenharmony_ci { 1561cb0ef41Sopenharmony_ci name: 'X448', 1571cb0ef41Sopenharmony_ci public: { message: 'Not a CryptoKey' } 1581cb0ef41Sopenharmony_ci }, 1591cb0ef41Sopenharmony_ci keys.X448.privateKey, 1601cb0ef41Sopenharmony_ci 8 * keys.X448.size), 1611cb0ef41Sopenharmony_ci { code: 'ERR_INVALID_ARG_TYPE' }); 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci { 1651cb0ef41Sopenharmony_ci // Mismatched types 1661cb0ef41Sopenharmony_ci await assert.rejects( 1671cb0ef41Sopenharmony_ci subtle.deriveBits( 1681cb0ef41Sopenharmony_ci { 1691cb0ef41Sopenharmony_ci name: 'X448', 1701cb0ef41Sopenharmony_ci public: keys.X25519.publicKey 1711cb0ef41Sopenharmony_ci }, 1721cb0ef41Sopenharmony_ci keys.X448.privateKey, 1731cb0ef41Sopenharmony_ci 8 * keys.X448.size), 1741cb0ef41Sopenharmony_ci { message: 'The public and private keys must be of the same type' }); 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci { 1781cb0ef41Sopenharmony_ci // Base key is not a private key 1791cb0ef41Sopenharmony_ci await assert.rejects(subtle.deriveBits({ 1801cb0ef41Sopenharmony_ci name: 'X448', 1811cb0ef41Sopenharmony_ci public: keys.X448.publicKey 1821cb0ef41Sopenharmony_ci }, keys.X448.publicKey, null), { 1831cb0ef41Sopenharmony_ci name: 'InvalidAccessError' 1841cb0ef41Sopenharmony_ci }); 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci { 1881cb0ef41Sopenharmony_ci // Base key is not a private key 1891cb0ef41Sopenharmony_ci await assert.rejects(subtle.deriveBits({ 1901cb0ef41Sopenharmony_ci name: 'X448', 1911cb0ef41Sopenharmony_ci public: keys.X448.privateKey 1921cb0ef41Sopenharmony_ci }, keys.X448.publicKey, null), { 1931cb0ef41Sopenharmony_ci name: 'InvalidAccessError' 1941cb0ef41Sopenharmony_ci }); 1951cb0ef41Sopenharmony_ci } 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci { 1981cb0ef41Sopenharmony_ci // Public is a secret key 1991cb0ef41Sopenharmony_ci const keyData = webcrypto.getRandomValues(new Uint8Array(32)); 2001cb0ef41Sopenharmony_ci const key = await subtle.importKey( 2011cb0ef41Sopenharmony_ci 'raw', 2021cb0ef41Sopenharmony_ci keyData, 2031cb0ef41Sopenharmony_ci { name: 'AES-CBC', length: 256 }, 2041cb0ef41Sopenharmony_ci false, ['encrypt']); 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci await assert.rejects(subtle.deriveBits({ 2071cb0ef41Sopenharmony_ci name: 'X448', 2081cb0ef41Sopenharmony_ci public: key 2091cb0ef41Sopenharmony_ci }, keys.X448.publicKey, null), { 2101cb0ef41Sopenharmony_ci name: 'InvalidAccessError' 2111cb0ef41Sopenharmony_ci }); 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci})().then(common.mustCall()); 214