Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
335 views
in Technique[技术] by (71.8m points)

libsodium - How do I convert an ed25519 scalar into x25519 for encryption?

My goal is to use the crypto_box_easy / crypto_box_open_easy routines where Alice and Bob each have their own Scalars / Points already previously generated with crypto_core_ed25519_scalar_random and crypto_scalarmult_ed25519_base_noclamp, respectively.

I did not want to use crypto_box_keypair because I want to re-use the existing keys which Alice and Bob already have.

I've tried to use the crypto_sign_ed25519_sk_to_curve25519 / crypto_sign_ed25519_pk_to_curve25519 routines to convert the Ed25519 scalar/points to x25519. However decryption fails, so this does not seem to be the correct approach.

This routine only seems to work when the keypairs were generated with crypto_sign_ed25519_keypair, and not crypto_core_ed25519_scalar_random and crypto_scalarmult_ed25519_base_noclamp.


I am including two snippets here. The first D snippet I'm showing works OK (You can ignore the serialization part):

unittest
{
    // alice: generate ed25519 key pair
    ubyte[crypto_sign_ed25519_PUBLICKEYBYTES] ed25519_alice_pk;
    ubyte[crypto_sign_ed25519_SECRETKEYBYTES] ed25519_alice_sk;
    crypto_sign_ed25519_keypair(ed25519_alice_pk.ptr, ed25519_alice_sk.ptr);

    // alice: convert ed25519 to x25519
    ubyte[crypto_scalarmult_curve25519_BYTES] x25519_alice_pk;
    ubyte[crypto_scalarmult_curve25519_BYTES] x25519_alice_sk;
    crypto_sign_ed25519_sk_to_curve25519(x25519_alice_sk.ptr, ed25519_alice_sk.ptr);
    crypto_sign_ed25519_pk_to_curve25519(x25519_alice_pk.ptr, ed25519_alice_pk.ptr);

    // alice: generate ed25519 key pair
    ubyte[crypto_sign_ed25519_PUBLICKEYBYTES] ed25519_bob_pk;
    ubyte[crypto_sign_ed25519_SECRETKEYBYTES] ed25519_bob_sk;
    crypto_sign_ed25519_keypair(ed25519_bob_pk.ptr, ed25519_bob_sk.ptr);

    // alice: convert ed25519 to x25519
    // secret key / point for x25519 encryption
    ubyte[crypto_scalarmult_curve25519_BYTES] x25519_bob_pk;
    ubyte[crypto_scalarmult_curve25519_BYTES] x25519_bob_sk;
    crypto_sign_ed25519_sk_to_curve25519(x25519_bob_sk.ptr, ed25519_bob_sk.ptr);
    crypto_sign_ed25519_pk_to_curve25519(x25519_bob_pk.ptr, ed25519_bob_pk.ptr);

    static struct S
    {
        int x = 123;
    }

    S s;
    const payload = s.serializeFull();

    ubyte[crypto_box_NONCEBYTES] nonce;
    randombytes_buf(nonce.ptr, nonce.length);

    auto ciphertext_len = crypto_box_MACBYTES + payload.length;
    ubyte[] ciphertext = new ubyte[](ciphertext_len);
    if (crypto_box_easy(ciphertext.ptr, payload.ptr, payload.length, nonce.ptr,
        x25519_bob_pk.ptr, x25519_alice_sk.ptr) != 0)
        assert(0);

    ubyte[] decrypted = new ubyte[](payload.length);
    if (crypto_box_open_easy(decrypted.ptr, ciphertext.ptr, ciphertext_len, nonce.ptr,
        x25519_alice_pk.ptr, x25519_bob_sk.ptr) != 0)
        assert(0);

    S deserialized = deserializeFull!S(decrypted);
    assert(deserialized.x == s.x);
}

And here is an example using key-pairs generated with crypto_core_ed25519_scalar_random / crypto_scalarmult_ed25519_base_noclamp which fails during decryption:

unittest
{
    // alice: generate ed25519 key pair
    ubyte[crypto_core_ed25519_BYTES] ed25519_alice_pk;
    ubyte[crypto_core_ed25519_SCALARBYTES] ed25519_alice_sk;
    crypto_core_ed25519_scalar_random(ed25519_alice_sk.ptr);
    crypto_scalarmult_ed25519_base_noclamp(ed25519_alice_pk.ptr, ed25519_alice_sk.ptr);

    // alice: convert ed25519 to x25519
    ubyte[crypto_scalarmult_curve25519_BYTES] x25519_alice_pk;
    ubyte[crypto_scalarmult_curve25519_BYTES] x25519_alice_sk;
    crypto_sign_ed25519_sk_to_curve25519(x25519_alice_sk.ptr, ed25519_alice_sk.ptr);
    crypto_sign_ed25519_pk_to_curve25519(x25519_alice_pk.ptr, ed25519_alice_pk.ptr);

    // bob: generate ed25519 key pair
    ubyte[crypto_core_ed25519_BYTES] ed25519_bob_pk;
    ubyte[crypto_core_ed25519_SCALARBYTES] ed25519_bob_sk;
    crypto_core_ed25519_scalar_random(ed25519_bob_sk.ptr);
    crypto_scalarmult_ed25519_base_noclamp(ed25519_bob_pk.ptr, ed25519_bob_sk.ptr);

    // bob: convert ed25519 to x25519
    ubyte[crypto_scalarmult_curve25519_BYTES] x25519_bob_pk;
    ubyte[crypto_scalarmult_curve25519_BYTES] x25519_bob_sk;
    crypto_sign_ed25519_sk_to_curve25519(x25519_bob_sk.ptr, ed25519_bob_sk.ptr);
    crypto_sign_ed25519_pk_to_curve25519(x25519_bob_pk.ptr, ed25519_bob_pk.ptr);

    static struct S
    {
        int x = 123;
    }

    S s;
    const payload = s.serializeFull();

    ubyte[crypto_box_NONCEBYTES] nonce;
    randombytes_buf(nonce.ptr, nonce.length);

    auto ciphertext_len = crypto_box_MACBYTES + payload.length;
    ubyte[] ciphertext = new ubyte[](ciphertext_len);
    if (crypto_box_easy(ciphertext.ptr, payload.ptr, payload.length, nonce.ptr,
        x25519_bob_pk.ptr, x25519_alice_sk.ptr) != 0)
        assert(0);

    ubyte[] decrypted = new ubyte[](payload.length);
    if (crypto_box_open_easy(decrypted.ptr, ciphertext.ptr, ciphertext_len, nonce.ptr,
        x25519_alice_pk.ptr, x25519_bob_sk.ptr) != 0)
        assert(0);  // FAILS

    S deserialized = deserializeFull!S(decrypted);
    assert(deserialized.x == s.x);
}

The examples are otherwise equivalent. So the question is, what is the right way to derive a key-pair for encryption if I only have a key-pair for signing which was generated with crypto_core_ed25519_scalar_random and crypto_scalarmult_ed25519_base_noclamp?

question from:https://stackoverflow.com/questions/65932254/how-do-i-convert-an-ed25519-scalar-into-x25519-for-encryption

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...