Add support for 32-byte Ed25519

This commit is contained in:
2025-09-27 05:46:51 -05:00
parent b59bb349dc
commit 911fe3ea8e

View File

@@ -44,7 +44,7 @@ const (
type Identity struct { type Identity struct {
privateKey []byte privateKey []byte
publicKey []byte publicKey []byte
signingKey ed25519.PrivateKey signingSeed []byte // 32-byte Ed25519 seed (compatible with Python RNS)
verificationKey ed25519.PublicKey verificationKey ed25519.PublicKey
hash []byte hash []byte
hexHash string hexHash string
@@ -76,13 +76,18 @@ func New() (*Identity, error) {
i.privateKey = privKey i.privateKey = privKey
i.publicKey = pubKey i.publicKey = pubKey
// Generate Ed25519 signing keypair // Generate 32-byte Ed25519 seed (compatible with Python RNS)
verificationKey, signingKey, err := cryptography.GenerateSigningKeyPair() var ed25519Seed [32]byte
if err != nil { if _, err := io.ReadFull(rand.Reader, ed25519Seed[:]); err != nil {
return nil, fmt.Errorf("failed to generate Ed25519 keypair: %v", err) return nil, fmt.Errorf("failed to generate Ed25519 seed: %v", err)
} }
i.signingKey = signingKey
i.verificationKey = verificationKey // Derive Ed25519 keypair from seed
privKeyEd := ed25519.NewKeyFromSeed(ed25519Seed[:])
pubKeyEd := privKeyEd.Public().(ed25519.PublicKey)
i.signingSeed = ed25519Seed[:]
i.verificationKey = pubKeyEd
return i, nil return i, nil
} }
@@ -96,11 +101,13 @@ func (i *Identity) GetPublicKey() []byte {
} }
func (i *Identity) GetPrivateKey() []byte { func (i *Identity) GetPrivateKey() []byte {
return append(i.privateKey, i.signingKey...) return append(i.privateKey, i.signingSeed...)
} }
func (i *Identity) Sign(data []byte) []byte { func (i *Identity) Sign(data []byte) []byte {
return cryptography.Sign(i.signingKey, data) // Derive Ed25519 private key from seed (compatible with Python RNS)
privKey := ed25519.NewKeyFromSeed(i.signingSeed)
return cryptography.Sign(privKey, data)
} }
func (i *Identity) Verify(data []byte, signature []byte) bool { func (i *Identity) Verify(data []byte, signature []byte) bool {
@@ -465,7 +472,7 @@ func (i *Identity) ToFile(path string) error {
data := map[string]interface{}{ data := map[string]interface{}{
"private_key": i.privateKey, "private_key": i.privateKey,
"public_key": i.publicKey, "public_key": i.publicKey,
"signing_key": i.signingKey, "signing_seed": i.signingSeed,
"verification_key": i.verificationKey, "verification_key": i.verificationKey,
"app_data": i.appData, "app_data": i.appData,
} }
@@ -525,11 +532,25 @@ func RecallIdentity(path string) (*Identity, error) {
return nil, err return nil, err
} }
var signingSeed []byte
var verificationKey ed25519.PublicKey
if seedData, exists := data["signing_seed"]; exists {
signingSeed = seedData.([]byte)
verificationKey = data["verification_key"].(ed25519.PublicKey)
} else if keyData, exists := data["signing_key"]; exists {
oldKey := keyData.(ed25519.PrivateKey)
signingSeed = oldKey[:32]
verificationKey = data["verification_key"].(ed25519.PublicKey)
} else {
return nil, fmt.Errorf("no signing key data found in identity file")
}
id := &Identity{ id := &Identity{
privateKey: data["private_key"].([]byte), privateKey: data["private_key"].([]byte),
publicKey: data["public_key"].([]byte), publicKey: data["public_key"].([]byte),
signingKey: data["signing_key"].(ed25519.PrivateKey), signingSeed: signingSeed,
verificationKey: data["verification_key"].(ed25519.PublicKey), verificationKey: verificationKey,
appData: data["app_data"].([]byte), appData: data["app_data"].([]byte),
ratchets: make(map[string][]byte), ratchets: make(map[string][]byte),
ratchetExpiry: make(map[string]int64), ratchetExpiry: make(map[string]int64),
@@ -638,12 +659,16 @@ func (i *Identity) SetRatchetKey(id string, key []byte) {
// NewIdentity creates a new Identity instance with fresh keys // NewIdentity creates a new Identity instance with fresh keys
func NewIdentity() (*Identity, error) { func NewIdentity() (*Identity, error) {
// Generate Ed25519 signing keypair // Generate 32-byte Ed25519 seed (compatible with Python RNS)
pubKey, privKey, err := ed25519.GenerateKey(rand.Reader) var ed25519Seed [32]byte
if err != nil { if _, err := io.ReadFull(rand.Reader, ed25519Seed[:]); err != nil {
return nil, fmt.Errorf("failed to generate Ed25519 keypair: %v", err) return nil, fmt.Errorf("failed to generate Ed25519 seed: %v", err)
} }
// Derive Ed25519 keypair from seed
privKey := ed25519.NewKeyFromSeed(ed25519Seed[:])
pubKey := privKey.Public().(ed25519.PublicKey)
// Generate X25519 encryption keypair // Generate X25519 encryption keypair
var encPrivKey [32]byte var encPrivKey [32]byte
if _, err := io.ReadFull(rand.Reader, encPrivKey[:]); err != nil { if _, err := io.ReadFull(rand.Reader, encPrivKey[:]); err != nil {
@@ -658,7 +683,7 @@ func NewIdentity() (*Identity, error) {
i := &Identity{ i := &Identity{
privateKey: encPrivKey[:], privateKey: encPrivKey[:],
publicKey: encPubKey, publicKey: encPubKey,
signingKey: privKey, signingSeed: ed25519Seed[:],
verificationKey: pubKey, verificationKey: pubKey,
ratchets: make(map[string][]byte), ratchets: make(map[string][]byte),
ratchetExpiry: make(map[string]int64), ratchetExpiry: make(map[string]int64),