30

While it is true that Elliptic Curve Diffie Hellman, Elliptic Curve Signature Generation and Elliptic Curve Signature Verification rely on scalar multiplications, these are usually implemented as different types of scalar multiplication for both security and efficiency reasons. In fact there are three types of scalar multiplications used in practice for ...


19

The old terminology was confusing, so they've rebranded a bit. X25519 is Elliptic Curve Diffie-Hellman (ECDH) over Curve25519 Ed25519 is Edwards-curve Digital Signature Algorithm (EdDSA) over Curve25519 Libsodium's ref10 curve25519 code is actually used both by crypto_scalarmult()/crypto_box() as well as crypto_sign().


18

You need to consider the weakest link property: a security system is never stronger than its weakest link. Since Argon2 is a password-based function, the weak link here is going to be the strength of your users' passwords. Choosing a longer output length doesn't help if the passwords' entropy is lower than that. Think of it this way: if the hash function ...


16

You can think of crypto_box_curve25519xsalsa20poly1305 as some composition of X25519, a key agreement scheme; XSalsa20, a symmetric-key stream cipher; and Poly1305, a one-time polynomial evaluation message authentication code. But that's not the best way to think about it when you're engineering something out of it—partly because there are many ways you ...


11

Curve25519 makes use of a special x-coordinate only form to achieve faster multiplication. Ed25519 uses Edwards curve for similar speedups, but includes a sign bit. While it could have been done differently, doing it this way simplifies implementations that only need one of encryption or signing.


8

The premise of boxes is that Alice and Bob know each other and write to each other. Alice can use a box to send a message to Bob. On receipt of the box, Bob knows (a) it came from Alice, and (b) nobody else could have read or tampered with it. The premise of sealed boxes is that Bob has an anonymous dropbox. Alice can use a sealed box to send a message ...


7

A common method for constant-time comparison goes $r←0$ for each bit/byte/word $x_i$ and $y_i$ to compare $r←r ∨ (x_i⊕y_i)$   where $∨$ stands for bitwise OR and $⊕$ stands for bitwise XOR all the $x_i$ match the corresponding $y_i$ if and only if $r$ is now $0$ The point is that the duration is independent of the data compared, thus measuring that ...


6

WireGuard uses keys that are on the Montgomery curve, not the Edwards curve. It's the standard X25519 or Curve25519 commonly used for ECDH. In libsodium, crypto_box_keypair calls crypto_box_curve25519xsalsa20poly1305_keypair which calls randombytes_buf(sk, 32), return crypto_scalarmult_curve25519_base(pk, sk). In WireGuard, wg genkey calls get_random_bytes(...


6

As I now understand the question: why doesn't NaCL provide a primitive for unauthenticated encryption, making ciphertext blobs that are only decrypt-able by a receiver identified by their public key? Note libsodium provides crypto_box_seal which does exactly this and NaCL claims to (try to) provide all necessary crypto primitives. In answer, notice ...


6

To take SEJPM's answer and be more explicit: Bob can also generate that ciphertext. One of the conditions on nonrepudiation is that no one (other than Alice, assuming her private key wasn't leaked) could possible generate that message. This doesn't hold here. If Bob can decrypt the ciphertext, he knows Alice must have generated it (as Bob knows he didn't),...


6

Short answer: You don't need to worry about the blacklist or point validation unless you are designing an exotic protocol. Medium answer: It depends on what you are trying to do. There is a short blacklist, and a much larger set of points (too large to list) that may cause you trouble—but only if you are setting yourself up for trouble by using the ...


6

I'm pretty sure this is an endianness issue. Specifically, taking the S_a value from the Josefsson draft and reversing the order of the bytes (i.e. pairs of hex digits) in it gives: 70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a which is almost the same as the value of a given in RFC 7748 § 6.1. In fact, XORing the values shows that ...


6

The only difference between these is the nonce size (and, consequently, the internal counter size). The core function is exactly the same. They all offer the exact same security level if they are used as expected. The trade-offs are described in the AEAD section of the documentation. XChaCha20-Poly1305-IETF is the one that has the largest nonce size. This ...


5

This function returns a string that the verification function will consider valid when given the same password. You shouldn't have to care about what the string actually contains. If only because the default algorithm and parameters can change. But the guarantee above will always be true. But indeed, the string will be different if given the same password ...


5

Found the solution. All that was needed was to reverse the bytes in the curve25519 secret point. Apparantly PGP uses little-endian for this, while ed25519 uses big-endian.


4

You are effectively using symmetric encryption. The crypto_box function uses elliptic curve Diffie–Hellman on Curve25519. With a given input private key and public key it always generates the same symmetric key, which is then used for authenticated encryption. By using the private and public key from the same key pair you are generating the point $a^2G$, ...


4

How can Alice says she didn't encrypt a ciphertext, if Bob can decrypt it using her public key? This is due to the way how the underlying implementation works.* For this purpose, every private key is an integer $d_A$ and $d_B$ and every public key is the multiple of the well-defined "generator" $G$, as follows: $P_A:=d_A\times G$ and $P_B:=d_B\times G$. ...


4

ArgonHashString calls the libsodium function crypto_pwhash_str which automatically generates a salt value that is part of the result.


4

If you are storing the file on disk then PKCS#12 Personal Information Exchange Syntax format is best practice. It is commonly referred to as a key store. But note that PKCS#12 relies on secret key encryption to encrypt the key store entries. That generally means that entries in such a store are encrypted with password based encryption. Which of course means ...


4

While point coordinates lie in the finite field over which the curve is defined, in this case $GF(p)$ with $p=2^{255}-19$, the scalars that you use lie in a field defined by the order of the generator, which is different from $p$. Therefore when you invert using feInvert you invert with respect to the wrong prime. You need to invert in $GF(n)$ with $n=2^{...


4

No need to implement padding, as it's already available. See the second example of the libsodium-PHP module. Partially-known plaintext has no implication on security, especially in counter mode where the encryption of a block is independent from the previous blocks. Creating a valid signature requires the secret key. Ed25519 has a 2^128 security target. The ...


4

Notice that $\operatorname{secretbox}$ has a $16$-byte MAC too. For reference, I've included $\operatorname{box}$ too. $$ \operatorname{secretbox} : \text{24 nonce} + \text{0 xsalsa} + \text{16 poly1305}\\ \operatorname{box} : \text{32 curve25519} + \text{24 nonce} + \text{0 xsalsa} + \text{16 poly1305} $$ However, the nonce is user-controlled and normally ...


4

memcmp() is not constant-time. The property called "constant-time" does not mean (confusingly) that every runs in a constant amount of time; an algorithm implementation is said to be "constant-time" if it does not leak information about secret data through timing-based side channels. In the case of memcmp(), the leak is simple: memcmp() looks at bytes in ...


3

However, Eve has a copy of Alice's key pair and intercepted the outgoing message. She uses crypto_box_open and passes in pKb and sKa, the same keys that were used to encrypt the message. This yields the plain text message. She changes the message, re-encrypts it, and sends it on to Bob. As you correctly observed, Eve having Alice's private key is insecure....


3

crypto_secretbox uses the first 32 bytes of XSalsa20 output as the key for Poly1305. Thus you are correct that using crypto_stream_xor on a known plaintext will reveal the authentication-key used by crypto_secretbox, allowing forgeries under that key and nonce. Not using a key for multiple purposes is a general crypto design principle. Perhaps that's why ...


3

Functions often become timing resistant by not using short circuit evaluation. There is conceivably a small performance price to be paid by not using short circuit evaluation. In reality, this is probably not a bottleneck or serious concern. Edit: It also might be possible that libsodiums function is faster anyways. I would have commented with this, but ...


3

Internally, libsodium public key encryption uses the same primitives as the (nonAEAD) secret key authenticated encryption, namely XSalsa20 and Poly1305. NaCl, which libsodium is based on, does not have an AEAD interface at all. Instead, libsodium added it from a TLS draft. There is no similar reference for public key AEAD use of these primitives, since in ...


3

The only requirement posed to the nonce in the "Security Model" paragraph of the crypto_box documentation is uniqueness for each pair of communicating parties. In fact, the documentation explicitly recommends incrementing nonces starting from zero (which an attacker could easily brute-force) or random nonces (which need to be transmitted together with the ...


3

It's not the algorithm that's more "efficient" (that's just a welcome side-effect) but the security level. Security levels are usually given in bits; to say that a cipher has 80 bits of security means that we assume it takes roughly $2^{80}$ effort to break it, for some definitions of "effort" and "break". For RSA, the main problem is factoring large ...


3

For symmetric encryption (encrypt data with a key, decrypt with the same key) use crypto_secretbox functions or possibly the crypto_secretstream functions. This seems to be what you want for problem 1. Crypto_generichash() is not an encryption function. It's a hashing function. It takes in a message and spits out a short value known as a hash. The hash is ...


Only top voted, non community-wiki answers of a minimum length are eligible