forked from TrueCloudLab/frostfs-node
[#1216] neofs-cli: Reuse key retrieving code between modules
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
006d6e8b48
commit
8d79168129
5 changed files with 169 additions and 127 deletions
26
cmd/neofs-cli/internal/key/nep2.go
Normal file
26
cmd/neofs-cli/internal/key/nep2.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
)
|
||||
|
||||
const nep2Base58Length = 58
|
||||
|
||||
// FromNEP2 extracts private key from NEP2-encrypted string.
|
||||
func FromNEP2(encryptedWif string) (*ecdsa.PrivateKey, error) {
|
||||
pass, err := getPassword()
|
||||
if err != nil {
|
||||
printVerbose("Can't read password: %v", err)
|
||||
return nil, ErrInvalidPassword
|
||||
}
|
||||
|
||||
k, err := keys.NEP2Decrypt(encryptedWif, pass, keys.NEP2ScryptParams())
|
||||
if err != nil {
|
||||
printVerbose("Invalid key or password: %v", err)
|
||||
return nil, ErrInvalidPassword
|
||||
}
|
||||
|
||||
return &k.PrivateKey, nil
|
||||
}
|
54
cmd/neofs-cli/internal/key/raw.go
Normal file
54
cmd/neofs-cli/internal/key/raw.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
)
|
||||
|
||||
// Get returns private key from the followind sources:
|
||||
// 1. WIF
|
||||
// 2. Raw binary key
|
||||
// 3. Wallet file
|
||||
// 4. NEP-2 encrypted WIF.
|
||||
// Ideally we want to touch file-system on the last step.
|
||||
// However, asking for NEP-2 password seems to be confusing if we provide a wallet.
|
||||
func Get(keyDesc string, address string) (*ecdsa.PrivateKey, error) {
|
||||
priv, err := keys.NewPrivateKeyFromWIF(keyDesc)
|
||||
if err == nil {
|
||||
return &priv.PrivateKey, nil
|
||||
}
|
||||
|
||||
p, err := getKeyFromFile(keyDesc)
|
||||
if err == nil {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
w, err := wallet.NewWalletFromFile(keyDesc)
|
||||
if err == nil {
|
||||
return FromWallet(w, address)
|
||||
}
|
||||
|
||||
if len(keyDesc) == nep2Base58Length {
|
||||
return FromNEP2(keyDesc)
|
||||
}
|
||||
|
||||
return nil, ErrInvalidKey
|
||||
}
|
||||
|
||||
func getKeyFromFile(keyPath string) (*ecdsa.PrivateKey, error) {
|
||||
data, err := os.ReadFile(keyPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrInvalidKey, err)
|
||||
}
|
||||
|
||||
priv, err := keys.NewPrivateKeyFromBytes(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrInvalidKey, err)
|
||||
}
|
||||
|
||||
return &priv.PrivateKey, nil
|
||||
}
|
74
cmd/neofs-cli/internal/key/wallet.go
Normal file
74
cmd/neofs-cli/internal/key/wallet.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/input"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// Key-related errors.
|
||||
var (
|
||||
ErrInvalidKey = errors.New("provided key is incorrect")
|
||||
ErrInvalidAddress = errors.New("--address option must be specified and valid")
|
||||
ErrInvalidPassword = errors.New("invalid password for the encrypted key")
|
||||
)
|
||||
|
||||
// FromWallet returns private key of the wallet account.
|
||||
func FromWallet(w *wallet.Wallet, addrStr string) (*ecdsa.PrivateKey, error) {
|
||||
var (
|
||||
addr util.Uint160
|
||||
err error
|
||||
)
|
||||
|
||||
if addrStr == "" {
|
||||
printVerbose("Using default wallet address")
|
||||
addr = w.GetChangeAddress()
|
||||
} else {
|
||||
addr, err = flags.ParseAddress(addrStr)
|
||||
if err != nil {
|
||||
printVerbose("Can't parse address: %s", addrStr)
|
||||
return nil, ErrInvalidAddress
|
||||
}
|
||||
}
|
||||
|
||||
acc := w.GetAccount(addr)
|
||||
if acc == nil {
|
||||
printVerbose("Can't find wallet account for %s", addrStr)
|
||||
return nil, ErrInvalidAddress
|
||||
}
|
||||
|
||||
pass, err := getPassword()
|
||||
if err != nil {
|
||||
printVerbose("Can't read password: %v", err)
|
||||
return nil, ErrInvalidPassword
|
||||
}
|
||||
|
||||
if err := acc.Decrypt(pass, keys.NEP2ScryptParams()); err != nil {
|
||||
printVerbose("Can't decrypt account: %v", err)
|
||||
return nil, ErrInvalidPassword
|
||||
}
|
||||
|
||||
return &acc.PrivateKey().PrivateKey, nil
|
||||
}
|
||||
|
||||
func getPassword() (string, error) {
|
||||
// this check allows empty passwords
|
||||
if viper.IsSet("password") {
|
||||
return viper.GetString("password"), nil
|
||||
}
|
||||
|
||||
return input.ReadPassword("Enter password > ")
|
||||
}
|
||||
|
||||
func printVerbose(format string, a ...interface{}) {
|
||||
if viper.GetBool("verbose") {
|
||||
fmt.Printf(format+"\n", a...)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue