> For the complete documentation index, see [llms.txt](https://docs.meycoin.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.meycoin.com/technical-specifications/keystore.md).

# Keystore

{% hint style="info" %}
Securing private keys is the responsibility of client software, but Meey has a recommended storage format for increased portability. This storage format is also used internally when storing accounts in meeycli.
{% endhint %}

This so-called Keystore format defines a file format (json) and encryption scheme.

### File format

Filename: `{address}__keystore.txt`

```
{
  "meey_address": "Amdxxxx",
  "ks_version": "1",
  "kdf": {
    "algorithm": "algorithm_name",
    "params": {
      "some_param": "some_value"
    },
    "mac": "mesasge_authentication_code"
  },
  "cipher": {
    "algorithm": "algorithm_name",
    "params": {
      "some_param": "some_value"
    },
    "ciphertext": "dxxxx",
  }
}
```

### Rules

* Version field is for choosing cipher algorithm. If version updates, cipher algorithm would be updated (also format can change).
* Every file has its own algorithm and parameters per version. If any of the parameters break, an error should be thrown.
* File name is ‘{address}\_\_keystore.txt’ or ‘{alias}\_\_keystore.txt’
* File name is used to identify keystore file. Duplicates are not allowed.
* For the alias file, you can have same keystore file representing same account using different alias. That’s fine.
* Address must be a valid base58-check encoded address. Alias must be form of `[a-zA-Z0-9]+`

### Examples

**Encrypt**

```
cipherText = AES_CTR.encrypt(rawPrivateKey, encryptionKey[0:16], nonce)
mac = Sha256(encryptionKey[16:32] + cipherText)

keystore = {
  "meey_address": "Amdxxxx",
  "ks_version": "1",
  "kdf": {
    "algorithm": "scrypt",
    "params": scryptParams,
    "mac": mac
  },
  "cipher": {
    "algorithm": "aes-128-ctr",
    "params": {
      "iv": nonce
    },
    "ciphertext": cipherText
  }
}
```

**Decrypt**

```
encryptionKey = Scrypt(rawPassword, keystore.kdf.params)
mac = Sha256(encryptionKey[16:32] + json.cipher.ciphertext)
if keystore.kdf.mac != mac {
  throw "invalid mac"
}
rawPrivateKey = AES_CTR.decrypt(json.cipher.ciphertext, encryptionKey[0:16], json.cipher.params.iv)
```

**Recommended parameters**

```
{
    kdfAlgorithm: 'scrypt',
    cipherAlgorithm: 'aes-128-ctr',
    kdfParams: {
        dklen: 32,
        n: 1 << 18,
        p: 1,
        r: 8,
    },
}
```
