33

I use the Mist wallet.

I would like to know:

  • How I can get the private key of my account.
  • How I can use this private key to sign messages.

9 Answers 9

26

You can use MyEtherWallet or MyCrypto(fork of MyEtherWallet) offline only wallet "view wallet details" function to extract private key from wallet json file. Feel free to use its offline version on an air gapped computer to secure your private key.

Edit: MyCrypto only provides this function in the offline version of the wallet now for obvious security issues of getting a private key from an internet site on a connected computer. So you are warned that you should only do that on an air-gaped computer.

4
17

If you have node.js, you can do this in node

var keyth=require('keythereum')

//install keythereum by runing "npm install keythereum"

var keyobj=keyth.importFromFile('0x...your..ether..address..','./Appdata/roaming/ethereum')

'./Appdata/roaming/ethereum' is the folder contains 'keystore'. importFile looks for 'keystore' in that folder.

var privateKey=keyth.recover('your_password',keyobj) //this takes a few seconds to finish

privateKey.toString('hex')

2
13

I will try to provide an alternative solution that is more "hands-on" than using a particular application, or JavaScript. It seems to me lacking "hands-on" details might be one of the reasons why similar questions keep spawning up (and ultimately get voted close and redirected to here -- see the list of linked questions).

The steps here are heavily influenced by answers to this question.

The Goal

Given

  • a keystone file
  • its password

output:

  • The raw 256-bit integer secret, which is the private key.

with steps

  • as "bare metal" as possible

Test steup

We will mainly use unix/linux shell and python3 (>3.6 for the scrypt support) for easier Keccak and scrypt.

To make the steps easy to reproduce, we create a test private key whose value is "1" (don't do it in production)

# create a temp work directory
cd $(mktemp -d)
echo "0000000000000000000000000000000000000000000000000000000000000001" > plain_key.txt
geth --datadir . account import plain_key.txt

Geth will ask for new password. Input a simple "a" (don't do in production), which will be used later in decryption.

Geth should output

Address: {7e5f4552091a69125d5dfcb7b8c2659029395bdf}

which, interestingly, often receives funds. Geth should have also created a file under ./keystore/UTC-<< timestamp >>-7e5f4552091a69125d5dfcb7b8c2659029395bdf:

$ cat keystore/UTC*
{  
   "address":"7e5f4552091a69125d5dfcb7b8c2659029395bdf",
   "crypto":{  
      "cipher":"aes-128-ctr",
      "ciphertext":"f97975cb858242372a7c910de23976be4f545ad6b4d6ddb86e54b7d9b3b1c6a1",
      "cipherparams":{  
         "iv":"7fa01f1d0d6a7117382632028cb0c323"
      },
      "kdf":"scrypt",
      "kdfparams":{  
         "dklen":32,
         "n":262144,
         "p":1,
         "r":8,
         "salt":"859c5d345ee58dfca293950c540016af3a889d0dacb00b8eff2ac2b150f0b07e"
      },
      "mac":"31ccb67e48aba5d64bf727a5c6589fd5857021540d25d12df31323f10ae2bf97"
   },
   "id":"dc74bc44-784b-4293-b1c7-b91e9fd7d6cc",
   "version":3
}

(note: the above output has been formatted for better display) The test setup is now complete. Next, we decrypt the private key with the known password "a", and compare the result with the expected value "1".

Decryption

As explained in answers to this question here,

  • the raw private key is encrypted in the keystore file's "ciphertext", with the given algorithm and parameters (e.g. in our example, it's aes-128-ctr and an initial vector).
  • The key to decrypt the above is not the user input password (i.e. "a" in our case), but is the result of feeding the user input password into the specified kdf (key derivation function) algorithm (in our case, it's scrypt).

Obtaining the derivation key

In our example, the key derivation function is scrypt. We use Python3 to do the decryption.

python3
>>> import hashlib
>>> dec_key = hashlib.scrypt(bytes('a', 'utf-8'), salt=bytes.fromhex('859c5d345ee58dfca293950c540016af3a889d0dacb00b8eff2ac2b150f0b07e'), n=262144, r=8, p=1, maxmem=2000000000, dklen=32)

Notice that we have taken the user-input password "a", together with the parameters "salt", "n", "r", "p", "dklen", whose values are from the keystore file. The output should be

>>> print(dec_key)
b'\xaeC\xdd\x02\xf98$h\x0b\x00\xfb\x83\x0c\xb9?\x04\xdd5\x91p\xfaM\xd4\xb7Ks\x9f0\xd3\xb1\xec\xd4'

Validating the derivation key

The keystore file's "mac" field can be used for validating the last step's result, which should be a 32-byte array. According to documentation, the first 16 bytes are for the next step (decrypting the raw key), the second 16 bytes, concatenated with the ciphertext, after going through Keccak hashing, the result should match "mac".

>>> validate = dec_key[16:] + bytes.fromhex('f97975cb858242372a7c910de23976be4f545ad6b4d6ddb86e54b7d9b3b1c6a1')
>>> from Crypto.Hash import keccak
>>> keccak_hash=keccak.new(digest_bits=256)
>>> keccak_hash.update(validate)
>>> print(keccak_hash.hexdigest())
31ccb67e48aba5d64bf727a5c6589fd5857021540d25d12df31323f10ae2bf97

The output matches the "mac", thus proving the user-input password is correct.

Decrypting with the derived key

This step is straightforward AES decryption. Many tools can be used, e.g. openssl. Here, for simplicity, we continue with Python3.

>>> from Crypto.Cipher import AES
>>> from Crypto.Util import Counter

Now feed in the "initial vector" value from the keystore file:

>>> iv_int=int('7fa01f1d0d6a7117382632028cb0c323', 16)
>>> ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)
>>> dec_suite = AES.new(key, AES.MODE_CTR, counter=ctr)

Finally feed in the ciphertext and the first 16 bytes of the derivation key:

>>> plain_key = dec_suite.decrypt(bytes.fromhex('f97975cb858242372a7c910de23976be4f545ad6b4d6ddb86e54b7d9b3b1c6a1'))
>>> print(plain_key)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'

This matches the known "secret" value of 1.

5
  • If we don't have any offline visual tools to do the recovery, I guess it means that Ethereum is dead and there's no use to recover. But it's still great to have a bare-bone answer to this issue and maybe will help people to understand how accounts are working. Thanks. Nov 26, 2019 at 11:03
  • It should be dec_suite = AES.new(dec_key,.... Also I had to use plain_key.hex() Sep 12, 2020 at 12:01
  • 1
    Using the dec_suite doesn't produce the right output for me. The mac variable does match, so it's correct up to that point. Nov 20, 2020 at 11:11
  • 1
    It actually should be dec_key[0:16], not dec_key or key. Dec 1, 2020 at 5:23
  • Implemented this with Go gist.github.com/rikonor/aea81f6834ec15e5cad8db4bdb4031c3 Feb 3, 2021 at 4:45
10

You can use the web3 CLI tool to do this easily:

web3 account extract --keyfile ~/Downloads/keystore-file --password password
1
  • 1
    short and sweet!
    – Burt
    Dec 16, 2020 at 11:07
7

I'm assuming your mist client runs a geth node in background.

Export of unencrypted key is not supported on purpose after deliberating the risk to end users. #1054

Unfortunately it seems not to be possible to extract the unencrypted private key.

If you got the key file under keystore then that is your private key encrypted with a password (plus other metadata) . There is really no need to export your actual ec private key (unless you well wanna do math with it or I don't know). You need to know your password though. You can copy the key to another client or machine. If you unlock the account you can use this address to sign transactions, ... r/cvckff5

If you want to dig deeper you could try:

  1. importing your keys from geth into eth using the ethkey utility. And after that you should be able to
  2. make the plain unencrypted private key visible with listbare (not recommended), and finally
  3. sign a message with eth_sign rpc call.
4
  • 1
    Can't myetherwallet.com extract private key from wallet json file? May 8, 2016 at 12:20
  • 1
    Yes via the "View Wallet Details" tab. Feel free to run offline / locally too.
    – tayvano
    May 8, 2016 at 15:40
  • 1
    Go ahead and post another answer. 3 answers per question is good, only 1 answer per question needs some work. On a healthy site, questions receive multiple answers and the best answer is voted to the top.
    – q9f
    May 9, 2016 at 8:38
  • @5chdn I made my comment an answer. May 9, 2016 at 13:46
6

ethereum/go-ethereum's ethkey tool can do this:

> ethkey inspect --private --passwordfile kottipass.txt UTC--2019-01-30T14-49-18.711193885Z--e5dfD67E3d46De4e2C918d894FdC591793492E53
Address:        0xe5dfD67E3d46De4e2C918d894FdC591793492E53
Public key:     046ab6d31f00e43df04226fbf8b16c62eed80eec200ac5d7f247fc3d15f3d1a27f7e9f74a214e7ddcef8a3618853622fd37354080959b17fe36d82a46a8c0aa41e
Private key:    0e459e429c4e36769e0ba7fad5acd3ac8627b9404a1f96f0a003fb22206c2d1d

3

You could also use the wallet functionality on EthTools.com.

This tool loads details about your address from your keyfile and displays them in an easily consumable manner.

The load wallet screen The load wallet screen

Select (or input) your keyfile Load your keyfile

Click advanced to view your private key View your private key

Using this tool is also explained here in video format.

2
  • 2
    It doesn't seem like good advice to use an online tool to decrypt a private key... Forgive me if I'm missing something, but how can someone be sure the website is no storing every data one inputs?
    – Renan
    Oct 16, 2017 at 11:54
  • 2
    You are not missing anything. You are absolutely correct. You should be very careful when trusting your private key to a web based service. There are ways to check that a website is not storing your data but it is quite complex for anyone without a tech background. In this case, as this is my companies product I can assure you that we do not store your private keys. I would personally always advise having a cold wallet and then having an active wallet (that never holds significant amounts of Ether) that you use to interface with unknown services. Oct 16, 2017 at 12:23
0

From this post: Export Parity private key this go program on github https://github.com/afterether/eacct was very helpful in obtaining a private key for my Kovan account. Most other references mentioned no longer support obtaining private keys but give me keystores only.

0

You can also get the list of accounts with their private keys using the below script:

Install keythereum: npm install keythereum

Create a file getPrivateKey.js and add below lines to it.

const keythereum = require('keythereum');
const async = require('async');
const datadir = 'path/to/datadir/where/keystore/is/located';

const accounts = [ ]; // add the account addresses whose private key has to be extracted

let keyObject, privateKey, count = 0;
let result = [];

async.forEach(accounts, (element, cb) => {
    keyObject = keythereum.importFromFile(element, datadir);
    privateKey = keythereum.recover('accountPassword', keyObject);
    result.push({
        address: element,
        privateKey: privateKey.toString('hex')
    });
    console.log('result: \n', result[count]);
    count++;
    cb();
  },() => {
    console.log('inside final callback of async.forEach: ');
    console.log('result array: ', result);
});

The script makes use of the keythereum, please go through it for more details.

Execute the script using: node getPrivateKey.js

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.