Ed25519 vs bls performance

SAFE network uses two types of asymmetric keys, ED25519 keys and BLS keys.

Sometimes the choice may be due to functionality, eg multisig is built in to bls whereas ed25519 requires custom code to do multisig.

Sometimes the choice may be due to performance (otherwise why not just use bls everywhere?).

Out of curiosity I had a look at how much difference there is between the two for signing and verifying.

All values are in microseconds per signature/verification, and is the average of 1000 samples. BLS is using a single keypair, ie not requiring any combining of signature shares, as a standard safecoin wallet would be doing.

BLS ED25519 BLS/ED25519
Sign 32 bytes 2220.78 19.36 114.72
Sign 1 MiB 5822.96 5826.58 1.00
Verify 32 bytes sig 5983.90 50.52 118.45
Verify 1 MiB sig 9478.69 2624.92 3.61

Signing small messages, BLS is about 100 times slower.

Signing large messages, they are identical, which was a big surprise to me.

Verifying signatures of small messages BLS is about 100 times slower.

Verify signatures of large messages BLS is about 3 times slower.

The info is I suppose not produced with any intention in mind, but I thought it was interesting to see the difference so I’ll put the figures here.


Me too, I had thought bls always slower. BTW @mav were these done using the libs we are using? I know some BLS impl’s are quite a bit slower again.



Code is here: https://github.com/iancoleman/ed25519_vs_bls_key_benchmarks

ed25519-dalek = "1.0.0"
threshold_crypto = "0.4.0"

Not sure if there’s any significant difference between ed25519-dalek 1.0.0 vs 1.0.0-pre.3 as used in maidsafe/routing, but I assume not.

Would be interested in others results.


Here are my results (similar to yours):

BLS ED25519 BLS/ED25519
Sign 32B (µs) 3428.03 27.91 122.84
Sign 1MiB (µs) 8354.38 7677.05 1.09
Verify 32B (µs) 8492.67 73.78 115.11
Verify 1MiB (µs) 13616.37 3924.91 3.47

As a random question, what does this mean for the ultimate performance of SAFE? How many verify operations are actually carried out? With a naiive reading, I see 8ms/verify32 = ~ 120 verifies/second per core? How many is a vault actually performing?


Would be good to know. For any individual vault it depends on

  • is elder or not
  • how many other nodes it’s connected to, ie network size and section size
  • the current rate of GET / PUT from clients
  • the amount of churn happening

So it’s a complex equation.

I’d be interested to see this info logged at some point so we can get some idea of it in testnets.


Hmm… If this is going to be some kind of a bottleneck, is it possible to make ASICs for these signature processes?


IMO This shows we should consider BLS a lot more. For multisig it’s great, however when not multisig then we should be using ed keys. Right now clients are all BLS, but that may need to change. Not a huge deal (it’s just another algo) so Signature for us may need to become

pub enum Signature {

So not a showstopper in any sense. It’s things like these checks @mav and others do that allow us to be significantly more efficient. We knew bls is much slower, but seeing it laid out is a compelling picture and stops us from ignoring that fact. Many client actions will be small messages so it makes sense, if a data item is individually owned then we use ed keys, otherwise, we use BLS keys. So all BLS use will be multisig and never individual key use, which is actually nice.


I thought that its typically the hash of a message youre signing, not the message itself, because of the slowness of pubkey crypto? But BLS seem not to be that bad for large msgs.


Yes, good point.

bls threshold_crypto uses sha3-256 for signatures

ed25519-dalek uses sha2-512 for signatures

I added these two hash functions to the test, these are the results

SHA2-512 SHA3-256 SHA2 / ED25519 Sign SHA3 / BLS Sign
32B (µs) 0.358 0.494 0.0194 0.0002
1 MiB (µs) 2607.408 3477.901 0.5081 0.6141

For small messages signature hashing is a tiny portion of the total time, less than 2%.

For large messages signature hashing is around 50-60% of the total time.

Added to the benchmarking tool in commit 4d64af4.


Should you be comparing sha2-512 to sha3-512?

The idea is to see what portion of the signing time is spent doing the hash, so it must be using the underlying hash in the implementations.

For bls (github.com/poanetwork/threshold_crypto) this is sha3_256

For ed25519 (github.com/dalek-cryptography/ed25519-dalek) this is sha2-512

So the comparison, despite being different lengths, is valid since it allows us to see the portion of time spent during each signature on the hashing.

This made me wonder though if we could remove the dependency on sha2-512 and use only sha3-256, since ed25519-dalek has a function sign_prehashed. But then I saw within that functin sha2-512 is called anyhow so there’s no avoiding it. Nice little comment to go with it: