Skip to content

Instantly share code, notes, and snippets.

@cmars
Created May 16, 2014 14:25
Show Gist options
  • Save cmars/8b6b9917664299df2704 to your computer and use it in GitHub Desktop.
Save cmars/8b6b9917664299df2704 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"flag"
"fmt"
"math/big"
"sort"
"time"
)
var privKey *ecdsa.PrivateKey
var signedTimes []float64
var verifyTimes []float64
type Message struct {
payload []byte
digest []byte
r, s *big.Int
}
var count *int = flag.Int("count", 1000, "Count of messages to sign and verify")
var size *int = flag.Int("size", 1000, "Size of message payload")
var keylen *int = flag.Int("keylen", 521, "ECDSA key length")
func main() {
flag.Parse()
var curve elliptic.Curve
switch *keylen {
case 256:
curve = elliptic.P256()
case 384:
curve = elliptic.P384()
case 521:
curve = elliptic.P521()
default:
panic(fmt.Errorf("unsupported key length"))
}
var err error
privKey, err = ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
panic(err)
}
c := make(chan Message)
done := make(chan struct{})
go generateSigned(*count, *size, c)
go verifySigned(c, done)
<-done
sort.Float64s(signedTimes)
sort.Float64s(verifyTimes)
var sumSigned, sumVerify float64
for i := 0; i < *count; i++ {
sumSigned += signedTimes[i]
sumVerify += verifyTimes[i]
}
fmt.Printf("ECDSA signing time: mean=%f median=%f ms\n", sumSigned/float64(*count), signedTimes[*count/2])
fmt.Printf("ECDSA verify time : mean=%f median=%f ms\n", sumVerify/float64(*count), verifyTimes[*count/2])
}
func generateSigned(n, size int, c chan Message) {
payload := make([]byte, size)
rand.Reader.Read(payload)
for i := 0; i < n; i++ {
start := time.Now()
h := sha256.New()
h.Write(payload)
digest := h.Sum(nil)
r, s, err := ecdsa.Sign(rand.Reader, privKey, digest)
if err != nil {
panic(err)
}
end := time.Now()
signedTimes = append(signedTimes, float64(end.Sub(start).Nanoseconds())/float64(1000000.0))
msg := Message{payload, digest, r, s}
c <- msg
}
close(c)
}
func verifySigned(c chan Message, done chan struct{}) {
for {
select {
case msg, ok := <-c:
if !ok {
close(done)
return
}
start := time.Now()
h := sha256.New()
h.Write(msg.payload)
digest := h.Sum(nil)
if bytes.Compare(digest, msg.digest) != 0 {
panic(fmt.Errorf("digests did not match: %x vs %x"))
}
sigOk := ecdsa.Verify(&privKey.PublicKey, digest, msg.r, msg.s)
if !sigOk {
panic(fmt.Errorf("invalid signature"))
}
end := time.Now()
verifyTimes = append(verifyTimes, float64(end.Sub(start).Nanoseconds())/float64(1000000.0))
case _, ok := <-done:
if !ok {
return
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment