mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-07 14:46:44 +00:00
Add dump unencrypted data sub command to the wallet (#1661)
This commit is contained in:
parent
73b36f12f0
commit
6dd3d4a9e7
@ -12,10 +12,11 @@ const (
|
|||||||
createSubCmd = "create"
|
createSubCmd = "create"
|
||||||
balanceSubCmd = "balance"
|
balanceSubCmd = "balance"
|
||||||
sendSubCmd = "send"
|
sendSubCmd = "send"
|
||||||
createUnsignedTransactionSubCmd = "createUnsignedTransaction"
|
createUnsignedTransactionSubCmd = "create-unsigned-transaction"
|
||||||
signSubCmd = "sign"
|
signSubCmd = "sign"
|
||||||
broadcastSubCmd = "broadcast"
|
broadcastSubCmd = "broadcast"
|
||||||
showAddressSubCmd = "show-address"
|
showAddressSubCmd = "show-address"
|
||||||
|
dumpUnencryptedDataSubCmd = "dump-unencrypted-data"
|
||||||
)
|
)
|
||||||
|
|
||||||
type configFlags struct {
|
type configFlags struct {
|
||||||
@ -70,6 +71,11 @@ type showAddressConfig struct {
|
|||||||
config.NetworkFlags
|
config.NetworkFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dumpUnencryptedDataConfig struct {
|
||||||
|
KeysFile string `long:"keys-file" short:"f" description:"Keys file location (default: ~/.kaspawallet/keys.json (*nix), %USERPROFILE%\\AppData\\Local\\Kaspawallet\\key.json (Windows))"`
|
||||||
|
config.NetworkFlags
|
||||||
|
}
|
||||||
|
|
||||||
func parseCommandLine() (subCommand string, config interface{}) {
|
func parseCommandLine() (subCommand string, config interface{}) {
|
||||||
cfg := &configFlags{}
|
cfg := &configFlags{}
|
||||||
parser := flags.NewParser(cfg, flags.PrintErrors|flags.HelpFlag)
|
parser := flags.NewParser(cfg, flags.PrintErrors|flags.HelpFlag)
|
||||||
@ -102,6 +108,11 @@ func parseCommandLine() (subCommand string, config interface{}) {
|
|||||||
parser.AddCommand(showAddressSubCmd, "Shows the public address of the current wallet",
|
parser.AddCommand(showAddressSubCmd, "Shows the public address of the current wallet",
|
||||||
"Shows the public address of the current wallet", showAddressConf)
|
"Shows the public address of the current wallet", showAddressConf)
|
||||||
|
|
||||||
|
dumpUnencryptedDataConf := &dumpUnencryptedDataConfig{}
|
||||||
|
parser.AddCommand(dumpUnencryptedDataSubCmd, "Prints the unencrypted wallet data",
|
||||||
|
"Prints the unencrypted wallet data including its private keys. Anyone that sees it can access "+
|
||||||
|
"the funds. Use only on safe environment.", dumpUnencryptedDataConf)
|
||||||
|
|
||||||
_, err := parser.Parse()
|
_, err := parser.Parse()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -164,6 +175,13 @@ func parseCommandLine() (subCommand string, config interface{}) {
|
|||||||
printErrorAndExit(err)
|
printErrorAndExit(err)
|
||||||
}
|
}
|
||||||
config = showAddressConf
|
config = showAddressConf
|
||||||
|
case dumpUnencryptedDataSubCmd:
|
||||||
|
combineNetworkFlags(&dumpUnencryptedDataConf.NetworkFlags, &cfg.NetworkFlags)
|
||||||
|
err := dumpUnencryptedDataConf.ResolveNetwork(parser)
|
||||||
|
if err != nil {
|
||||||
|
printErrorAndExit(err)
|
||||||
|
}
|
||||||
|
config = dumpUnencryptedDataConf
|
||||||
}
|
}
|
||||||
|
|
||||||
return parser.Command.Active.Name, config
|
return parser.Command.Active.Name, config
|
||||||
|
69
cmd/kaspawallet/dump_unencrypted_data.go
Normal file
69
cmd/kaspawallet/dump_unencrypted_data.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
|
||||||
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func dumpUnencryptedData(conf *dumpUnencryptedDataConfig) error {
|
||||||
|
err := confirmDump()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
keysFile, err := keys.ReadKeysFile(conf.KeysFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKeys, err := keysFile.DecryptPrivateKeys()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKeysPublicKeys := make(map[string]struct{})
|
||||||
|
for i, privateKey := range privateKeys {
|
||||||
|
fmt.Printf("Private key #%d:\n%x\n\n", i+1, privateKey)
|
||||||
|
publicKey, err := libkaspawallet.PublicKeyFromPrivateKey(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKeysPublicKeys[string(publicKey)] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 1
|
||||||
|
for _, publicKey := range keysFile.PublicKeys {
|
||||||
|
if _, exists := privateKeysPublicKeys[string(publicKey)]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Public key #%d:\n%x\n\n", i, publicKey)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Minimum number of signatures: %d\n", keysFile.MinimumSignatures)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func confirmDump() error {
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
fmt.Printf("This operation will print your unencrypted keys on the screen. Anyone that sees this information " +
|
||||||
|
"will be able to steal your funds. Are you sure you want to proceed (y/N)? ")
|
||||||
|
line, isPrefix, err := reader.ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
if isPrefix || string(line) != "y" {
|
||||||
|
return errors.Errorf("Dump aborted by user")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -29,7 +30,17 @@ func ImportKeyPairs(numKeys uint32) (encryptedPrivateKeys []*EncryptedPrivateKey
|
|||||||
if isPrefix {
|
if isPrefix {
|
||||||
return nil, nil, errors.Errorf("Private key is too long")
|
return nil, nil, errors.Errorf("Private key is too long")
|
||||||
}
|
}
|
||||||
return libkaspawallet.KeyPairFromPrivateKeyHex(string(line))
|
privateKey, err := hex.DecodeString(string(line))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKey, err := libkaspawallet.PublicKeyFromPrivateKey(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return privateKey, publicKey, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
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"
|
||||||
@ -10,24 +9,40 @@ import (
|
|||||||
|
|
||||||
// CreateKeyPair generates a private-public key pair
|
// CreateKeyPair generates a private-public key pair
|
||||||
func CreateKeyPair() ([]byte, []byte, error) {
|
func CreateKeyPair() ([]byte, []byte, error) {
|
||||||
privateKey, err := secp256k1.GenerateSchnorrKeyPair()
|
keyPair, err := secp256k1.GenerateSchnorrKeyPair()
|
||||||
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")
|
||||||
}
|
}
|
||||||
return keyPairBytes(privateKey)
|
publicKey, err := keyPair.SchnorrPublicKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "Failed to generate public key")
|
||||||
|
}
|
||||||
|
publicKeySerialized, err := publicKey.Serialize()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "Failed to serialize public key")
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyPairFromPrivateKeyHex decodes a private-public key pair out of `privateKeyHex`
|
return keyPair.SerializePrivateKey()[:], publicKeySerialized[:], nil
|
||||||
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)
|
|
||||||
|
// PublicKeyFromPrivateKey returns the public key associated with a private key
|
||||||
|
func PublicKeyFromPrivateKey(privateKeyBytes []byte) ([]byte, error) {
|
||||||
|
keyPair, err := secp256k1.DeserializeSchnorrPrivateKeyFromSlice(privateKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "Failed to deserialized private key")
|
return nil, errors.Wrap(err, "Failed to deserialized private key")
|
||||||
}
|
}
|
||||||
return keyPairBytes(privateKey)
|
|
||||||
|
publicKey, err := keyPair.SchnorrPublicKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Failed to generate public key")
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKeySerialized, err := publicKey.Serialize()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Failed to serialize public key")
|
||||||
|
}
|
||||||
|
|
||||||
|
return publicKeySerialized[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func keyPairBytes(keyPair *secp256k1.SchnorrKeyPair) ([]byte, []byte, error) {
|
func keyPairBytes(keyPair *secp256k1.SchnorrKeyPair) ([]byte, []byte, error) {
|
||||||
|
@ -21,6 +21,8 @@ func main() {
|
|||||||
err = broadcast(config.(*broadcastConfig))
|
err = broadcast(config.(*broadcastConfig))
|
||||||
case showAddressSubCmd:
|
case showAddressSubCmd:
|
||||||
err = showAddress(config.(*showAddressConfig))
|
err = showAddress(config.(*showAddressConfig))
|
||||||
|
case dumpUnencryptedDataSubCmd:
|
||||||
|
err = dumpUnencryptedData(config.(*dumpUnencryptedDataConfig))
|
||||||
default:
|
default:
|
||||||
err = errors.Errorf("Unknown sub-command '%s'\n", subCmd)
|
err = errors.Errorf("Unknown sub-command '%s'\n", subCmd)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user