Secp256k1 Signature verification

The current implementation of Crypto.ecverify_secp256k1(msg: hash, pk: bytes(64), sig: bytes(64)): bool that Sophia now natively supports can be used to verify a signed message.

From what I see in the code it only supports secp256k1 DER encoded messages (which bitcoin uses).

Are there any plans on supporting RLP encoded secp256k1 signed messages (this is what ethereum uses)? - It will ease lots of transitioning and interoperability between decentralized applications.

Some more context:
Although Ethereum similar to Bitcoin uses secp256k1 curve, ethereum message signatures are RLP encoded whereas Bitcoin message signatures are DER encoded.

The difference is that in RLP encoded signature there are three values present: R,S, and v, the last one v allowing public key recovery from the signature, whereas bitcoin’s DER encoding signature contains only R and S.

So, the current Sophia Crypto.ecverify_secp256k1(msg: hash, pk: bytes(64), sig: bytes(64)) : bool implementation is not allowing us to make Ethereum signed messages verification as the ethereum rlp encoded message signature is 65 bytes long with the additional parameter - longer than the function is expecting (as can be seen here

Taking a look at the crypto helper functions in aeternity core repo here: we can see that there is only der encoding supported currently, so the signature length is not the only stop.

A bit of info for developers trying to verify ethereum signed messages into Sophia smart contracts:

  • There is the possibility of conversion the RLP encoded signature to DER (theoretically possible, but I personally haven’t found any reliable info how to do so easily) and then feed it to the smart contract for verification.

I would have submitted a PR with the proposal otherwise, but I’m not an expert into cryptography, so that is why I’m posting this here, to start a discussion and bring more attention to this.
I would love to help with the efforts to support secp256k1 RLP encoded signature verification in Sophia as it would be very handy for developers later on.

Some helpers:


For some reason Ethereum has decided to provide and work with ecrecover - if I remember correctly that is basically signature verification with some extra stuff (that extra stuff is useful in some particular situations). For Sophia we opted to provide just the standard signature verification primitive. This is also symmetric to the curve25519 signature verification already in the system.

I don’t think anyone would strongly object to adding ecrecover to Sophia (and AEVM/FATE) - it shouldn’t be too hard although there needs to be some implementation effort at the crypto level (libsodium doesn’t support the Etherum quirks…) - there are no plans for this at the moment but if a well written set of patches would appear I am sure no one would turn them down!


Is there another way to implement and use secp256k1 RLP with generalised accounts? Or any other way you could think of?

This isn’t about RLP/DER, the existing function doesn’t imply any encoding.

The problem is that ecverify_secp256k1 does actual signature verification, not the “first do ecrecovery then do a comparison” variant that Ethereum has - this implies knowing the public key, not just the (compressed/short) address… So this is a mismatch if you come from Ethereum - the best solution would be to add ecrecover_secp256k1 - this isn’t impossible, but also not trivial.


What needs to be done to get ecrecover into Sophia?

  • extend libsodium
  • integrate a crypto library that supports it

ecrecover_secp256k1 is strongly needed and i think aeternity should implement it even if its not trivial :slight_smile: or is there any hack (on Sophia level) that we can use to verify those kind of messages without it?

libsodium is not involved here (my bad implying that), it is only used for ed25519 stuff, not the secp256k1 computations. For secp256k1 we use the built-in Erlang crypto module (backed by openssl). There is AFAIK no way to do the necessary ad hoc crypto operations with the crypto module (nor with libsodium) so we need to get them in another way - either implementing them or interfacing something that does have them.


Thanks for that!! What do you think is the expected workload implementing them (obviously we’re currently not aware with what we could interface that have it already).

1 Like