Hi all,
catching up on that topic, I am currently facing an issue when I try to sign / verify on a msg that is already a digest.
I generate the secp256k1
keypair, sign a message with it and verify it. so far so good:
iex> {public, secret} = :crypto.generate_key(:ecdh, :secp256k1)
{<<4, 108, 222, 220, 9, 10, 7, 227, 52, 162, 49, 185, 119, 228, 116, 89, 21,
210, 55, 68, 13, 11, 70, 113, 3, 194, 158, 157, 245, 222, 92, 60, 221, 50,
90, 180, 241, 14, 23, 202, 116, 170, 41, 90, 117, 191, 83, 57, 78, 99, 125,
17, 181, 181, 81, 250, 239, 169, 40, 86, 24, 202, 204, 221, 70>>,
<<114, 167, 169, 229, 133, 167, 126, 185, 69, 244, 173, 52, 202, 173, 193, 33,
246, 242, 111, 23, 76, 108, 22, 196, 39, 170, 154, 65, 184, 139, 220, 87>>}
iex> sig = :crypto.sign(:ecdsa, :sha256, "toto", [secret, :secp256k1])
<<48, 69, 2, 32, 4, 143, 152, 145, 255, 133, 228, 8, 216, 31, 4, 212, 212, 85,
37, 182, 66, 127, 147, 128, 251, 44, 104, 192, 145, 110, 0, 198, 133, 201,
175, 4, 2, 33, 0, 178, 100, 197, 149, 49, 160, 214, 171, 191, 151, 190, 17,
107, 165, 213, 7, 123, 122, 37, 95, 46, 31, 8, 217, 8, 14, 7, 157, 40, 51, 88,
205>>
iex> :crypto.verify(:ecdsa, :sha256, "toto", sig, [public, :secp256k1])
true
Now my issue is when instead of passing a plaintext message and a hash algorithm, i want to pass the digest directly, I followed the doc and tried the following:
iex> hash = :crypto.hash(:sha256, "toto")
<<49, 247, 166, 94, 49, 85, 134, 172, 25, 139, 215, 152, 182, 98, 156, 228, 144,
61, 8, 153, 71, 109, 87, 65, 169, 243, 46, 46, 82, 27, 106, 102>>
iex> hash_hex = hash |> Base.encode16(case: :lower)
"31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66"
and i am now trying to sign with the {:digest, hash_hex}
as a parameter, I get the following error:
iex> :crypto.sign(:ecdsa, nil, {:digest, hash_hex}, [secret, :secp256k1])
** (ArgumentError) argument error
(crypto 4.7) :crypto.pkey_sign_nif(:ecdsa, nil, {:digest, "31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66"}, {{{:prime_field, <<255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 252, 47>>}, {<<0>>, "\a", :none}, <<4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72, 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, ...>>, <<255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 186, 174, 220, 230, 175, 72, 160, 59, 191, 210, 94, 140, 208, 54, 65, 65>>, <<1>>}, <<114, 167, 169, 229, 133, 167, 126, 185, 69, 244, 173, 52, 202, 173, 193, 33, 246, 242, 111, 23, 76, 108, 22, 196, 39, 170, 154, 65, 184, 139, 220, 87>>}, [])
(crypto 4.7) crypto.erl:1907: :crypto.sign/5
I tried to check if this was my syntax that was wrong by running the same kind of operation with and ed25519
keypair (I used OTP 23 RC3 for that experiment):
iex> {pk, sk} = :crypto.generate_key(:eddsa, :ed25519)
{<<7, 84, 240, 17, 249, 10, 185, 55, 19, 229, 253, 30, 71, 155, 132, 115, 59,
35, 231, 100, 64, 72, 246, 213, 49, 254, 59, 190, 56, 228, 216, 80>>,
<<127, 237, 190, 166, 201, 23, 218, 16, 218, 181, 201, 87, 97, 164, 101, 252,
227, 204, 98, 90, 139, 52, 26, 14, 108, 88, 218, 62, 195, 205, 188, 87>>}
iex> sig = :crypto.sign(:eddsa, nil, {:digest, hash_hex}, [sk, :ed25519])
<<197, 9, 223, 65, 1, 186, 44, 246, 4, 86, 6, 90, 170, 125, 190, 240, 113, 71,
90, 57, 10, 61, 77, 144, 27, 150, 22, 245, 85, 144, 119, 159, 213, 116, 146,
70, 27, 170, 202, 92, 130, 26, 73, 51, 59, 201, 90, 250, 242, 250, 3, 120,
102, 109, 226, 189, 160, 191, 101, 252, 138, 213, 204, 11>>
iex> :crypto.verify(:eddsa, nil, {:digest, hash_hex}, sig, [pk, :ed25519])
true
so it works as expected for eddsa
but not for ecdsa
, anyone knows what is going on? what I am missing?
thanks