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_ciasync function testEncrypt({ keyBuffer, algorithm, plaintext, result }) { 131cb0ef41Sopenharmony_ci // Using a copy of plaintext to prevent tampering of the original 141cb0ef41Sopenharmony_ci plaintext = Buffer.from(plaintext); 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci const key = await subtle.importKey( 171cb0ef41Sopenharmony_ci 'raw', 181cb0ef41Sopenharmony_ci keyBuffer, 191cb0ef41Sopenharmony_ci { name: algorithm.name }, 201cb0ef41Sopenharmony_ci false, 211cb0ef41Sopenharmony_ci ['encrypt', 'decrypt']); 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci const output = await subtle.encrypt(algorithm, key, plaintext); 241cb0ef41Sopenharmony_ci plaintext[0] = 255 - plaintext[0]; 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci assert.strictEqual( 271cb0ef41Sopenharmony_ci Buffer.from(output).toString('hex'), 281cb0ef41Sopenharmony_ci Buffer.from(result).toString('hex')); 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci // Converting the returned ArrayBuffer into a Buffer right away, 311cb0ef41Sopenharmony_ci // so that the next line works 321cb0ef41Sopenharmony_ci const check = Buffer.from(await subtle.decrypt(algorithm, key, output)); 331cb0ef41Sopenharmony_ci check[0] = 255 - check[0]; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci assert.strictEqual( 361cb0ef41Sopenharmony_ci Buffer.from(check).toString('hex'), 371cb0ef41Sopenharmony_ci Buffer.from(plaintext).toString('hex')); 381cb0ef41Sopenharmony_ci} 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ciasync function testEncryptNoEncrypt({ keyBuffer, algorithm, plaintext }) { 411cb0ef41Sopenharmony_ci const key = await subtle.importKey( 421cb0ef41Sopenharmony_ci 'raw', 431cb0ef41Sopenharmony_ci keyBuffer, 441cb0ef41Sopenharmony_ci { name: algorithm.name }, 451cb0ef41Sopenharmony_ci false, 461cb0ef41Sopenharmony_ci ['decrypt']); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci return assert.rejects(subtle.encrypt(algorithm, key, plaintext), { 491cb0ef41Sopenharmony_ci message: /The requested operation is not valid for the provided key/ 501cb0ef41Sopenharmony_ci }); 511cb0ef41Sopenharmony_ci} 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ciasync function testEncryptNoDecrypt({ keyBuffer, algorithm, plaintext }) { 541cb0ef41Sopenharmony_ci const key = await subtle.importKey( 551cb0ef41Sopenharmony_ci 'raw', 561cb0ef41Sopenharmony_ci keyBuffer, 571cb0ef41Sopenharmony_ci { name: algorithm.name }, 581cb0ef41Sopenharmony_ci false, 591cb0ef41Sopenharmony_ci ['encrypt']); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci const output = await subtle.encrypt(algorithm, key, plaintext); 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci return assert.rejects(subtle.decrypt(algorithm, key, output), { 641cb0ef41Sopenharmony_ci message: /The requested operation is not valid for the provided key/ 651cb0ef41Sopenharmony_ci }); 661cb0ef41Sopenharmony_ci} 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ciasync function testEncryptWrongAlg({ keyBuffer, algorithm, plaintext }, alg) { 691cb0ef41Sopenharmony_ci assert.notStrictEqual(algorithm.name, alg); 701cb0ef41Sopenharmony_ci const key = await subtle.importKey( 711cb0ef41Sopenharmony_ci 'raw', 721cb0ef41Sopenharmony_ci keyBuffer, 731cb0ef41Sopenharmony_ci { name: alg }, 741cb0ef41Sopenharmony_ci false, 751cb0ef41Sopenharmony_ci ['encrypt']); 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci return assert.rejects(subtle.encrypt(algorithm, key, plaintext), { 781cb0ef41Sopenharmony_ci message: /The requested operation is not valid for the provided key/ 791cb0ef41Sopenharmony_ci }); 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciasync function testDecrypt({ keyBuffer, algorithm, result }) { 831cb0ef41Sopenharmony_ci const key = await subtle.importKey( 841cb0ef41Sopenharmony_ci 'raw', 851cb0ef41Sopenharmony_ci keyBuffer, 861cb0ef41Sopenharmony_ci { name: algorithm.name }, 871cb0ef41Sopenharmony_ci false, 881cb0ef41Sopenharmony_ci ['encrypt', 'decrypt']); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci await subtle.decrypt(algorithm, key, result); 911cb0ef41Sopenharmony_ci} 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci// Test aes-cbc vectors 941cb0ef41Sopenharmony_ci{ 951cb0ef41Sopenharmony_ci const { 961cb0ef41Sopenharmony_ci passing, 971cb0ef41Sopenharmony_ci failing, 981cb0ef41Sopenharmony_ci decryptionFailing 991cb0ef41Sopenharmony_ci } = require('../fixtures/crypto/aes_cbc')(); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci (async function() { 1021cb0ef41Sopenharmony_ci const variations = []; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci passing.forEach((vector) => { 1051cb0ef41Sopenharmony_ci variations.push(testEncrypt(vector)); 1061cb0ef41Sopenharmony_ci variations.push(testEncryptNoEncrypt(vector)); 1071cb0ef41Sopenharmony_ci variations.push(testEncryptNoDecrypt(vector)); 1081cb0ef41Sopenharmony_ci variations.push(testEncryptWrongAlg(vector, 'AES-CTR')); 1091cb0ef41Sopenharmony_ci }); 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci failing.forEach((vector) => { 1121cb0ef41Sopenharmony_ci variations.push(assert.rejects(testEncrypt(vector), { 1131cb0ef41Sopenharmony_ci message: /algorithm\.iv must contain exactly 16 bytes/ 1141cb0ef41Sopenharmony_ci })); 1151cb0ef41Sopenharmony_ci variations.push(assert.rejects(testDecrypt(vector), { 1161cb0ef41Sopenharmony_ci message: /algorithm\.iv must contain exactly 16 bytes/ 1171cb0ef41Sopenharmony_ci })); 1181cb0ef41Sopenharmony_ci }); 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci decryptionFailing.forEach((vector) => { 1211cb0ef41Sopenharmony_ci variations.push(assert.rejects(testDecrypt(vector), { 1221cb0ef41Sopenharmony_ci name: 'OperationError' 1231cb0ef41Sopenharmony_ci })); 1241cb0ef41Sopenharmony_ci }); 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci await Promise.all(variations); 1271cb0ef41Sopenharmony_ci })().then(common.mustCall()); 1281cb0ef41Sopenharmony_ci} 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci// Test aes-ctr vectors 1311cb0ef41Sopenharmony_ci{ 1321cb0ef41Sopenharmony_ci const { 1331cb0ef41Sopenharmony_ci passing, 1341cb0ef41Sopenharmony_ci failing, 1351cb0ef41Sopenharmony_ci decryptionFailing 1361cb0ef41Sopenharmony_ci } = require('../fixtures/crypto/aes_ctr')(); 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci (async function() { 1391cb0ef41Sopenharmony_ci const variations = []; 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci passing.forEach((vector) => { 1421cb0ef41Sopenharmony_ci variations.push(testEncrypt(vector)); 1431cb0ef41Sopenharmony_ci variations.push(testEncryptNoEncrypt(vector)); 1441cb0ef41Sopenharmony_ci variations.push(testEncryptNoDecrypt(vector)); 1451cb0ef41Sopenharmony_ci variations.push(testEncryptWrongAlg(vector, 'AES-CBC')); 1461cb0ef41Sopenharmony_ci }); 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci // TODO(@jasnell): These fail for different reasons. Need to 1491cb0ef41Sopenharmony_ci // make them consistent 1501cb0ef41Sopenharmony_ci failing.forEach((vector) => { 1511cb0ef41Sopenharmony_ci variations.push(assert.rejects(testEncrypt(vector), { 1521cb0ef41Sopenharmony_ci message: /.*/ 1531cb0ef41Sopenharmony_ci })); 1541cb0ef41Sopenharmony_ci variations.push(assert.rejects(testDecrypt(vector), { 1551cb0ef41Sopenharmony_ci message: /.*/ 1561cb0ef41Sopenharmony_ci })); 1571cb0ef41Sopenharmony_ci }); 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci decryptionFailing.forEach((vector) => { 1601cb0ef41Sopenharmony_ci variations.push(assert.rejects(testDecrypt(vector), { 1611cb0ef41Sopenharmony_ci name: 'OperationError' 1621cb0ef41Sopenharmony_ci })); 1631cb0ef41Sopenharmony_ci }); 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci await Promise.all(variations); 1661cb0ef41Sopenharmony_ci })().then(common.mustCall()); 1671cb0ef41Sopenharmony_ci} 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci// Test aes-gcm vectors 1701cb0ef41Sopenharmony_ci{ 1711cb0ef41Sopenharmony_ci const { 1721cb0ef41Sopenharmony_ci passing, 1731cb0ef41Sopenharmony_ci failing, 1741cb0ef41Sopenharmony_ci decryptionFailing 1751cb0ef41Sopenharmony_ci } = require('../fixtures/crypto/aes_gcm')(); 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci (async function() { 1781cb0ef41Sopenharmony_ci const variations = []; 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci passing.forEach((vector) => { 1811cb0ef41Sopenharmony_ci variations.push(testEncrypt(vector)); 1821cb0ef41Sopenharmony_ci variations.push(testEncryptNoEncrypt(vector)); 1831cb0ef41Sopenharmony_ci variations.push(testEncryptNoDecrypt(vector)); 1841cb0ef41Sopenharmony_ci variations.push(testEncryptWrongAlg(vector, 'AES-CBC')); 1851cb0ef41Sopenharmony_ci }); 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci failing.forEach((vector) => { 1881cb0ef41Sopenharmony_ci variations.push(assert.rejects(testEncrypt(vector), { 1891cb0ef41Sopenharmony_ci message: /is not a valid AES-GCM tag length/ 1901cb0ef41Sopenharmony_ci })); 1911cb0ef41Sopenharmony_ci variations.push(assert.rejects(testDecrypt(vector), { 1921cb0ef41Sopenharmony_ci message: /is not a valid AES-GCM tag length/ 1931cb0ef41Sopenharmony_ci })); 1941cb0ef41Sopenharmony_ci }); 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci decryptionFailing.forEach((vector) => { 1971cb0ef41Sopenharmony_ci variations.push(assert.rejects(testDecrypt(vector), { 1981cb0ef41Sopenharmony_ci name: 'OperationError' 1991cb0ef41Sopenharmony_ci })); 2001cb0ef41Sopenharmony_ci }); 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci await Promise.all(variations); 2031cb0ef41Sopenharmony_ci })().then(common.mustCall()); 2041cb0ef41Sopenharmony_ci} 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci{ 2071cb0ef41Sopenharmony_ci (async function() { 2081cb0ef41Sopenharmony_ci const secretKey = await subtle.generateKey( 2091cb0ef41Sopenharmony_ci { 2101cb0ef41Sopenharmony_ci name: 'AES-GCM', 2111cb0ef41Sopenharmony_ci length: 256, 2121cb0ef41Sopenharmony_ci }, 2131cb0ef41Sopenharmony_ci false, 2141cb0ef41Sopenharmony_ci ['encrypt', 'decrypt'], 2151cb0ef41Sopenharmony_ci ); 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci const iv = webcrypto.getRandomValues(new Uint8Array(12)); 2181cb0ef41Sopenharmony_ci const aad = webcrypto.getRandomValues(new Uint8Array(32)); 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci const encrypted = await subtle.encrypt( 2211cb0ef41Sopenharmony_ci { 2221cb0ef41Sopenharmony_ci name: 'AES-GCM', 2231cb0ef41Sopenharmony_ci iv, 2241cb0ef41Sopenharmony_ci additionalData: aad, 2251cb0ef41Sopenharmony_ci tagLength: 128 2261cb0ef41Sopenharmony_ci }, 2271cb0ef41Sopenharmony_ci secretKey, 2281cb0ef41Sopenharmony_ci webcrypto.getRandomValues(new Uint8Array(32)) 2291cb0ef41Sopenharmony_ci ); 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci await subtle.decrypt( 2321cb0ef41Sopenharmony_ci { 2331cb0ef41Sopenharmony_ci name: 'AES-GCM', 2341cb0ef41Sopenharmony_ci iv, 2351cb0ef41Sopenharmony_ci additionalData: aad, 2361cb0ef41Sopenharmony_ci tagLength: 128, 2371cb0ef41Sopenharmony_ci }, 2381cb0ef41Sopenharmony_ci secretKey, 2391cb0ef41Sopenharmony_ci new Uint8Array(encrypted), 2401cb0ef41Sopenharmony_ci ); 2411cb0ef41Sopenharmony_ci })().then(common.mustCall()); 2421cb0ef41Sopenharmony_ci} 243