Skip to content

Commit cac9d1b

Browse files
committed
[FAB-3315] Certificate sanitization
In order to address the FAB, this change-set does the following: 1. When an msp identity is created, the corresponding x509 certificate gets sanitized first. Sanitization means the following: In case of certificate signed with ECDSA, the sanitization checks that the signature is in low-S, if this is not the case, a clone of the certificate is created with the new signature. Change-Id: I0ca6938d26dcc98352ccd1b5498a68cd670afdea Signed-off-by: Angelo De Caro <[email protected]>
1 parent 8c4fa8e commit cac9d1b

File tree

7 files changed

+469
-75
lines changed

7 files changed

+469
-75
lines changed

bccsp/sw/ecdsa.go

+59-23
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727
"github.com/hyperledger/fabric/bccsp"
2828
)
2929

30-
type ecdsaSignature struct {
30+
type ECDSASignature struct {
3131
R, S *big.Int
3232
}
3333

@@ -44,13 +44,13 @@ var (
4444
}
4545
)
4646

47-
func marshalECDSASignature(r, s *big.Int) ([]byte, error) {
48-
return asn1.Marshal(ecdsaSignature{r, s})
47+
func MarshalECDSASignature(r, s *big.Int) ([]byte, error) {
48+
return asn1.Marshal(ECDSASignature{r, s})
4949
}
5050

51-
func unmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
51+
func UnmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
5252
// Unmarshal
53-
sig := new(ecdsaSignature)
53+
sig := new(ECDSASignature)
5454
_, err := asn1.Unmarshal(raw, sig)
5555
if err != nil {
5656
return nil, nil, fmt.Errorf("Failed unmashalling signature [%s]", err)
@@ -80,40 +80,76 @@ func signECDSA(k *ecdsa.PrivateKey, digest []byte, opts bccsp.SignerOpts) (signa
8080
return nil, err
8181
}
8282

83-
// check for low-S
84-
halfOrder, ok := curveHalfOrders[k.Curve]
85-
if !ok {
86-
return nil, fmt.Errorf("Curve not recognized [%s]", k.Curve)
87-
}
88-
89-
// is s > halfOrder Then
90-
if s.Cmp(halfOrder) == 1 {
91-
// Set s to N - s that will be then in the lower part of signature space
92-
// less or equal to half order
93-
s.Sub(k.Params().N, s)
83+
s, _, err = ToLowS(&k.PublicKey, s)
84+
if err != nil {
85+
return nil, err
9486
}
9587

96-
return marshalECDSASignature(r, s)
88+
return MarshalECDSASignature(r, s)
9789
}
9890

9991
func verifyECDSA(k *ecdsa.PublicKey, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
100-
r, s, err := unmarshalECDSASignature(signature)
92+
r, s, err := UnmarshalECDSASignature(signature)
10193
if err != nil {
10294
return false, fmt.Errorf("Failed unmashalling signature [%s]", err)
10395
}
10496

105-
// check for low-S
97+
lowS, err := IsLowS(k, s)
98+
if err != nil {
99+
return false, err
100+
}
101+
102+
if !lowS {
103+
return false, fmt.Errorf("Invalid S. Must be smaller than half the order [%s][%s].", s, curveHalfOrders[k.Curve])
104+
}
105+
106+
return ecdsa.Verify(k, digest, r, s), nil
107+
}
108+
109+
func SignatureToLowS(k *ecdsa.PublicKey, signature []byte) ([]byte, error) {
110+
r, s, err := UnmarshalECDSASignature(signature)
111+
if err != nil {
112+
return nil, err
113+
}
114+
115+
s, modified, err := ToLowS(k, s)
116+
if err != nil {
117+
return nil, err
118+
}
119+
120+
if modified {
121+
return MarshalECDSASignature(r, s)
122+
}
123+
124+
return signature, nil
125+
}
126+
127+
// IsLow checks that s is a low-S
128+
func IsLowS(k *ecdsa.PublicKey, s *big.Int) (bool, error) {
106129
halfOrder, ok := curveHalfOrders[k.Curve]
107130
if !ok {
108131
return false, fmt.Errorf("Curve not recognized [%s]", k.Curve)
109132
}
110133

111-
// If s > halfOrder Then
112-
if s.Cmp(halfOrder) == 1 {
113-
return false, fmt.Errorf("Invalid S. Must be smaller than half the order [%s][%s].", s, halfOrder)
134+
return s.Cmp(halfOrder) != 1, nil
135+
136+
}
137+
138+
func ToLowS(k *ecdsa.PublicKey, s *big.Int) (*big.Int, bool, error) {
139+
lowS, err := IsLowS(k, s)
140+
if err != nil {
141+
return nil, false, err
142+
}
143+
144+
if !lowS {
145+
// Set s to N - s that will be then in the lower part of signature space
146+
// less or equal to half order
147+
s.Sub(k.Params().N, s)
148+
149+
return s, true, nil
114150
}
115151

116-
return ecdsa.Verify(k, digest, r, s), nil
152+
return s, false, nil
117153
}
118154

119155
type ecdsaSigner struct{}

bccsp/sw/ecdsa_test.go

+64-15
Original file line numberDiff line numberDiff line change
@@ -29,45 +29,45 @@ import (
2929
)
3030

3131
func TestUnmarshalECDSASignature(t *testing.T) {
32-
_, _, err := unmarshalECDSASignature(nil)
32+
_, _, err := UnmarshalECDSASignature(nil)
3333
assert.Error(t, err)
3434
assert.Contains(t, err.Error(), "Failed unmashalling signature [")
3535

36-
_, _, err = unmarshalECDSASignature([]byte{})
36+
_, _, err = UnmarshalECDSASignature([]byte{})
3737
assert.Error(t, err)
3838
assert.Contains(t, err.Error(), "Failed unmashalling signature [")
3939

40-
_, _, err = unmarshalECDSASignature([]byte{0})
40+
_, _, err = UnmarshalECDSASignature([]byte{0})
4141
assert.Error(t, err)
4242
assert.Contains(t, err.Error(), "Failed unmashalling signature [")
4343

44-
sigma, err := marshalECDSASignature(big.NewInt(-1), big.NewInt(1))
44+
sigma, err := MarshalECDSASignature(big.NewInt(-1), big.NewInt(1))
4545
assert.NoError(t, err)
46-
_, _, err = unmarshalECDSASignature(sigma)
46+
_, _, err = UnmarshalECDSASignature(sigma)
4747
assert.Error(t, err)
4848
assert.Contains(t, err.Error(), "Invalid signature. R must be larger than zero")
4949

50-
sigma, err = marshalECDSASignature(big.NewInt(0), big.NewInt(1))
50+
sigma, err = MarshalECDSASignature(big.NewInt(0), big.NewInt(1))
5151
assert.NoError(t, err)
52-
_, _, err = unmarshalECDSASignature(sigma)
52+
_, _, err = UnmarshalECDSASignature(sigma)
5353
assert.Error(t, err)
5454
assert.Contains(t, err.Error(), "Invalid signature. R must be larger than zero")
5555

56-
sigma, err = marshalECDSASignature(big.NewInt(1), big.NewInt(0))
56+
sigma, err = MarshalECDSASignature(big.NewInt(1), big.NewInt(0))
5757
assert.NoError(t, err)
58-
_, _, err = unmarshalECDSASignature(sigma)
58+
_, _, err = UnmarshalECDSASignature(sigma)
5959
assert.Error(t, err)
6060
assert.Contains(t, err.Error(), "Invalid signature. S must be larger than zero")
6161

62-
sigma, err = marshalECDSASignature(big.NewInt(1), big.NewInt(-1))
62+
sigma, err = MarshalECDSASignature(big.NewInt(1), big.NewInt(-1))
6363
assert.NoError(t, err)
64-
_, _, err = unmarshalECDSASignature(sigma)
64+
_, _, err = UnmarshalECDSASignature(sigma)
6565
assert.Error(t, err)
6666
assert.Contains(t, err.Error(), "Invalid signature. S must be larger than zero")
6767

68-
sigma, err = marshalECDSASignature(big.NewInt(1), big.NewInt(1))
68+
sigma, err = MarshalECDSASignature(big.NewInt(1), big.NewInt(1))
6969
assert.NoError(t, err)
70-
R, S, err := unmarshalECDSASignature(sigma)
70+
R, S, err := UnmarshalECDSASignature(sigma)
7171
assert.NoError(t, err)
7272
assert.Equal(t, big.NewInt(1), R)
7373
assert.Equal(t, big.NewInt(1), S)
@@ -126,10 +126,10 @@ func TestVerifyECDSA(t *testing.T) {
126126
assert.Error(t, err)
127127
assert.Contains(t, err.Error(), "Failed unmashalling signature [")
128128

129-
R, S, err := unmarshalECDSASignature(sigma)
129+
R, S, err := UnmarshalECDSASignature(sigma)
130130
assert.NoError(t, err)
131131
S.Add(curveHalfOrders[elliptic.P256()], big.NewInt(1))
132-
sigmaWrongS, err := marshalECDSASignature(R, S)
132+
sigmaWrongS, err := MarshalECDSASignature(R, S)
133133
assert.NoError(t, err)
134134
_, err = verifyECDSA(&lowLevelKey.PublicKey, sigmaWrongS, msg, nil)
135135
assert.Error(t, err)
@@ -236,3 +236,52 @@ func TestEcdsaPublicKey(t *testing.T) {
236236
assert.Error(t, err)
237237
assert.Contains(t, err.Error(), "Failed marshalling key [")
238238
}
239+
240+
func TestIsLowS(t *testing.T) {
241+
lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
242+
assert.NoError(t, err)
243+
244+
lowS, err := IsLowS(&lowLevelKey.PublicKey, big.NewInt(0))
245+
assert.NoError(t, err)
246+
assert.True(t, lowS)
247+
248+
s := new(big.Int)
249+
s = s.Set(curveHalfOrders[elliptic.P256()])
250+
251+
lowS, err = IsLowS(&lowLevelKey.PublicKey, s)
252+
assert.NoError(t, err)
253+
assert.True(t, lowS)
254+
255+
s = s.Add(s, big.NewInt(1))
256+
lowS, err = IsLowS(&lowLevelKey.PublicKey, s)
257+
assert.NoError(t, err)
258+
assert.False(t, lowS)
259+
s, modified, err := ToLowS(&lowLevelKey.PublicKey, s)
260+
assert.NoError(t, err)
261+
assert.True(t, modified)
262+
lowS, err = IsLowS(&lowLevelKey.PublicKey, s)
263+
assert.NoError(t, err)
264+
assert.True(t, lowS)
265+
}
266+
267+
func TestSignatureToLowS(t *testing.T) {
268+
lowLevelKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
269+
assert.NoError(t, err)
270+
271+
s := new(big.Int)
272+
s = s.Set(curveHalfOrders[elliptic.P256()])
273+
s = s.Add(s, big.NewInt(1))
274+
275+
lowS, err := IsLowS(&lowLevelKey.PublicKey, s)
276+
assert.NoError(t, err)
277+
assert.False(t, lowS)
278+
sigma, err := MarshalECDSASignature(big.NewInt(1), s)
279+
assert.NoError(t, err)
280+
sigma2, err := SignatureToLowS(&lowLevelKey.PublicKey, sigma)
281+
assert.NoError(t, err)
282+
_, s, err = UnmarshalECDSASignature(sigma2)
283+
assert.NoError(t, err)
284+
lowS, err = IsLowS(&lowLevelKey.PublicKey, s)
285+
assert.NoError(t, err)
286+
assert.True(t, lowS)
287+
}

bccsp/sw/impl_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -1039,35 +1039,35 @@ func TestKeyImportFromX509ECDSAPublicKey(t *testing.T) {
10391039

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

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

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

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

10691069
v = []byte{0x30, 0x0A, 0x02, 0x01, 0x8F, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x8F}
1070-
_, err = asn1.Unmarshal(v, &ecdsaSignature{})
1070+
_, err = asn1.Unmarshal(v, &ECDSASignature{})
10711071
if err == nil {
10721072
t.Fatalf("Unmarshalling should fail for [% x]", v)
10731073
}
@@ -1094,7 +1094,7 @@ func TestECDSALowS(t *testing.T) {
10941094
t.Fatalf("Failed generating ECDSA signature [%s]", err)
10951095
}
10961096

1097-
_, S, err := unmarshalECDSASignature(signature)
1097+
_, S, err := UnmarshalECDSASignature(signature)
10981098
if err != nil {
10991099
t.Fatalf("Failed unmarshalling signature [%s]", err)
11001100
}
@@ -1124,7 +1124,7 @@ func TestECDSALowS(t *testing.T) {
11241124
}
11251125
}
11261126

1127-
sig, err := marshalECDSASignature(R, S)
1127+
sig, err := MarshalECDSASignature(R, S)
11281128
if err != nil {
11291129
t.Fatalf("Failing unmarshalling signature [%s]", err)
11301130
}

0 commit comments

Comments
 (0)