Confidential identities
confidential-identities
module is still not stabilised, so this API may change in future releases.
See API stability guarantees.Confidential identities are key pairs where the corresponding X.509 certificate (and path) are not made public, so that
parties who are not involved in the transaction cannot identify the owner. They are owned by a well-known identity,
which must sign the X.509 certificate. Before constructing a new transaction the involved parties must generate and
exchange new confidential identities, a process which is managed using SwapIdentitiesFlow
(discussed below). The
public keys of these confidential identities are then used when generating output states and commands for the
transaction.
Where using outputs from a previous transaction in a new transaction, counterparties may need to know who the involved
parties are. One example is the TwoPartyTradeFlow
, where an existing asset is exchanged for cash. If confidential
identities are being used, the buyer will want to ensure that the asset being transferred is owned by the seller, and
the seller will likewise want to ensure that the cash being transferred is owned by the buyer. Verifying this requires
both nodes to have a copy of the confidential identities for the asset and cash input states. IdentitySyncFlow
manages this process. It takes as inputs a transaction and a counterparty, and for every confidential identity involved
in that transaction for which the calling node holds the certificate path, it sends this certificate path to the
counterparty.
SwapIdentitiesFlow
SwapIdentitiesFlow
is typically run as a subflow of another flow. It takes as its sole constructor argument the
counterparty we want to exchange confidential identities with. It returns a mapping from the identities of the caller
and the counterparty to their new confidential identities. In the future, this flow will be extended to handle swapping
identities with multiple parties at once.
You can see an example of using SwapIdentitiesFlow
in TwoPartyDealFlow.kt
.
SwapIdentitiesFlow
goes through the following key steps:
- Generate a new confidential identity from our well-known identity
- Create a
CertificateOwnershipAssertion
object containing the new confidential identity (X500 name, public key) - Sign this object with the confidential identity’s private key
- Send the confidential identity and aforementioned signature to counterparties, while receiving theirs
- Verify the signatures to ensure that identities were generated by the involved set of parties
- Verify the confidential identities are owned by the expected well known identities
- Store the confidential identities and return them to the calling flow
This ensures not only that the confidential identity X.509 certificates are signed by the correct well-known identities, but also that the confidential identity private key is held by the counterparty, and that a party cannot claim ownership of another party’s confidential identities.
IdentitySyncFlow
When constructing a transaction whose input states reference confidential identities, it is common for counterparties
to require knowledge of which well-known identity each confidential identity maps to. IdentitySyncFlow
handles this
process. You can see an example of its use in TwoPartyTradeFlow.kt
.
IdentitySyncFlow
is divided into two parts:
IdentitySyncFlow.Send
IdentitySyncFlow.Receive
IdentitySyncFlow.Send
is invoked by the party initiating the identity synchronization:
The identity synchronization flow goes through the following key steps:
- Extract participant identities from all input and output states and remove any well known identities. Required signers on commands are currently ignored as they are presumed to be included in the participants on states, or to be well-known identities of services (such as an oracle service)
- For each counterparty node, send a list of the public keys of the confidential identities, and receive back a list of those the counterparty needs the certificate path for
- Verify the requested list of identities contains only confidential identities in the offered list, and abort otherwise
- Send the requested confidential identities as
PartyAndCertificate
instances to the counterparty
IdentitySyncFlow
works on a push basis. The initiating node can only send confidential identities it has
the X.509 certificates for, and the remote nodes can only request confidential identities being offered (are
referenced in the transaction passed to the initiating flow). There is no standard flow for nodes to collect
confidential identities before assembling a transaction, and this is left for individual flows to manage if
required.IdentitySyncFlow.Receive
is invoked by all the other (non-initiating) parties involved in the identity
synchronization process.IdentitySyncFlow
will serve all confidential identities in the provided transaction, irrespective of well-known
identity. This is important for more complex transaction cases with 3 or more parties, for example:
- Alice is building the transaction, and provides some input state x owned by a confidential identity of Alice
- Bob provides some input state y owned by a confidential identity of Bob
- Charlie provides some input state z owned by a confidential identity of Charlie
Alice may know all of the confidential identities ahead of time, but Bob not know about Charlie’s and vice-versa.
The assembled transaction therefore has three input states x, y and z, for which only Alice possesses
certificates for all confidential identities. IdentitySyncFlow
must send not just Alice’s confidential identity but
also any other identities in the transaction to the Bob and Charlie.
Was this page helpful?
Thanks for your feedback!
Chat with us
Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.
Propose documentation improvements directly
Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.
We're sorry this page wasn't helpful. Let us know how we can make it better!
Chat with us
Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.
Create an issue
Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.
Propose documentation improvements directly
Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.