mirror of
https://github.com/luxfi/sdk.git
synced 2026-10-30 15:19:23 +00:00
- Migrate from github.com/luxfi/const to github.com/luxfi/constants - Update all wallet, validatormanager, and utility imports
159 lines
4.3 KiB
Go
159 lines
4.3 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
//go:build ignore
|
|
|
|
package keychain
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/luxfi/crypto"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/math/set"
|
|
)
|
|
|
|
// UnifiedKeychain uses the unified crypto interface for all key operations
|
|
type UnifiedKeychain struct {
|
|
crypto crypto.UnifiedCrypto
|
|
keysByAddress map[ids.ShortID]*UnifiedSigner
|
|
addressSet set.Set[ids.ShortID]
|
|
defaultAlgo crypto.Algorithm
|
|
}
|
|
|
|
// NewUnifiedKeychain creates a new keychain using the unified crypto interface
|
|
func NewUnifiedKeychain(defaultAlgo crypto.Algorithm) *UnifiedKeychain {
|
|
return &UnifiedKeychain{
|
|
crypto: crypto.NewUnifiedCrypto(),
|
|
keysByAddress: make(map[ids.ShortID]*UnifiedSigner),
|
|
addressSet: set.NewSet[ids.ShortID](0),
|
|
defaultAlgo: defaultAlgo,
|
|
}
|
|
}
|
|
|
|
// GenerateKey generates a new key with the default algorithm
|
|
func (kc *UnifiedKeychain) GenerateKey() (ids.ShortID, error) {
|
|
privKey, pubKey, err := kc.crypto.GenerateKey(kc.defaultAlgo)
|
|
if err != nil {
|
|
return ids.ShortEmpty, err
|
|
}
|
|
|
|
return kc.AddKey(privKey, pubKey), nil
|
|
}
|
|
|
|
// GenerateKeyWithAlgo generates a new key with the specified algorithm
|
|
func (kc *UnifiedKeychain) GenerateKeyWithAlgo(algo crypto.Algorithm) (ids.ShortID, error) {
|
|
privKey, pubKey, err := kc.crypto.GenerateKey(algo)
|
|
if err != nil {
|
|
return ids.ShortEmpty, err
|
|
}
|
|
|
|
return kc.AddKey(privKey, pubKey), nil
|
|
}
|
|
|
|
// AddKey adds a key pair to the keychain
|
|
func (kc *UnifiedKeychain) AddKey(privKey crypto.PrivateKey, pubKey crypto.PublicKey) ids.ShortID {
|
|
addrBytes := pubKey.Address()
|
|
if len(addrBytes) < 20 {
|
|
// Pad if necessary
|
|
padded := make([]byte, 20)
|
|
copy(padded, addrBytes)
|
|
addrBytes = padded
|
|
}
|
|
|
|
addr := ids.ShortID{}
|
|
copy(addr[:], addrBytes[:20])
|
|
|
|
signer := &UnifiedSigner{
|
|
privKey: privKey,
|
|
pubKey: pubKey,
|
|
address: addr,
|
|
crypto: kc.crypto,
|
|
}
|
|
|
|
kc.keysByAddress[addr] = signer
|
|
kc.addressSet.Add(addr)
|
|
|
|
return addr
|
|
}
|
|
|
|
// Get returns the signer for the given address
|
|
func (kc *UnifiedKeychain) Get(addr ids.ShortID) (Signer, bool) {
|
|
signer, exists := kc.keysByAddress[addr]
|
|
if !exists {
|
|
return nil, false
|
|
}
|
|
return signer, true
|
|
}
|
|
|
|
// Addresses returns all addresses in the keychain
|
|
func (kc *UnifiedKeychain) Addresses() []ids.ShortID {
|
|
addrs := make([]ids.ShortID, 0, kc.addressSet.Len())
|
|
for addr := range kc.addressSet {
|
|
addrs = append(addrs, addr)
|
|
}
|
|
return addrs
|
|
}
|
|
|
|
// GetUnifiedSigner returns the unified signer for advanced operations
|
|
func (kc *UnifiedKeychain) GetUnifiedSigner(addr ids.ShortID) (*UnifiedSigner, bool) {
|
|
signer, exists := kc.keysByAddress[addr]
|
|
return signer, exists
|
|
}
|
|
|
|
// UnifiedSigner implements the Signer interface using unified crypto
|
|
type UnifiedSigner struct {
|
|
privKey crypto.PrivateKey
|
|
pubKey crypto.PublicKey
|
|
address ids.ShortID
|
|
crypto crypto.UnifiedCrypto
|
|
}
|
|
|
|
// Sign signs a message
|
|
func (s *UnifiedSigner) Sign(msg []byte) ([]byte, error) {
|
|
return s.crypto.Sign(s.privKey, msg)
|
|
}
|
|
|
|
// SignHash signs a hash (for compatibility)
|
|
func (s *UnifiedSigner) SignHash(hash []byte) ([]byte, error) {
|
|
// For algorithms that expect raw hashes
|
|
switch s.privKey.Algorithm() {
|
|
case crypto.AlgoSecp256k1:
|
|
// secp256k1 expects 32-byte hash
|
|
if len(hash) != 32 {
|
|
return nil, errors.New("invalid hash length for secp256k1")
|
|
}
|
|
}
|
|
return s.privKey.Sign(hash)
|
|
}
|
|
|
|
// Address returns the address
|
|
func (s *UnifiedSigner) Address() ids.ShortID {
|
|
return s.address
|
|
}
|
|
|
|
// Algorithm returns the algorithm used by this signer
|
|
func (s *UnifiedSigner) Algorithm() crypto.Algorithm {
|
|
return s.privKey.Algorithm()
|
|
}
|
|
|
|
// PublicKey returns the public key
|
|
func (s *UnifiedSigner) PublicKey() crypto.PublicKey {
|
|
return s.pubKey
|
|
}
|
|
|
|
// SignRing creates a ring signature (for privacy-preserving signatures)
|
|
func (s *UnifiedSigner) SignRing(message []byte, ring []crypto.PublicKey) ([]byte, error) {
|
|
return s.crypto.SignRing(s.privKey, message, ring)
|
|
}
|
|
|
|
// Encapsulate creates a ciphertext and shared secret (for ML-KEM)
|
|
func (s *UnifiedSigner) Encapsulate(pubKey crypto.PublicKey) (ciphertext []byte, sharedSecret []byte, err error) {
|
|
return s.crypto.Encapsulate(pubKey)
|
|
}
|
|
|
|
// Decapsulate recovers the shared secret from ciphertext (for ML-KEM)
|
|
func (s *UnifiedSigner) Decapsulate(ciphertext []byte) (sharedSecret []byte, err error) {
|
|
return s.crypto.Decapsulate(s.privKey, ciphertext)
|
|
}
|