Skip to content

Commit

Permalink
Merge "[FAB-7107] BCCSP common ECDSA utils"
Browse files Browse the repository at this point in the history
  • Loading branch information
mastersingh24 authored and Gerrit Code Review committed Nov 29, 2017
2 parents 92be90e + 62b0e22 commit 56638b7
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 385 deletions.
82 changes: 11 additions & 71 deletions bccsp/pkcs11/ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,99 +17,39 @@ package pkcs11

import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/asn1"
"errors"
"fmt"
"math/big"

"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/utils"
)

type ecdsaSignature struct {
R, S *big.Int
}

var (
// curveHalfOrders contains the precomputed curve group orders halved.
// It is used to ensure that signature' S value is lower or equal to the
// curve group order halved. We accept only low-S signatures.
// They are precomputed for efficiency reasons.
curveHalfOrders map[elliptic.Curve]*big.Int = map[elliptic.Curve]*big.Int{
elliptic.P224(): new(big.Int).Rsh(elliptic.P224().Params().N, 1),
elliptic.P256(): new(big.Int).Rsh(elliptic.P256().Params().N, 1),
elliptic.P384(): new(big.Int).Rsh(elliptic.P384().Params().N, 1),
elliptic.P521(): new(big.Int).Rsh(elliptic.P521().Params().N, 1),
}
)

func marshalECDSASignature(r, s *big.Int) ([]byte, error) {
return asn1.Marshal(ecdsaSignature{r, s})
}

func unmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
// Unmarshal
sig := new(ecdsaSignature)
_, err := asn1.Unmarshal(raw, sig)
if err != nil {
return nil, nil, fmt.Errorf("Failed unmashalling signature [%s]", err)
}

// Validate sig
if sig.R == nil {
return nil, nil, errors.New("Invalid signature. R must be different from nil.")
}
if sig.S == nil {
return nil, nil, errors.New("Invalid signature. S must be different from nil.")
}

if sig.R.Sign() != 1 {
return nil, nil, errors.New("Invalid signature. R must be larger than zero")
}
if sig.S.Sign() != 1 {
return nil, nil, errors.New("Invalid signature. S must be larger than zero")
}

return sig.R, sig.S, nil
}

func (csp *impl) signECDSA(k ecdsaPrivateKey, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
r, s, err := csp.signP11ECDSA(k.ski, digest)
if err != nil {
return nil, err
}

// check for low-S
halfOrder, ok := curveHalfOrders[k.pub.pub.Curve]
if !ok {
return nil, fmt.Errorf("Curve not recognized [%s]", k.pub.pub.Curve)
}

// is s > halfOrder Then
if s.Cmp(halfOrder) == 1 {
// Set s to N - s that will be then in the lower part of signature space
// less or equal to half order
s.Sub(k.pub.pub.Params().N, s)
s, _, err = utils.ToLowS(k.pub.pub, s)
if err != nil {
return nil, err
}

return marshalECDSASignature(r, s)
return utils.MarshalECDSASignature(r, s)
}

func (csp *impl) verifyECDSA(k ecdsaPublicKey, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
r, s, err := unmarshalECDSASignature(signature)
r, s, err := utils.UnmarshalECDSASignature(signature)
if err != nil {
return false, fmt.Errorf("Failed unmashalling signature [%s]", err)
}

// check for low-S
halfOrder, ok := curveHalfOrders[k.pub.Curve]
if !ok {
return false, fmt.Errorf("Curve not recognized [%s]", k.pub.Curve)
lowS, err := utils.IsLowS(k.pub, s)
if err != nil {
return false, err
}

// If s > halfOrder Then
if s.Cmp(halfOrder) == 1 {
return false, fmt.Errorf("Invalid S. Must be smaller than half the order [%s][%s].", s, halfOrder)
if !lowS {
return false, fmt.Errorf("Invalid S. Must be smaller than half the order [%s][%s].", s, utils.GetCurveHalfOrdersAt(k.pub.Curve))
}

if csp.softVerify {
Expand Down
69 changes: 0 additions & 69 deletions bccsp/pkcs11/ecdsa_test.go

This file was deleted.

18 changes: 9 additions & 9 deletions bccsp/pkcs11/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1066,35 +1066,35 @@ func TestKeyImportFromX509ECDSAPublicKey(t *testing.T) {

func TestECDSASignatureEncoding(t *testing.T) {
v := []byte{0x30, 0x07, 0x02, 0x01, 0x8F, 0x02, 0x02, 0xff, 0xf1}
_, err := asn1.Unmarshal(v, &ecdsaSignature{})
_, err := asn1.Unmarshal(v, &utils.ECDSASignature{})
if err == nil {
t.Fatalf("Unmarshalling should fail for [% x]", v)
}
t.Logf("Unmarshalling correctly failed for [% x] [%s]", v, err)

v = []byte{0x30, 0x07, 0x02, 0x01, 0x8F, 0x02, 0x02, 0x00, 0x01}
_, err = asn1.Unmarshal(v, &ecdsaSignature{})
_, err = asn1.Unmarshal(v, &utils.ECDSASignature{})
if err == nil {
t.Fatalf("Unmarshalling should fail for [% x]", v)
}
t.Logf("Unmarshalling correctly failed for [% x] [%s]", v, err)

v = []byte{0x30, 0x07, 0x02, 0x01, 0x8F, 0x02, 0x81, 0x01, 0x01}
_, err = asn1.Unmarshal(v, &ecdsaSignature{})
_, err = asn1.Unmarshal(v, &utils.ECDSASignature{})
if err == nil {
t.Fatalf("Unmarshalling should fail for [% x]", v)
}
t.Logf("Unmarshalling correctly failed for [% x] [%s]", v, err)

v = []byte{0x30, 0x07, 0x02, 0x01, 0x8F, 0x02, 0x81, 0x01, 0x8F}
_, err = asn1.Unmarshal(v, &ecdsaSignature{})
_, err = asn1.Unmarshal(v, &utils.ECDSASignature{})
if err == nil {
t.Fatalf("Unmarshalling should fail for [% x]", v)
}
t.Logf("Unmarshalling correctly failed for [% x] [%s]", v, err)

v = []byte{0x30, 0x0A, 0x02, 0x01, 0x8F, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x8F}
_, err = asn1.Unmarshal(v, &ecdsaSignature{})
_, err = asn1.Unmarshal(v, &utils.ECDSASignature{})
if err == nil {
t.Fatalf("Unmarshalling should fail for [% x]", v)
}
Expand All @@ -1121,12 +1121,12 @@ func TestECDSALowS(t *testing.T) {
t.Fatalf("Failed generating ECDSA signature [%s]", err)
}

R, S, err := unmarshalECDSASignature(signature)
R, S, err := utils.UnmarshalECDSASignature(signature)
if err != nil {
t.Fatalf("Failed unmarshalling signature [%s]", err)
}

if S.Cmp(curveHalfOrders[k.(*ecdsaPrivateKey).pub.pub.Curve]) >= 0 {
if S.Cmp(utils.GetCurveHalfOrdersAt(k.(*ecdsaPrivateKey).pub.pub.Curve)) >= 0 {
t.Fatal("Invalid signature. It must have low-S")
}

Expand All @@ -1145,12 +1145,12 @@ func TestECDSALowS(t *testing.T) {
t.Fatalf("Failed generating signature [%s]", err)
}

if S.Cmp(curveHalfOrders[k.(*ecdsaPrivateKey).pub.pub.Curve]) > 0 {
if S.Cmp(utils.GetCurveHalfOrdersAt(k.(*ecdsaPrivateKey).pub.pub.Curve)) > 0 {
break
}
}

sig, err := marshalECDSASignature(R, S)
sig, err := utils.MarshalECDSASignature(R, S)
if err != nil {
t.Fatalf("Failing unmarshalling signature [%s]", err)
}
Expand Down
108 changes: 6 additions & 102 deletions bccsp/sw/ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,141 +17,45 @@ package sw

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/asn1"
"errors"
"fmt"
"math/big"

"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/utils"
)

type ECDSASignature struct {
R, S *big.Int
}

var (
// curveHalfOrders contains the precomputed curve group orders halved.
// It is used to ensure that signature' S value is lower or equal to the
// curve group order halved. We accept only low-S signatures.
// They are precomputed for efficiency reasons.
curveHalfOrders map[elliptic.Curve]*big.Int = map[elliptic.Curve]*big.Int{
elliptic.P224(): new(big.Int).Rsh(elliptic.P224().Params().N, 1),
elliptic.P256(): new(big.Int).Rsh(elliptic.P256().Params().N, 1),
elliptic.P384(): new(big.Int).Rsh(elliptic.P384().Params().N, 1),
elliptic.P521(): new(big.Int).Rsh(elliptic.P521().Params().N, 1),
}
)

func MarshalECDSASignature(r, s *big.Int) ([]byte, error) {
return asn1.Marshal(ECDSASignature{r, s})
}

func UnmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
// Unmarshal
sig := new(ECDSASignature)
_, err := asn1.Unmarshal(raw, sig)
if err != nil {
return nil, nil, fmt.Errorf("Failed unmashalling signature [%s]", err)
}

// Validate sig
if sig.R == nil {
return nil, nil, errors.New("Invalid signature. R must be different from nil.")
}
if sig.S == nil {
return nil, nil, errors.New("Invalid signature. S must be different from nil.")
}

if sig.R.Sign() != 1 {
return nil, nil, errors.New("Invalid signature. R must be larger than zero")
}
if sig.S.Sign() != 1 {
return nil, nil, errors.New("Invalid signature. S must be larger than zero")
}

return sig.R, sig.S, nil
}

func signECDSA(k *ecdsa.PrivateKey, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
r, s, err := ecdsa.Sign(rand.Reader, k, digest)
if err != nil {
return nil, err
}

s, _, err = ToLowS(&k.PublicKey, s)
s, _, err = utils.ToLowS(&k.PublicKey, s)
if err != nil {
return nil, err
}

return MarshalECDSASignature(r, s)
return utils.MarshalECDSASignature(r, s)
}

func verifyECDSA(k *ecdsa.PublicKey, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
r, s, err := UnmarshalECDSASignature(signature)
r, s, err := utils.UnmarshalECDSASignature(signature)
if err != nil {
return false, fmt.Errorf("Failed unmashalling signature [%s]", err)
}

lowS, err := IsLowS(k, s)
lowS, err := utils.IsLowS(k, s)
if err != nil {
return false, err
}

if !lowS {
return false, fmt.Errorf("Invalid S. Must be smaller than half the order [%s][%s].", s, curveHalfOrders[k.Curve])
return false, fmt.Errorf("Invalid S. Must be smaller than half the order [%s][%s].", s, utils.GetCurveHalfOrdersAt(k.Curve))
}

return ecdsa.Verify(k, digest, r, s), nil
}

func SignatureToLowS(k *ecdsa.PublicKey, signature []byte) ([]byte, error) {
r, s, err := UnmarshalECDSASignature(signature)
if err != nil {
return nil, err
}

s, modified, err := ToLowS(k, s)
if err != nil {
return nil, err
}

if modified {
return MarshalECDSASignature(r, s)
}

return signature, nil
}

// IsLow checks that s is a low-S
func IsLowS(k *ecdsa.PublicKey, s *big.Int) (bool, error) {
halfOrder, ok := curveHalfOrders[k.Curve]
if !ok {
return false, fmt.Errorf("Curve not recognized [%s]", k.Curve)
}

return s.Cmp(halfOrder) != 1, nil

}

func ToLowS(k *ecdsa.PublicKey, s *big.Int) (*big.Int, bool, error) {
lowS, err := IsLowS(k, s)
if err != nil {
return nil, false, err
}

if !lowS {
// Set s to N - s that will be then in the lower part of signature space
// less or equal to half order
s.Sub(k.Params().N, s)

return s, true, nil
}

return s, false, nil
}

type ecdsaSigner struct{}

func (s *ecdsaSigner) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
Expand Down
Loading

0 comments on commit 56638b7

Please sign in to comment.