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

CLASS

SignerClient

public class SignerClient : SpatiumProtocol

Pre-configured Protocol intended for communication with Spatium Signer Service

  • For transport it uses HTTP(S) + SSE bidirectional transport.
  • For cache it uses an in-memory storage
  • For crypto driver it uses any provided Crypto

As it uses SSETransportDriver internally, one should also keep in mind that client starts listening as soon as connect(timeout:) is called and does not stop untill disconnect() is called.

  • SeeAlso: SpatiumSDKSwift/ProtocolSwift

Properties

auth

public final let auth: AuthorizationSession

Methods

init(url:auth:crypto:timeout:)

public init(url: String, auth: AuthorizationSession, crypto: Crypto, timeout: UInt?)

Note

requests are attributed to accountId of an authorization session, thus storing data independently for each authorized user

Example

 // Assuming an already initialised Crypto

 let auth = AuthorizationSession(
     url: "https://api-cloud-dev.spatium.io/authorization/v1",
     tokenId: UUID().uuidString,
     permissions: ["read", "secret"]
 )

 let clientProtocol = SignerClient(
     url: "https://api-cloud-dev.spatium.io/signer/v1",
     auth: auth,
     crypto: clientCrypto,
     timeout: 10 * 1000
 )

 // Connect to signer service (with 10 sec timeout)
 try await clientProtocol.connect(timeout: 10 * 1000)

 // Generate random secret ID for a new secret (should be done exactly once and kept)
 let secretId = UUID().uuidString

 // Generate both secerts (first on a connected server, and then locally) (should be done once per secret ID)
 try await clientProtocol.generateDistributedSecret(
     secretId: secretId
 )

 // Generate random session ID for a new synchronisation session
 let syncSessionId = UUID().uuidString

 // Perform a ECDSA-over-secp256k1 synchronisation procedure for a key with path m/44'/0'/0'/0'/0'`
 let publicKey = try await syncDistributedEcdsaKey(
     driver: clientProtocol,
     secretId: secretId,
     syncSessionId: syncSessionId,
     curve: .secp256k1,
     derivationCoin: 0,
     derivationAccount: 0
 )

 // At this point synchronisation data is saved to the storage so one may access it to get a compound public key
 let _publicKey = try await getEcdsaPublicKey(
     driver: clientProtocol,
     secretId: secretId,
     syncSessionId: syncSessionId
 )

 // Which is obviously the same key that was returned from the synchronisation procedure itself
 XCTAssertEqual(publicKey, _publicKey)

 // Generate random session ID for a new signing session
 let signSessionId = UUID().uuidString

 // Message to be signed
 let message = "7hJ9yN2OdIQo2kJu0arZgw2EKnMX5FGtQ6jlCWuLXCM="

 // Generate a ECDSA signature
 let signature = try await signEcdsaMessage(
     driver: clientProtocol,
     secretId: secretId,
     syncSessionId: syncSessionId,
     signSessionId: signSessionId,
     message: message
 )

 // Verify the resulting signature against a compound public key
 print([
     "curve": EcdsaCurve.secp256k1,
     "publicKey": publicKey,
     "message": message,
     "signature": [
         "r": signature.r,
         "s": signature.s,
         "recovery": signature.recovery
     ] as [String : Any]
 ] as [String : Any])

Parameters

Name Description
url signer service endpoint (HTTP(S))
auth authorization AuthorizationSession session to use
crypto any valid Crypto to hadle data and computations
timeout UInt? per-message request timeout, after which a procedure is dropped

connect(timeout:)

public func connect(timeout: UInt?) async throws

Connect and start listening to events

disconnect()

public func disconnect()

Stop listening for messages and disconnect

generateDistributedSecret(secretId:)

public func generateDistributedSecret(secretId: String) async throws

Simultaneous generation of a distributed secret with the same secret ID

This method is not strictly required as one may simply generate secrets with the same ID independently with the help of underlying Crypto Driver, however it's still userful at least for demonstration purposes.

As a result of this operation, new secrets are saved to a persistent storage, accessible by the provided secret ID From this point one may freely call syncDistributedEcdsaKey and syncDistributedEddsaKey as long as secret is accessible in the storage.

Example

// Assume an initialised and already connected SignerClient

// Generate random secret ID for a new secret
let secretId = UUID().uuidString

// Generate both secerts (first on a connected server, and then locally)
try await clientProtocol.generateDistributedSecret(
    secretId: secretId
)

// At this point the secret is already generated an ready to be used with MPC

Parameters

Name Description
secretId ID (UUID) of a secrets in question