Repository: codenotary/immudb
File: pkg/signer/ecdsa.go (Go)

Code before:
}

// NewSignerFromPKey returns a signer from a io.Reader and a *ecdsa.PrivateKey.
func NewSignerFromPKey(r io.Reader, pk *ecdsa.PrivateKey) Signer {
	return signer{rand: r, privateKey: pk}
}

// sign sign a payload and returns asn1 marshal byte sequence
func (sig signer) Sign(payload []byte) ([]byte, []byte, error) {
	hash := sha256.Sum256(payload)
	r, s, err := ecdsa.Sign(sig.rand, sig.privateKey, hash[:])
	if err != nil {
		return nil, nil, err
	}
	sigToMarshal := ecdsaSignature{R: r, S: s}
	m, _ := asn1.Marshal(sigToMarshal)
	pk := sig.privateKey.PublicKey
	p := elliptic.Marshal(pk.Curve, pk.X, pk.Y)

	return m, p, nil
}

func UnmarshalKey(publicKey []byte) (*ecdsa.PublicKey, error) {
	x, y := elliptic.Unmarshal(elliptic.P256(), publicKey)
	if x == nil {
		return nil, errors.New("invalid public key")
	}
	return &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}, nil
}

// verify verifies a signed payload
func Verify(payload []byte, signature []byte, publicKey *ecdsa.PublicKey) (bool, error) {
	hash := sha256.Sum256(payload)
	es := ecdsaSignature{}
	if _, err := asn1.Unmarshal(signature, &es); err != nil {
		return false, err
	}
	return ecdsa.Verify(publicKey, hash[:], es.R, es.S), nil
}

func ParsePublicKeyFile(filePath string) (*ecdsa.PublicKey, error) {
	publicKeyBytes, err := ioutil.ReadFile(filePath)
	if err != nil {
		return nil, err
	}
	publicKeyBlock, _ := pem.Decode(publicKeyBytes)
	if publicKeyBlock == nil {
		return nil, errors.New("no ecdsa key found in provided public key file")
	}
	cert, err := x509.ParsePKIXPublicKey(publicKeyBlock.Bytes)
	if err != nil {

Review comment (refactor):
Please extract this error into a variable (like in https://github.com/codenotary/immudb/blob/master/embedded/ahtree/ahtree.go#L33) - that way the value returned from `UnmarshalKey` can easily be compared with a set of known errors.

Code after:
	}
	return signer{rand: rand.Reader, privateKey: privateKey}, nil
}

// NewSignerFromPKey returns a signer from a io.Reader and a *ecdsa.PrivateKey.
func NewSignerFromPKey(r io.Reader, pk *ecdsa.PrivateKey) Signer {
	return signer{rand: r, privateKey: pk}
}

// sign sign a payload and returns asn1 marshal byte sequence
func (sig signer) Sign(payload []byte) ([]byte, []byte, error) {
	hash := sha256.Sum256(payload)
	r, s, err := ecdsa.Sign(sig.rand, sig.privateKey, hash[:])
	if err != nil {
		return nil, nil, err
	}
	sigToMarshal := ecdsaSignature{R: r, S: s}
	m, _ := asn1.Marshal(sigToMarshal)
	pk := sig.privateKey.PublicKey
	p := elliptic.Marshal(pk.Curve, pk.X, pk.Y)

	return m, p, nil
}

func UnmarshalKey(publicKey []byte) (*ecdsa.PublicKey, error) {
	x, y := elliptic.Unmarshal(elliptic.P256(), publicKey)
	if x == nil {
		return nil, ErrInvalidPublicKey
	}
	return &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}, nil
}

// verify verifies a signed payload
func Verify(payload []byte, signature []byte, publicKey *ecdsa.PublicKey) (bool, error) {
	hash := sha256.Sum256(payload)
	es := ecdsaSignature{}
	if _, err := asn1.Unmarshal(signature, &es); err != nil {
		return false, err
	}
	return ecdsa.Verify(publicKey, hash[:], es.R, es.S), nil
}

func ParsePublicKeyFile(filePath string) (*ecdsa.PublicKey, error) {
	publicKeyBytes, err := ioutil.ReadFile(filePath)
	if err != nil {
		return nil, err
	}
	publicKeyBlock, _ := pem.Decode(publicKeyBytes)
	if publicKeyBlock == nil {
		return nil, errors.New("no ecdsa key found in provided public key file")
	}