Skip to content

Commit ac95117

Browse files
committed
Update libraries for ed25519 + curve25519 key support
1 parent aec058e commit ac95117

4 files changed

Lines changed: 43 additions & 46 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/google/uuid v1.6.0
1111
github.com/json-iterator/go v1.1.12
1212
github.com/mr-tron/base58 v1.2.0
13+
github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729
1314
go.mongodb.org/mongo-driver/v2 v2.5.0
1415
)
1516

@@ -61,7 +62,6 @@ require (
6162
)
6263

6364
require (
64-
filippo.io/edwards25519 v1.2.0
6565
github.com/AlekSi/pointer v1.2.0
6666
github.com/buger/jsonparser v1.1.2
6767
github.com/davecgh/go-spew v1.1.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIi
44
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
55
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
66
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
7-
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
8-
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
97
github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w=
108
github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0=
119
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
@@ -106,6 +104,8 @@ github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
106104
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
107105
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
108106
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
107+
github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 h1:yfQ2sO9WJXUAIUR+g7NUkxJSKCAFJcR5sUDu+ZmjTZI=
108+
github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s=
109109
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
110110
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
111111
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=

keys.go

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ package solana
2020
import (
2121
"bytes"
2222
"crypto"
23-
"crypto/ed25519"
2423
crypto_rand "crypto/rand"
2524
"crypto/sha256"
2625
"errors"
@@ -29,9 +28,10 @@ import (
2928
"os"
3029
"sort"
3130

32-
"filippo.io/edwards25519/field"
3331
"github.com/gagliardetto/solana-go/base58"
3432
mrtronbase58 "github.com/mr-tron/base58"
33+
"github.com/oasisprotocol/curve25519-voi/curve"
34+
voied25519 "github.com/oasisprotocol/curve25519-voi/primitives/ed25519"
3535
"go.mongodb.org/mongo-driver/v2/bson"
3636
)
3737

@@ -69,17 +69,17 @@ func PrivateKeyFromBase58(privkey string) (PrivateKey, error) {
6969
}
7070

7171
func ValidatePrivateKey(b []byte) (bool, error) {
72-
if len(b) != ed25519.PrivateKeySize {
73-
return false, fmt.Errorf("invalid private key size, expected %v, got %d", ed25519.PrivateKeySize, len(b))
74-
}
75-
76-
// ed25519 private keys are seed(32) + public(32); ensure they match.
77-
derived := ed25519.NewKeyFromSeed(b[:ed25519.SeedSize])
78-
if !bytes.Equal(derived, b) {
79-
if !IsOnCurve(b[ed25519.SeedSize:]) {
80-
return false, errors.New("invalid private key: seed/public key mismatch (provided public key is NOT on the ed25519 curve)")
81-
}
82-
return false, errors.New("invalid private key: seed/public key mismatch")
72+
if len(b) != voied25519.PrivateKeySize {
73+
return false, fmt.Errorf("invalid private key size, expected %v, got %d", voied25519.PrivateKeySize, len(b))
74+
}
75+
<<<<<<< HEAD
76+
// check if the public key is on the ed25519 curve
77+
=======
78+
// check if the public key is on the voied25519 curve
79+
>>>>>>> f4f19e0 (rename)
80+
pub := voied25519.PrivateKey(b).Public().(voied25519.PublicKey)
81+
if !IsOnCurve(pub) {
82+
return false, errors.New("the corresponding public key is NOT on the voied25519 curve")
8383
}
8484
return true, nil
8585
}
@@ -114,7 +114,7 @@ func (k PrivateKey) String() string {
114114
}
115115

116116
func NewRandomPrivateKey() (PrivateKey, error) {
117-
pub, priv, err := ed25519.GenerateKey(crypto_rand.Reader)
117+
pub, priv, err := voied25519.GenerateKey(crypto_rand.Reader)
118118
if err != nil {
119119
return nil, err
120120
}
@@ -127,7 +127,7 @@ func (k PrivateKey) Sign(payload []byte) (Signature, error) {
127127
if err := k.Validate(); err != nil {
128128
return Signature{}, err
129129
}
130-
p := ed25519.PrivateKey(k)
130+
p := voied25519.PrivateKey(k)
131131
signData, err := p.Sign(crypto_rand.Reader, payload, crypto.Hash(0))
132132
if err != nil {
133133
return Signature{}, err
@@ -144,8 +144,8 @@ func (k PrivateKey) PublicKey() PublicKey {
144144
panic(err)
145145
}
146146

147-
p := ed25519.PrivateKey(k)
148-
pub := p.Public().(ed25519.PublicKey)
147+
p := voied25519.PrivateKey(k)
148+
pub := p.Public().(voied25519.PublicKey)
149149

150150
var publicKey PublicKey
151151
copy(publicKey[:], pub)
@@ -156,9 +156,17 @@ func (k PrivateKey) PublicKey() PublicKey {
156156
// PK is a convenience alias for PublicKey
157157
type PK = PublicKey
158158

159+
<<<<<<< HEAD
160+
// done to keep verify the same as stdlib crypto/ed25519
161+
=======
162+
// done to keep verify the same as stdlib crypto/voied25519
163+
>>>>>>> f4f19e0 (rename)
164+
var verifyOptsStdLib = &voied25519.Options{
165+
Verify: voied25519.VerifyOptionsStdLib,
166+
}
167+
159168
func (p PublicKey) Verify(message []byte, signature Signature) bool {
160-
pub := ed25519.PublicKey(p[:])
161-
return ed25519.Verify(pub, message, signature[:])
169+
return voied25519.VerifyWithOptions(p[:], message, signature[:], verifyOptsStdLib)
162170
}
163171

164172
type PublicKey [PublicKeyLength]byte
@@ -300,7 +308,7 @@ func (p PublicKey) Bytes() []byte {
300308
return []byte(p[:])
301309
}
302310

303-
// Check if a `Pubkey` is on the ed25519 curve.
311+
// Check if a `Pubkey` is on the voied25519 curve.
304312
func (p PublicKey) IsOnCurve() bool {
305313
return IsOnCurve(p[:])
306314
}
@@ -621,7 +629,7 @@ const (
621629
SignatureLength = 64
622630

623631
// Number of bytes in a private key.
624-
PrivateKeyLength = ed25519.PrivateKeySize
632+
PrivateKeyLength = voied25519.PrivateKeySize
625633

626634
// // Maximum string length of a base58 encoded pubkey.
627635
// MaxBase58Length = 44
@@ -682,32 +690,20 @@ func CreateProgramAddress(seeds [][]byte, programID PublicKey) (PublicKey, error
682690
return PublicKeyFromBytes(hash[:]), nil
683691
}
684692

685-
var feOne = new(field.Element).One()
686-
var d, _ = new(field.Element).SetBytes([]byte{
687-
0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
688-
0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
689-
0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
690-
0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52})
691-
692693
// Check if the provided `b` is on the ed25519 curve.
693694
func IsOnCurve(b []byte) bool {
694-
if len(b) != ed25519.PublicKeySize {
695+
if len(b) != voied25519.PublicKeySize {
695696
return false
696697
}
697-
//_, err := new(edwards25519.Point).SetBytes(b)
698-
y, err := new(field.Element).SetBytes(b)
699-
if err != nil {
698+
var compressed curve.CompressedEdwardsY
699+
if _, err := compressed.SetBytes(b); err != nil {
700700
return false
701701
}
702-
703-
y2 := new(field.Element).Square(y)
704-
u := new(field.Element).Subtract(y2, feOne)
705-
706-
vv := new(field.Element).Multiply(y2, d)
707-
vv = vv.Add(vv, feOne)
708-
709-
_, wasSquare := new(field.Element).SqrtRatio(u, vv)
710-
return wasSquare != 0
702+
var p curve.EdwardsPoint
703+
if _, err := p.SetCompressedY(&compressed); err != nil {
704+
return false
705+
}
706+
return true
711707
}
712708

713709
// Find a valid program address and its corresponding bump seed.

nativetypes.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
package solana
1919

2020
import (
21-
"crypto/ed25519"
2221
"encoding/base64"
2322
"fmt"
2423
"io"
2524

25+
voied25519 "github.com/oasisprotocol/curve25519-voi/primitives/ed25519"
26+
2627
bin "github.com/gagliardetto/binary"
2728
"github.com/gagliardetto/solana-go/base58"
2829
"github.com/mostynb/zstdpool-freelist"
@@ -186,7 +187,7 @@ func (p *Signature) UnmarshalJSON(data []byte) (err error) {
186187

187188
// Verify checks that the signature is valid for the given public key and message.
188189
func (s Signature) Verify(pubkey PublicKey, msg []byte) bool {
189-
return ed25519.Verify(pubkey[:], msg, s[:])
190+
return voied25519.VerifyWithOptions(pubkey[:], msg, s[:], verifyOptsStdLib)
190191
}
191192

192193
func (p Signature) String() string {

0 commit comments

Comments
 (0)