I'm trying to encrypt (and decrypt) messages send from one device to another by using NSec.Cryptography, but I find the documentation a bit vague. As I understood I need a Key
and PublicKey
of device A and B, respectively. I can turn these into a SharedSecret
:
var sharedSecret = KeyAgreementAlgorithm.X25519.Agree(encryption.Key, deviceKey);
However, this shared secret doesn't seem useful for encryption as the Encrypt(...)
method asks for a Key in its parameters:
var cyphertext = AeadAlgorithm.ChaCha20Poly1305.Encrypt(sharedSecret, nonce, new byte[0], message);
^-- will not work
I have multiple questions:
ChaCha20Poly1305.Encrypt
method useful if it uses one key which can't be a shared secret?Note: I wanna use X25519 keys.
Read the documentation for SharedSecret
:
Represents the output of a key agreement and the input for key derivation
So you first need to generate one or more keys using a specific KDF and NSec seems to implement HKDF (using SHA-256 or-512, I'd prefer the latter because it is more secure and - on 64 bit machines - possibly even faster. The shared secret itself is not fully random to an adversary, so a KDF is required to create the most cryptographically secure keys from it.
This should answer 1 & 2: SharedSecret
is used to derive the actual keys, it isn't a key in itself.
How do I encrypt a message using the private key of A and public key of B (like box and secret box in libsodium)?
As for 3: You need an ephemeral key pair on the sender A and the public key of receiver B. Then you perform the key agreement & key derivation (as above) using the sender's ephemeral private key and send the ephemeral public key with the ciphertext. Don't forget to destroy the ephemeral private key of the sender after the key agreement; you don't need it anymore, and leaking it will compromise the ciphertext.
The receiver can now perform the same agreement using their static private key and the received ephemeral public key, and finally decrypt the message.