---
title: "Визначення секретного сховища Web3"
description: "Формальне визначення для секретного сховища Web3"
lang: uk
sidebarDepth: 2
---

Щоб ваш застосунок працював в Етеріумі, ви можете використовувати об'єкт web3, який надає бібліотека Web3.js. Технічно він взаємодіє з локальним вузлом через RPC-виклики. [web3](https://github.com/ethereum/web3.js/) працює з будь-яким вузлом Етеріуму, який відкриває доступ до рівня RPC.

`web3` містить об'єкт `eth` — web3.eth.

```js
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)
})

/** результат
 *               [ 'web3', 3 ]   файл ключа Web3 (v3)
 *  [ 'ethersale', undefined ]   файл ключа Ethersale
 *                        null     недійсний файл ключа
 */
```

Цей документ описує **версію 3** визначення секретного сховища Web3.

## Визначення {#definition}

Фактичне кодування та декодування файлу залишається переважно незмінним порівняно з версією 1, за винятком того, що криптоалгоритм більше не фіксується як AES-128-CBC (тепер мінімальною вимогою є AES-128-CTR). Більшість значень/алгоритмів подібні до версії 1, за винятком `mac`, який подається як SHA3 (Кеччак-256) від конкатенації других зліва 16 байтів похідного ключа разом із повним `ciphertext`.

Файли секретних ключів зберігаються безпосередньо в `~/.web3/keystore` (для Unix-подібних систем) та `~/AppData/Web3/keystore` (для Windows). Вони можуть мати будь-яку назву, але хорошою практикою є використання формату `<uuid>.json`, де `<uuid>` — це 128-бітний UUID, наданий секретному ключу (проксі-ідентифікатор для адреси секретного ключа, що зберігає приватність).

Усі такі файли мають пов'язаний пароль. Щоб отримати секретний ключ певного файлу `.json`, спочатку потрібно отримати ключ шифрування файлу; це робиться шляхом взяття пароля файлу та його передачі через функцію формування ключа (KDF), як описано в ключі `kdf`. Статичні та динамічні параметри, що залежать від KDF і передаються до функції KDF, описані в ключі `kdfparams`.

PBKDF2 має підтримуватися всіма мінімально сумісними реалізаціями, що позначається як:

- `kdf`: `pbkdf2`

Для PBKDF2 параметри kdfparams включають:

- `prf`: Має бути `hmac-sha256` (може бути розширено в майбутньому);
- `c`: кількість ітерацій;
- `salt`: сіль, передана до PBKDF;
- `dklen`: довжина похідного ключа. Має бути >= 32.

Після того, як ключ файлу було отримано, його слід перевірити шляхом обчислення MAC. MAC має обчислюватися як хеш SHA3 (Кеччак-256) від масиву байтів, утвореного конкатенацією других зліва 16 байтів похідного ключа з вмістом ключа `ciphertext`, тобто:

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

(де `++` — це оператор конкатенації)

Це значення слід порівняти з вмістом ключа `mac`; якщо вони відрізняються, слід запросити альтернативний пароль (або скасувати операцію).

Після перевірки ключа файлу зашифрований текст (ключ `ciphertext` у файлі) можна розшифрувати за допомогою алгоритму симетричного шифрування, вказаного ключем `cipher` та параметризованого через ключ `cipherparams`. Якщо розмір похідного ключа та розмір ключа алгоритму не збігаються, як ключ для алгоритму слід використовувати крайні праві байти похідного ключа, доповнені нулями.

Усі мінімально сумісні реалізації повинні підтримувати алгоритм AES-128-CTR, що позначається як:

- `cipher: aes-128-ctr`

Цей шифр приймає такі параметри, задані як ключі для ключа cipherparams:

- `iv`: 128-бітний вектор ініціалізації для шифру.

Ключем для шифру є крайні ліві 16 байтів похідного ключа, тобто `DK[0..15]`

Створення/шифрування секретного ключа має бути по суті зворотним до цих інструкцій. Переконайтеся, що `uuid`, `salt` та `iv` дійсно є випадковими.

Окрім поля `version`, яке має діяти як «жорсткий» ідентифікатор версії, реалізації також можуть використовувати `minorversion` для відстеження менших змін у форматі, що не порушують сумісність.

## Тестові вектори {#test-vectors}

Деталі:

- `Address`: `008aeeda4d805471df9b2a5b0f38a0c3bcba786b`
- `ICAP`: `XE542A5PZHH8PYIZUBEJEO0MFWRAPPIL67`
- `UUID`: `3198bc9c-6672-5ab3-d9954942343ae5b6`
- `Password`: `testpassword`
- `Secret`: `7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d`

### PBKDF2-SHA-256 {#pbkdf2-sha-256}

Тестовий вектор із використанням `AES-128-CTR` та `PBKDF2-SHA-256`:

Вміст файлу `~/.web3/keystore/3198bc9c-6672-5ab3-d9954942343ae5b6.json`:

```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
}
```

**Проміжні значення**:

`Derived key`: `f06d69cdc7da0faffb1008270bca38f5e31891a3a773950e6d0fea48a7188551`
`MAC Body`: `e31891a3a773950e6d0fea48a71885515318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46`
`MAC`: `517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2`
`Cipher key`: `f06d69cdc7da0faffb1008270bca38f5`

### Scrypt {#scrypt}

Тестовий вектор із використанням AES-128-CTR та Scrypt:

```json
{
  "crypto": {
    "cipher": "aes-128-ctr",
    "cipherparams": {
      "iv": "740770fce12ce862af21264dab25f1da"
    },
    "ciphertext": "dd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2",
    "kdf": "scrypt",
    "kdfparams": {
      "dklen": 32,
      "n": 262144,
      "p": 1,
      "r": 8,
      "salt": "25710c2ccd7c610b24d068af83b959b7a0e5f40641f0c82daeb1345766191034"
    },
    "mac": "337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c"
  },
  "id": "3198bc9c-6672-5ab3-d995-4942343ae5b6",
  "version": 3
}
```

**Проміжні значення**:

`Derived key`: `7446f59ecc301d2d79bc3302650d8a5cedc185ccbb4bf3ca1ebd2c163eaa6c2d`
`MAC Body`: `edc185ccbb4bf3ca1ebd2c163eaa6c2ddd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2`
`MAC`: `337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c`
`Cipher key`: `7446f59ecc301d2d79bc3302650d8a5c`

## Зміни порівняно з версією 1 {#alterations-from-v2}

Ця версія виправляє кілька невідповідностей із версією 1, опублікованою [тут](https://github.com/ethereum/homestead-guide/blob/master/old-docs-for-reference/go-ethereum-wiki.rst/Passphrase-protected-key-store-spec.rst). Коротко кажучи, це:

- Використання великих літер є невиправданим і непослідовним (scrypt з малої літери, Kdf зі змішаним регістром, MAC з великої літери).
- Адреса є непотрібною та ставить під загрозу приватність.
- `Salt` за своєю суттю є параметром функції формування ключа і має бути пов'язаний з нею, а не з крипто загалом.
- _SaltLen_ є непотрібним (його можна просто отримати з Salt).
- Функція формування ключа задана, проте криптографічний алгоритм жорстко визначений.
- `Version` за своєю суттю є числовим значенням, але представлений як рядок (структуроване керування версіями було б можливим за допомогою рядка, але це можна вважати таким, що виходить за рамки формату конфігураційного файлу, який рідко змінюється).
- `KDF` та `cipher` є концептуально спорідненими поняттями, проте організовані по-різному.
- `MAC` обчислюється через фрагмент даних, що не залежить від пробілів(!)

До формату було внесено зміни, щоб отримати наступний файл, функціонально еквівалентний прикладу, наведеному на сторінці за посиланням вище:

```json
{
  "crypto": {
    "cipher": "aes-128-cbc",
    "ciphertext": "07533e172414bfa50e99dba4a0ce603f654ebfa1ff46277c3e0c577fdc87f6bb4e4fe16c5a94ce6ce14cfa069821ef9b",
    "cipherparams": {
      "iv": "16d67ba0ce5a339ff2f07951253e6ba8"
    },
    "kdf": "scrypt",
    "kdfparams": {
      "dklen": 32,
      "n": 262144,
      "p": 1,
      "r": 8,
      "salt": "06870e5e6a24e183a5c807bd1c43afd86d573f7db303ff4853d135cd0fd3fe91"
    },
    "mac": "8ccded24da2e99a11d48cda146f9cc8213eb423e2ea0d8427f41c3be414424dd",
    "version": 1
  },
  "id": "0498f19a-59db-4d54-ac95-33901b4f1870",
  "version": 2
}
```

## Зміни порівняно з версією 2 {#alterations-from-v2-2}

Версія 2 була ранньою реалізацією на C++ із низкою помилок. Усі основні елементи залишилися незмінними порівняно з нею.