1

I am developing a REST client (from an Android Point Of Sale) where I'm given a public RSA 2048-bit key and I need to encrypt transaction information. Since that single block cannot be encrypted (and AFAIK it should not) with the public key, we need to encrypt it using AES 128-bit. So we generate a random key (using KeyGenerator class), encrypt the info and send the AES key encrypted under their public key. AES is in ECB mode for their requirement which I know is insecure.

So the question would be: what pitfalls (apart from ECB) this method has?

My idea was to implement a kind of ECIES (but without Elliptic Curve) where a key derivation function is used (altough I'm a noob and don't know how to implement it) and using an authenticated encryption method like AES-GCM.

To extend the question I will like some context as I think I have sparse information and need to "connect altogether".

Ella Rose
  • 19,971
  • 6
  • 56
  • 103

2 Answers2

3

You have the right idea! There's a very general construction for public-key encryption called KEM/DEM that works as follows to encrypt a message $m$:

  1. Key encapsulation mechanism, KEM: Generate a key $k$ and an encapsulation $y$ using a public key.
  2. Data encapsulation mechanism, DEM: Use $k$ to authenticate and encrypt $m$ giving an authenticated ciphertext $c$.
  3. Transmit the encapsulation $y$ along with the ciphertext $c$.

The recipient, with the secret key, can recover $k$ from $y$ and then decrypt $c$.

For RSA, you can make a KEM as follows with a public key $n$:

  • Pick an integer $x$ between $0$ and $n$ uniformly at random.
  • Compute $y = x^3 \bmod n$.
  • Compute $k = H(x)$, where $H$ is (say) SHA-256.

The recipient uses secret knowledge of the solution $d$ to $3d \equiv 1 \pmod{\lambda(n)}$, where $\lambda(n) = \operatorname{lcm}(p - 1, q - 1)$ if $n = pq$, to recover $x = y^d \bmod n$, and then computes the same $k = H(x)$.

The security requirement for a DEM is modest. An authenticated cipher like AES-GCM or NaCl crypto_secretbox_xsalsa20poly1305, with nonce set to zero, will do just fine. (I recommend AES-256 if you must use AES, to avoid multi-target attacks; I recommend crypto_secretbox_xsalsa20poly1305 over AES-GCM, to avoid side channel attacks on AES and GHASH in fast software implementations.)

ECIES is an example of the KEM/DEM structure—for a public key $A$ on an elliptic curve with standard base point $B$, you pick a scalar $t$ uniformly at random, compute $T = [t]B$, derive the key $k = H([t]A)$, and use $T$ as the encapsulation of the secret key $k$ which you use in an authenticated cipher to encrypt the message; the recipient knows the secret $a$ such that $A = [a]B$, and given $T$ recovers $H([a]T) = H([a\cdot t] B) = H([t\cdot a]B) = H([t]A) = k$ to decrypt the authenticated ciphertext.

You can also generate $k$ independently and shoe-horn it into an encapsulation like RSAES-OAEP. But, while this is probably the most common way to do RSA encryption out of inertia, it is more complicated than necessary.

Squeamish Ossifrage
  • 49,816
  • 3
  • 122
  • 230
1

So in order to give an answer to the actual question and with the help of @eckes:

ECIES is a good option, a good library for implementing it in C# is Inferno: https://securitydriven.net/inferno

In Java (and also C#) there is BouncyCastle, altough author of Inferno bashes it saying that is "a huge (145k LOC), poorly-performing museum catalogue of crypto (some of it ancient), with old Java implementations ported to equally-old .NET (2.0?)". This is relevant since its known that altough cryptographic algorithms can be safe in their definition, poor implementations lead to unsecure systems.