1
$\begingroup$

I'm playing with cryptography and its use with typescript on one side and PHP on the other side. Now I'm looking for routines that can encrypt and decrypt with ecdh's private and shared keys. Any recommendations? At the moment its in a testenvironment to figure out how it works basically. The keys (private and shared) are generated with elliptic.

Edit: The plan is to use tweetnacl and tweetnacl-utilities for Typescript on the clientside and sodium from php 7.2 on the backend. The tweetnacl is well documented and it works to create two keypairs and two shared keys. I can encrypt a string for 'Alice' and decrypt it for 'Bob'. But on the backend I did not found the right corresponding functions...

Next steps after this is a save key exchange...

$\endgroup$
2
  • $\begingroup$ Also related: crypto.stackexchange.com/questions/9987/… $\endgroup$
    – tylo
    Sep 3, 2019 at 15:42
  • $\begingroup$ I don't think the alleged duplicates are helpful. They both discuss how EC-Elgamal works, which makes little sense to use for general-purpose applications like this; the only reason to use it would be in exotic applications requiring the homomorphic properties of Elgamal (and even then, EC-Elgamal requires a map between messages and curve points, which is even weirder to work out). $\endgroup$ Oct 31, 2019 at 14:23

1 Answer 1

1
$\begingroup$

Use crypto_box_curve25519xsalsa20poly1305 from libsodium/nacl.

How it works, roughly summarized with all details of encoding and coordinates omitted:

  1. Alice and Bob have public keys $A = [a]G = \underbrace{G + \dotsb + G}_{\text{$a$ times}}$ and $B = [b]G$.
    Here $G$ is the standard base point of Curve25519, $a$ is a secret 256-bit integer known only to Alice, and $b$ is a secret 256-bit integer known only to Bob.

  2. When Alice wants to send the $n^{\mathit{th}}$ message $m_n$ to Bob, she sends the box $c_n = \operatorname{crypto\_box}(m_n, n, B, a)$ to Bob. What this does is:

    • Computes the shared secret key $k = H([a]B) = H([a\cdot b]G)$, where $H$ is HSalsa20.

    • Uses $k$ as the key and $n$ as the nonce to authenticate and encrypt the message $m_n$ using crypto_secretbox_xsalsa20poly1305.

  3. When Bob receives the alleged $n^{\mathit{th}}$ box $c'_n$, which may be $c_n$ or may have been modified in transit or otherwise forged, he opens it with $\operatorname{crypto\_box\_open}(c'_n, n, A, b)$—but he makes sure to immediately drop it on the floor if crypto_box_open fails, meaning that it was a forgery. What this does is:

    • Computes the shared secret key $k = H([b]A) = H([a\cdot b]G)$.

    • Uses $k$ as the key and $n$ as the nonce to authenticate and decrypt the box $c_n$ using crypto_secretbox_xsalsa20poly1305_open.

In other words, crypto_box and crypto_box_open first do a static/static Diffie–Hellman key agreement, and then use the resulting key for an authenticated cipher.

Alice and Bob must never reuse any message number or nonce $n$ with a single pair of sender/receiver public keys or else the security will evaporate. If the communication is bidirectional, i.e. if Alice and Bob both need to send messages to each other, you might have Alice choose even values for $n$ and Bob choose odd values.

$\endgroup$
11
  • $\begingroup$ Thanks for the explanation. The background is interessting. I prefer to use existing and well tested libraries ;) For Typescript I used tweetnacl and its utilities. This works well for this environment. For the backend on PHP I'm a bit confused. In PHP 7.2 there is a implementation of sodium but I did not found compatibel functions coresponding with tweetnacl. On Typescript I use the box functions: box.keypair() for a new key pair and box.before for the shared key. But I got stuck on the php side... $\endgroup$
    – Ritchie
    Oct 31, 2019 at 7:52
  • $\begingroup$ @Ritchie \Sodium\crypto_box? $\endgroup$ Oct 31, 2019 at 14:25
  • $\begingroup$ yes that's the one I used. On the clientside I have the box.keypair() function to create a new keypair and the box.before to calculate a shared key from the first public key and the second secred key. Also vice versa. On the client it works well: [code] kp1 = box.keyPair(); sk1 = kp1.secretKey; $\endgroup$
    – Ritchie
    Nov 4, 2019 at 9:59
  • $\begingroup$ was to slow... yes that's the one I used. On the clientside I have the box.keypair() function to create a new keypair and the box.before to calculate a shared key from the first public key and the second secred key. Also vice versa. On the client it works well: kp1 = box.keyPair(); sk1 = kp1.secretKey; pk1 = kp1.publicKey; kp2 = box.keyPair(); sk2 = kp2.secretKey; pk2 = kp2.publicKey; sk1 = box.before(pk2, sk1); sk2 = box.before(pk1, sk2); $\endgroup$
    – Ritchie
    Nov 4, 2019 at 10:13
  • $\begingroup$ both shared keys are identically. But I did not found a corresponding function on the sodium side. I can create key pairs on php and here also in the same way the shared keys. But I can't create shared keys with the public from tweetnacl on typescript on the client and the private from php on the server and vice versa. The shared are not identically. $\endgroup$
    – Ritchie
    Nov 4, 2019 at 10:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.