Определение секретного хранилища Web3
Чтобы ваше приложение работало в Эфириуме, вы можете использовать объект web3, предоставляемый библиотекой Web3.js. Внутри он взаимодействует с локальным узлом через RPC-вызовы. web3 (opens in a new tab) работает с любым узлом Эфириума, который предоставляет слой RPC.
web3 содержит объект eth — web3.eth.
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.
Определение
Фактическое кодирование и декодирование файла остается в значительной степени неизменным по сравнению с версией 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:008aeeda4d805471df9b2a5b0f38a0c3bcba786bICAP:XE542A5PZHH8PYIZUBEJEO0MFWRAPPIL67UUID:3198bc9c-6672-5ab3-d9954942343ae5b6Password:testpasswordSecret:7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d
PBKDF2-SHA-256
Тестовый вектор с использованием AES-128-CTR и PBKDF2-SHA-256:
Содержимое файла ~/.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
}
Промежуточные значения:
Derived key: f06d69cdc7da0faffb1008270bca38f5e31891a3a773950e6d0fea48a7188551
MAC Body: e31891a3a773950e6d0fea48a71885515318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46
MAC: 517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2
Cipher key: f06d69cdc7da0faffb1008270bca38f5
Scrypt
Тестовый вектор с использованием AES-128-CTR и Scrypt:
{
"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
В этой версии исправлено несколько несоответствий с версией 1, опубликованной здесь (opens in a new tab). Вкратце это:
- Использование заглавных букв необоснованно и непоследовательно (scrypt в нижнем регистре, Kdf в смешанном, MAC в верхнем).
- Адрес не нужен и ставит под угрозу приватность.
Saltпо своей сути является параметром функции формирования ключа и должен быть связан с ней, а не с криптографией в целом.- SaltLen не нужен (просто выводится из Salt).
- Функция формирования ключа задана, однако криптографический алгоритм жестко определен.
Versionпо своей сути является числовым значением, но представлен в виде строки (структурированное управление версиями было бы возможно со строкой, но это можно считать выходящим за рамки редко меняющегося формата конфигурационного файла).KDFиcipherусловно являются родственными концепциями, но организованы по-разному.MACвычисляется через фрагмент данных, не зависящий от пробелов(!)
В формат были внесены изменения, чтобы получить следующий файл, функционально эквивалентный примеру, приведенному на странице по ссылке выше:
{
"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
Версия 2 была ранней реализацией на C++ с рядом ошибок. Все основные элементы остались в ней без изменений.