Skip to content

Passphrase protected key store spec

Gav Wood edited this page May 7, 2015 · 18 revisions

Version 2 documented here

Summary

This page details the crypto & encodings in the passphrase protected key store in Go. To implement this in another Ethereum implementation the steps below can be followed. The example JSON also acts as a test vector.

TODO: update github links to mainline branch once the latest key store PR is merged.

References

The source code comments there have a list of further references.

From JSON to privkey

We start with the JSON in the key file on disk and list operations to get a privkey for signing.

JSON in key file on disk (password is "foo") :

{
    "Address": "d4584b5f6229b7be90727b0fc8c6b91bb427821f",
    "Crypto": {
        "CipherText": "07533e172414bfa50e99dba4a0ce603f654ebfa1ff46277c3e0c577fdc87f6bb4e4fe16c5a94ce6ce14cfa069821ef9b",
        "IV": "16d67ba0ce5a339ff2f07951253e6ba8",
        "KeyHeader": {
            "Kdf": "scrypt",
            "KdfParams": {
                "DkLen": 32,
                "N": 262144,
                "P": 1,
                "R": 8,
                "SaltLen": 32
            },
            "Version": "1"
        },
        "MAC": "8ccded24da2e99a11d48cda146f9cc8213eb423e2ea0d8427f41c3be414424dd",
        "Salt": "06870e5e6a24e183a5c807bd1c43afd86d573f7db303ff4853d135cd0fd3fe91"
    },
    "Id": "0498f19a-59db-4d54-ac95-33901b4f1870",
    "Version": "1"
}

Go code unmarshaling and decrypting this: https://github.com/Gustav-Simonsson/go-ethereum/blob/improve_key_store_crypto/crypto/key_store_passphrase.go#L199

  1. Read in the JSON and parse out the KeyHeader field. Get the JSON representation of the KeyHeader as a string / byte array. We need this for MAC calculation.

  2. Get the derived key by calling scrypt with the scrypt params, the salt and the passphrase.

  3. Calculate MAC by taking SHA3 of concatentation of KeyHeader JSON, last 16 bytes of derived key and cipher text:

SHA3( KeyHeaderJSON || derivedKey[16:32] || cipherText )
  1. Compare calculated MAC with MAC from the JSON object. If not equal, abort and return an error.

  2. Decrypt the cipherText using AES-128 with CBC mode and the IV from the JSON. The key used to decrypt is the last 16 bytes of SHA3 of the last 16 bytes of the scrypt derived key:

AES_128_CBC_Decrypt( SHA3(derivedKey[:16])[:16], cipherText, iv )
  1. The decrypted plaintext is the 32 bytes EC privkey.

  2. For encryption: reverse the above steps. Ensure both salt and iv are generated by CSPRNG.

Further notes:

  • The "Address" is OPTIONAL. It is the ethereum address of the key.
  • The Id is OPTIONAL. It is a UUID Version 4. It is used to identify a key not using key-derived data such as the ethereum address, for e.g. key file names.
Clone this wiki locally