11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ciif (!common.hasCrypto) 41cb0ef41Sopenharmony_ci common.skip('missing crypto'); 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ciconst assert = require('assert'); 71cb0ef41Sopenharmony_ciconst fs = require('fs'); 81cb0ef41Sopenharmony_ciconst path = require('path'); 91cb0ef41Sopenharmony_ciconst exec = require('child_process').exec; 101cb0ef41Sopenharmony_ciconst crypto = require('crypto'); 111cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures'); 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci// Test certificates 141cb0ef41Sopenharmony_ciconst certPem = fixtures.readKey('rsa_cert.crt'); 151cb0ef41Sopenharmony_ciconst keyPem = fixtures.readKey('rsa_private.pem'); 161cb0ef41Sopenharmony_ciconst keySize = 2048; 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci{ 191cb0ef41Sopenharmony_ci const Sign = crypto.Sign; 201cb0ef41Sopenharmony_ci const instance = Sign('SHA256'); 211cb0ef41Sopenharmony_ci assert(instance instanceof Sign, 'Sign is expected to return a new ' + 221cb0ef41Sopenharmony_ci 'instance when called without `new`'); 231cb0ef41Sopenharmony_ci} 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci{ 261cb0ef41Sopenharmony_ci const Verify = crypto.Verify; 271cb0ef41Sopenharmony_ci const instance = Verify('SHA256'); 281cb0ef41Sopenharmony_ci assert(instance instanceof Verify, 'Verify is expected to return a new ' + 291cb0ef41Sopenharmony_ci 'instance when called without `new`'); 301cb0ef41Sopenharmony_ci} 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci// Test handling of exceptional conditions 331cb0ef41Sopenharmony_ci{ 341cb0ef41Sopenharmony_ci const library = { 351cb0ef41Sopenharmony_ci configurable: true, 361cb0ef41Sopenharmony_ci set() { 371cb0ef41Sopenharmony_ci throw new Error('bye, bye, library'); 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci }; 401cb0ef41Sopenharmony_ci Object.defineProperty(Object.prototype, 'library', library); 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci assert.throws(() => { 431cb0ef41Sopenharmony_ci crypto.createSign('sha1').sign( 441cb0ef41Sopenharmony_ci `-----BEGIN RSA PRIVATE KEY----- 451cb0ef41Sopenharmony_ci AAAAAAAAAAAA 461cb0ef41Sopenharmony_ci -----END RSA PRIVATE KEY-----`); 471cb0ef41Sopenharmony_ci }, { message: 'bye, bye, library' }); 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci delete Object.prototype.library; 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci const errorStack = { 521cb0ef41Sopenharmony_ci configurable: true, 531cb0ef41Sopenharmony_ci set() { 541cb0ef41Sopenharmony_ci throw new Error('bye, bye, error stack'); 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci }; 571cb0ef41Sopenharmony_ci Object.defineProperty(Object.prototype, 'opensslErrorStack', errorStack); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci assert.throws(() => { 601cb0ef41Sopenharmony_ci crypto.createSign('SHA1') 611cb0ef41Sopenharmony_ci .update('Test123') 621cb0ef41Sopenharmony_ci .sign({ 631cb0ef41Sopenharmony_ci key: keyPem, 641cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_OAEP_PADDING 651cb0ef41Sopenharmony_ci }); 661cb0ef41Sopenharmony_ci }, { message: common.hasOpenSSL3 ? 671cb0ef41Sopenharmony_ci 'error:1C8000A5:Provider routines::illegal or unsupported padding mode' : 681cb0ef41Sopenharmony_ci 'bye, bye, error stack' }); 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci delete Object.prototype.opensslErrorStack; 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ciassert.throws( 741cb0ef41Sopenharmony_ci () => crypto.createVerify('SHA256').verify({ 751cb0ef41Sopenharmony_ci key: certPem, 761cb0ef41Sopenharmony_ci padding: null, 771cb0ef41Sopenharmony_ci }, ''), 781cb0ef41Sopenharmony_ci { 791cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_VALUE', 801cb0ef41Sopenharmony_ci name: 'TypeError', 811cb0ef41Sopenharmony_ci message: "The property 'options.padding' is invalid. Received null", 821cb0ef41Sopenharmony_ci }); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ciassert.throws( 851cb0ef41Sopenharmony_ci () => crypto.createVerify('SHA256').verify({ 861cb0ef41Sopenharmony_ci key: certPem, 871cb0ef41Sopenharmony_ci saltLength: null, 881cb0ef41Sopenharmony_ci }, ''), 891cb0ef41Sopenharmony_ci { 901cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_VALUE', 911cb0ef41Sopenharmony_ci name: 'TypeError', 921cb0ef41Sopenharmony_ci message: "The property 'options.saltLength' is invalid. Received null", 931cb0ef41Sopenharmony_ci }); 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci// Test signing and verifying 961cb0ef41Sopenharmony_ci{ 971cb0ef41Sopenharmony_ci const s1 = crypto.createSign('SHA1') 981cb0ef41Sopenharmony_ci .update('Test123') 991cb0ef41Sopenharmony_ci .sign(keyPem, 'base64'); 1001cb0ef41Sopenharmony_ci let s1stream = crypto.createSign('SHA1'); 1011cb0ef41Sopenharmony_ci s1stream.end('Test123'); 1021cb0ef41Sopenharmony_ci s1stream = s1stream.sign(keyPem, 'base64'); 1031cb0ef41Sopenharmony_ci assert.strictEqual(s1, s1stream, `${s1} should equal ${s1stream}`); 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci const verified = crypto.createVerify('SHA1') 1061cb0ef41Sopenharmony_ci .update('Test') 1071cb0ef41Sopenharmony_ci .update('123') 1081cb0ef41Sopenharmony_ci .verify(certPem, s1, 'base64'); 1091cb0ef41Sopenharmony_ci assert.strictEqual(verified, true); 1101cb0ef41Sopenharmony_ci} 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci{ 1131cb0ef41Sopenharmony_ci const s2 = crypto.createSign('SHA256') 1141cb0ef41Sopenharmony_ci .update('Test123') 1151cb0ef41Sopenharmony_ci .sign(keyPem, 'latin1'); 1161cb0ef41Sopenharmony_ci let s2stream = crypto.createSign('SHA256'); 1171cb0ef41Sopenharmony_ci s2stream.end('Test123'); 1181cb0ef41Sopenharmony_ci s2stream = s2stream.sign(keyPem, 'latin1'); 1191cb0ef41Sopenharmony_ci assert.strictEqual(s2, s2stream, `${s2} should equal ${s2stream}`); 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci let verified = crypto.createVerify('SHA256') 1221cb0ef41Sopenharmony_ci .update('Test') 1231cb0ef41Sopenharmony_ci .update('123') 1241cb0ef41Sopenharmony_ci .verify(certPem, s2, 'latin1'); 1251cb0ef41Sopenharmony_ci assert.strictEqual(verified, true); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci const verStream = crypto.createVerify('SHA256'); 1281cb0ef41Sopenharmony_ci verStream.write('Tes'); 1291cb0ef41Sopenharmony_ci verStream.write('t12'); 1301cb0ef41Sopenharmony_ci verStream.end('3'); 1311cb0ef41Sopenharmony_ci verified = verStream.verify(certPem, s2, 'latin1'); 1321cb0ef41Sopenharmony_ci assert.strictEqual(verified, true); 1331cb0ef41Sopenharmony_ci} 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci{ 1361cb0ef41Sopenharmony_ci const s3 = crypto.createSign('SHA1') 1371cb0ef41Sopenharmony_ci .update('Test123') 1381cb0ef41Sopenharmony_ci .sign(keyPem, 'buffer'); 1391cb0ef41Sopenharmony_ci let verified = crypto.createVerify('SHA1') 1401cb0ef41Sopenharmony_ci .update('Test') 1411cb0ef41Sopenharmony_ci .update('123') 1421cb0ef41Sopenharmony_ci .verify(certPem, s3); 1431cb0ef41Sopenharmony_ci assert.strictEqual(verified, true); 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci const verStream = crypto.createVerify('SHA1'); 1461cb0ef41Sopenharmony_ci verStream.write('Tes'); 1471cb0ef41Sopenharmony_ci verStream.write('t12'); 1481cb0ef41Sopenharmony_ci verStream.end('3'); 1491cb0ef41Sopenharmony_ci verified = verStream.verify(certPem, s3); 1501cb0ef41Sopenharmony_ci assert.strictEqual(verified, true); 1511cb0ef41Sopenharmony_ci} 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci// Special tests for RSA_PKCS1_PSS_PADDING 1541cb0ef41Sopenharmony_ci{ 1551cb0ef41Sopenharmony_ci function testPSS(algo, hLen) { 1561cb0ef41Sopenharmony_ci // Maximum permissible salt length 1571cb0ef41Sopenharmony_ci const max = keySize / 8 - hLen - 2; 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci function getEffectiveSaltLength(saltLength) { 1601cb0ef41Sopenharmony_ci switch (saltLength) { 1611cb0ef41Sopenharmony_ci case crypto.constants.RSA_PSS_SALTLEN_DIGEST: 1621cb0ef41Sopenharmony_ci return hLen; 1631cb0ef41Sopenharmony_ci case crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN: 1641cb0ef41Sopenharmony_ci return max; 1651cb0ef41Sopenharmony_ci default: 1661cb0ef41Sopenharmony_ci return saltLength; 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci const signSaltLengths = [ 1711cb0ef41Sopenharmony_ci crypto.constants.RSA_PSS_SALTLEN_DIGEST, 1721cb0ef41Sopenharmony_ci getEffectiveSaltLength(crypto.constants.RSA_PSS_SALTLEN_DIGEST), 1731cb0ef41Sopenharmony_ci crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN, 1741cb0ef41Sopenharmony_ci getEffectiveSaltLength(crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN), 1751cb0ef41Sopenharmony_ci 0, 16, 32, 64, 128, 1761cb0ef41Sopenharmony_ci ]; 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci const verifySaltLengths = [ 1791cb0ef41Sopenharmony_ci crypto.constants.RSA_PSS_SALTLEN_DIGEST, 1801cb0ef41Sopenharmony_ci getEffectiveSaltLength(crypto.constants.RSA_PSS_SALTLEN_DIGEST), 1811cb0ef41Sopenharmony_ci getEffectiveSaltLength(crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN), 1821cb0ef41Sopenharmony_ci 0, 16, 32, 64, 128, 1831cb0ef41Sopenharmony_ci ]; 1841cb0ef41Sopenharmony_ci const errMessage = /^Error:.*data too large for key size$/; 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci const data = Buffer.from('Test123'); 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci signSaltLengths.forEach((signSaltLength) => { 1891cb0ef41Sopenharmony_ci if (signSaltLength > max) { 1901cb0ef41Sopenharmony_ci // If the salt length is too big, an Error should be thrown 1911cb0ef41Sopenharmony_ci assert.throws(() => { 1921cb0ef41Sopenharmony_ci crypto.createSign(algo) 1931cb0ef41Sopenharmony_ci .update(data) 1941cb0ef41Sopenharmony_ci .sign({ 1951cb0ef41Sopenharmony_ci key: keyPem, 1961cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 1971cb0ef41Sopenharmony_ci saltLength: signSaltLength 1981cb0ef41Sopenharmony_ci }); 1991cb0ef41Sopenharmony_ci }, errMessage); 2001cb0ef41Sopenharmony_ci assert.throws(() => { 2011cb0ef41Sopenharmony_ci crypto.sign(algo, data, { 2021cb0ef41Sopenharmony_ci key: keyPem, 2031cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2041cb0ef41Sopenharmony_ci saltLength: signSaltLength 2051cb0ef41Sopenharmony_ci }); 2061cb0ef41Sopenharmony_ci }, errMessage); 2071cb0ef41Sopenharmony_ci } else { 2081cb0ef41Sopenharmony_ci // Otherwise, a valid signature should be generated 2091cb0ef41Sopenharmony_ci const s4 = crypto.createSign(algo) 2101cb0ef41Sopenharmony_ci .update(data) 2111cb0ef41Sopenharmony_ci .sign({ 2121cb0ef41Sopenharmony_ci key: keyPem, 2131cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2141cb0ef41Sopenharmony_ci saltLength: signSaltLength 2151cb0ef41Sopenharmony_ci }); 2161cb0ef41Sopenharmony_ci const s4_2 = crypto.sign(algo, data, { 2171cb0ef41Sopenharmony_ci key: keyPem, 2181cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2191cb0ef41Sopenharmony_ci saltLength: signSaltLength 2201cb0ef41Sopenharmony_ci }); 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci [s4, s4_2].forEach((sig) => { 2231cb0ef41Sopenharmony_ci let verified; 2241cb0ef41Sopenharmony_ci verifySaltLengths.forEach((verifySaltLength) => { 2251cb0ef41Sopenharmony_ci // Verification should succeed if and only if the salt length is 2261cb0ef41Sopenharmony_ci // correct 2271cb0ef41Sopenharmony_ci verified = crypto.createVerify(algo) 2281cb0ef41Sopenharmony_ci .update(data) 2291cb0ef41Sopenharmony_ci .verify({ 2301cb0ef41Sopenharmony_ci key: certPem, 2311cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2321cb0ef41Sopenharmony_ci saltLength: verifySaltLength 2331cb0ef41Sopenharmony_ci }, sig); 2341cb0ef41Sopenharmony_ci assert.strictEqual(verified, crypto.verify(algo, data, { 2351cb0ef41Sopenharmony_ci key: certPem, 2361cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2371cb0ef41Sopenharmony_ci saltLength: verifySaltLength 2381cb0ef41Sopenharmony_ci }, sig)); 2391cb0ef41Sopenharmony_ci const saltLengthCorrect = getEffectiveSaltLength(signSaltLength) === 2401cb0ef41Sopenharmony_ci getEffectiveSaltLength(verifySaltLength); 2411cb0ef41Sopenharmony_ci assert.strictEqual(verified, saltLengthCorrect); 2421cb0ef41Sopenharmony_ci }); 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci // Verification using RSA_PSS_SALTLEN_AUTO should always work 2451cb0ef41Sopenharmony_ci verified = crypto.createVerify(algo) 2461cb0ef41Sopenharmony_ci .update(data) 2471cb0ef41Sopenharmony_ci .verify({ 2481cb0ef41Sopenharmony_ci key: certPem, 2491cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2501cb0ef41Sopenharmony_ci saltLength: crypto.constants.RSA_PSS_SALTLEN_AUTO 2511cb0ef41Sopenharmony_ci }, sig); 2521cb0ef41Sopenharmony_ci assert.strictEqual(verified, true); 2531cb0ef41Sopenharmony_ci assert.strictEqual(verified, crypto.verify(algo, data, { 2541cb0ef41Sopenharmony_ci key: certPem, 2551cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2561cb0ef41Sopenharmony_ci saltLength: crypto.constants.RSA_PSS_SALTLEN_AUTO 2571cb0ef41Sopenharmony_ci }, sig)); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci // Verifying an incorrect message should never work 2601cb0ef41Sopenharmony_ci const wrongData = Buffer.from('Test1234'); 2611cb0ef41Sopenharmony_ci verified = crypto.createVerify(algo) 2621cb0ef41Sopenharmony_ci .update(wrongData) 2631cb0ef41Sopenharmony_ci .verify({ 2641cb0ef41Sopenharmony_ci key: certPem, 2651cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2661cb0ef41Sopenharmony_ci saltLength: crypto.constants.RSA_PSS_SALTLEN_AUTO 2671cb0ef41Sopenharmony_ci }, sig); 2681cb0ef41Sopenharmony_ci assert.strictEqual(verified, false); 2691cb0ef41Sopenharmony_ci assert.strictEqual(verified, crypto.verify(algo, wrongData, { 2701cb0ef41Sopenharmony_ci key: certPem, 2711cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2721cb0ef41Sopenharmony_ci saltLength: crypto.constants.RSA_PSS_SALTLEN_AUTO 2731cb0ef41Sopenharmony_ci }, sig)); 2741cb0ef41Sopenharmony_ci }); 2751cb0ef41Sopenharmony_ci } 2761cb0ef41Sopenharmony_ci }); 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci testPSS('SHA1', 20); 2801cb0ef41Sopenharmony_ci testPSS('SHA256', 32); 2811cb0ef41Sopenharmony_ci} 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci// Test vectors for RSA_PKCS1_PSS_PADDING provided by the RSA Laboratories: 2841cb0ef41Sopenharmony_ci// https://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-rsa-cryptography-standard.htm 2851cb0ef41Sopenharmony_ci{ 2861cb0ef41Sopenharmony_ci // We only test verification as we cannot specify explicit salts when signing 2871cb0ef41Sopenharmony_ci function testVerify(cert, vector) { 2881cb0ef41Sopenharmony_ci const verified = crypto.createVerify('SHA1') 2891cb0ef41Sopenharmony_ci .update(Buffer.from(vector.message, 'hex')) 2901cb0ef41Sopenharmony_ci .verify({ 2911cb0ef41Sopenharmony_ci key: cert, 2921cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 2931cb0ef41Sopenharmony_ci saltLength: vector.salt.length / 2 2941cb0ef41Sopenharmony_ci }, vector.signature, 'hex'); 2951cb0ef41Sopenharmony_ci assert.strictEqual(verified, true); 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci const examples = JSON.parse(fixtures.readSync('pss-vectors.json', 'utf8')); 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci for (const key in examples) { 3011cb0ef41Sopenharmony_ci const example = examples[key]; 3021cb0ef41Sopenharmony_ci const publicKey = example.publicKey.join('\n'); 3031cb0ef41Sopenharmony_ci example.tests.forEach((test) => testVerify(publicKey, test)); 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci} 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci// Test exceptions for invalid `padding` and `saltLength` values 3081cb0ef41Sopenharmony_ci{ 3091cb0ef41Sopenharmony_ci [null, NaN, 'boom', {}, [], true, false] 3101cb0ef41Sopenharmony_ci .forEach((invalidValue) => { 3111cb0ef41Sopenharmony_ci assert.throws(() => { 3121cb0ef41Sopenharmony_ci crypto.createSign('SHA256') 3131cb0ef41Sopenharmony_ci .update('Test123') 3141cb0ef41Sopenharmony_ci .sign({ 3151cb0ef41Sopenharmony_ci key: keyPem, 3161cb0ef41Sopenharmony_ci padding: invalidValue 3171cb0ef41Sopenharmony_ci }); 3181cb0ef41Sopenharmony_ci }, { 3191cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_VALUE', 3201cb0ef41Sopenharmony_ci name: 'TypeError' 3211cb0ef41Sopenharmony_ci }); 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci assert.throws(() => { 3241cb0ef41Sopenharmony_ci crypto.createSign('SHA256') 3251cb0ef41Sopenharmony_ci .update('Test123') 3261cb0ef41Sopenharmony_ci .sign({ 3271cb0ef41Sopenharmony_ci key: keyPem, 3281cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING, 3291cb0ef41Sopenharmony_ci saltLength: invalidValue 3301cb0ef41Sopenharmony_ci }); 3311cb0ef41Sopenharmony_ci }, { 3321cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_VALUE', 3331cb0ef41Sopenharmony_ci name: 'TypeError' 3341cb0ef41Sopenharmony_ci }); 3351cb0ef41Sopenharmony_ci }); 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci assert.throws(() => { 3381cb0ef41Sopenharmony_ci crypto.createSign('SHA1') 3391cb0ef41Sopenharmony_ci .update('Test123') 3401cb0ef41Sopenharmony_ci .sign({ 3411cb0ef41Sopenharmony_ci key: keyPem, 3421cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_OAEP_PADDING 3431cb0ef41Sopenharmony_ci }); 3441cb0ef41Sopenharmony_ci }, common.hasOpenSSL3 ? { 3451cb0ef41Sopenharmony_ci code: 'ERR_OSSL_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE', 3461cb0ef41Sopenharmony_ci message: /illegal or unsupported padding mode/, 3471cb0ef41Sopenharmony_ci } : { 3481cb0ef41Sopenharmony_ci code: 'ERR_OSSL_RSA_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE', 3491cb0ef41Sopenharmony_ci message: /illegal or unsupported padding mode/, 3501cb0ef41Sopenharmony_ci opensslErrorStack: [ 3511cb0ef41Sopenharmony_ci 'error:06089093:digital envelope routines:EVP_PKEY_CTX_ctrl:' + 3521cb0ef41Sopenharmony_ci 'command not supported', 3531cb0ef41Sopenharmony_ci ], 3541cb0ef41Sopenharmony_ci }); 3551cb0ef41Sopenharmony_ci} 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci// Test throws exception when key options is null 3581cb0ef41Sopenharmony_ci{ 3591cb0ef41Sopenharmony_ci assert.throws(() => { 3601cb0ef41Sopenharmony_ci crypto.createSign('SHA1').update('Test123').sign(null, 'base64'); 3611cb0ef41Sopenharmony_ci }, { 3621cb0ef41Sopenharmony_ci code: 'ERR_CRYPTO_SIGN_KEY_REQUIRED', 3631cb0ef41Sopenharmony_ci name: 'Error' 3641cb0ef41Sopenharmony_ci }); 3651cb0ef41Sopenharmony_ci} 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci{ 3681cb0ef41Sopenharmony_ci const sign = crypto.createSign('SHA1'); 3691cb0ef41Sopenharmony_ci const verify = crypto.createVerify('SHA1'); 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci [1, [], {}, undefined, null, true, Infinity].forEach((input) => { 3721cb0ef41Sopenharmony_ci const errObj = { 3731cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 3741cb0ef41Sopenharmony_ci name: 'TypeError', 3751cb0ef41Sopenharmony_ci message: 'The "algorithm" argument must be of type string.' + 3761cb0ef41Sopenharmony_ci `${common.invalidArgTypeHelper(input)}` 3771cb0ef41Sopenharmony_ci }; 3781cb0ef41Sopenharmony_ci assert.throws(() => crypto.createSign(input), errObj); 3791cb0ef41Sopenharmony_ci assert.throws(() => crypto.createVerify(input), errObj); 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci errObj.message = 'The "data" argument must be of type string or an ' + 3821cb0ef41Sopenharmony_ci 'instance of Buffer, TypedArray, or DataView.' + 3831cb0ef41Sopenharmony_ci common.invalidArgTypeHelper(input); 3841cb0ef41Sopenharmony_ci assert.throws(() => sign.update(input), errObj); 3851cb0ef41Sopenharmony_ci assert.throws(() => verify.update(input), errObj); 3861cb0ef41Sopenharmony_ci assert.throws(() => sign._write(input, 'utf8', () => {}), errObj); 3871cb0ef41Sopenharmony_ci assert.throws(() => verify._write(input, 'utf8', () => {}), errObj); 3881cb0ef41Sopenharmony_ci }); 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ci [ 3911cb0ef41Sopenharmony_ci Uint8Array, Uint16Array, Uint32Array, Float32Array, Float64Array, 3921cb0ef41Sopenharmony_ci ].forEach((clazz) => { 3931cb0ef41Sopenharmony_ci // These should all just work 3941cb0ef41Sopenharmony_ci sign.update(new clazz()); 3951cb0ef41Sopenharmony_ci verify.update(new clazz()); 3961cb0ef41Sopenharmony_ci }); 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci [1, {}, [], Infinity].forEach((input) => { 3991cb0ef41Sopenharmony_ci const errObj = { 4001cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 4011cb0ef41Sopenharmony_ci name: 'TypeError', 4021cb0ef41Sopenharmony_ci }; 4031cb0ef41Sopenharmony_ci assert.throws(() => sign.sign(input), errObj); 4041cb0ef41Sopenharmony_ci assert.throws(() => verify.verify(input), errObj); 4051cb0ef41Sopenharmony_ci assert.throws(() => verify.verify('test', input), errObj); 4061cb0ef41Sopenharmony_ci }); 4071cb0ef41Sopenharmony_ci} 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci{ 4101cb0ef41Sopenharmony_ci assert.throws( 4111cb0ef41Sopenharmony_ci () => crypto.createSign('sha8'), 4121cb0ef41Sopenharmony_ci /Invalid digest/); 4131cb0ef41Sopenharmony_ci assert.throws( 4141cb0ef41Sopenharmony_ci () => crypto.sign('sha8', Buffer.alloc(1), keyPem), 4151cb0ef41Sopenharmony_ci /Invalid digest/); 4161cb0ef41Sopenharmony_ci} 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci[ 4191cb0ef41Sopenharmony_ci { private: fixtures.readKey('ed25519_private.pem', 'ascii'), 4201cb0ef41Sopenharmony_ci public: fixtures.readKey('ed25519_public.pem', 'ascii'), 4211cb0ef41Sopenharmony_ci algo: null, 4221cb0ef41Sopenharmony_ci sigLen: 64 }, 4231cb0ef41Sopenharmony_ci { private: fixtures.readKey('ed448_private.pem', 'ascii'), 4241cb0ef41Sopenharmony_ci public: fixtures.readKey('ed448_public.pem', 'ascii'), 4251cb0ef41Sopenharmony_ci algo: null, 4261cb0ef41Sopenharmony_ci sigLen: 114 }, 4271cb0ef41Sopenharmony_ci { private: fixtures.readKey('rsa_private_2048.pem', 'ascii'), 4281cb0ef41Sopenharmony_ci public: fixtures.readKey('rsa_public_2048.pem', 'ascii'), 4291cb0ef41Sopenharmony_ci algo: 'sha1', 4301cb0ef41Sopenharmony_ci sigLen: 256 }, 4311cb0ef41Sopenharmony_ci].forEach((pair) => { 4321cb0ef41Sopenharmony_ci const algo = pair.algo; 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci { 4351cb0ef41Sopenharmony_ci const data = Buffer.from('Hello world'); 4361cb0ef41Sopenharmony_ci const sig = crypto.sign(algo, data, pair.private); 4371cb0ef41Sopenharmony_ci assert.strictEqual(sig.length, pair.sigLen); 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify(algo, data, pair.private, sig), 4401cb0ef41Sopenharmony_ci true); 4411cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify(algo, data, pair.public, sig), 4421cb0ef41Sopenharmony_ci true); 4431cb0ef41Sopenharmony_ci } 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci { 4461cb0ef41Sopenharmony_ci const data = Buffer.from('Hello world'); 4471cb0ef41Sopenharmony_ci const privKeyObj = crypto.createPrivateKey(pair.private); 4481cb0ef41Sopenharmony_ci const pubKeyObj = crypto.createPublicKey(pair.public); 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci const sig = crypto.sign(algo, data, privKeyObj); 4511cb0ef41Sopenharmony_ci assert.strictEqual(sig.length, pair.sigLen); 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify(algo, data, privKeyObj, sig), true); 4541cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify(algo, data, pubKeyObj, sig), true); 4551cb0ef41Sopenharmony_ci } 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci { 4581cb0ef41Sopenharmony_ci const data = Buffer.from('Hello world'); 4591cb0ef41Sopenharmony_ci const otherData = Buffer.from('Goodbye world'); 4601cb0ef41Sopenharmony_ci const otherSig = crypto.sign(algo, otherData, pair.private); 4611cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify(algo, data, pair.private, otherSig), 4621cb0ef41Sopenharmony_ci false); 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci [ 4661cb0ef41Sopenharmony_ci Uint8Array, Uint16Array, Uint32Array, Float32Array, Float64Array, 4671cb0ef41Sopenharmony_ci ].forEach((clazz) => { 4681cb0ef41Sopenharmony_ci const data = new clazz(); 4691cb0ef41Sopenharmony_ci const sig = crypto.sign(algo, data, pair.private); 4701cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify(algo, data, pair.private, sig), 4711cb0ef41Sopenharmony_ci true); 4721cb0ef41Sopenharmony_ci }); 4731cb0ef41Sopenharmony_ci}); 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci[1, {}, [], true, Infinity].forEach((input) => { 4761cb0ef41Sopenharmony_ci const data = Buffer.alloc(1); 4771cb0ef41Sopenharmony_ci const sig = Buffer.alloc(1); 4781cb0ef41Sopenharmony_ci const errObj = { 4791cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 4801cb0ef41Sopenharmony_ci name: 'TypeError', 4811cb0ef41Sopenharmony_ci }; 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ci assert.throws(() => crypto.sign(null, input, 'asdf'), errObj); 4841cb0ef41Sopenharmony_ci assert.throws(() => crypto.verify(null, input, 'asdf', sig), errObj); 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_ci assert.throws(() => crypto.sign(null, data, input), errObj); 4871cb0ef41Sopenharmony_ci assert.throws(() => crypto.verify(null, data, input, sig), errObj); 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci errObj.message = 'The "signature" argument must be an instance of ' + 4901cb0ef41Sopenharmony_ci 'Buffer, TypedArray, or DataView.' + 4911cb0ef41Sopenharmony_ci common.invalidArgTypeHelper(input); 4921cb0ef41Sopenharmony_ci assert.throws(() => crypto.verify(null, data, 'test', input), errObj); 4931cb0ef41Sopenharmony_ci}); 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ci{ 4961cb0ef41Sopenharmony_ci const data = Buffer.from('Hello world'); 4971cb0ef41Sopenharmony_ci const keys = [['ec-key.pem', 64], ['dsa_private_1025.pem', 40]]; 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci for (const [file, length] of keys) { 5001cb0ef41Sopenharmony_ci const privKey = fixtures.readKey(file); 5011cb0ef41Sopenharmony_ci [ 5021cb0ef41Sopenharmony_ci crypto.createSign('sha1').update(data).sign(privKey), 5031cb0ef41Sopenharmony_ci crypto.sign('sha1', data, privKey), 5041cb0ef41Sopenharmony_ci crypto.sign('sha1', data, { key: privKey, dsaEncoding: 'der' }), 5051cb0ef41Sopenharmony_ci ].forEach((sig) => { 5061cb0ef41Sopenharmony_ci // Signature length variability due to DER encoding 5071cb0ef41Sopenharmony_ci assert(sig.length >= length + 4 && sig.length <= length + 8); 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci assert.strictEqual( 5101cb0ef41Sopenharmony_ci crypto.createVerify('sha1').update(data).verify(privKey, sig), 5111cb0ef41Sopenharmony_ci true 5121cb0ef41Sopenharmony_ci ); 5131cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify('sha1', data, privKey, sig), true); 5141cb0ef41Sopenharmony_ci }); 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_ci // Test (EC)DSA signature conversion. 5171cb0ef41Sopenharmony_ci const opts = { key: privKey, dsaEncoding: 'ieee-p1363' }; 5181cb0ef41Sopenharmony_ci let sig = crypto.sign('sha1', data, opts); 5191cb0ef41Sopenharmony_ci // Unlike DER signatures, IEEE P1363 signatures have a predictable length. 5201cb0ef41Sopenharmony_ci assert.strictEqual(sig.length, length); 5211cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify('sha1', data, opts, sig), true); 5221cb0ef41Sopenharmony_ci assert.strictEqual(crypto.createVerify('sha1') 5231cb0ef41Sopenharmony_ci .update(data) 5241cb0ef41Sopenharmony_ci .verify(opts, sig), true); 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_ci // Test invalid signature lengths. 5271cb0ef41Sopenharmony_ci for (const i of [-2, -1, 1, 2, 4, 8]) { 5281cb0ef41Sopenharmony_ci sig = crypto.randomBytes(length + i); 5291cb0ef41Sopenharmony_ci let result; 5301cb0ef41Sopenharmony_ci try { 5311cb0ef41Sopenharmony_ci result = crypto.verify('sha1', data, opts, sig); 5321cb0ef41Sopenharmony_ci } catch (err) { 5331cb0ef41Sopenharmony_ci assert.match(err.message, /asn1 encoding/); 5341cb0ef41Sopenharmony_ci assert.strictEqual(err.library, 'asn1 encoding routines'); 5351cb0ef41Sopenharmony_ci continue; 5361cb0ef41Sopenharmony_ci } 5371cb0ef41Sopenharmony_ci assert.strictEqual(result, false); 5381cb0ef41Sopenharmony_ci } 5391cb0ef41Sopenharmony_ci } 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_ci // Test verifying externally signed messages. 5421cb0ef41Sopenharmony_ci const extSig = Buffer.from('494c18ab5c8a62a72aea5041966902bcfa229821af2bf65' + 5431cb0ef41Sopenharmony_ci '0b5b4870d1fe6aebeaed9460c62210693b5b0a300033823' + 5441cb0ef41Sopenharmony_ci '33d9529c8abd8c5948940af944828be16c', 'hex'); 5451cb0ef41Sopenharmony_ci for (const ok of [true, false]) { 5461cb0ef41Sopenharmony_ci assert.strictEqual( 5471cb0ef41Sopenharmony_ci crypto.verify('sha256', data, { 5481cb0ef41Sopenharmony_ci key: fixtures.readKey('ec-key.pem'), 5491cb0ef41Sopenharmony_ci dsaEncoding: 'ieee-p1363' 5501cb0ef41Sopenharmony_ci }, extSig), 5511cb0ef41Sopenharmony_ci ok 5521cb0ef41Sopenharmony_ci ); 5531cb0ef41Sopenharmony_ci 5541cb0ef41Sopenharmony_ci assert.strictEqual( 5551cb0ef41Sopenharmony_ci crypto.createVerify('sha256').update(data).verify({ 5561cb0ef41Sopenharmony_ci key: fixtures.readKey('ec-key.pem'), 5571cb0ef41Sopenharmony_ci dsaEncoding: 'ieee-p1363' 5581cb0ef41Sopenharmony_ci }, extSig), 5591cb0ef41Sopenharmony_ci ok 5601cb0ef41Sopenharmony_ci ); 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_ci extSig[Math.floor(Math.random() * extSig.length)] ^= 1; 5631cb0ef41Sopenharmony_ci } 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci // Non-(EC)DSA keys should ignore the option. 5661cb0ef41Sopenharmony_ci const sig = crypto.sign('sha1', data, { 5671cb0ef41Sopenharmony_ci key: keyPem, 5681cb0ef41Sopenharmony_ci dsaEncoding: 'ieee-p1363' 5691cb0ef41Sopenharmony_ci }); 5701cb0ef41Sopenharmony_ci assert.strictEqual(crypto.verify('sha1', data, certPem, sig), true); 5711cb0ef41Sopenharmony_ci assert.strictEqual( 5721cb0ef41Sopenharmony_ci crypto.verify('sha1', data, { 5731cb0ef41Sopenharmony_ci key: certPem, 5741cb0ef41Sopenharmony_ci dsaEncoding: 'ieee-p1363' 5751cb0ef41Sopenharmony_ci }, sig), 5761cb0ef41Sopenharmony_ci true 5771cb0ef41Sopenharmony_ci ); 5781cb0ef41Sopenharmony_ci assert.strictEqual( 5791cb0ef41Sopenharmony_ci crypto.verify('sha1', data, { 5801cb0ef41Sopenharmony_ci key: certPem, 5811cb0ef41Sopenharmony_ci dsaEncoding: 'der' 5821cb0ef41Sopenharmony_ci }, sig), 5831cb0ef41Sopenharmony_ci true 5841cb0ef41Sopenharmony_ci ); 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci for (const dsaEncoding of ['foo', null, {}, 5, true, NaN]) { 5871cb0ef41Sopenharmony_ci assert.throws(() => { 5881cb0ef41Sopenharmony_ci crypto.sign('sha1', data, { 5891cb0ef41Sopenharmony_ci key: certPem, 5901cb0ef41Sopenharmony_ci dsaEncoding 5911cb0ef41Sopenharmony_ci }); 5921cb0ef41Sopenharmony_ci }, { 5931cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_VALUE' 5941cb0ef41Sopenharmony_ci }); 5951cb0ef41Sopenharmony_ci } 5961cb0ef41Sopenharmony_ci} 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ci 5991cb0ef41Sopenharmony_ci// RSA-PSS Sign test by verifying with 'openssl dgst -verify' 6001cb0ef41Sopenharmony_ci// Note: this particular test *must* be the last in this file as it will exit 6011cb0ef41Sopenharmony_ci// early if no openssl binary is found 6021cb0ef41Sopenharmony_ci{ 6031cb0ef41Sopenharmony_ci if (!common.opensslCli) 6041cb0ef41Sopenharmony_ci common.skip('node compiled without OpenSSL CLI.'); 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci const pubfile = fixtures.path('keys', 'rsa_public_2048.pem'); 6071cb0ef41Sopenharmony_ci const privkey = fixtures.readKey('rsa_private_2048.pem'); 6081cb0ef41Sopenharmony_ci 6091cb0ef41Sopenharmony_ci const msg = 'Test123'; 6101cb0ef41Sopenharmony_ci const s5 = crypto.createSign('SHA256') 6111cb0ef41Sopenharmony_ci .update(msg) 6121cb0ef41Sopenharmony_ci .sign({ 6131cb0ef41Sopenharmony_ci key: privkey, 6141cb0ef41Sopenharmony_ci padding: crypto.constants.RSA_PKCS1_PSS_PADDING 6151cb0ef41Sopenharmony_ci }); 6161cb0ef41Sopenharmony_ci 6171cb0ef41Sopenharmony_ci const tmpdir = require('../common/tmpdir'); 6181cb0ef41Sopenharmony_ci tmpdir.refresh(); 6191cb0ef41Sopenharmony_ci 6201cb0ef41Sopenharmony_ci const sigfile = path.join(tmpdir.path, 's5.sig'); 6211cb0ef41Sopenharmony_ci fs.writeFileSync(sigfile, s5); 6221cb0ef41Sopenharmony_ci const msgfile = path.join(tmpdir.path, 's5.msg'); 6231cb0ef41Sopenharmony_ci fs.writeFileSync(msgfile, msg); 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ci const cmd = 6261cb0ef41Sopenharmony_ci `"${common.opensslCli}" dgst -sha256 -verify "${pubfile}" -signature "${ 6271cb0ef41Sopenharmony_ci sigfile}" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-2 "${ 6281cb0ef41Sopenharmony_ci msgfile}"`; 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci exec(cmd, common.mustCall((err, stdout, stderr) => { 6311cb0ef41Sopenharmony_ci assert(stdout.includes('Verified OK')); 6321cb0ef41Sopenharmony_ci })); 6331cb0ef41Sopenharmony_ci} 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_ci{ 6361cb0ef41Sopenharmony_ci // Test RSA-PSS. 6371cb0ef41Sopenharmony_ci { 6381cb0ef41Sopenharmony_ci // This key pair does not restrict the message digest algorithm or salt 6391cb0ef41Sopenharmony_ci // length. 6401cb0ef41Sopenharmony_ci const publicPem = fixtures.readKey('rsa_pss_public_2048.pem'); 6411cb0ef41Sopenharmony_ci const privatePem = fixtures.readKey('rsa_pss_private_2048.pem'); 6421cb0ef41Sopenharmony_ci 6431cb0ef41Sopenharmony_ci const publicKey = crypto.createPublicKey(publicPem); 6441cb0ef41Sopenharmony_ci const privateKey = crypto.createPrivateKey(privatePem); 6451cb0ef41Sopenharmony_ci 6461cb0ef41Sopenharmony_ci for (const key of [privatePem, privateKey]) { 6471cb0ef41Sopenharmony_ci // Any algorithm should work. 6481cb0ef41Sopenharmony_ci for (const algo of ['sha1', 'sha256']) { 6491cb0ef41Sopenharmony_ci // Any salt length should work. 6501cb0ef41Sopenharmony_ci for (const saltLength of [undefined, 8, 10, 12, 16, 18, 20]) { 6511cb0ef41Sopenharmony_ci const signature = crypto.sign(algo, 'foo', { key, saltLength }); 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci for (const pkey of [key, publicKey, publicPem]) { 6541cb0ef41Sopenharmony_ci const okay = crypto.verify( 6551cb0ef41Sopenharmony_ci algo, 6561cb0ef41Sopenharmony_ci 'foo', 6571cb0ef41Sopenharmony_ci { key: pkey, saltLength }, 6581cb0ef41Sopenharmony_ci signature 6591cb0ef41Sopenharmony_ci ); 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci assert.ok(okay); 6621cb0ef41Sopenharmony_ci } 6631cb0ef41Sopenharmony_ci } 6641cb0ef41Sopenharmony_ci } 6651cb0ef41Sopenharmony_ci } 6661cb0ef41Sopenharmony_ci } 6671cb0ef41Sopenharmony_ci 6681cb0ef41Sopenharmony_ci { 6691cb0ef41Sopenharmony_ci // This key pair enforces sha256 as the message digest and the MGF1 6701cb0ef41Sopenharmony_ci // message digest and a salt length of at least 16 bytes. 6711cb0ef41Sopenharmony_ci const publicPem = 6721cb0ef41Sopenharmony_ci fixtures.readKey('rsa_pss_public_2048_sha256_sha256_16.pem'); 6731cb0ef41Sopenharmony_ci const privatePem = 6741cb0ef41Sopenharmony_ci fixtures.readKey('rsa_pss_private_2048_sha256_sha256_16.pem'); 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ci const publicKey = crypto.createPublicKey(publicPem); 6771cb0ef41Sopenharmony_ci const privateKey = crypto.createPrivateKey(privatePem); 6781cb0ef41Sopenharmony_ci 6791cb0ef41Sopenharmony_ci for (const key of [privatePem, privateKey]) { 6801cb0ef41Sopenharmony_ci // Signing with anything other than sha256 should fail. 6811cb0ef41Sopenharmony_ci assert.throws(() => { 6821cb0ef41Sopenharmony_ci crypto.sign('sha1', 'foo', key); 6831cb0ef41Sopenharmony_ci }, /digest not allowed/); 6841cb0ef41Sopenharmony_ci 6851cb0ef41Sopenharmony_ci // Signing with salt lengths less than 16 bytes should fail. 6861cb0ef41Sopenharmony_ci for (const saltLength of [8, 10, 12]) { 6871cb0ef41Sopenharmony_ci assert.throws(() => { 6881cb0ef41Sopenharmony_ci crypto.sign('sha256', 'foo', { key, saltLength }); 6891cb0ef41Sopenharmony_ci }, /pss saltlen too small/); 6901cb0ef41Sopenharmony_ci } 6911cb0ef41Sopenharmony_ci 6921cb0ef41Sopenharmony_ci // Signing with sha256 and appropriate salt lengths should work. 6931cb0ef41Sopenharmony_ci for (const saltLength of [undefined, 16, 18, 20]) { 6941cb0ef41Sopenharmony_ci const signature = crypto.sign('sha256', 'foo', { key, saltLength }); 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_ci for (const pkey of [key, publicKey, publicPem]) { 6971cb0ef41Sopenharmony_ci const okay = crypto.verify( 6981cb0ef41Sopenharmony_ci 'sha256', 6991cb0ef41Sopenharmony_ci 'foo', 7001cb0ef41Sopenharmony_ci { key: pkey, saltLength }, 7011cb0ef41Sopenharmony_ci signature 7021cb0ef41Sopenharmony_ci ); 7031cb0ef41Sopenharmony_ci 7041cb0ef41Sopenharmony_ci assert.ok(okay); 7051cb0ef41Sopenharmony_ci } 7061cb0ef41Sopenharmony_ci } 7071cb0ef41Sopenharmony_ci } 7081cb0ef41Sopenharmony_ci } 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ci { 7111cb0ef41Sopenharmony_ci // This key enforces sha512 as the message digest and sha256 as the MGF1 7121cb0ef41Sopenharmony_ci // message digest. 7131cb0ef41Sopenharmony_ci const publicPem = 7141cb0ef41Sopenharmony_ci fixtures.readKey('rsa_pss_public_2048_sha512_sha256_20.pem'); 7151cb0ef41Sopenharmony_ci const privatePem = 7161cb0ef41Sopenharmony_ci fixtures.readKey('rsa_pss_private_2048_sha512_sha256_20.pem'); 7171cb0ef41Sopenharmony_ci 7181cb0ef41Sopenharmony_ci const publicKey = crypto.createPublicKey(publicPem); 7191cb0ef41Sopenharmony_ci const privateKey = crypto.createPrivateKey(privatePem); 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci // Node.js usually uses the same hash function for the message and for MGF1. 7221cb0ef41Sopenharmony_ci // However, when a different MGF1 message digest algorithm has been 7231cb0ef41Sopenharmony_ci // specified as part of the key, it should automatically switch to that. 7241cb0ef41Sopenharmony_ci // This behavior is required by sections 3.1 and 3.3 of RFC4055. 7251cb0ef41Sopenharmony_ci for (const key of [privatePem, privateKey]) { 7261cb0ef41Sopenharmony_ci // sha256 matches the MGF1 hash function and should be used internally, 7271cb0ef41Sopenharmony_ci // but it should not be permitted as the main message digest algorithm. 7281cb0ef41Sopenharmony_ci for (const algo of ['sha1', 'sha256']) { 7291cb0ef41Sopenharmony_ci assert.throws(() => { 7301cb0ef41Sopenharmony_ci crypto.sign(algo, 'foo', key); 7311cb0ef41Sopenharmony_ci }, /digest not allowed/); 7321cb0ef41Sopenharmony_ci } 7331cb0ef41Sopenharmony_ci 7341cb0ef41Sopenharmony_ci // sha512 should produce a valid signature. 7351cb0ef41Sopenharmony_ci const signature = crypto.sign('sha512', 'foo', key); 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ci for (const pkey of [key, publicKey, publicPem]) { 7381cb0ef41Sopenharmony_ci const okay = crypto.verify('sha512', 'foo', pkey, signature); 7391cb0ef41Sopenharmony_ci 7401cb0ef41Sopenharmony_ci assert.ok(okay); 7411cb0ef41Sopenharmony_ci } 7421cb0ef41Sopenharmony_ci } 7431cb0ef41Sopenharmony_ci } 7441cb0ef41Sopenharmony_ci} 7451cb0ef41Sopenharmony_ci 7461cb0ef41Sopenharmony_ci// The sign function should not swallow OpenSSL errors. 7471cb0ef41Sopenharmony_ci// Regression test for https://github.com/nodejs/node/issues/40794. 7481cb0ef41Sopenharmony_ci{ 7491cb0ef41Sopenharmony_ci assert.throws(() => { 7501cb0ef41Sopenharmony_ci const { privateKey } = crypto.generateKeyPairSync('rsa', { 7511cb0ef41Sopenharmony_ci modulusLength: 512 7521cb0ef41Sopenharmony_ci }); 7531cb0ef41Sopenharmony_ci crypto.sign('sha512', 'message', privateKey); 7541cb0ef41Sopenharmony_ci }, { 7551cb0ef41Sopenharmony_ci code: 'ERR_OSSL_RSA_DIGEST_TOO_BIG_FOR_RSA_KEY', 7561cb0ef41Sopenharmony_ci message: /digest too big for rsa key/ 7571cb0ef41Sopenharmony_ci }); 7581cb0ef41Sopenharmony_ci} 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ci{ 7611cb0ef41Sopenharmony_ci // This should not cause a crash: https://github.com/nodejs/node/issues/44471 7621cb0ef41Sopenharmony_ci for (const key of ['', 'foo', null, undefined, true, Boolean]) { 7631cb0ef41Sopenharmony_ci assert.throws(() => { 7641cb0ef41Sopenharmony_ci crypto.verify('sha256', 'foo', { key, format: 'jwk' }, Buffer.alloc(0)); 7651cb0ef41Sopenharmony_ci }, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ }); 7661cb0ef41Sopenharmony_ci assert.throws(() => { 7671cb0ef41Sopenharmony_ci crypto.createVerify('sha256').verify({ key, format: 'jwk' }, Buffer.alloc(0)); 7681cb0ef41Sopenharmony_ci }, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ }); 7691cb0ef41Sopenharmony_ci assert.throws(() => { 7701cb0ef41Sopenharmony_ci crypto.sign('sha256', 'foo', { key, format: 'jwk' }); 7711cb0ef41Sopenharmony_ci }, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ }); 7721cb0ef41Sopenharmony_ci assert.throws(() => { 7731cb0ef41Sopenharmony_ci crypto.createSign('sha256').sign({ key, format: 'jwk' }); 7741cb0ef41Sopenharmony_ci }, { code: 'ERR_INVALID_ARG_TYPE', message: /The "key\.key" property must be of type object/ }); 7751cb0ef41Sopenharmony_ci } 7761cb0ef41Sopenharmony_ci} 777