Skip to content

Commit 9baac02

Browse files
authored
Merge pull request #8 from aidantwoods/ed25519-validation
Validate ed25519 private keys during import
2 parents a0275ff + 6433e0b commit 9baac02

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

errors.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ var errorPayloadShort = fmt.Errorf("payload is not long enough to be a valid PAS
3434
var errorBadSignature = fmt.Errorf("bad signature")
3535
var errorBadMAC = fmt.Errorf("bad message authentication code")
3636

37+
var errorKeyInvalid = fmt.Errorf("key was not valid")
38+
3739
func errorDecrypt(err error) error {
3840
return fmt.Errorf("the message could not be decrypted: %w", err)
3941
}

keys_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package paseto_test
2+
3+
import (
4+
"testing"
5+
6+
"aidanwoods.dev/go-paseto"
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestV2AsymmetricSecretKeyImport(t *testing.T) {
11+
badKey := "4737385058576e39434c7537735233507544516e3337744f4245666e53376835636d664437784b646e44663454435257594a6356443530465177704a694b6f4c"
12+
13+
_, err := paseto.NewV2AsymmetricSecretKeyFromHex(badKey)
14+
require.Error(t, err)
15+
16+
goodKey := "b4cbfb43df4ce210727d953e4a713307fa19bb7d9f85041438d9e11b942a37741eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2"
17+
18+
_, err = paseto.NewV2AsymmetricSecretKeyFromHex(goodKey)
19+
require.NoError(t, err)
20+
}
21+
22+
func TestV4AsymmetricSecretKeyImport(t *testing.T) {
23+
badKey := "4737385058576e39434c7537735233507544516e3337744f4245666e53376835636d664437784b646e44663454435257594a6356443530465177704a694b6f4c"
24+
25+
_, err := paseto.NewV4AsymmetricSecretKeyFromHex(badKey)
26+
require.Error(t, err)
27+
28+
goodKey := "b4cbfb43df4ce210727d953e4a713307fa19bb7d9f85041438d9e11b942a37741eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2"
29+
30+
_, err = paseto.NewV4AsymmetricSecretKeyFromHex(goodKey)
31+
require.NoError(t, err)
32+
}

v2_keys.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ func NewV2AsymmetricSecretKeyFromBytes(privateKey []byte) (V2AsymmetricSecretKey
110110
return NewV2AsymmetricSecretKey(), errorKeyLength(64, len(privateKey))
111111
}
112112

113+
if isEd25519KeyPairMalformed(privateKey) {
114+
// even though we return error, return a random key here rather than
115+
// a nil key
116+
// This should catch poorly formed private keys (ones that do not embed
117+
// a public key which corresponds to their private portion)
118+
return NewV2AsymmetricSecretKey(), errorKeyInvalid
119+
}
120+
113121
return V2AsymmetricSecretKey{privateKey}, nil
114122
}
115123

v4_keys.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ func NewV4AsymmetricSecretKeyFromHex(hexEncoded string) (V4AsymmetricSecretKey,
104104
return NewV4AsymmetricSecretKeyFromBytes(privateKey)
105105
}
106106

107+
func isEd25519KeyPairMalformed(privateKey []byte) bool {
108+
seed := privateKey[:32]
109+
110+
pubKeyFromGiven := ed25519.PrivateKey(privateKey).Public().(ed25519.PublicKey)
111+
pubKeyFromSeed := ed25519.NewKeyFromSeed(seed).Public().(ed25519.PublicKey)
112+
113+
return !pubKeyFromGiven.Equal(pubKeyFromSeed)
114+
}
115+
107116
// NewV4AsymmetricSecretKeyFromBytes creates a secret key from bytes
108117
func NewV4AsymmetricSecretKeyFromBytes(privateKey []byte) (V4AsymmetricSecretKey, error) {
109118
if len(privateKey) != 64 {
@@ -112,6 +121,14 @@ func NewV4AsymmetricSecretKeyFromBytes(privateKey []byte) (V4AsymmetricSecretKey
112121
return NewV4AsymmetricSecretKey(), errorKeyLength(64, len(privateKey))
113122
}
114123

124+
if isEd25519KeyPairMalformed(privateKey) {
125+
// even though we return error, return a random key here rather than
126+
// a nil key
127+
// This should catch poorly formed private keys (ones that do not embed
128+
// a public key which corresponds to their private portion)
129+
return NewV4AsymmetricSecretKey(), errorKeyInvalid
130+
}
131+
115132
return V4AsymmetricSecretKey{privateKey}, nil
116133
}
117134

0 commit comments

Comments
 (0)