Note

This page is a work in progress. It may contain incomplete or incorrect information.

Secure Synchronizer APIs

Sequencer Public API

Public API

The synchronizer configuration requires the same configuration of the Admin API as the participant. Next to the Admin API, we need to configure the Public API, which is the API where all participants connect.

TLS Encryption

As with the Admin API, network traffic can (and should) be encrypted using TLS. This is particularly crucial for the Public API.

An example configuration section which enables TLS encryption and server-side TLS authentication is given by:

canton.synchronizer.acme.public-api {
  port = 5028
  address = localhost // defaults to 127.0.0.1
  tls {
    cert-chain-file = "./tls/public-api.crt"
    private-key-file = "./tls/public-api.pem"
    // minimum-server-protocol-version = TLSv1.3, optional argument
    // ciphers = null // use null to default to JVM ciphers
  }
}

If TLS is used on the server side with a self-signed certificate, we need to pass the certificate chain during the connect call of the participant. Otherwise, the default root certificates of the Java runtime will be used. An example would be:

Server Authentication

Canton has two ways to perform server authentication to protect from man-in-the-middle attacks: TLS and the synchronizer id.

If TLS is used on the Public API as described above, TLS also takes care of server authentication. This is one of the core functions of TLS.

Server authentication can also be performed by the synchronizer operator passing their synchronizer identity to the participant node operator, and checking that the identity matches that reported by the synchronizer to the participant node. Like all nodes, the synchronizer has an identity that corresponds to the fingerprint of its namespace root key. It reports its identity to connecting participant nodes and signs all its messages with keys authorized by that namespace root key on the topology ledger. Assuming no key compromises, this gives participants a guarantee that the reported identity is authentic. The synchronizer id of the sole connected synchronizer can be read out using console commands like:

participant1.synchronizers.list_connected.last.synchronizerId.filterString

Client Authentication

Unlike the ledger or Admin API, the Public API uses Canton’s cryptography and topology state for client authentication rather than mutual TLS (mTLS). Clients need to connect to the Public API in several steps:

  1. The client calls the SequencerConnectService to align on Canton Protocol versions and obtain the synchronizer id.

  2. During the first connection, the client registers by sending its minimal topology state (identity, key delegations, public keys) to the sequencer.

  3. The client calls the SequencerAuthenticationService to authenticate using a challenge-response protocol and get an access token for the other sequencer services.

  4. The client connects to the main SequencerService using the access token from 3.

The information the client provides in step 2 is verifiable since it is a certificate chain of keys. The synchronizer rejects this if the namespace root key fingerprint included is not permissioned (see Bootstrap a permissioned Synchronizer) or if the topology state provided is invalid.

During step 3, the client claims an identity, which is the fingerprint of a namespace root key. If that identity is registered (as done in step 2), the sequencer responds with a challenge consisting of a nonce and all fingerprints of signing keys authorized for that member as per the topology ledger. If the challenge is met successfully by signing the nonce appropriately with a key matching one of the authorized keys, the SequencerAuthenticationService responds with a time-limited token which can be used to authenticate more cheaply on the other Public API services.

This authentication mechanism for the restricted services is built into the public sequencer API. You don’t need to do anything to set this up; it is enforced automatically and can’t be turned off.

The expiration of the token generated in step 2 is valid for one hour by default. The nodes automatically renew the token in the background before it expires. The lifetime of the tokens and of the nonce can be reconfigured using

canton.sequencers.sequencer1.public-api {
    max-token-expiration-interval = 60m
    nonce-expiration-interval = 1m
}

However, we suggest keeping the default values.

As mentioned above, an issued token allows the member that provides it during a call to authenticate on public sequencer API services. Therefore, these tokens are sensitive information that must not be disclosed. If an operator suspects that the authentication token for a member has been leaked or somehow compromised, they should use the logout console command to immediately revoke all valid tokens of that member and close the sequencer connections. The legitimate member automatically reconnects and obtains new tokens through the challenge-response protocol described above.

The command is slightly different depending on whether the member is a participant or a mediator, for example:

participant1.synchronizers.logout(mySynchronizerAlias)
mediator1.sequencer_connections.logout()