Перейти к основному контенту
Change page

Определение секретного хранилища Web3

Чтобы ваше приложение работало в Эфириуме, вы можете использовать объект web3, предоставляемый библиотекой Web3.js. Внутри он взаимодействует с локальным узлом через RPC-вызовы. web3 (opens in a new tab) работает с любым узлом Эфириума, который предоставляет слой RPC.

web3 содержит объект eth — web3.eth.

В этом документе описывается версия 3 определения секретного хранилища Web3.

Определение

Фактическое кодирование и декодирование файла остается в значительной степени неизменным по сравнению с версией 1, за исключением того, что криптографический алгоритм больше не привязан жестко к AES-128-CBC (теперь минимальным требованием является AES-128-CTR). Большинство значений и алгоритмов аналогичны версии 1, за исключением mac, который задается как SHA3 (Keccak-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 (Keccak-256) от массива байтов, образованного конкатенацией вторых слева 16 байтов производного ключа с содержимым ключа ciphertext, то есть:

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 для отслеживания небольших, не нарушающих совместимость изменений в формате.

Тестовые векторы

Детали:

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

PBKDF2-SHA-256

Тестовый вектор с использованием AES-128-CTR и PBKDF2-SHA-256:

Содержимое файла ~/.web3/keystore/3198bc9c-6672-5ab3-d9954942343ae5b6.json:

Промежуточные значения:

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

Scrypt

Тестовый вектор с использованием AES-128-CTR и Scrypt:

Промежуточные значения:

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

Изменения по сравнению с версией 1

В этой версии исправлено несколько несоответствий с версией 1, опубликованной здесь (opens in a new tab). Вкратце это:

  • Использование заглавных букв необоснованно и непоследовательно (scrypt в нижнем регистре, Kdf в смешанном, MAC в верхнем).
  • Адрес не нужен и ставит под угрозу приватность.
  • Salt по своей сути является параметром функции формирования ключа и должен быть связан с ней, а не с криптографией в целом.
  • SaltLen не нужен (просто выводится из Salt).
  • Функция формирования ключа задана, однако криптографический алгоритм жестко определен.
  • Version по своей сути является числовым значением, но представлен в виде строки (структурированное управление версиями было бы возможно со строкой, но это можно считать выходящим за рамки редко меняющегося формата конфигурационного файла).
  • KDF и cipher условно являются родственными концепциями, но организованы по-разному.
  • MAC вычисляется через фрагмент данных, не зависящий от пробелов(!)

В формат были внесены изменения, чтобы получить следующий файл, функционально эквивалентный примеру, приведенному на странице по ссылке выше:

Изменения по сравнению с версией 2

Версия 2 была ранней реализацией на C++ с рядом ошибок. Все основные элементы остались в ней без изменений.