Skip to content

Commit 0cce607

Browse files
core/crypto: restrict RSA keys to <= 8192 bits (#2454)
* Error if RSA key is too big * Update core/crypto/rsa_common.go Co-authored-by: Marten Seemann <[email protected]> * Update core/crypto/rsa_common.go Co-authored-by: Marten Seemann <[email protected]> * Fix rename * Make this var again so the tests work --------- Co-authored-by: Marten Seemann <[email protected]>
1 parent 68ad5ea commit 0cce607

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

core/crypto/rsa_common.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ const WeakRsaKeyEnv = "LIBP2P_ALLOW_WEAK_RSA_KEYS"
1212

1313
var MinRsaKeyBits = 2048
1414

15+
var maxRsaKeyBits = 8192
16+
1517
// ErrRsaKeyTooSmall is returned when trying to generate or parse an RSA key
1618
// that's smaller than MinRsaKeyBits bits. In test
1719
var ErrRsaKeyTooSmall error
20+
var ErrRsaKeyTooBig error = fmt.Errorf("rsa keys must be <= %d bits", maxRsaKeyBits)
1821

1922
func init() {
2023
if _, ok := os.LookupEnv(WeakRsaKeyEnv); ok {

core/crypto/rsa_go.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ func GenerateRSAKeyPair(bits int, src io.Reader) (PrivKey, PubKey, error) {
3131
if bits < MinRsaKeyBits {
3232
return nil, nil, ErrRsaKeyTooSmall
3333
}
34+
if bits > maxRsaKeyBits {
35+
return nil, nil, ErrRsaKeyTooBig
36+
}
3437
priv, err := rsa.GenerateKey(src, bits)
3538
if err != nil {
3639
return nil, nil, err
@@ -124,6 +127,9 @@ func UnmarshalRsaPrivateKey(b []byte) (key PrivKey, err error) {
124127
if sk.N.BitLen() < MinRsaKeyBits {
125128
return nil, ErrRsaKeyTooSmall
126129
}
130+
if sk.N.BitLen() > maxRsaKeyBits {
131+
return nil, ErrRsaKeyTooBig
132+
}
127133
return &RsaPrivateKey{sk: *sk}, nil
128134
}
129135

@@ -141,6 +147,9 @@ func UnmarshalRsaPublicKey(b []byte) (key PubKey, err error) {
141147
if pk.N.BitLen() < MinRsaKeyBits {
142148
return nil, ErrRsaKeyTooSmall
143149
}
150+
if pk.N.BitLen() > maxRsaKeyBits {
151+
return nil, ErrRsaKeyTooBig
152+
}
144153

145154
return &RsaPublicKey{k: *pk}, nil
146155
}

core/crypto/rsa_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,44 @@ func TestRSASmallKey(t *testing.T) {
6868
}
6969
}
7070

71+
func TestRSABigKeyFailsToGenerate(t *testing.T) {
72+
_, _, err := GenerateRSAKeyPair(maxRsaKeyBits*2, rand.Reader)
73+
if err != ErrRsaKeyTooBig {
74+
t.Fatal("should have refused to create too big RSA key")
75+
}
76+
}
77+
78+
func TestRSABigKey(t *testing.T) {
79+
// Make the global limit smaller for this test to run faster.
80+
// Note we also change the limit below, but this is different
81+
origSize := maxRsaKeyBits
82+
maxRsaKeyBits = 2048
83+
defer func() { maxRsaKeyBits = origSize }() //
84+
85+
maxRsaKeyBits *= 2
86+
badPriv, badPub, err := GenerateRSAKeyPair(maxRsaKeyBits, rand.Reader)
87+
if err != nil {
88+
t.Fatalf("should have succeeded, got: %s", err)
89+
}
90+
pubBytes, err := MarshalPublicKey(badPub)
91+
if err != nil {
92+
t.Fatal(err)
93+
}
94+
privBytes, err := MarshalPrivateKey(badPriv)
95+
if err != nil {
96+
t.Fatal(err)
97+
}
98+
maxRsaKeyBits /= 2
99+
_, err = UnmarshalPublicKey(pubBytes)
100+
if err != ErrRsaKeyTooBig {
101+
t.Fatal("should have refused to unmarshal a too big key")
102+
}
103+
_, err = UnmarshalPrivateKey(privBytes)
104+
if err != ErrRsaKeyTooBig {
105+
t.Fatal("should have refused to unmarshal a too big key")
106+
}
107+
}
108+
71109
func TestRSASignZero(t *testing.T) {
72110
priv, pub, err := GenerateRSAKeyPair(2048, rand.Reader)
73111
if err != nil {

0 commit comments

Comments
 (0)