14

I want to know the details about key generation and handling in Parity. The questions listed are all related, so I put them all in this one question post.

When a new Ethereum account is created on Parity, a new file is created under .../ethcore/<node-name>/keys/<chain-name>. As an example, the contents of such a file are:

{
    "id":"eca798d8-8e68-a096-a35f-174133f86e43",
    "version":3,
    "crypto":
    {
        "cipher":"aes-128-ctr",
        "cipherparams": { "iv":"45092c0a2032250e66a9d0bd2a33acaa" },
        "ciphertext":"0385fd52dfc528713d7b0b72073b992b93aa78f32b0576848a9de69d6e836c3d",
        "kdf":"pbkdf2",
        "kdfparams":
        {
            "c":10240,
            "dklen":32,
            "prf":"hmac-sha256",
            "salt":"e04e80b6174ca47c86e9174fd952949e53c900852d5c3cb62b863c5241e54f28"
        },
        "mac":"178d2c012e1970b853e1551fa9bb0a51b86955cc4ed8db53a9b60cbbdbca8c7b"
    },
    "address":"00faf16e4909296f5cca76e1ccd7cd811fba93d0",
    "name":"User-007",
    "meta":"{}"
}

Looks like the KDF is PBKDF2, i.e. password-based KDF. I guess the account password is used to derive the keys and the parameters for that are given in "kdfparams".

So, I am looking for answers to the following questions:

  1. Is the private key derived using this KDF and the given param values, on-demand whenever the password is supplied?
  2. What is the public key, or how is it generated? The password should not be needed for that.
  3. What is the plain text that "ciphertext" is the encryption of?
  4. This file is generated and saved on the Parity node. Doesn't that mean that the private key is not completely and solely in the hands of the account owner?

Thanks for throwing some light on this issue.

  • github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition may have some of the answers – eth Apr 25 '17 at 7:37
  • Could you clarify your 4th question? Why is the operator of the node not in full control of the keys? – Waqar Lim Apr 25 '17 at 10:59
  • Re: Q4: Perhaps I did not understand it correctly earlier but it occurred to me after posting that the person creating the account is also the owner of the node on which the account creation operation (personal.newAccountFromPhrase or any other) is called. So that means that one should run the Parity (or any Ethereum) client on a node one controls, and invoke the account creation operation on it. Is that right? i.e. I should not create an account by invoking the API of a remote node that is not in my control? – Ajoy Bhatia Apr 25 '17 at 16:41
  • @AjoyBhatia yes. A remote (RPC) node will probably not allow the personal API anyway, unless they specify this with --rpcapi. You should generate your private key file on your computer only. It's also possible to decrypt it and obtain your raw private key, see here. – jeff Apr 25 '17 at 22:55
  • @eth - Thanks for the wiki link. That is good info. Now the only thing remaining is - where is the public key? OR How does the signature verification algorithm know what the public key of a given address is, to be able to verify that a given message has been signed with the private key corresponding to that address? I will look for that info, and post a new question if I cannot find it. – Ajoy Bhatia Apr 26 '17 at 18:43
10

Some of the links in the comments helped me get the answers to my questions. I have collected all that information combined with my own (recently acquired) knowledge of cryptography from the Coursera Cryptography-I class (for the answer to question number 3).

A1. The private key is never (or should never be) saved unencrypted on disk. It is generated from the info in the keystore file when the user enters the password.

A2. The public key can be generated from the private key. However, it is needed by other parties (that do not have the private key) to verify signatures by this account. These parties would derive it from a signature, as explained here: Get public key of any ethereum account Then, the signer's address is the last 20 bytes of the Keccak-256 hash of the public key. Presumably, that should match the from: address of the transaction.

A3. Here is a (somewhat long) answer about the structure and meaning of the private key's JSON representation:

I got a lot of this information from the wiki page: https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition and added some of my own to make it more comprehensive.

All the information to decrypt the private key is in the crypto element. The cipher element identifies the symmetric encryption scheme used to encrypt the private key. In the given example, the scheme is aes-128-ctr, the Advanced Encryption Standard (aes) block cipher with a key length of 128 bits in the counter (ctr) mode of operation. Aside: The other mode of operation is cipher block chaining (CBC). cipherparams contains the values of any parameters used in the encryption. For AES-128-CTR, there is only one parameter, iv (Initialization Vector). ciphertext is the encrypted private key.

To decrypt the private key's ciphertext, we need the above values. We also need the symmetric encryption key, which was used to encrypt the private key. The encryption key is not shown in plain text either. It needs to be derived using the specified key derivation function (kdf) using the values of the parameters that the specified KDF needs (kdfparams). The KDF in the given example is pbkdf2 - a password-based KDF. The parameters for pbkdf2 are the password (to be entered by the user), a pseudo-random hashing function (prf) (in example, it is HMAC-SHA256 hmac-sha256), a salt value (salt), an iteration count (c) and the derived key length (dklen) in bytes. The key is derived by taking the concatenation of the password and salt values, and applying the hashing function c times. This is done because passwords selected by humans do not have sufficient entropy. To defend against that, a random salt value is used and also a slow hash function. (The number of iterations is to make the hash function slower. It does not make the key derivation any more secure (as some believe). It only makes it take longer so as to make brute-force attacks more difficult.)

After deriving the encryption key, it is verified using the MAC value (mac). The second block of 128 bits (16 bytes) is concatenated with the ciphertext value. The Keccak-256 hash of the resulting byte array should be equal to the mac value.

If the encryption key passes verification, then it is used to decrypt the ciphertext, using the decryption function of the specified cipher with the parameter values given in cipherparams. The result of this decryption is the plain text private key.

A4. I realized later that a new account should be created only on a node controlled by oneself. That is the reason that the personal API is enabled by default on IPC, but not on RPC, to prevent a new account creation request being accepted by a remote node.

  • A lot of text a about Question 3 but not actually answering the question. Everybody seem to dance around key decryption. I have the UTC file, i have the password to the UTC: What command to use to decrypt and display the private key And no security lecture please. My key, my wallet, my responsibility. – Martin May 17 '18 at 11:28
  • Well, it was my question and, after deep digging, my answer. I did not want to extract a specific private key from a specific UTC file. I wanted to understand what the contents of the UTC file meant. I did not even know what data the ciphertext is supposed to be the encryption of. From Q.1, you can see I was guessing the KDF is used its params and the password to derive the private key. So, what is the purpose of ciphertext? What data is it supposed to represent? The information in my answer was just what I was looking for when I asked those questions. My question, my answer. – Ajoy Bhatia May 17 '18 at 22:29
  • If it was useful to you, that is good. If not, perhaps you are looking for something else, which you may find somewhere else :-) – Ajoy Bhatia May 17 '18 at 22:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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