Using a LibSodium CryptoBox KeyPair with `crypto_sign` More of a theoretical question...

Taking a system where Lib Sodium has been used for asymmetric encryption, where a "crypto_box_keypair" has been generated, and the public key has been distributed to a number of different systems.

Would it be possible to sign a message using that keypair?

As in, the message remains in plain text, and a signature is generated with the secret key (possibly indirectly), and anyone in possession of (and trusts) the public key, can verify that the message hasn't been tampered with.

Considering that the "crypto_sign" function requires the use of "crypto_sign_keypair", not "crypto_box_keypair".



From a PHP implementation point of view, I was wondering if you could...

Take the keypair that has been previously generated by:

&lt;?php
$key_pair = sodium_crypto_box_keypair();
$key_secret = sodium_crypto_box_secretkey($key_pair);
$key_public = sodium_crypto_box_publickey($key_pair);
?&gt;


Then, for every message you want to sign, create a "crypto_sign_keypair", and use sodium_crypto_sign() as intended:

&lt;?php

// $sign_seed = random_bytes(SODIUM_CRYPTO_SIGN_SEEDBYTES);
// $sign_pair = sodium_crypto_sign_seed_keypair($sign_seed);

$sign_pair = sodium_crypto_sign_keypair();
$sign_secret = sodium_crypto_sign_secretkey($sign_pair);
$sign_public = sodium_crypto_sign_publickey($sign_pair);

$message = 'Hello';

$message_signed = sodium_crypto_sign($message, $sign_secret);

?&gt;


The $sign_secret and $sign_pair can be destroyed, because the recipient just needs to use $sign_public:

&lt;?php
$message = sodium_crypto_sign_open($message_signed, $sign_public);
?&gt;


The problem is that $sign_public needs to be sent to the recipient.

Where they need to verify it hasn't been tampered with, and that it came from the owner of the original $key_secret, by using their trusted copy of $key_public.

Noting that:


sodium_crypto_sign_detached is basically the same thing, but does not contain the message in its output.
sodium_crypto_box requires the recipient to have a keypair as well.
sodium_crypto_box_seal uses the public key to encrypt.
sodium_crypto_secretbox and sodium_crypto_aead_* use a shared key (symmetric).
sodium_crypto_auth uses a shared key.
It's possible to go the other way around (thanks Scott Arciszewski)

&lt;?php

$sign_pair = sodium_crypto_sign_keypair();
$sign_secret = sodium_crypto_sign_secretkey($sign_pair);
$sign_public = sodium_crypto_sign_publickey($sign_pair);

$key_secret = sodium_crypto_sign_ed25519_sk_to_curve25519($sign_secret);
$key_public = sodium_crypto_sign_ed25519_pk_to_curve25519($sign_public);

$key_public = sodium_crypto_box_publickey_from_secretkey($key_secret);

?&gt;