potatosalad / erlang-libsodium

libsodium asynchronous port driver for Erlang and Elixir
MIT License
51 stars 13 forks source link

Crash on calling libsodium_crypto_sign_ed25519:detached(...) #4

Closed rvangraan closed 7 years ago

rvangraan commented 8 years ago

If I run this code (version 0.0.4):

Salt = libsodium_randombytes:buf(libsodium_crypto_pwhash_scryptsalsa208sha256:saltbytes()),
SecretKey = libsodium_crypto_pwhash_scryptsalsa208sha256:crypto_pwhash_scryptsalsa208sha256(
libsodium_crypto_box:seedbytes(),
<<"ABCDEF">>, Salt,
libsodium_crypto_pwhash_scryptsalsa208sha256:opslimit_interactive(),
libsodium_crypto_pwhash_scryptsalsa208sha256:memlimit_interactive()),
{PublicKey, PrivateKey} = libsodium_crypto_box:seed_keypair(SecretKey),
Signature = libsodium_crypto_sign_ed25519:detached(<<"This is a message">>, PrivateKey).

I get this error:

** exception error: bad argument
     in function  erlang:port_call/3
        called as erlang:port_call(#Port<0.686>,1,
                                   {#Ref<0.0.8.46>,crypto_sign_ed25519,detached,
                                    {<<"This is a message">>,
                                     <<234,169,185,73,238,103,117,164,58,15,170,124,28,233,
                                       56,243,200,204,52,81,...>>}})
     in call from libsodium:driver_call/5 (src/libsodium.erl, line 81)

It could be that it's already been fixed, but as in https://github.com/potatosalad/erlang-libsodium/issues/3 I can't test if its working.

rvangraan commented 8 years ago

I just tried the same on Linux with 0.0.8 and it still happens:

Erlang/OTP 18 [erts-7.3.1] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V7.3.1  (abort with ^G)
1> application:start(crypto),
1> application:start(asn1),
1> application:start(public_key),
1> application:start(libsodium),
1> Salt = libsodium_randombytes:buf(libsodium_crypto_pwhash_scryptsalsa208sha256:saltbytes()),
1> SecretKey = libsodium_crypto_pwhash_scryptsalsa208sha256:crypto_pwhash_scryptsalsa208sha256(
1> libsodium_crypto_box:seedbytes(),
1> <<"ABCDEF">>, Salt,
1> libsodium_crypto_pwhash_scryptsalsa208sha256:opslimit_interactive(),
1> libsodium_crypto_pwhash_scryptsalsa208sha256:memlimit_interactive()),
1> {PublicKey, PrivateKey} = libsodium_crypto_box:seed_keypair(SecretKey),
1> Signature = libsodium_crypto_sign_ed25519:detached(<<"This is a message">>, PrivateKey).
** exception error: bad argument
     in function  erlang:port_call/3
        called as erlang:port_call(#Port<0.671>,1,
                                   {#Ref<0.0.1.48>,crypto_sign_ed25519,detached,
                                    {<<"This is a message">>,
                                     <<148,248,123,17,86,57,21,48,101,187,246,103,59,220,
                                       244,64,104,26,106,76,...>>}})
     in call from libsodium:driver_call/5 (src/libsodium.erl, line 81)
potatosalad commented 8 years ago

Hey @rvangraan,

The keys used for Ed25519 and X25519 are actually two different types of keys:

Ed25519 keys

X25519 keys

So, in simplified form (you can swap out keypair/0 for seed_keypair/1 if you want) with libsodium_crypto_sign:

{PublicKey, SecretKey} = libsodium_crypto_sign:keypair(),
Signature = libsodium_crypto_sign:detached(<<"This is a message">>, SecretKey).

Alternatively with libsodium_crypto_sign_ed25519:

{PublicKey, SecretKey} = libsodium_crypto_sign_ed25519:keypair(),
Signature = libsodium_crypto_sign_ed25519:detached(<<"This is a message">>, SecretKey).

Let me know if you have any other issues with this. I still need to take a closer look at #3 to see what's going on there.

rvangraan commented 8 years ago

hi @potatosalad thanks for the explanation - I eventually discovered this myself. Maybe you should tag the different key types in a tuple so that it crashes with badmatch or perhaps throw an exception?

potatosalad commented 8 years ago

Yeah, I've thought about doing something like that to avoid confusion. I noticed this project the other day that has an interesting idea using maps related to that.

What do you think of the following syntax, @rvangraan?

#{ secret_key := SecretKey, public_key := PublicKey } = libsodium_crypto_sign:keypair(),
#{ signature := Signature } = libsodium_crypto_sign:detached(#{ message => <<"This is a message">>, secret_key => SecretKey }).

Also, were you able to get #3 resolved on OSX?

potatosalad commented 8 years ago

Also, in regards to the tuple key, we could do that, but we can also just filter out binaries that aren't 64-bytes in length for the secret key for signing operations.

rvangraan commented 8 years ago

Personally I'd have stuck with records, similar to the map #keypair{secret_key = ..., public_key = ...}. That way you'd get compile time checks on the fields which you won't get with a map.