11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciif (!common.hasCrypto) 51cb0ef41Sopenharmony_ci common.skip('missing crypto'); 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ciif (common.hasFipsCrypto) 81cb0ef41Sopenharmony_ci common.skip('not supported in FIPS mode'); 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ciconst crypto = require('crypto'); 111cb0ef41Sopenharmony_ciconst assert = require('assert'); 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cicommon.expectWarning({ 141cb0ef41Sopenharmony_ci Warning: [ 151cb0ef41Sopenharmony_ci ['Use Cipheriv for counter mode of aes-256-gcm'], 161cb0ef41Sopenharmony_ci ], 171cb0ef41Sopenharmony_ci DeprecationWarning: [ 181cb0ef41Sopenharmony_ci ['crypto.createCipher is deprecated.', 'DEP0106'], 191cb0ef41Sopenharmony_ci ] 201cb0ef41Sopenharmony_ci}); 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cifunction testCipher1(key) { 231cb0ef41Sopenharmony_ci // Test encryption and decryption 241cb0ef41Sopenharmony_ci const plaintext = 'Keep this a secret? No! Tell everyone about node.js!'; 251cb0ef41Sopenharmony_ci const cipher = crypto.createCipher('aes192', key); 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci // Encrypt plaintext which is in utf8 format 281cb0ef41Sopenharmony_ci // to a ciphertext which will be in hex 291cb0ef41Sopenharmony_ci let ciph = cipher.update(plaintext, 'utf8', 'hex'); 301cb0ef41Sopenharmony_ci // Only use binary or hex, not base64. 311cb0ef41Sopenharmony_ci ciph += cipher.final('hex'); 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci const decipher = crypto.createDecipher('aes192', key); 341cb0ef41Sopenharmony_ci let txt = decipher.update(ciph, 'hex', 'utf8'); 351cb0ef41Sopenharmony_ci txt += decipher.final('utf8'); 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci assert.strictEqual(txt, plaintext); 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci // Streaming cipher interface 401cb0ef41Sopenharmony_ci // NB: In real life, it's not guaranteed that you can get all of it 411cb0ef41Sopenharmony_ci // in a single read() like this. But in this case, we know it's 421cb0ef41Sopenharmony_ci // quite small, so there's no harm. 431cb0ef41Sopenharmony_ci const cStream = crypto.createCipher('aes192', key); 441cb0ef41Sopenharmony_ci cStream.end(plaintext); 451cb0ef41Sopenharmony_ci ciph = cStream.read(); 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci const dStream = crypto.createDecipher('aes192', key); 481cb0ef41Sopenharmony_ci dStream.end(ciph); 491cb0ef41Sopenharmony_ci txt = dStream.read().toString('utf8'); 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci assert.strictEqual(txt, plaintext); 521cb0ef41Sopenharmony_ci} 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_cifunction testCipher2(key) { 561cb0ef41Sopenharmony_ci // Encryption and decryption with Base64. 571cb0ef41Sopenharmony_ci // Reported in https://github.com/joyent/node/issues/738 581cb0ef41Sopenharmony_ci const plaintext = 591cb0ef41Sopenharmony_ci '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' + 601cb0ef41Sopenharmony_ci 'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' + 611cb0ef41Sopenharmony_ci 'jAfaFg**'; 621cb0ef41Sopenharmony_ci const cipher = crypto.createCipher('aes256', key); 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci // Encrypt plaintext which is in utf8 format to a ciphertext which will be in 651cb0ef41Sopenharmony_ci // Base64. 661cb0ef41Sopenharmony_ci let ciph = cipher.update(plaintext, 'utf8', 'base64'); 671cb0ef41Sopenharmony_ci ciph += cipher.final('base64'); 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci const decipher = crypto.createDecipher('aes256', key); 701cb0ef41Sopenharmony_ci let txt = decipher.update(ciph, 'base64', 'utf8'); 711cb0ef41Sopenharmony_ci txt += decipher.final('utf8'); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci assert.strictEqual(txt, plaintext); 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_citestCipher1('MySecretKey123'); 771cb0ef41Sopenharmony_citestCipher1(Buffer.from('MySecretKey123')); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_citestCipher2('0123456789abcdef'); 801cb0ef41Sopenharmony_citestCipher2(Buffer.from('0123456789abcdef')); 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci{ 831cb0ef41Sopenharmony_ci const Cipher = crypto.Cipher; 841cb0ef41Sopenharmony_ci const instance = crypto.Cipher('aes-256-cbc', 'secret'); 851cb0ef41Sopenharmony_ci assert(instance instanceof Cipher, 'Cipher is expected to return a new ' + 861cb0ef41Sopenharmony_ci 'instance when called without `new`'); 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci assert.throws( 891cb0ef41Sopenharmony_ci () => crypto.createCipher(null), 901cb0ef41Sopenharmony_ci { 911cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 921cb0ef41Sopenharmony_ci name: 'TypeError', 931cb0ef41Sopenharmony_ci message: 'The "cipher" argument must be of type string. ' + 941cb0ef41Sopenharmony_ci 'Received null' 951cb0ef41Sopenharmony_ci }); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci assert.throws( 981cb0ef41Sopenharmony_ci () => crypto.createCipher('aes-256-cbc', null), 991cb0ef41Sopenharmony_ci { 1001cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1011cb0ef41Sopenharmony_ci name: 'TypeError' 1021cb0ef41Sopenharmony_ci }); 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci assert.throws( 1051cb0ef41Sopenharmony_ci () => crypto.createCipher('aes-256-cbc', 'secret').update(null), 1061cb0ef41Sopenharmony_ci { 1071cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1081cb0ef41Sopenharmony_ci name: 'TypeError', 1091cb0ef41Sopenharmony_ci }); 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci assert.throws( 1121cb0ef41Sopenharmony_ci () => crypto.createCipher('aes-256-cbc', 'secret').setAAD(null), 1131cb0ef41Sopenharmony_ci { 1141cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1151cb0ef41Sopenharmony_ci name: 'TypeError', 1161cb0ef41Sopenharmony_ci }); 1171cb0ef41Sopenharmony_ci} 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci{ 1201cb0ef41Sopenharmony_ci const Decipher = crypto.Decipher; 1211cb0ef41Sopenharmony_ci const instance = crypto.Decipher('aes-256-cbc', 'secret'); 1221cb0ef41Sopenharmony_ci assert(instance instanceof Decipher, 'Decipher is expected to return a new ' + 1231cb0ef41Sopenharmony_ci 'instance when called without `new`'); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci assert.throws( 1261cb0ef41Sopenharmony_ci () => crypto.createDecipher(null), 1271cb0ef41Sopenharmony_ci { 1281cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1291cb0ef41Sopenharmony_ci name: 'TypeError', 1301cb0ef41Sopenharmony_ci message: 'The "cipher" argument must be of type string. ' + 1311cb0ef41Sopenharmony_ci 'Received null' 1321cb0ef41Sopenharmony_ci }); 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci assert.throws( 1351cb0ef41Sopenharmony_ci () => crypto.createDecipher('aes-256-cbc', 'secret').setAuthTag(null), 1361cb0ef41Sopenharmony_ci { 1371cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1381cb0ef41Sopenharmony_ci name: 'TypeError', 1391cb0ef41Sopenharmony_ci }); 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci assert.throws( 1421cb0ef41Sopenharmony_ci () => crypto.createDecipher('aes-256-cbc', null), 1431cb0ef41Sopenharmony_ci { 1441cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 1451cb0ef41Sopenharmony_ci name: 'TypeError', 1461cb0ef41Sopenharmony_ci }); 1471cb0ef41Sopenharmony_ci} 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci// Base64 padding regression test, see 1501cb0ef41Sopenharmony_ci// https://github.com/nodejs/node-v0.x-archive/issues/4837. 1511cb0ef41Sopenharmony_ci{ 1521cb0ef41Sopenharmony_ci const c = crypto.createCipher('aes-256-cbc', 'secret'); 1531cb0ef41Sopenharmony_ci const s = c.update('test', 'utf8', 'base64') + c.final('base64'); 1541cb0ef41Sopenharmony_ci assert.strictEqual(s, '375oxUQCIocvxmC5At+rvA=='); 1551cb0ef41Sopenharmony_ci} 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci// Calling Cipher.final() or Decipher.final() twice should error but 1581cb0ef41Sopenharmony_ci// not assert. See https://github.com/nodejs/node-v0.x-archive/issues/4886. 1591cb0ef41Sopenharmony_ci{ 1601cb0ef41Sopenharmony_ci const c = crypto.createCipher('aes-256-cbc', 'secret'); 1611cb0ef41Sopenharmony_ci try { c.final('xxx'); } catch { /* Ignore. */ } 1621cb0ef41Sopenharmony_ci try { c.final('xxx'); } catch { /* Ignore. */ } 1631cb0ef41Sopenharmony_ci try { c.final('xxx'); } catch { /* Ignore. */ } 1641cb0ef41Sopenharmony_ci const d = crypto.createDecipher('aes-256-cbc', 'secret'); 1651cb0ef41Sopenharmony_ci try { d.final('xxx'); } catch { /* Ignore. */ } 1661cb0ef41Sopenharmony_ci try { d.final('xxx'); } catch { /* Ignore. */ } 1671cb0ef41Sopenharmony_ci try { d.final('xxx'); } catch { /* Ignore. */ } 1681cb0ef41Sopenharmony_ci} 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci// Regression test for https://github.com/nodejs/node-v0.x-archive/issues/5482: 1711cb0ef41Sopenharmony_ci// string to Cipher#update() should not assert. 1721cb0ef41Sopenharmony_ci{ 1731cb0ef41Sopenharmony_ci const c = crypto.createCipher('aes192', '0123456789abcdef'); 1741cb0ef41Sopenharmony_ci c.update('update'); 1751cb0ef41Sopenharmony_ci c.final(); 1761cb0ef41Sopenharmony_ci} 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci// https://github.com/nodejs/node-v0.x-archive/issues/5655 regression tests, 1791cb0ef41Sopenharmony_ci// 'utf-8' and 'utf8' are identical. 1801cb0ef41Sopenharmony_ci{ 1811cb0ef41Sopenharmony_ci let c = crypto.createCipher('aes192', '0123456789abcdef'); 1821cb0ef41Sopenharmony_ci c.update('update', ''); // Defaults to "utf8". 1831cb0ef41Sopenharmony_ci c.final('utf-8'); // Should not throw. 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci c = crypto.createCipher('aes192', '0123456789abcdef'); 1861cb0ef41Sopenharmony_ci c.update('update', 'utf8'); 1871cb0ef41Sopenharmony_ci c.final('utf-8'); // Should not throw. 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci c = crypto.createCipher('aes192', '0123456789abcdef'); 1901cb0ef41Sopenharmony_ci c.update('update', 'utf-8'); 1911cb0ef41Sopenharmony_ci c.final('utf8'); // Should not throw. 1921cb0ef41Sopenharmony_ci} 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci// Regression tests for https://github.com/nodejs/node/issues/8236. 1951cb0ef41Sopenharmony_ci{ 1961cb0ef41Sopenharmony_ci const key = '0123456789abcdef'; 1971cb0ef41Sopenharmony_ci const plaintext = 'Top secret!!!'; 1981cb0ef41Sopenharmony_ci const c = crypto.createCipher('aes192', key); 1991cb0ef41Sopenharmony_ci let ciph = c.update(plaintext, 'utf16le', 'base64'); 2001cb0ef41Sopenharmony_ci ciph += c.final('base64'); 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci let decipher = crypto.createDecipher('aes192', key); 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci let txt; 2051cb0ef41Sopenharmony_ci txt = decipher.update(ciph, 'base64', 'ucs2'); 2061cb0ef41Sopenharmony_ci txt += decipher.final('ucs2'); 2071cb0ef41Sopenharmony_ci assert.strictEqual(txt, plaintext); 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci decipher = crypto.createDecipher('aes192', key); 2101cb0ef41Sopenharmony_ci txt = decipher.update(ciph, 'base64', 'ucs-2'); 2111cb0ef41Sopenharmony_ci txt += decipher.final('ucs-2'); 2121cb0ef41Sopenharmony_ci assert.strictEqual(txt, plaintext); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci decipher = crypto.createDecipher('aes192', key); 2151cb0ef41Sopenharmony_ci txt = decipher.update(ciph, 'base64', 'utf-16le'); 2161cb0ef41Sopenharmony_ci txt += decipher.final('utf-16le'); 2171cb0ef41Sopenharmony_ci assert.strictEqual(txt, plaintext); 2181cb0ef41Sopenharmony_ci} 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci// setAutoPadding/setAuthTag/setAAD should return `this` 2211cb0ef41Sopenharmony_ci{ 2221cb0ef41Sopenharmony_ci const key = '0123456789'; 2231cb0ef41Sopenharmony_ci const tagbuf = Buffer.from('auth_tag'); 2241cb0ef41Sopenharmony_ci const aadbuf = Buffer.from('aadbuf'); 2251cb0ef41Sopenharmony_ci const decipher = crypto.createDecipher('aes-256-gcm', key); 2261cb0ef41Sopenharmony_ci assert.strictEqual(decipher.setAutoPadding(), decipher); 2271cb0ef41Sopenharmony_ci assert.strictEqual(decipher.setAuthTag(tagbuf), decipher); 2281cb0ef41Sopenharmony_ci assert.strictEqual(decipher.setAAD(aadbuf), decipher); 2291cb0ef41Sopenharmony_ci} 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci// Error throwing in setAAD/setAuthTag/getAuthTag/setAutoPadding 2321cb0ef41Sopenharmony_ci{ 2331cb0ef41Sopenharmony_ci const key = '0123456789'; 2341cb0ef41Sopenharmony_ci const aadbuf = Buffer.from('aadbuf'); 2351cb0ef41Sopenharmony_ci const data = Buffer.from('test-crypto-cipher-decipher'); 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci const cipher = crypto.createCipher('aes-256-gcm', key); 2381cb0ef41Sopenharmony_ci cipher.setAAD(aadbuf); 2391cb0ef41Sopenharmony_ci cipher.setAutoPadding(); 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci assert.throws( 2421cb0ef41Sopenharmony_ci () => cipher.getAuthTag(), 2431cb0ef41Sopenharmony_ci { 2441cb0ef41Sopenharmony_ci code: 'ERR_CRYPTO_INVALID_STATE', 2451cb0ef41Sopenharmony_ci name: 'Error', 2461cb0ef41Sopenharmony_ci message: 'Invalid state for operation getAuthTag' 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci ); 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci const encrypted = Buffer.concat([cipher.update(data), cipher.final()]); 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci const decipher = crypto.createDecipher('aes-256-gcm', key); 2531cb0ef41Sopenharmony_ci decipher.setAAD(aadbuf); 2541cb0ef41Sopenharmony_ci decipher.setAuthTag(cipher.getAuthTag()); 2551cb0ef41Sopenharmony_ci decipher.setAutoPadding(); 2561cb0ef41Sopenharmony_ci decipher.update(encrypted); 2571cb0ef41Sopenharmony_ci decipher.final(); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci assert.throws( 2601cb0ef41Sopenharmony_ci () => decipher.setAAD(aadbuf), 2611cb0ef41Sopenharmony_ci { 2621cb0ef41Sopenharmony_ci code: 'ERR_CRYPTO_INVALID_STATE', 2631cb0ef41Sopenharmony_ci name: 'Error', 2641cb0ef41Sopenharmony_ci message: 'Invalid state for operation setAAD' 2651cb0ef41Sopenharmony_ci }); 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci assert.throws( 2681cb0ef41Sopenharmony_ci () => decipher.setAuthTag(cipher.getAuthTag()), 2691cb0ef41Sopenharmony_ci { 2701cb0ef41Sopenharmony_ci code: 'ERR_CRYPTO_INVALID_STATE', 2711cb0ef41Sopenharmony_ci name: 'Error', 2721cb0ef41Sopenharmony_ci message: 'Invalid state for operation setAuthTag' 2731cb0ef41Sopenharmony_ci }); 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci assert.throws( 2761cb0ef41Sopenharmony_ci () => decipher.setAutoPadding(), 2771cb0ef41Sopenharmony_ci { 2781cb0ef41Sopenharmony_ci code: 'ERR_CRYPTO_INVALID_STATE', 2791cb0ef41Sopenharmony_ci name: 'Error', 2801cb0ef41Sopenharmony_ci message: 'Invalid state for operation setAutoPadding' 2811cb0ef41Sopenharmony_ci } 2821cb0ef41Sopenharmony_ci ); 2831cb0ef41Sopenharmony_ci} 284