Web3 Secret Storage Definition

Contents

To make your app work on Quadrans, you can use the web3 object provided by the web3.js library. Under the hood it communicates to a local node through RPC calls. web3 works with any Quadrans node, which exposes an RPC layer.

web3 contains the eth object - web3.eth (for specifically Quadrans blockchain interactions) and the shh object - web3.shh (for Whisper interaction). Over time we’ll introduce other objects for each of the other web3 protocols. Working examples can be found here.

var fs = require('fs');
var recognizer = require('ethereum-keyfile-recognizer');

fs.readFile('keyfile.json', (err, data) => {
var json = JSON.parse(data);
var result = recognizer(json);**# **
/** result
  *               [ 'web3', 3 ]   web3 (v3) keyfile
  *  [ 'ethersale', undefined ]   Ethersale keyfile
  *                        null     invalid keyfile
 */
 }));

This documents version 3 of the Web3 Secret Storage Definition.

Definition

The actual encoding and decoding of the file remains largely unchanged from version 1, except that the crypto algorithm is no longer fixed to AES-128-CBC (AES-128-CTR is now the minimal requirement). Most of the meanings/algorithm are similar to version 1, except mac, which is given as the SHA3 (keccak-256) of the concatenations of the second-leftmost 16 bytes of the derived key together with the full ciphertext.

Secret key files are stored directly in ~/.web3/keystore (for Unix-like systems) and ~/AppData/Web3/keystore (for Windows). They may be named anything, but a good convention is <uuid>.json, where <uuid> is the 128-bit UUID given to the secret key (a privacy-preserving proxy for the secret key’s address).

All such files have an associated password. To derive a given .json file’s secret key, first derive the file’s encryption key; this is done through taking the file’s password and passing it through a key derivation function as described by the kdf key. KDF-dependent static and dynamic parameters to the KDF function are described in kdfparams key.

PBKDF2 must be supported by all minimally-compliant implementations, denoted though:

  • kdf: pbkdf2

For PBKDF2, the kdfparams include:

  • prf: Must be hmac-sha256 (may be extended in the future);

  • c: number of iterations;

  • salt: salt passed to PBKDF;

  • dklen: length for the derived key. Must be >= 32.

Once the file’s key has been derived, it should be verified through the derivation of the MAC. The MAC should be calculated as the SHA3 (keccak-256) hash of the byte array formed as the concatenations of the second-leftmost 16 bytes of the derived key with the ciphertext key’s contents, i.e.:

KECCAK(DK[16..31] ++ <ciphertext>)

(where ++ is the concatenation operator)

This value should be compared to the contents of the mac key; if they are different, an alternative password should be requested (or the operation cancelled).

After the file’s key has been verified, the cipher text (the ciphertext key in the file) may be decrypted using the symmetric encryption algorithm specified by the cipher key and parameterised through the cipherparams key. If the derived key size and the algorithm’s key size are mismatched, the zero padded, rightmost bytes of the derived key should be used as the key to the algorithm.

All minimally-compliant implementations must support the AES-128-CTR algorithm, denoted through:

  • cipher: aes-128-ctr

This cipher takes the following parameters, given as keys to the cipherparams key:

  • iv: 128-bit initialisation vector for the cipher.

The key for the cipher is the leftmost 16 bytes of the derived key, i.e. DK[0..15]

The creation/encryption of a secret key should be essentially the reverse of these instructions. Make sure the uuid, salt and iv are actually random.

In addition to the version field, which should act as a “hard” identifier of version, implementations may also use minorversion to track smaller, non-breaking changes to the format.

Test Vectors

Details:

  • Address: 008aeeda4d805471df9b2a5b0f38a0c3bcba786b

  • ICAP: XE542A5PZHH8PYIZUBEJEO0MFWRAPPIL67

  • UUID: 3198bc9c-6672-5ab3-d9954942343ae5b6

  • Password: testpassword

  • Secret: 7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d

PBKDF2-SHA-256

Test vector using AES-128-CTR and PBKDF2-SHA-256:

File contents of ~/.web3/keystore/3198bc9c-6672-5ab3-d9954942343ae5b6.json:

{
    "crypto" : {
        "cipher" : "aes-128-ctr",
        "cipherparams" : {
            "iv" : "6087dab2f9fdbbfaddc31a909735c1e6"
        },
        "ciphertext" : "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46",
        "kdf" : "pbkdf2",
        "kdfparams" : {
            "c" : 262144,
            "dklen" : 32,
            "prf" : "hmac-sha256",
            "salt" : "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"
        },
        "mac" : "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2"
    },
    "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6",
    "version" : 3
}

Intermediates:

  • Derived key: f06d69cdc7da0faffb1008270bca38f5e31891a3a773950e6d0fea48a7188551

  • MAC Body: e31891a3a773950e6d0fea48a71885515318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46

  • MAC 517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2

  • Cipher key: f06d69cdc7da0faffb1008270bca38f5

Scrypt

Test vector using AES-128-CTR and Scrypt:

{
    "crypto" : {
        "cipher" : "aes-128-ctr",
        "cipherparams" : {
            "iv" : "83dbcc02d8ccb40e466191a123791e0e"
        },
        "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c",
        "kdf" : "scrypt",
        "kdfparams" : {
            "dklen" : 32,
            "n" : 262144,
            "p" : 8,
            "r" : 1,
            "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19"
        },
        "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097"
    },
    "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6",
    "version" : 3
}

Intermediates:

  • Derived key: fac192ceb5fd772906bea3e118a69e8bbb5cc24229e20d8766fd298291bba6bd

  • MAC Body bb5cc24229e20d8766fd298291bba6bdd172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c

  • MAC: 2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097

  • Cipher key: fac192ceb5fd772906bea3e118a69e8b