package service import ( "crypto/ecdsa" "encoding/hex" "errors" logging "github.com/ipfs/go-log/v2" "key-manager/crypto" "key-manager/dao" "key-manager/hd" "sync" ) var log = logging.Logger("key-manager") type KeyManager struct { UnimplementedKeyManagerServer lk sync.Mutex dao *dao.Dao password string whitelists map[string]struct{} // key = address mnemonics map[string]string // key = name signers map[string]*ecdsa.PrivateKey // key = address } func NewKeyManager(dao *dao.Dao, password string) (*KeyManager, error) { var km = &KeyManager{ UnimplementedKeyManagerServer: UnimplementedKeyManagerServer{}, lk: sync.Mutex{}, dao: dao, password: password, whitelists: map[string]struct{}{}, mnemonics: map[string]string{}, signers: map[string]*ecdsa.PrivateKey{}, } whitelists, err := dao.GetAllWhitelists() if err != nil { return nil, err } for _, whitelist := range whitelists { km.whitelists[whitelist.WhiteAddress] = struct{}{} log.Warnf("whitelist address: %s - %s", whitelist.Name, whitelist.WhiteAddress) } encryptedMnemonics, err := dao.GetAllMnemonics() if err != nil { return nil, err } passwordKey := crypto.GenerateEncryptKey([]byte(password)) for _, encryptedMnemonic := range encryptedMnemonics { mnemonic, err := decryptMnemonic(encryptedMnemonic.Mnemonic, passwordKey) if err != nil { log.Errorw("decryptMnemonic failed", "name", encryptedMnemonic.Name, "encryptedMnemonic", encryptedMnemonic.Mnemonic) return nil, err } if ok := hd.CheckMnemonic(mnemonic); !ok { return nil, errors.New("invalid mnemonic") } km.mnemonics[encryptedMnemonic.Name] = mnemonic log.Infow("load mnemonic", "name", encryptedMnemonic.Name) } return km, nil } func encryptMnemonic(mnemonic string, key []byte) (string, error) { encryptedMnemonic, err := crypto.Encrypt([]byte(mnemonic), key) if err != nil { return "", err } return hex.EncodeToString(encryptedMnemonic), err } func decryptMnemonic(encryptedData string, key []byte) (string, error) { encryptedMnemonic, err := hex.DecodeString(encryptedData) if err != nil { return "", err } mnemonic, err := crypto.Decrypt(encryptedMnemonic, key) if err != nil { return "", err } return string(mnemonic), nil } func checkNetwork(network string) error { switch network { case eth, tron: return nil default: return errors.New("network must be eth or tron") } }