2019-02-07 09:04:29 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package pkcrypto
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"crypto/elliptic"
|
|
|
|
"crypto/rand"
|
|
|
|
)
|
|
|
|
|
|
|
|
var authECCurve = elliptic.P256()
|
|
|
|
|
|
|
|
// GeneratePrivateKey returns a new PrivateKey for signing messages
|
|
|
|
func GeneratePrivateKey() (*ecdsa.PrivateKey, error) {
|
|
|
|
return ecdsa.GenerateKey(authECCurve, rand.Reader)
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifySignature checks the signature against the passed data and public key
|
2019-02-07 17:08:52 +00:00
|
|
|
func VerifySignature(signedData, data []byte, pubKey crypto.PublicKey) error {
|
2019-02-07 09:04:29 +00:00
|
|
|
key, ok := pubKey.(*ecdsa.PublicKey)
|
|
|
|
if !ok {
|
|
|
|
return ErrUnsupportedKey.New("%T", key)
|
|
|
|
}
|
|
|
|
|
2019-02-07 18:40:28 +00:00
|
|
|
r, s, err := unmarshalECDSASignature(signedData)
|
|
|
|
if err != nil {
|
2019-02-07 09:04:29 +00:00
|
|
|
return ErrVerifySignature.New("unable to unmarshal ecdsa signature: %v", err)
|
|
|
|
}
|
2019-02-07 17:08:52 +00:00
|
|
|
digest := SHA256Hash(data)
|
2019-02-07 18:40:28 +00:00
|
|
|
if !ecdsa.Verify(key, digest, r, s) {
|
2019-02-07 09:04:29 +00:00
|
|
|
return ErrVerifySignature.New("signature is not valid")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SignBytes signs the given data with the private key and returns the new
|
|
|
|
// signature. Normally, data here is a digest of some longer string of bytes.
|
|
|
|
func SignBytes(key crypto.PrivateKey, data []byte) ([]byte, error) {
|
|
|
|
ecKey, ok := key.(*ecdsa.PrivateKey)
|
|
|
|
if !ok {
|
|
|
|
return nil, ErrUnsupportedKey.New("%T", key)
|
|
|
|
}
|
|
|
|
|
|
|
|
r, s, err := ecdsa.Sign(rand.Reader, ecKey, data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, ErrSign.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2019-02-07 18:40:28 +00:00
|
|
|
return marshalECDSASignature(r, s)
|
2019-02-07 09:04:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SignHashOf signs a SHA-256 digest of the given data and returns the new
|
|
|
|
// signature.
|
|
|
|
func SignHashOf(key crypto.PrivateKey, data []byte) ([]byte, error) {
|
2019-02-07 17:08:52 +00:00
|
|
|
hash := SHA256Hash(data)
|
2019-02-07 09:04:29 +00:00
|
|
|
signature, err := SignBytes(key, hash)
|
|
|
|
if err != nil {
|
|
|
|
return nil, ErrSign.Wrap(err)
|
|
|
|
}
|
|
|
|
return signature, nil
|
|
|
|
}
|