Skip to content

Instantly share code, notes, and snippets.

@LukaGiorgadze
Last active March 18, 2024 08:02
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save LukaGiorgadze/85b9e09d2008a03adfdfd5eea5964f93 to your computer and use it in GitHub Desktop.
Save LukaGiorgadze/85b9e09d2008a03adfdfd5eea5964f93 to your computer and use it in GitHub Desktop.
Golang ECDSA (Elliptic Curve Digital Signature Algorithm) example, generate Private/Public key pairs, verify and test
package ec
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/md5"
"crypto/rand"
"crypto/x509"
"encoding/pem"
"errors"
"io"
"reflect"
)
// Elliptic Curve Cryptography (ECC) is a key-based technique for encrypting data.
// ECC focuses on pairs of public and private keys for decryption and encryption of web traffic.
// ECC is frequently discussed in the context of the Rivest–Shamir–Adleman (RSA) cryptographic algorithm.
// EllipticCurve data struct
type EllipticCurve struct {
pubKeyCurve elliptic.Curve // http://golang.org/pkg/crypto/elliptic/#P256
privateKey *ecdsa.PrivateKey
publicKey *ecdsa.PublicKey
}
// New EllipticCurve instance
func New(curve elliptic.Curve) *EllipticCurve {
return &EllipticCurve{
pubKeyCurve: curve,
privateKey: new(ecdsa.PrivateKey),
}
}
// GenerateKeys EllipticCurve public and private keys
func (ec *EllipticCurve) GenerateKeys() (privKey *ecdsa.PrivateKey, pubKey *ecdsa.PublicKey, err error) {
privKey, err = ecdsa.GenerateKey(ec.pubKeyCurve, rand.Reader)
if err == nil {
ec.privateKey = privKey
ec.publicKey = &privKey.PublicKey
}
return
}
// EncodePrivate private key
func (ec *EllipticCurve) EncodePrivate(privKey *ecdsa.PrivateKey) (key string, err error) {
encoded, err := x509.MarshalECPrivateKey(privKey)
if err != nil {
return
}
pemEncoded := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: encoded})
key = string(pemEncoded)
return
}
// EncodePublic public key
func (ec *EllipticCurve) EncodePublic(pubKey *ecdsa.PublicKey) (key string, err error) {
encoded, err := x509.MarshalPKIXPublicKey(pubKey)
if err != nil {
return
}
pemEncodedPub := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: encoded})
key = string(pemEncodedPub)
return
}
// DecodePrivate private key
func (ec *EllipticCurve) DecodePrivate(pemEncodedPriv string) (privateKey *ecdsa.PrivateKey, err error) {
blockPriv, _ := pem.Decode([]byte(pemEncodedPriv))
x509EncodedPriv := blockPriv.Bytes
privateKey, err = x509.ParseECPrivateKey(x509EncodedPriv)
return
}
// DecodePublic public key
func (ec *EllipticCurve) DecodePublic(pemEncodedPub string) (publicKey *ecdsa.PublicKey, err error) {
blockPub, _ := pem.Decode([]byte(pemEncodedPub))
x509EncodedPub := blockPub.Bytes
genericPublicKey, err := x509.ParsePKIXPublicKey(x509EncodedPub)
publicKey = genericPublicKey.(*ecdsa.PublicKey)
return
}
// VerifySignature sign ecdsa style and verify signature
func (ec *EllipticCurve) VerifySignature(privKey *ecdsa.PrivateKey, pubKey *ecdsa.PublicKey) (signature []byte, ok bool, err error) {
h := md5.New()
_, err = io.WriteString(h, "This is a message to be signed and verified by ECDSA!")
if err != nil {
return
}
signhash := h.Sum(nil)
r, s, serr := ecdsa.Sign(rand.Reader, privKey, signhash)
if serr != nil {
return []byte(""), false, serr
}
signature = r.Bytes()
signature = append(signature, s.Bytes()...)
ok = ecdsa.Verify(pubKey, signhash, r, s)
return
}
// Can be used in _test.go
// Test encode, decode and test it with deep equal
func (ec *EllipticCurve) Test(privKey *ecdsa.PrivateKey, pubKey *ecdsa.PublicKey) (err error) {
encPriv, err := ec.EncodePrivate(privKey)
if err != nil {
return
}
encPub, err := ec.EncodePublic(pubKey)
if err != nil {
return
}
priv2, err := ec.DecodePrivate(encPriv)
if err != nil {
return
}
pub2, err := ec.DecodePublic(encPub)
if err != nil {
return
}
if !reflect.DeepEqual(privKey, priv2) {
err = errors.New("private keys do not match")
return
}
if !reflect.DeepEqual(pubKey, pub2) {
err = errors.New("public keys do not match")
return
}
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment