Confidential Identities SDK

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 initiating party must request that the counter-party generate and exchange a new confidential identity, a process which is managed using RequestKeyFlow (discussed below). The public key of this confidential identity is 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. 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. SyncKeyMappingFlow manages this process. It takes as inputs a transaction and a counter-party session, 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 counter-party. Alternatively, instead of taking a transaction as an input, a list of confidential identities to sync can be given as input.

For convenience, these two flows have initiating flows available in com.r3.corda.lib.ci.workflows.InitiatingFlows which can be called as subflows instead of initiating sessions in a custom flow.

About this version

This version of Confidential Identities is for use only with the Corda 5 Developer preview. It cannot be used with any other version of Corda.

Install the Confidential Identities SDK

To install Confidential Identities, build the Confidential Identities SDK against the master branch with the following commands:

git clone https://github.com/corda/corda5-confidential-identities.git
git fetch
git checkout origin release/2.0

Then run ./gradlew clean install from the root directory.

What’s inside Confidential Identities

The Confidential Identities SDK is a single .cpk:

  • ci-workflows, which contains the flows for creating and syncing confidential identities.

RequestKeyFlow

As mentioned above, RequestKeyFlow can be run by calling initiating flows found in InitiatingFlows.kt. These flows are RequestKey, RequestKeyForUUIDInitiator, and VerifyAndAddKey.

RequestKey is used for requesting a new key from a counter-party. It has a single constructor which accepts a counter-party as a parameter.

RequestKeyForUUIDInitiator is used for requesting a new key from a counter-party and have that counter-party assign it to a specified account. It takes as its sole constructor the party from which to request a new key and a UUID representing an account id for the account hosted on the counter-party node.

VerifyAndAddKey has a single constructor which takes the counter-party to request a new key from and a public key to request an ownership claim for from that same counter-party. It is for requesting an ownership claim that the specified public key was generated by the node corresponding to the supplied party.

RequestKeyFlow takes as its constructor arguments the counter-party session we want to exchange confidential identities with initiated by one of the three flows mentioned above. It returns an anonymous party representing the counter-party. The three initiating flows mentioned above also return this same anonymous party.

RequestKeyFlow goes through the following key steps:

  • Request a new key from the specified counter-party.
  • The counter-party generates a new key-pair representing their own confidential identity.
  • The counter-party signs this key and returns it to the initiating flow.
  • The initiating flow verifies the signatures to ensure that identities were generated by the involved party.
  • The key-party mapping is stored to be used as a confidential identity.
  • An anonymous party is return by the flow representing the counter-party and the newly generated key.

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 counter-party, and that a party cannot claim ownership of another party’s confidential identities.

SyncKeyMappingFlow

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. SyncKeyMappingFlow handles this process. You can see an example of its use in TwoPartyTradeFlow.kt.

SyncKeyMappingFlow is divided into two parts:

  • SyncKeyMappingFlow
  • SyncKeyMappingFlowHandler

SyncKeyMappingFlow is invoked by the party initiating the identity synchronization. It could be called by a custom initiating flow, or it could be called via the initiating flow SyncKeyMappingInitiator found in InitiatingFlows.kt.

SyncKeyMappingInitiator must always be provided with the counter-party to synchronize well-known identities for confidential identities with. A wire transaction and/or a list of parties should also be passed to this flow. If a wire transaction is present, the flow will attempt to synchronize the confidential identities present in the transaction with the counter-party. If no wire transaction is provided but a list of parties is, then the flow will attempt to synchronize the confidential identities present in the list with the counter-party. If both are provided the wire transaction takes precedence.

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 if using a transaction. 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). If a list of parties is provided instead of a transaction, then this list is used.
  • For each counter-party node, send a list of the public keys of the confidential identities, and receive back a list of those the counter-party 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 a map of confidential identity public keys to well-known parties to the counter-party

Meanwhile, SyncKeyMappingFlowHandler is invoked by all the other (non-initiating) parties involved in the identity synchronization process:

SyncKeyMappingFlow will serve all confidential identities in the provided transaction, irrespective of well-known identity. This is important for more complex transaction cases with 3+ 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 does 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. SyncKeyMappingFlow must send not just Alice’s confidential identity but also any other identities in the transaction to the Bob and Charlie.

Install the Confidential Identities SDK

Build Confidential Identities SDK against Corda release branch

You can build the Confidential Identities SDK against the master branch with the following commands:

git clone https://github.com/corda/corda5-confidential-identities.git
git fetch
git checkout origin release/2.0

Then run ./gradlew clean install from the root directory.

What’s inside Confidential Identities

The Confidential Identities SDK is a single .cpk:

  • ci-workflows, which contains the flows for creating and syncing confidential identities.

Add Tokens SDK dependencies to an existing CorDapp

  1. Add a variable for the confidential identities release group and the version you wish to use. Set the Corda version to the one you have installed locally:
    buildscript {
        ext {
            confidential_id_release_version = '2.0.0-DevPreview-RC05'
            confidential_id_release_group = 'com.r3.corda.lib.ci'
        }
    }
  1. Add the confidential identities' development artifactory repository to the list of repositories for your project:
    repositories {
        maven { url 'https://software.r3.com/artifactory/corda-os-maven-stable' }
    }
  1. Add the confidential identities SDK dependency to the dependencies block in your CorDapp module (where applicable).

    cordapp “$confidential_id_release_group:ci-workflows:$confidential_id_release_version”

  2. Deploy your corDapp CPKs along with the following CPKs:

  • ci-workflows

You have installed the Confidential Identities SDK.

Identity Service API changes from Corda 4

Changes to the way confidential identities are handled have prompted updates to some elements of the Identity Service API. The core concepts have not changed—it is still a directory of parties, with their names and public keys.

In the identity service API:

  • Confidential identities are associated with an X.500 name, rather than a party. If a method previously associated a confidential identity with a party, it now associates the confidential identity with an X.500 name.
  • The partiesFromName method has been removed. You can achieve similar RPC functionality with the member lookup service .
  • The prefix “wellKnown” has been removed. All parties are considered well-known unless they use a confidential identity. In this case, they are referred to as “anonymous”.
  • The identity utilities service methods IdentityUtils.kt has moved to application-internal/src/main/kotlin/net/corda/internal/application/identity/IdentityInternalUtils.kt
  • These methods have been removed:
    • verifyAndRegisterIdentity
    • assertOwnership
    • getAllIdentities
    • certificateFromKey
    • requireWellKnownPartyFromAnonymous
    • partiesFromName

In the persistent identity service:

  • The persistent identity service database structure only includes two tables:
  • Key hash to name.
  • Key hash to key.
  • The partyFromAnonymous method has been simplified to support key rotation, as there is now only one method for keeping confidential identities.
  • The notary lookup method has been removed. Register notaries with member-info files.

Additionally, the unknownAnonymousPartyException and InMemoryIdentityService have been removed.

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.