Gotaiba
Gotaiba

Reputation: 11

How to perform RSA encrytion with ECB mode using Javascript in React Native?

I'm a beginner at cryptography so bear with me. I want to use RSA encryption with EBC mode included I have searched around and found a library in JavaScript called JsEncrypt that perform RSA encrytion with keys generation but there is nothing on the documentation about the padding the cipher mode that is use. I'm working on React Native project and I request the public key from secure third-party API. All I want to do is to encrypt using the public key already provided with the third party using RSA encryption and cipher mode must be ECB. Any help will be appreciated

Upvotes: 1

Views: 1696

Answers (1)

Scott Arciszewski
Scott Arciszewski

Reputation: 34113

I'm a beginner at cryptography so bear with me.

Sure thing! Everyone has to start somewhere.

I want to use RSA encryption

You almost certainly do not.

Encrypting arbitrary messages directly with your asymmetric primitive is almost never what you want to do in the real world. I'll explain what you want to do below.

with EBC mode

You never want to use ECB mode either.

RSA+ECB is a javax.crypto.Cipher idiom. Don't follow their examples.

I have searched around and found a library in JavaScript called JsEncrypt that perform RSA encrytion with keys generation but there is nothing on the documentation about the padding the cipher mode that is use.

To sate your curiosity: It uses PKCS #1 padding, version 2.

What to Do Instead of RSA-ECB

Most cryptographers don't recommend RSA anymore. Most security experts also advise against its use.

You want libsodium instead.

On the front-end, you want to use crypto_box_seal() with an ECDH public key. On the back-end, you want to use crypto_box_seal_open() with your ECDH keypair.

This is easily demonstrated using sodium-plus (a cross-platform, asynchronous JavaScript implementation of libsodium).

Client-Side Asymmetric Encryption

const { SodiumPlus, X25519PublicKey } = require('sodium-plus');
let sodium;

const publicKey = X25519Publickey.from(
    'fb1a219011c1e0d17699900ef22723e8a2b6e3b52ddbc268d763df4b0c002e73',
    'hex'
);

(async function () {
    if (!sodium) sodium = await SodiumPlus.auto();

    const message = 'Your message here.';
    let sendMe = await sodium.crypto_box_seal(message, publicKey);
    console.log(sendMe);
})();

You can then transmit your encrypted data (stored in sendMe) and have it decrypted elsewhere.

You can then find a congruent libsodium implementation for your back-end language.

If you're using Node.js server-side, you can use a very similar API for decryption.

Server-Side Asymmetric Decryption

const { SodiumPlus, X25519PublicKey, X25519SecretKey } = require('sodium-plus');
let sodium;

const secretKey = X25519SecretKey.from(
    '0202040a9fbf98e1e712b0be8f4e46e73e4f72e25edb72e0cdec026b370f4787',
    'hex'
);
const publicKey = X25519Publickey.from(
    'fb1a219011c1e0d17699900ef22723e8a2b6e3b52ddbc268d763df4b0c002e73',
    'hex'
);

(async function () {
    if (!sodium) sodium = await SodiumPlus.auto();

    const encrypted = ''; // Get from client-side
    let decrypted = await sodium.crypto_box_seal_open(encrypted, publicKey, secretKey);
    console.log(decrypted);
})();

What's Happening Under the Hood?

The beauty of libsodium is that you don't have to even care what's going on under the hood in order to use it correctly. That's the entire point of libsodium.

But for the curious: This is a sealing API which combines an Elliptic Curve Diffie-Hellman key agreement protocol (where one keypair is only used once) with authenticated symmetric-key encryption.

Your message is actually encrypted with XSalsa20-Poly1305. The encryption key is calculated from ECDH of the one-time (sk, pk) keypair generated client-side with the server's public key. (A nonce is calculated from the BLAKE2b hash of the two public keys.) The ephemeral (one-time) public key is prepended to the ciphertext.

On the server-side, it strips the public key from the sealed message, performs a congruent ECDH calculation (to arrive at the same symmetric key you generated client-side). Then it performs the XSalsa20-Poly1305 decryption with this shared key.

If anything goes wrong server-side, it will throw a SodiumError. This means that chosen-ciphertext attacks will fail. (Can you guarantee the same with RSA-ECB?)

But all you need to know is:

  • Encryption: encrypted = crypto_box_seal(message, pk)
  • Decryption: decrypted = crypto_box_seal_open(encrypted, pk, sk)

There are similar APIs in sodium-plus (and other libsodium APIs) that solve different cryptography problems.

Getting familiar with a hard-to-misuse library like libsodium is a great use of one's time as a beginner. After that, there's CryptoPals for self-education.

Upvotes: 2

Related Questions