mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-10-14 00:59:33 +00:00
Implement importing private keys into the wallet (#1655)
* Implement importing private keys into the wallet. * Fix bad --import default. * Fix typo in --import annotation. * Make go lint happy. * Make go lint happier. Co-authored-by: Ori Newman <orinewman1@gmail.com>
This commit is contained in:
parent
a795a9e619
commit
73b36f12f0
@ -25,8 +25,9 @@ type configFlags struct {
|
|||||||
type createConfig struct {
|
type createConfig struct {
|
||||||
KeysFile string `long:"keys-file" short:"f" description:"Keys file location (default: ~/.kaspawallet/keys.json (*nix), %USERPROFILE%\\AppData\\Local\\Kaspawallet\\key.json (Windows))"`
|
KeysFile string `long:"keys-file" short:"f" description:"Keys file location (default: ~/.kaspawallet/keys.json (*nix), %USERPROFILE%\\AppData\\Local\\Kaspawallet\\key.json (Windows))"`
|
||||||
MinimumSignatures uint32 `long:"min-signatures" short:"m" description:"Minimum required signatures" default:"1"`
|
MinimumSignatures uint32 `long:"min-signatures" short:"m" description:"Minimum required signatures" default:"1"`
|
||||||
NumPrivateKeys uint32 `long:"num-private-keys" short:"k" description:"Number of private keys to generate" default:"1"`
|
NumPrivateKeys uint32 `long:"num-private-keys" short:"k" description:"Number of private keys" default:"1"`
|
||||||
NumPublicKeys uint32 `long:"num-public-keys" short:"n" description:"Total number of keys" default:"1"`
|
NumPublicKeys uint32 `long:"num-public-keys" short:"n" description:"Total number of keys" default:"1"`
|
||||||
|
Import bool `long:"import" short:"i" description:"Import private keys (as opposed to generating them)"`
|
||||||
config.NetworkFlags
|
config.NetworkFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func create(conf *createConfig) error {
|
func create(conf *createConfig) error {
|
||||||
encryptedPrivateKeys, publicKeys, err := keys.CreateKeyPairs(conf.NumPrivateKeys)
|
var encryptedPrivateKeys []*keys.EncryptedPrivateKey
|
||||||
|
var publicKeys [][]byte
|
||||||
|
var err error
|
||||||
|
if !conf.Import {
|
||||||
|
encryptedPrivateKeys, publicKeys, err = keys.CreateKeyPairs(conf.NumPrivateKeys)
|
||||||
|
} else {
|
||||||
|
encryptedPrivateKeys, publicKeys, err = keys.ImportKeyPairs(conf.NumPrivateKeys)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,41 @@
|
|||||||
package keys
|
package keys
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
"fmt"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateKeyPairs generates `numKeys` number of key pairs.
|
// CreateKeyPairs generates `numKeys` number of key pairs.
|
||||||
func CreateKeyPairs(numKeys uint32) (encryptedPrivateKeys []*EncryptedPrivateKey, publicKeys [][]byte, err error) {
|
func CreateKeyPairs(numKeys uint32) (encryptedPrivateKeys []*EncryptedPrivateKey, publicKeys [][]byte, err error) {
|
||||||
|
return createKeyPairsFromFunction(numKeys, func(_ uint32) ([]byte, []byte, error) {
|
||||||
|
return libkaspawallet.CreateKeyPair()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportKeyPairs imports a `numKeys` of private keys and generates key pairs out of them.
|
||||||
|
func ImportKeyPairs(numKeys uint32) (encryptedPrivateKeys []*EncryptedPrivateKey, publicKeys [][]byte, err error) {
|
||||||
|
return createKeyPairsFromFunction(numKeys, func(keyIndex uint32) ([]byte, []byte, error) {
|
||||||
|
fmt.Printf("Enter private key #%d here:\n", keyIndex+1)
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
line, isPrefix, err := reader.ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if isPrefix {
|
||||||
|
return nil, nil, errors.Errorf("Private key is too long")
|
||||||
|
}
|
||||||
|
return libkaspawallet.KeyPairFromPrivateKeyHex(string(line))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func createKeyPairsFromFunction(numKeys uint32, keyPairFunction func(keyIndex uint32) ([]byte, []byte, error)) (
|
||||||
|
encryptedPrivateKeys []*EncryptedPrivateKey, publicKeys [][]byte, err error) {
|
||||||
|
|
||||||
password := getPassword("Enter password for the key file:")
|
password := getPassword("Enter password for the key file:")
|
||||||
confirmPassword := getPassword("Confirm password:")
|
confirmPassword := getPassword("Confirm password:")
|
||||||
|
|
||||||
@ -18,7 +45,7 @@ func CreateKeyPairs(numKeys uint32) (encryptedPrivateKeys []*EncryptedPrivateKey
|
|||||||
|
|
||||||
encryptedPrivateKeys = make([]*EncryptedPrivateKey, 0, numKeys)
|
encryptedPrivateKeys = make([]*EncryptedPrivateKey, 0, numKeys)
|
||||||
for i := uint32(0); i < numKeys; i++ {
|
for i := uint32(0); i < numKeys; i++ {
|
||||||
privateKey, publicKey, err := libkaspawallet.CreateKeyPair()
|
privateKey, publicKey, err := keyPairFunction(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package libkaspawallet
|
package libkaspawallet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"github.com/kaspanet/go-secp256k1"
|
"github.com/kaspanet/go-secp256k1"
|
||||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||||
"github.com/kaspanet/kaspad/util"
|
"github.com/kaspanet/kaspad/util"
|
||||||
@ -13,7 +14,24 @@ func CreateKeyPair() ([]byte, []byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "Failed to generate private key")
|
return nil, nil, errors.Wrap(err, "Failed to generate private key")
|
||||||
}
|
}
|
||||||
publicKey, err := privateKey.SchnorrPublicKey()
|
return keyPairBytes(privateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyPairFromPrivateKeyHex decodes a private-public key pair out of `privateKeyHex`
|
||||||
|
func KeyPairFromPrivateKeyHex(privateKeyHex string) ([]byte, []byte, error) {
|
||||||
|
privateKeyBytes, err := hex.DecodeString(privateKeyHex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "Failed to deserialized private key")
|
||||||
|
}
|
||||||
|
privateKey, err := secp256k1.DeserializeSchnorrPrivateKeyFromSlice(privateKeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "Failed to deserialized private key")
|
||||||
|
}
|
||||||
|
return keyPairBytes(privateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyPairBytes(keyPair *secp256k1.SchnorrKeyPair) ([]byte, []byte, error) {
|
||||||
|
publicKey, err := keyPair.SchnorrPublicKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "Failed to generate public key")
|
return nil, nil, errors.Wrap(err, "Failed to generate public key")
|
||||||
}
|
}
|
||||||
@ -22,7 +40,7 @@ func CreateKeyPair() ([]byte, []byte, error) {
|
|||||||
return nil, nil, errors.Wrap(err, "Failed to serialize public key")
|
return nil, nil, errors.Wrap(err, "Failed to serialize public key")
|
||||||
}
|
}
|
||||||
|
|
||||||
return privateKey.SerializePrivateKey()[:], publicKeySerialized[:], nil
|
return keyPair.SerializePrivateKey()[:], publicKeySerialized[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addressFromPublicKey(params *dagconfig.Params, publicKeySerialized []byte) (util.Address, error) {
|
func addressFromPublicKey(params *dagconfig.Params, publicKeySerialized []byte) (util.Address, error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user