70 lines
1.7 KiB
Go
70 lines
1.7 KiB
Go
package ecdsa
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"math/big"
|
|
)
|
|
|
|
// GenPrivKey generates a new secp256r1 private key. It uses operating system randomness.
|
|
func GenPrivKey(curve elliptic.Curve) (PrivKey, error) {
|
|
key, err := ecdsa.GenerateKey(curve, rand.Reader)
|
|
if err != nil {
|
|
return PrivKey{}, err
|
|
}
|
|
return PrivKey{*key}, nil
|
|
}
|
|
|
|
type PrivKey struct {
|
|
ecdsa.PrivateKey
|
|
}
|
|
|
|
// PubKey returns ECDSA public key associated with this private key.
|
|
func (sk *PrivKey) PubKey() PubKey {
|
|
return PubKey{sk.PublicKey, nil}
|
|
}
|
|
|
|
// Bytes serialize the private key using big-endian.
|
|
func (sk *PrivKey) Bytes() []byte {
|
|
if sk == nil {
|
|
return nil
|
|
}
|
|
fieldSize := (sk.Curve.Params().BitSize + 7) / 8
|
|
bz := make([]byte, fieldSize)
|
|
sk.D.FillBytes(bz)
|
|
return bz
|
|
}
|
|
|
|
// Sign hashes and signs the message usign ECDSA. Implements SDK PrivKey interface.
|
|
func (sk *PrivKey) Sign(msg []byte) ([]byte, error) {
|
|
digest := sha256.Sum256(msg)
|
|
return sk.PrivateKey.Sign(rand.Reader, digest[:], nil)
|
|
}
|
|
|
|
// String returns a string representation of the public key based on the curveName.
|
|
func (sk *PrivKey) String(name string) string {
|
|
return name + "{-}"
|
|
}
|
|
|
|
// MarshalTo implements proto.Marshaler interface.
|
|
func (sk *PrivKey) MarshalTo(dAtA []byte) (int, error) {
|
|
bz := sk.Bytes()
|
|
copy(dAtA, bz)
|
|
return len(bz), nil
|
|
}
|
|
|
|
// Unmarshal implements proto.Marshaler interface.
|
|
func (sk *PrivKey) Unmarshal(bz []byte, curve elliptic.Curve, expectedSize int) error {
|
|
if len(bz) != expectedSize {
|
|
return fmt.Errorf("wrong ECDSA SK bytes, expecting %d bytes", expectedSize)
|
|
}
|
|
|
|
sk.Curve = curve
|
|
sk.D = new(big.Int).SetBytes(bz)
|
|
sk.X, sk.Y = curve.ScalarBaseMult(bz)
|
|
return nil
|
|
}
|