"Если вы хотите сохранить секрет, вы также должны скрывать его от себя".

Джордж Оруэлл, 1984

Использование таких сервисов, как GCP (Google Cloud Platform) или AWS (Amazon Web Service) для аутсорсинга частного хранилища и управления секретами, такими как API и ключи шифрования, становится обычной практикой. Это предоставляет разработчику более чистый код и снижает вероятность утечки конфиденциальной информации.

Кстати, шифрование и хранение закрытых ключей особенно важны в блокчейне Flow (https://flow.com/). Для этого блокчейна на основе NFT требуется 128-символьный открытый ключ в виде шестнадцатеричной строки для создания учетной записи и соответствующий закрытый ключ для подписи транзакций учетной записи.

В этой статье показано, как использовать GCP KMS(служба управления ключами Google Cloud Platform) и библиотеку npm, которую я недавно создал: fcl -kms-gcp-authorizer (https://github.com/lukaracki/fcl-kms-gcp-authorizer). Я объясню, как использовать указанную библиотеку для создания объекта авторизации, чтобы подписывать транзакции в потоковой цепочке блоков с помощью Flow JavaScript SDK.

Много сложных слов, но на самом деле это не так уж и сложно, так что приступим:

Установка

Примечание.
Чтобы это руководство не было слишком длинным, я предполагаю, что у вас уже есть настроенный серверный проект потока на основе NodeJ, например: https://github.com/onflow/kitty-items/tree/master/api.Если это не так, обратитесь к файлу README.md, расположенному в корневой папке репозитория, ссылка на который приведена выше. и следуйте инструкциям, описанным там.

Перед использованием библиотеки npm fcl-kms-gcp-authorizer необходимо выполнить шаги, описанные в следующих разделах.

Установка библиотеки

Первым шагом является установка библиотеки library fcl-kms-gcp-authorizer npm. Для этого перейдите в репозиторий папки вашего проекта и выполните следующий скрипт bash:

$ npm install fcl-gcp-kms-authorizer

Эта библиотека использует ключи на основе ECDSA_P256, SHA2_256. На следующем этапе этой записи в блоге нам нужно будет сгенерировать ключ в GCP KMS со следующими настройками(*):

* Уровень защиты: программный
* Назначение: асимметричный знак
* Алгоритм по умолчанию: ключ P-256 эллиптической кривой, дайджест SHA256

Настройка GCP KMS

После того, как мы установили вышеупомянутую библиотеку, пришло время настроить нашу облачную инфраструктуру. Начнем с настройки учетной записи службы GCP и получения открытого ключа от GCP KMS.

Очевидно, что вы не можете создать учетную запись службы, если у вас еще нет проекта Google, поэтому вы можете создать новый проект Google или использовать существующий. (https://cloud.google.com/resource-manager/docs/creating-managing-projects)

Чтобы ваше приложение могло получить доступ и использовать GCP KMS, ему потребуется учетная запись службы с правильно настроенными привилегиями и правами доступа. Первый раздел следующей документации Google содержит краткое объяснение того, как создать учетную запись службы: https://cloud.google.com/docs/authentication/getting-started.

Примечание.
После создания сервисного аккаунта обязательно назначьте ему роль администратора Cloud KMS. Вот полезная ссылка из документов Google:
https://cloud.google.com/iam/docs/granting-changing-revoking-access

После того, как вы это сделали, пришло время перейти к следующему шагу, который заключается в создании открытого ключа для использования для создания вашей потоковой учетной записи. Опять же, Google предоставляет подробные инструкции о том, как это сделать, поэтому обязательно следуйте инструкциям из этого руководства: https://cloud.google.com/kms/docs/creating-asymmetric-keys.

Соответствующие настройки, которые следует выбрать при создании ключа, показаны на рисунке ниже.

Важно!
Обязательно задайте указанные ранее настройки (*) при создании ключа, как показано на изображении выше:
Назначение: асимметричный знак
Тип ключа и алгоритм: ключ P-256 эллиптической кривой, дайджест SHA256

После того, как вы создали свой ключ, скопируйте идентификатор ресурса ключа и сохраните его где-нибудь на потом. На этой странице документации Google показано, как получить идентификатор ресурса ключа: https://cloud.google.com/kms/docs/getting-resource-ids

Мы будем использовать этот идентификатор ресурса на более позднем этапе для создания экземпляра авторизатора GCP KMS, поэтому обязательно сохраните его где-нибудь. Вот фрагмент кода, показывающий пример сохранения и использования идентификатора ресурса:

const resourceId: string = {yourResourceId}
const authorizer = new GcpKmsAuthorizer(resourceId);

Замените yourResourceName на (да, действительно) имя вашего ресурса.

Например:

yourResourceId = 'projects/your-project-name/locations/global/keyRings/flow/cryptoKeys/flow-minter-key'

Для использования библиотеки @google-cloud/kms требуется аутентификация в Google. Рекомендуется использовать переменную среды для настройки аутентификации с использованием JSON-файла аутентификации учетной записи Google (один из предыдущего шага при создании учетной записи службы). Эта переменная применяется только к вашему текущему сеансу оболочки, поэтому, если вы открываете новый сеанс, установите переменную снова. Если вам нужна помощь, ознакомьтесь с параграфом Установка переменной среды по следующей ссылке: https://cloud.google.com/docs/authentication/getting-started

Вот пример bash, используемый для связывания переменной среды Google с вашим аутентификационным JSON:

$ export GOOGLE_APPLICATION_CREDENTIALS= "PATH"

Замените PATH значением пути к файлу JSON, содержащему ключ вашей учетной записи службы.

Например:

# export GOOGLE_APPLICATION_CREDENTIALS= /home/user/Downloads/service-account-file.json

После выполнения всех вышеперечисленных шагов мы должны быть готовы к следующему шагу — созданию нашей учетной записи Flow с использованием библиотеки GCP KMS и блокчейна Flow.

Создание учетной записи Flow с использованием необработанного шестнадцатеричного ключа GCP KMS

Чтобы создать учетную запись в блокчейне Flow, вам необходимо указать открытый ключ 128 в шестнадцатеричном формате. Вы можете получить 128 Raw Hex версию вашего открытого ключа GCP, asn1parsing открытый ключ в формате PEM из GCP, а затем удалив первые 2 байта. Однако есть более простой способ — библиотека npm fcl-gcp-kms-authorizer может сделать это за вас.

Внутри уже существующего внутреннего проекта Flow NodeJS создайте новый файл TypeScript и вставьте следующий код:

import { GcpKmsAuthorizer } from ''fcl-gcp-kms-authorizer”;
async function main() {
  // Your GCP Resource Name Goes Here
  const resourceId: string =   'projects/your-project-id/locations/global/keyRings/flow/cryptoKeys/flow-minter-key/cryptoKeyVersions/1';
  const authorizer = new GcpKmsAuthorizer(resourceId);
  const publicKey = await authorizer.getPublicKey();
  console.log('\nFetched Raw Hex Public Key: ' + publicKey);
}
main().catch(e => console.error(e));

Если все было настроено правильно, после компиляции и выполнения программа должна вывести ваш необработанный открытый ключ в шестнадцатеричном формате, ключ должен быть в шестнадцатеричном формате 128.

Например:

ee3df35fdb6aaa1e84ee27c2cb9dd98b57d951b74b64fef13a70b9ce2ac659b1a41f0f352824e2c1a3622d44db41we02192b49285de

Теперь, когда мы получили наш ключ, мы можем, наконец, создать потоковую учетную запись. Существует несколько способов создания учетной записи. Подробнее см. в документации Flow.

Использование интерфейса командной строки потока

Использование сборщика Flow Testnet (для Testnet)

Использование Flow Go SDK

Важно!
При создании потоковой учетной записи с использованием извлеченного открытого ключа обязательно используйте тот же алгоритм шифрования, который мы использовали при создании нашего открытого ключа GCP.

Алгоритм подписи: ECDSA_P256

Алгоритм хеширования: SHA2_256

Вот пример bash для создания открытого ключа с хеш-алгоритмом SHA2_256 с помощью Flow CLI (по умолчанию алгоритм подписи ECDSA_P256, поэтому нам не нужно указывать его при использовании Flow CLI).

$ flow accounts create \ 
      --key ee3df35fdb6aaa1e84ee27c2cb9dd98b57d951b74b64fef13a70b9ce2ac659b1a41f0f352824e2c1a3622d44db417e02172b49285de5dee3c90ad612b990447c \
      --hash-algo SHA2_256

После того, как вы создали свою учетную запись с помощью открытого ключа GCP KMS, вы должны были получить адрес своей учетной записи, и все готово! Вы можете настроить аутентификацию внутри файла flow.json вашего проекта Flow, добавив следующие строки:

Важно!
Обязательно замените адрес учетной записи на адрес вашей учетной записи, а resourceIDна имя ресурса вашего ключа!

“accounts”:{
"admin-account": {
      "address": "0xfa5c16359bca3cfd", // <- Your account’s address
      "key": {
        "type": "google-kms",
        "index": 0,
        "signatureAlgorithm": "ECDSA_P256",
        "hashAlgorithm": "SHA2_256",
        "resourceID": "projects/your-project-name/locations/global/keyRings/flow/cryptoKeys/flow-minter-key" <- Your account’s resource name
      }
    }
}

Добавив эти строки в свой файл flow.json, вы включили Flow CLI для аутентификации с помощью GCP KMS. В следующем разделе я покажу вам пример создания функции авторизации с помощью библиотеки fcl-gcp-kms-authorizer для авторизации транзакций внутри вашего серверного приложения NodeJS Flow.

Пример использования

Мы, наконец, завершили часть настройки, давайте перейдем непосредственно к примеру создания функции авторизации. Это очень просто.

Сначала мы используем имя нашего ресурса для создания экземпляра авторизатора GCP KMS.

const resourceId: string =    'projects/your-project-id/locations/global/keyRings/flow/cryptoKeys/flow-minter-key/cryptoKeyVersions/1'; <- Your GCP Resource Name
const authorizer = new GcpKmsAuthorizer(resourceId);

Затем для создания функции авторизации мы используем адрес своей учетной записи и индекс ключа (который мы получили после создания нашей учетной записи).

const address = '0x01cf0e2f2f715450'; <- Your Flow Account Address
const keyIndex = 0; <- Your Flow Key Index
const authorization = authorizer.authorize(address, keyIndex);

После этого мы можем просто использовать функцию авторизации для авторизации транзакций внутри Flow Javascript SDK:

const response = await fcl.send([
    fcl.transaction`
      transaction {
        prepare(signer: AuthAccount) {
          log("Test transaction signed by fcl-gcp-kms-authorizer")
        }
      }
    `,
    fcl.args([]),
    fcl.proposer(authorization),
    fcl.authorizations([authorization]),
    fcl.payer(authorization),
    fcl.limit(9999),
  ]);

Наконец, вот полный пример кода с использованием всех функций из библиотеки fcl-gcp-kms-authorize.

Примечание.
В следующем примере кода я использую созданную эмулятором учетную запись и подключаюсь к узлу доступа к API эмулятора, который запущен на моем локальном хосте. Ранее я создал учетную запись эмулятора потока с помощью команды bash create учетных записей потока.

import { GcpKmsAuthorizer } from '../src/auth/authorizer';
import * as fcl from '@onflow/fcl';
// emulator url
const apiUrl = 'http://localhost:8080';
fcl.config().put('accessNode.api', apiUrl);
async function main() {
// Your GCP resource name
  const resourceId: string = 'projects/your-project-id/locations/global/keyRings/flow/cryptoKeys/flow-minter-key/cryptoKeyVersions/1';
// Your account key (emulator or testnet)
// Create account first using flow accounts create --key {yourRawHexPublicKey}
  const address = '0x01cf0e2f2f715450';
  const keyIndex = 0;
  const authorizer = new GcpKmsAuthorizer(resourceId);
  const authorization = authorizer.authorize(address, keyIndex);
  const response = await fcl.send([
    fcl.transaction`
      transaction {
        prepare(signer: AuthAccount) {
          log("Test transaction signed by fcl-gcp-kms-authorizer")
        }
      }
    `,
    fcl.args([]),
    fcl.proposer(authorization),
    fcl.authorizations([authorization]),
    fcl.payer(authorization),
    fcl.limit(9999),
  ]);
  console.log('=====Transaction Succeeded=====\n');
  const publicKey = await authorizer.getPublicKey();
  const flowPublicKey = await authorizer.getFlowPublicKey();
  console.log('\nFetched Raw Hex Public Key: ' + publicKey);
  console.log('\nFetched Flow Public Key: ' + flowPublicKey + '\n');
}
main().catch(e => console.error(e));

Заключение

Завершая эту запись в блоге, мы надеемся, что вы узнали, как аутентифицировать свои транзакции Flow с помощью GCP KMS.

Особая благодарность https://github.com/doublejumptokyo за создание версии этой библиотеки для AWS и за то, что вдохновил меня на создание версии для GCP! Он мне очень помог, так как я разветвил большую часть его кода и настроил его для работы с облачной платформой Google. Пакет npm в настоящее время находится в версии 0.0.1, и я буду продолжать обновлять его и добавлять новые функции по мере развития экосистемы блокчейна Flow.

Спасибо, что прочитали это! Надеюсь, вам понравилось и вы сможете использовать полученные знания.