Skip to content

Instantly share code, notes, and snippets.

@nilsmagnus
Created September 20, 2019 12:41
Show Gist options
  • Save nilsmagnus/bcccb9ec2f30d403ca003bf06a20a4c7 to your computer and use it in GitHub Desktop.
Save nilsmagnus/bcccb9ec2f30d403ca003bf06a20a4c7 to your computer and use it in GitHub Desktop.
Sign/verify with rsa and ec comparison
package main
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"log"
"time"
"gonum.org/v1/plot"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/plotutil"
"gonum.org/v1/plot/vg"
)
type result struct {
ecTime int64
rsaTime int64
name string
}
func main() {
data := `This is the data we want to sign and verify, using both RSA and ECDSA algorithms.
EC is supposed to be lighter on the cpu, but hey, we have to check right?.`
iterations := 500
type bitSizePairs struct {
rsaBitSize int
ecBitSize elliptic.Curve
prettyName string
}
bitSizes := []bitSizePairs{
bitSizePairs{2048, elliptic.P224(), "2048/224"},
bitSizePairs{3072, elliptic.P256(), "3072/256"},
bitSizePairs{7680, elliptic.P384(), "7680/384"},
bitSizePairs{15360, elliptic.P521(), "15360/521"},
}
plots := make([]result, 0)
for _, bitSize := range bitSizes {
rsaPrivateKey, _ := rsa.GenerateKey(rand.Reader, bitSize.rsaBitSize)
ecPrivateKey, _ := ecdsa.GenerateKey(bitSize.ecBitSize, rand.Reader)
spentTimeEc := ecSignAndVerify(ecPrivateKey, data, iterations)
spentTimeRsa := rsaKeySignAndVerify(rsaPrivateKey, data, iterations)
plots = append(plots, result{spentTimeEc, spentTimeRsa, bitSize.prettyName})
log.Printf("%s (rsa-bitsize/ec-bitsize): \t%dns \t%dns", bitSize.prettyName, spentTimeRsa, spentTimeEc)
}
plots = append(plots, result{0, 0, ""})
drawPlots(plots, "plots.png")
}
func ecSignAndVerify(key *ecdsa.PrivateKey, data string, iterations int) int64 {
digest := sha256.Sum256([]byte(data))
t1 := time.Now()
for ; iterations > 0; iterations-- {
r, s, err := ecdsa.Sign(rand.Reader, key, digest[:])
if err != nil {
log.Fatal(err.Error())
}
if !ecdsa.Verify(&key.PublicKey, digest[:], r, s) {
log.Fatal("Signature not verified")
}
}
return time.Now().UnixNano() - t1.UnixNano()
}
func rsaKeySignAndVerify(key *rsa.PrivateKey, data string, iterations int) int64 {
digest := sha256.Sum256([]byte(data))
t1 := time.Now()
for ; iterations > 0; iterations-- {
signature, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, digest[:])
if err != nil {
log.Fatal(err.Error())
}
verificationErr := rsa.VerifyPKCS1v15(&key.PublicKey, crypto.SHA256, digest[:], signature)
if verificationErr != nil {
log.Fatal(err.Error())
}
}
return time.Now().UnixNano() - t1.UnixNano()
}
func drawPlots(results []result, filename string) error {
resultPlot, err := plot.New()
if err != nil {
panic(err)
}
resultPlot.Title.Text = "EC vs RSA sign/verify"
resultPlot.Y.Label.Text = "Time(ns)"
resultPlot.X.Label.Text = "Bitsizes"
groupWidth := vg.Points(20)
names := make([]string, 0)
ec := make(plotter.Values, 0)
rsa := make(plotter.Values, 0)
for _, res := range results {
names = append(names, res.name)
ec = append(ec, float64(res.ecTime))
rsa = append(rsa, float64(res.rsaTime))
}
eCbarGroup, err := plotter.NewBarChart(ec, groupWidth)
if err != nil {
return err
}
eCbarGroup.LineStyle.Width = vg.Length(0)
eCbarGroup.Color = plotutil.Color(1)
eCbarGroup.Offset = vg.Points(0)
resultPlot.Add(eCbarGroup)
resultPlot.Legend.Add("EC", eCbarGroup)
rsabarGroup, err := plotter.NewBarChart(rsa, groupWidth)
if err != nil {
return err
}
rsabarGroup.LineStyle.Width = vg.Length(0)
rsabarGroup.Color = plotutil.Color(2)
rsabarGroup.Offset = vg.Points(20)
resultPlot.Add(rsabarGroup)
resultPlot.Legend.Add("RSA", rsabarGroup)
resultPlot.Legend.Top = true
resultPlot.NominalX(names...)
return resultPlot.Save(6*vg.Inch, 4*vg.Inch, filename)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment