86 lines
1.8 KiB
Go
86 lines
1.8 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"errors"
|
|
"io"
|
|
"math/big"
|
|
|
|
"github.com/tutus-one/tutus-consensus"
|
|
)
|
|
|
|
type (
|
|
// ECDSAPub is a wrapper over *ecsda.PublicKey.
|
|
ECDSAPub struct {
|
|
*ecdsa.PublicKey
|
|
}
|
|
|
|
// ECDSAPriv is a wrapper over *ecdsa.PrivateKey.
|
|
ECDSAPriv struct {
|
|
*ecdsa.PrivateKey
|
|
}
|
|
)
|
|
|
|
func generateECDSA(r io.Reader) (dbft.PrivateKey, dbft.PublicKey) {
|
|
key, err := ecdsa.GenerateKey(elliptic.P256(), r)
|
|
if err != nil {
|
|
return nil, nil
|
|
}
|
|
|
|
return NewECDSAPrivateKey(key), NewECDSAPublicKey(&key.PublicKey)
|
|
}
|
|
|
|
// NewECDSAPublicKey returns new PublicKey from *ecdsa.PublicKey.
|
|
func NewECDSAPublicKey(pub *ecdsa.PublicKey) dbft.PublicKey {
|
|
return &ECDSAPub{
|
|
PublicKey: pub,
|
|
}
|
|
}
|
|
|
|
// NewECDSAPrivateKey returns new PublicKey from *ecdsa.PrivateKey.
|
|
func NewECDSAPrivateKey(key *ecdsa.PrivateKey) dbft.PrivateKey {
|
|
return &ECDSAPriv{
|
|
PrivateKey: key,
|
|
}
|
|
}
|
|
|
|
// Sign signs message using P-256 curve.
|
|
func (e ECDSAPriv) Sign(msg []byte) ([]byte, error) {
|
|
h := sha256.Sum256(msg)
|
|
r, s, err := ecdsa.Sign(rand.Reader, e.PrivateKey, h[:])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sig := make([]byte, 32*2)
|
|
_ = r.FillBytes(sig[:32])
|
|
_ = s.FillBytes(sig[32:])
|
|
|
|
return sig, nil
|
|
}
|
|
|
|
// Equals implements dbft.PublicKey interface.
|
|
func (e *ECDSAPub) Equals(other dbft.PublicKey) bool {
|
|
return e.Equal(other.(*ECDSAPub).PublicKey)
|
|
}
|
|
|
|
// Compare does three-way comparison of ECDSAPub.
|
|
func (e *ECDSAPub) Compare(p *ECDSAPub) int {
|
|
return e.X.Cmp(p.X)
|
|
}
|
|
|
|
// Verify verifies signature using P-256 curve.
|
|
func (e ECDSAPub) Verify(msg, sig []byte) error {
|
|
h := sha256.Sum256(msg)
|
|
rBytes := new(big.Int).SetBytes(sig[0:32])
|
|
sBytes := new(big.Int).SetBytes(sig[32:64])
|
|
res := ecdsa.Verify(e.PublicKey, h[:], rBytes, sBytes)
|
|
if !res {
|
|
return errors.New("bad signature")
|
|
}
|
|
return nil
|
|
}
|