Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running under node, io.js does not properly pass OAEP hash and label parameters to crypto.publicEncrypt() #229

Open
tonesandtones opened this issue Nov 10, 2023 · 1 comment

Comments

@tonesandtones
Copy link

tonesandtones commented Nov 10, 2023

The problem

When running in a Node process, encrypting with PKCS1 OAEP padding with custom label and SHA 256 hash algorithm, io.js does not pass the OAEP hash and OAEP label parameters to crypto.publicEncrypt().

Expected behaviour

When run in a node process, OAEP padding is applied with the chosen hash function and label before being encrypted.

Actual behaviour

OAEP padding is applied with node crypto defaults of SHA1 and no label instead of the requested hash and label. See https://nodejs.org/api/crypto.html#cryptopublicencryptkey-buffer

image

The cause

When running in a node process, node-rsa selects an encrypt engine wrapper encryptEngines/io.js or encryptEngines/node12.js. Neither passes the configured oaep hash or label to crypto.publicEncrypt().

Workaround

When specifying your NodeRSA options object, set environment: 'browser' to cause node-rsa to select the encrypt engine encryptEngines/js.js, which implements is own oaep padding.

Example workaround

//MUST set environment: 'browser'. When run with environment == 'node' (or autodetected
//to be running in a node process), node-rsa doesn't properly pass the oaep hash and
//label parameters to node crypto and defaults to SHA-1 and no label.
//Using 'browser' causes node-rsa to use its own OAEP implementation and uses the hash
//and label parameters correctly.
const options = {
    environment: 'browser', //CRIITICAL - MUST BE 'browser'
    encryptionScheme:{
        hash: 'sha256', //message and mgf1 hash function
        label: '<OAEP padding label>', //oaep padding label, a.k.a. encoding parameter
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
    }
};

const key = new NodeRSA(undefined, options); //set the current key to undefined so it doesn't try to create a new public/private keypair

const rsaMod = '<long modulus component>';
const rsaExp = '<short exponent components>';

//now import the public component of our key
key.importKey({
    n: Buffer.from(rsaMod, 'hex'),
    e: Buffer.from(rsaExp, 'hex')
}, 'components-public');

const encryptedBuffer = key.encrypt(Buffer.from('<message to encrypt>'), 'buffer');
@tonesandtones
Copy link
Author

tonesandtones commented Nov 10, 2023

encryptEngines/io.js#L35-L36 should pass the OAEP label and hash function to crypto.publicEncrypt() here.

return crypto.publicEncrypt({
        key: options.rsaUtils.exportKey('public'),
        padding: padding
        // <-- oaepLabel: options.encryptionSchemeOptions.label
        // <-- oaepHash: options.encryptionSchemeOptions.hash
}, data);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant