2

I am using Golang to verify digital signatures, signed by ECDSA keys with secp256r1/scep384r1/secp521r1.

The difference in signature verification performance for secp256r1/scep384r1/secp521r1 is shocking.

For Digital signatures which are signed by key secp256r1, Golang is able to verify around 27k signatures per second.

For signatures which are signed by key secp384r1, it is able to verify around 1700 signatures per second and for signatures which are signed by key of secp521r1, just 350 signatures are being verified per second.

The difference in verification of digital signature is really huge, signature algorithm is same for all three cases i.e. SHA256withECDSA.

Sample code which is being used to verify signatures:

package main

import (
    "crypto/ecdsa"
    "crypto/sha256"
    "encoding/asn1"
    "encoding/base64"
    "encoding/json"
    "errors"
 //   "fmt"
    "math/big"
   "sync/atomic"
)

type ECDSASignature struct {
    R, S *big.Int
}

type Envelope struct {
    RawMessage json.RawMessage `json:"message"`
    Message    interface{}     `json:"-"`
    Signature  string          `json:"signature"`
}

func hash(b []byte) []byte {
    h := sha256.New()
    h.Write(b)
    return h.Sum(nil)
}

func (e *Envelope) Validate(publicKey *ecdsa.PublicKey) bool{
    der, err := base64.StdEncoding.DecodeString(e.Signature)
    if err != nil {
        return err
    }
    sig := &ECDSASignature{}
    _, err = asn1.Unmarshal(der, sig)
    if err != nil {
        return err
    }
    h := hash(e.RawMessage)
    valid := ecdsa.Verify(
        publicKey,
        h,
        sig.R,
        sig.S,
    )
    return valid 
}

Am I missing something here? Do I need to handle secp384r1 & secp521r1 differently for verifying signatures? How can I improve performance for verification of these signatures? Is it an expected behavior in Golang for these key types?

Nitish Bhardwaj
  • 1,113
  • 12
  • 29
  • 2
    have you tried `openssl speed ecdsap256 ecdsap384 ecdsap521` for comparison? The order of magnitude different between 256 and 384 is not unusual. Or search for [sample results](https://www.silicom-usa.com/silicom-pe3isco3-ecc-performance-tests-with-intel-8955/) out there. – Marc Oct 07 '20 at 05:56
  • @Marc Thanks for pointing to this. You just saved a day. :) I am glad that it's a usual behavior. – Nitish Bhardwaj Oct 07 '20 at 06:10
  • It might be worth asking this on the golang-nuts mailing list. – Volker Oct 07 '20 at 06:13
  • @Marc, I used multi core and these are the numbers I got for my machine: 256 bits ecdsa (nistp256) 0.0000s 0.0000s 552855.5 163878.5 384 bits ecdsa (nistp384) 0.0001s 0.0000s 15108.3 20175.4 521 bits ecdsa (nistp521) 0.0002s 0.0001s 6346.4 8970.1 There is a huge difference in 8970 and 350 though I am utilizing all core in both the programs. – Nitish Bhardwaj Oct 07 '20 at 10:27
  • [Peter](https://stackoverflow.com/users/14877425) posted an [Answer](https://stackoverflow.com/a/65423278) saying "P256 curve has optimized implementations for arm64 and amd64:https://go-review.googlesource.com/c/go/+/121360/" – Scratte Dec 23 '20 at 17:18
  • Thanks for the update. My requirements were to process all three EC curves signatures efficiently. I noticed that NodeJs has a capability to do so and it's performance is equivalent to Openssl on multiple cores. I switched to NodeJs for now until Golang is optimized for secp384r1 & secp521r1. – Nitish Bhardwaj Dec 24 '20 at 02:20

0 Answers0