Перейти к содержанию

Class: SpatiumProtocol

Надежный MPC протокол подписания для ECDSA и EDDSA систем

Основан на Crypto и Transport Drivers, следовательно, полностью инкапсулирует криптографические данные и данные передачи сообщений внутри MPC алгоритмов. Сейчас поддерживается только 2-из-2 схема подписания, однако интерфейс должен остаться таким же для большего количества схем.

Пример

// Предполагаем что уже есть существующий секрет, связанный с secretId

// Генерируем случайный session ID для новой сессии синхронизации
const syncSessionId = uuid(randomBytes);

// Выполняем ECDSA-over-secp256k1 процедуру синхронизации для ключа с путем ```m/44'/0'/0'/0'/0'```
const publicKey = await syncDistributedEcdsaKey(protocol, secretId, syncSessionId, 'secp256k1', 0, 0);

// К этому моменту данные синхронизации уже сохранены в хранилище и составной ключ доступен к получению
const _publicKey = await getEcdsaPublicKey(protocol, secretId, syncSessionId);

// Этот ключ, очевидно, является тем же ключом, который мы получаем из самой процедуры синхронизации
expect(publicKey).toBe(_publicKey);

// Генерируем случайный session ID для новой сессии подписания
const signSessionId = uuid(randomBytes);

// Сообщение к подписанию
const message = '7hJ9yN2OdIQo2kJu0arZgw2EKnMX5FGtQ6jlCWuLXCM='

//  Генерируем EDDSA подпись
const signature = await signEcdsaMessage(protocol, secretId, syncSessionId, signSessionId, message);

// Верифицируем подпись к составному ключу с внешней библиотекой (тут - elliptic.js)
expect(new ec('secp256k1').verify(
  Buffer.from(message, 'base64'),
  {
    s: Buffer.from(signature.s, 'base64'),
    r: Buffer.from(signature.r, 'base64'),
    recoveryParam: signature.recovery,
  },
  Buffer.from(publicKey, 'base64'),
)).toBeTruthy();

Имплементирует

Конструкторы

constructor

new SpatiumProtocol(crypto, transport, timeout?)

SpatiumProtocol Конструктор

Параметры

Имя Тип Описание
crypto Crypto программный или аппаратный крипто-модуль для выполнения вычислений
transport TransportDriver имплементация передачи сообщения как через сокеты, HTTP(S) или с помощью других средств коммуникации
timeout? number (опционально) таймаут запроса каждого сообщения, после которого процедура завершается

Properties

crypto

crypto: Crypto

программный или аппаратный крипто-модуль для выполнения вычислений


transport

transport: TransportDriver

имплементация передачи сообщения как через сокеты, HTTP(S) или с помощью других средств коммуникации

Методы

getEcdsaPublicKey

getEcdsaPublicKey(secretId, syncSessionId): Promise<string>

Получение составного публичного ключа из уже выполненного сеанса синхронизации

Пример

// Считаем, что процедура синхронизации уже пройдена

const publicKey = await getEcdsaPublicKey(protocol, secretId, syncSessionId);

Параметры

Имя Тип Описание
secretId string ID (UUID) секрета, использующегося для синхронизации
syncSessionId string ID (UUID) процедуры синхронизации

Возвращает

Promise<string>

составной публичный ключ, синхронизированный в ходе этой сессии

Имплементация

Protocol.getEcdsaPublicKey


getEddsaPublicKey

getEddsaPublicKey(secretId, syncSessionId): Promise<string>

Получение составного публичного ключа из уже выполненного сеанса синхронизации

Пример

// Считаем, что процедура синхронизации уже пройдена

const publicKey = await getEddsaPublicKey(protocol, secretId, syncSessionId);

Параметры

Имя Тип Описание
secretId string ID (UUID) секрета, использующегося для синхронизации
syncSessionId string ID (UUID) процедуры синхронизации

Возвращает

Promise<string>

составной публичный ключ, синхронизированный в ходе этой сессии

Имплементация

Protocol.getEddsaPublicKey


off

off(): void

Отписка от серверных событий

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

Возвращает

void

Имплементация

Protocol.off


on

on(): void

Подписка на серверные события

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

Возвращает

void

Имплементация

Protocol.on


removeDistributedEcdsaKey

removeDistributedEcdsaKey(secretId, syncSessionId): Promise<void>

Удаляет уже существующую сессию синхронизации из хранилища

Example

// Считаем, что процедура синхронизации уже пройдена

await removeDistributedEcdsaKey(protocol, secretId, syncSessionId);

Параметры

Имя Тип Описание
secretId string ID (UUID) секрета, использующегося для синхронизации
syncSessionId string ID (UUID) процедуры синхронизации

Возвращает

Promise<void>

Имплементация

Protocol.removeDistributedEcdsaKey


removeDistributedEddsaKey

removeDistributedEddsaKey(secretId, syncSessionId): Promise<void>

Удаляет уже существующую сессию синхронизации из хранилища

Example

// Считаем, что процедура синхронизации уже пройдена

await removeDistributedEddsaKey(protocol, secretId, syncSessionId);

Параметры

Имя Тип Описание
secretId string ID (UUID) секрета, использующегося для синхронизации
syncSessionId string ID (UUID) процедуры синхронизации

Возвращает

Promise<void>

Имплементация

Protocol.removeDistributedEddsaKey


signEcdsaMessage

signEcdsaMessage(secretId, syncSessionId, signSessionId, message): Promise<EcdsaSignature>

Генерирует распределенную ECDSA подпись для данного сообщения

Для этого метода необходима уже пройденная процедура синхронизации и так же ничего не должно быть помещено в постоянное хранилище. Сообщения с объемом информации отличным от 32 байт будут дополнены/урезаны в соответствии с ECDSA алгоритмом.

Пример

// Считаем, что процедура синхронизации уже пройдена и соединение установлено

// Генерируем рандомный session ID для новой сессии подписания
const signSessionId = uuid(randomBytes);

// Сообщение к подписанию
const message = '7hJ9yN2OdIQo2kJu0arZgw2EKnMX5FGtQ6jlCWuLXCM='

//  Генерируем ECDSA подпись
const signature = await signEcdsaMessage(protocol, secretId, syncSessionId, signSessionId, message);

// Верифицируем подпись к составному ключу с внешней библиотекой (тут - elliptic.js)
expect(new ec('secp256k1').verify(
  Buffer.from(message, 'base64'),
  {
    s: Buffer.from(signature.s, 'base64'),
    r: Buffer.from(signature.r, 'base64'),
    recoveryParam: signature.recovery,
  },
  Buffer.from(publicKey, 'base64'),
)).toBeTruthy();

Параметры

Имя Тип Описание
secretId string ID (UUID) секрета для синхронизации
signSessionId string ID (UUID) данной процедуры подписания
syncSessionId string ID (UUID) соответствующей процедуры синхронизации
message string сообщение (32 байта base64-encoded) к подписанию

Возвращает

Promise<EcdsaSignature>

ECDSA подпись в стандартном формате

Имплементация

Protocol.signEcdsaMessage


signEddsaMessage

signEddsaMessage(secretId, syncSessionId, signSessionId, message): Promise<EddsaSignature>

Генерирует распределенную EDDSA подпись для данного сообщения

Для этого метода необходима уже пройденная процедура синхронизации и так же ничего не должно быть помещено в постоянное хранилище. Сообщения с объемом информации отличным от 32 байт будут дополнены/урезаны в соответствии с EDDSA алгоритмом.

Пример

// Считаем, что процедура синхронизации уже пройдена и соединение установлено

// Генерируем рандомный session ID для новой сессии подписания
const signSessionId = uuid(randomBytes);

// Сообщение к подписанию
const message = '7hJ9yN2OdIQo2kJu0arZgw2EKnMX5FGtQ6jlCWuLXCM='

//  Генерируем EDDSA подпись
const signature = await signEddsaMessage(protocol, secretId, syncSessionId, signSessionId,  message);

// Верифицируем подпись к составному ключу с внешней библиотекой (тут - elliptic.js)
expect(new ed('ed25519').verify(
  Buffer.from(message, 'base64').toString('hex'),
  Buffer.concat([
    Buffer.from(encodeEddsaPoint('ed25519', signature.R), 'base64'),
    Buffer.from(encodeEddsaBN('ed25519', signature.s), 'base64'),
  ]).toString('hex'),
  Buffer.from(encodeEddsaPoint('ed25519', publicKey), 'base64').toString('hex'),
)).toBeTruthy();

Параметры

Имя Тип Описание
secretId string ID (UUID) секрета для синхронизации
signSessionId string ID (UUID) данной процедуры подписания
syncSessionId string ID (UUID) соответствующей процедуры синхронизации
message string сообщение (32 байта base64-encoded) к подписанию

Возвращает

Promise<EddsaSignature>

EDDSA подпись в стандартном формате

Имплементация

Protocol.signEddsaMessage


syncDistributedEcdsaKey

syncDistributedEcdsaKey(secretId, syncSessionId, curve, derivationCoin, derivationAccount): Promise<string>

Выполняет процедуру синхронизации распределенного ключа (отдельный помощник)

Каждый секрет используется независимо для генерации фрагментов распределенного ключа (BIP-44 с путем m/44'/(coin)'/(account)'/0'/0'), и после с этими фрагментами выполняется синхронизация MPC ключа для получения составного публичного ключа для этой пары.

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

В результате этой операции новые данные синхронизации сохранены в постоянное хранилище, доступ к которым можно получить с помощью session ID.

С этого момента можно свободно вызывать getEcdsaPublicKey или signEcdsaMessage пока данные синхронизации (или секрет) доступны в хранилище.

Пример

// Считаем, что процедура синхронизации уже пройдена и соединение установлено

// Генерируем рандомный session ID для новой сессии подписания
const syncSessionId = uuid(randomBytes);

// Выполняем ECDSA-over-secp256k1 процедуру синхронизации для ключа с путем ```m/44'/0'/0'/0'/0'```
const publicKey = await syncDistributedEcdsaKey(protocol, secretId, syncSessionId, 'secp256k1', 0, 0);

// К этому моменту данные синхронизации уже сохранены в хранилище и составной ключ доступен к получению
const _publicKey = await getEcdsaPublicKey(protocol, secretId, syncSessionId);

// Этот ключ, очевидно, является тем же ключом, который мы получаем из самой процедуры синхронизации
expect(publicKey).toBe(_publicKey);

Параметры

Имя Тип Описание
syncSessionId string ID (UUID) данной процедуры синхронизации
secretId string ID (UUID) секрета используемого для синхронизации
curve "secp256k1" эллиптическая кривая (ECC) (на данный момент поддерживается только secp256k1)
derivationCoin number coin свойство формирования HD ключа (BIP-44)
derivationAccount number account свойство формирования HD ключа (BIP-44)

Возвращает

Promise<string>

составной публичный ключ (который так же можно получить позже с помощью getEcdsaPublicKey)

Имплементация

Protocol.syncDistributedEcdsaKey


syncDistributedEddsaKey

syncDistributedEddsaKey(secretId, syncSessionId, curve, derivationCoin, derivationAccount): Promise<string>

Выполняет процедуру синхронизации распределенного ключа (отдельный помощник)

Каждый секрет используется независимо для генерации фрагментов распределенного ключа (BIP-44 с путем m/44'/(coin)'/(account)'/0'/0'), и после с этими фрагментами выполняется синхронизация MPC ключа для получения составного публичного ключа для этой пары.

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

В результате этой операции новые данные синхронизации сохранены в постоянное хранилище, доступ к которым можно получить с помощью session ID.

С этого момента можно свободно вызывать getEddsaPublicKey или signEddsaMessage пока данные синхронизации (или секрет) доступны в хранилище.

Пример

// Считаем, что процедура синхронизации уже пройдена и соединение установлено

// Генерируем рандомный session ID для новой сессии подписания
const syncSessionId = uuid(randomBytes);

// Выполняем EDDSA-over-secp256k1 процедуру синхронизации для ключа с путем ```m/44'/0'/0'/0'/0'```
const publicKey = await syncDistributedEddsaKey(protocol, syncSessionId, secretId, 'ed25519', 0, 0);

// К этому моменту данные синхронизации уже сохранены в хранилище и составной ключ доступен к получению
const _publicKey = await getEddsaPublicKey(protocol, secretId, syncSessionId);

// Этот ключ, очевидно, является тем же ключом, который мы получаем из самой процедуры синхронизации
expect(publicKey).toBe(_publicKey);

Параметры

Имя Тип Описание
secretId string ID (UUID) секрета используемого для синхронизации
syncSessionId string ID (UUID) данной процедуры синхронизации
curve "ed25519" эллиптическая кривая (ECC) (на данный момент поддерживается только secp256k1)
derivationCoin number coinсвойство формирования HD ключа (BIP-44)
derivationAccount number accountсвойство формирования HD ключа (BIP-44)

Возвращает

Promise<string>

составной публичный ключ (который так же можно получить позже с помощью getEddsaPublicKey)

Имплементация

Protocol.syncDistributedEddsaKey