Created
May 16, 2014 14:25
-
-
Save cmars/8b6b9917664299df2704 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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