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

ПРОТОКОЛ

ProtocolSwift

public protocol ProtocolSwift: AnyObject

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

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

Пример

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

 // Генерируем случайный session ID для новой сессии синхронизации
 let syncSessionId = UUID().uuidString

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

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

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

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

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

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

 // Верифицируем подпись к составному ключу
 print([
     "curve": EcdsaCurve.secp256k1,
     "publicKey": publicKey,
     "message": message,
     "signature": [
         "r": signature.r,
         "s": signature.s,
         "recovery": signature.recovery
     ] as [String : Any]
 ] as [String : Any])

Методы

syncDistributedEcdsaKey(secretId:syncSessionId:curve:derivationCoin:derivationAccount:)

func syncDistributedEcdsaKey(secretId: String, syncSessionId: String, curve: EcdsaCurve, derivationCoin: UInt32, derivationAccount: UInt32) async throws -> String

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

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

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

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

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

Пример

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

 // Генерируем рандомный session ID для новой сессии подписания
 let syncSessionId = UUID().uuidString

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

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

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

Параметры

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

Возвращает

String

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

getEcdsaPublicKey(secretId:syncSessionId:)

func getEcdsaPublicKey(secretId: String, syncSessionId: String) async throws -> String

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

Пример

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

 let publicKey = await getEcdsaPublicKey(secretId: secretId, syncSessionId: syncSessionId)

Параметры

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

Возвращает

String

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

removeDistributedEcdsaKey(secretId:syncSessionId:)

func removeDistributedEcdsaKey(secretId: String, syncSessionId: String) async throws

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

Пример

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

 await removeDistributedEcdsaKey(secretId: secretId, syncSessionId: syncSessionId)

Параметры

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

Возвращает

void

signEcdsaMessage(secretId:syncSessionId:signSessionId:message:signatureToken:)

func signEcdsaMessage(secretId: String, syncSessionId: String, signSessionId: String, message: String, signatureToken: String) async throws -> EcdsaSignature

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

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

Пример

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

 // Генерируем рандомный session ID для новой сессии подписания
 let signSessionId = UUID().uuidString

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

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

 // Верифицируем подпись к составному ключу
 print([
     "curve": EcdsaCurve.secp256k1,
     "publicKey": publicKey,
     "message": message,
     "signature": [
         "r": signature.r,
         "s": signature.s,
         "recovery": signature.recovery
     ] as [String : Any]
 ] as [String : Any])

Параметры

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

Возвращает

EcdsaSignature

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

syncDistributedEddsaKey(secretId:syncSessionId:curve:derivationCoin:derivationAccount:)

func syncDistributedEddsaKey(secretId: String, syncSessionId: String, curve: EddsaCurve, derivationCoin: UInt32, derivationAccount: UInt32) async throws -> String

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

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

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

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

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

Пример

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

 // Генерируем рандомный session ID для новой сессии подписания
 let syncSessionId = UUID().uuidString

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

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

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

Параметры

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

Возвращает

String

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

getEddsaPublicKey(secretId:syncSessionId:)

func getEddsaPublicKey(secretId: String, syncSessionId: String) async throws -> String

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

Пример

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

 let publicKey = await getEddsaPublicKey(secretId: secretId, syncSessionId: syncSessionId)

Параметры

Имя Описание
secretId ID (UUID) of a secret used for synchronisation
syncSessionId ID (UUID) of a synchronisation procedure

Возвращает

String

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

removeDistributedEddsaKey(secretId:syncSessionId:)

func removeDistributedEddsaKey(secretId: String, syncSessionId: String) async throws

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

Пример

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

 await removeDistributedEddsaKey(secretId: secretId, syncSessionId: syncSessionId)

Параметры

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

Возвращает

void

signEddsaMessage(secretId:syncSessionId:signSessionId:message:signatureToken)

func signEddsaMessage(secretId: String, syncSessionId: String, signSessionId: String, message: String, signatureToken: String) async throws -> EddsaSignature

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

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

Пример

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

 // Генерируем рандомный session ID для новой сессии подписания
 let signSessionId = UUID().uuidString

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

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

 // Верифицируем подпись к составному ключу
 print([
     "curve": EddsaCurve.ed25519,
     "publicKey": publicKey,
     "message": message,
     "signature": [
         "R": signature.R,
         "s": signature.s
     ] as [String : Any]
 ] as [String : Any])

Параметры

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

Возвращает

EddsaSignature

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

on(validateMessage:)

func on(validateMessage: @escaping (_ message: String, _ signatureToken: String) async -> Bool)

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

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

Параметры

Имя Описание
validateMessage Внешний валидатор транзакции

Возвращает

void

off()

func off()

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

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

Возвращает

void