RSA encryption by Modulus and Exp with node-rsa

I do authorization on the site, the password is encrypted by the public RSA mod+e.

Key HEX:

d3bcef1f00424f3261c89323fa8cdfa12bbac400d9fe8bb627e8d27a44bd5d59dce559135d678a8143beb5b8d7056c4e1f89c4e1f152470625b7b41944a97f02da6f605a49a93ec6eb9cbaf2e7ac2b26a354ce69eb265953d2c29e395d6d8c1cdb688978551aa0f7521f290035fad381178da0bea8f9e6adce39020f513133fb

Exp HEX: 10001 or else DEC 65537

When encrypted on website online-everything works and the encrypted text is valid

Website

But, as soon as I try to do the same on node-rsa-the resulting cipher is incorrect.

const NodeRSA = require('node-rsa');

let key = new NodeRSA();

key = key.importKey({
    n: Buffer.from('d3bcef1f00424f3261c89323fa8cdfa12bbac400d9fe8bb627e8d27a44bd5d59dce559135d678a8143beb5b8d7056c4e1f89c4e1f152470625b7b41944a97f02da6f605a49a93ec6eb9cbaf2e7ac2b26a354ce69eb265953d2c29e395d6d8c1cdb688978551aa0f7521f290035fad381178da0bea8f9e6adce39020f513133fb', 'hex'),
    e: 65537
}, 'components-public');

const encrypted = key.encrypt('qwerty', 'hex');
console.log(encrypted);
Author: viiprogrammer, 2020-11-29

1 answers

Updating the response Quick answer: in node-rsa, you need to set the encryption mode 'pkcs1'

key.setOptions({encryptionScheme: 'pkcs1'})

const encrypted = key.encrypt('qwerty', 'hex');

Detailed response.

In RSA, there are several ways to pad the plaintext to the full block (padding). The reason why the text encrypted in node-rsa did not pass through the website is because of various padding schemes. Node-rsa uses the pkcs1-oaep scheme by default, and the crypts/rsa library used on the site uses the pkcs1-pad2 scheme.

In node-rsa this scheme is also supported, called 'pkcs1'. Set by calling the function key.setOptions({encryptionScheme: 'pkcs1'}).

I also figured out the site. They call the "public key" n, the "private key" d, and the exponent e is fixed 65537.

For verification, I generated a pair of n and d on the site, the string qwerty in node-rsa, and successfully decrypted it on the site.

const NodeRSA = require('node-rsa');

let key = new NodeRSA();

n = Buffer.from("817d1e54c65d819ab659285c14742a7aa3ea0e94e37dc73594ce52fdb2d932281583dd3309e45498ec86a82de9a43d76998cc20c588073d664e464ddf37314a3", "hex");
d = Buffer.from("24b7ee19ec0627f24f330916d355fd95b9556dbd1aa55810019a603e40b1065f9dbc447d3a363dca4f2c1c87c1f204429088aaa5865c9f7de89bf0e114a228c1", "hex")
e = 65537

key = key.importKey({n: n, e: e}, "components-public")
key.setOptions({encryptionScheme: 'pkcs1'})

const encrypted = key.encrypt('qwerty', 'hex');
console.log(encrypted.toString("hex"))

Encryption result

1ed253c66f41658fb37c3f2386ed9507079d063816c4297a10af89d7e77cb5d525a72678b55e0d75cb6dfaec88bcd6179171d6bb8f6b3f41975d98138bdf8d3c

Checking for website: decoding a string on a website

Original response

In short, your encryption verification method is incorrect.

If it is more detailed, then I see several strange things in your question.

Is it possible to compare two ciphertexts?

node-rsa implements the encryption scheme pkcs1_oaep, which is defined in RFC 3447. In this scheme, the message before encryption is supplemented with random padding. So every every time you encrypt the same string with the same key, you will get different results. That is, it is impossible to verify the correctness of the encryption by comparing it with the ciphertext obtained somewhere else.

The correctness of the encryption is checked not by comparison with the standard, but by the correctness of the decryption. That is, you need to encrypt it in your program with a public key, and then decrypt it somewhere else with a private key. If the decryption result matches the encryption result, then everything is fine. a beam.

But! Without a private key, you will not be able to verify the correctness of your encryption.

Key format on the site you selected

The very concept of "RSA key in hex format" is ambiguous. Everywhere, several different formats are used to represent the key: PKCS1, PKCS8, OpenSSH. Which of these formats does the site you showed expect?

On the site you specified, I clicked the "generate" button and received a public key - private key pair. The public key started with the bytes "8f25". But such bytes at the beginning do not correspond to either the PKCS1/8-DER or OpenSSH formats. PKCS keys in DER encoding must start with 0x30, and the OpenSSH key in binary representation starts with bytes 00 00 00 07.

Strange site, in a word.

The way you use it adds to the strangeness. You enter n in the "Public Key" field, and the exponent in the "Key Length" field. But this is not true! The public key itself must contain both n and the exponent. And the key length must not be used - the key length (the number of bits in the number n) must be extracted by the program itself from a properly encoded public key.

 1
Author: Pak Uula, 2020-12-01 04:04:55