Skip to content

Kaytrust Core SDK

Introduction

Kaytrust Core SDK is a library built on java, it allows developers to interact with the Lacchain Ethereum Network in order to perform actions related to the creation and validation of DIDs and verifiable credentials.

Key concepts and considerations

  • Public/private keys used here are based on elliptic curve cryptography.
  • DID: Decentralized Identifier. A a new type of identifier for verifiable, decentralized digital identity. Find the W3C definition here
  • Verifiable credential: a tamper-evident credential that has authorship that can be cryptographically verified. Verifiable credentials can be used to build verifiable presentations, which can also be cryptographically verified. The claims in a credential can be about different subjects.
    • Reference: https://www.w3.org/TR/vc-imp-guide/
    • Examples: https://www.w3.org/TR/vc-imp-guide/#example-1-a-subject-disputes-a-credential
  • Address: Is the short descriptor, composed with 40 hexadecimal characters, which is derived from the ECC public key.
  • Capability: This an authorization capability which is set in the identity Manager smart contract. Capabilities associate granted permissions over a proxy address for a certain or indefinitely time. There are currently four defined capalibities (forward, devicemanager, admin and auth)
  • Key authorization validation: Means verifying that a certain key has a capability to perform some action related to a DID.
  • Identity Provider: For DID method "ev", this is the entity that helps users create their DIDs and more importantly helps to recover the use of a DID.
  • Issue a credential: The process by which an issuer emits a verifiable credential on behalf of a user, the proof of validity is a signed range of time in which a hash (that represents a verifiable credential) is made available on a smart contract (Verification Registry).

Requisites

  • Java 8

Repository URL

What can I do with this SDK?

  • Profile creation for a user: This functionality can be in two steps:

    • An Identity Provider creates a DID for the new profile, the SDK goes to the blockchain and generates a new DID for you. As a result the new profile is returned. Lets see it in a diagram:

    • The provider associates the user's key identifier with the DID obtained in the previous step.

    • Note: Adding another key follows the exact process, but the DID (that contains the smart contract proxy address) must be specified. In a later example this will be explained with an example.

  • Key Authorization Validation: Check what capabilities a key has.

  • Issue a Verifiable Credential: Lets see what is the flow when this sdk generates a verifiable credential

  • Check for a verifiable credential validity

Examples

  • You can also find all examples in src/test into the packages:

    • id.kaytrust.core.identity.ethereum
    • id.kaytrust.core.verifiableCredential.ethereum
  • Assumptions:

    • A new user wants to deploy a new contract (Proxy contract) that represents a profile's DID. The user will do this through the existing Identity Manager contract, which will create the Proxy and make the association between the user's key and the Proxy Contract.

Previous setting

  • Setting an Identity Manager instance
EthereumIdentityManager identityManager;
String rpcConnection = "http://eth-lacchain.kaytrust.id"; //The ethereum node to access the Lacchain Network
String IdentityManagerContractAddress = "0xa6b4540a2bfbe8663caa78027c83d0dcb1b7c837"; //This is the existing IdentityManager contract address
String providerPrivateKey = "0x9eb5a43839e8ff36fcdaed658136c51623be3af7de304d1c9181a6be9fac0863"; //Provider private key

{
    identityManager = new EthereumIdentityManagerImpl(); //Sets a new instance of IdentityManager to interact with.

    try {
        identityManager.instance(rpcConnection, providerPrivateKey, IdentityManagerContractAddress);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Creating a new profile with the provider key

try{
    System.out.println("*****************************************************************************");
    System.out.println("************************* Create Identity ********************************");
    String did = identityManager.createIdentity(); //Deploys a new  Proxy Contract and sets Identity Provider private key
    // with all capabilities (it allows recovery functionalities)
    // Now verifying the did is not null
    boolean isTrue = !did.isEmpty();
    System.out.println("Created DID: " + did);//At this point only the identity provider has authorization over the proxy
    if (isTrue){
        System.out.println("SUCCESS");
    }
    assertNotNull(did);
}catch(Exception e){
    e.printStackTrace();
    fail();
}

By creating a profile, a new DID (decentralized identifier) is returned. That DID has been associated with a provider address. At this point only the provider can add keys on behalf of a user.

  • Associating a user's key to the new DID.
try {
    System.out.println("*****************************************************************************");
    System.out.println("************************* Authorize Device *******************************");
    String devicePublicKey = "fadb30ab306603e1806e1fbd324cf21aaefb32c8a1f3f4cf701f3eafd17df68e97ec33dd77d7d6e7dc436905dc47f2f3da907e3a3be05cce348d10d51323dd5e";
    identityManager.authorizeDevice(did, devicePublicKey, CapabilityEnum.FORWARD.description()); //Setting forward
    // capability, between the Proxy and the device, in the IdentityManager contract.
    System.out.println("SUCCESS");
    assertNotNull(did);
} catch (Exception e) {
    System.out.println("FAILED");
    e.printStackTrace();
    fail();
}

Notes:

  • Note that the identity Manager instance has been initialized with a private key that has all permissions over the deployed proxy, that is why it is possible to associate a new key with the Proxy contract.
  • The association process can be repeated "n" times to add as many devices as required.

Identity Validation

Now that a new DID has been created, let's verify if the "deviceA" has the "forward" capability. Note the some variables which has been previously defined are being reused.

try {
    EthereumIdentityConsumer identityConsumer=new EthereumIdentityConsumerImpl();
    identityConsumer.instance(rpcConnection, null, identityManagerContractAddress);
    boolean isTrue = identityConsumer.isDeviceAuthorized(did, devicePublicKey,CapabilityEnum.FORWARD.description());//you can check other capabilities like FORWARD, AUTH or DEVICE_MANAGER
    if (isTrue){
        System.out.println("SUCCESS");
    }
    assertTrue(isTrue);
} catch (Exception e) {
    e.printStackTrace();
    fail();
}

Issuing a credential

  • Setting a Subject example class definition:
//Setting a Subject example class definition:
class CredentialSubject {
    @SerializedName("@id")
    String id;
    String name;
    String birthDate;
}

//Defining general variables before executing examples related to credential issuance
String issuerPrivateKey;
EthereumCredentialIssuer credentialIssuer;

{    
    String verificationRegistryContractAddress = "0x9f8c1e196F5696e014F4d1E4961B92db866BE271";
    credentialIssuer = new EthereumCredentialIssuerImpl();

    try {
        issuerPrivateKey = "0x9eb5a43839e8ff36fcdaed658136c51623be3af7de304d1c9181a6be9fac0863";
        credentialIssuer.instance(rpcConnection, issuerPrivateKey, verificationRegistryContractAddress);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • Issuance process:
public void issueCredential() {
    System.out.println("*****************************************************************************");
    System.out.println("************************* Credential Issuance *******************************");
    try {
        String subject = "{" +
                "\"@id\":" +
                "\"did:ev:cwMLLiMQGm9EaTqzY2k58refSoXdTsYvJ9Znp\"," +
                "\"name\":\"John Doe\"," +
                "\"birthDate\":\"2018-01-01\"}";

        CredentialSubject sc = new Gson().fromJson(subject, CredentialSubject.class);
        String[] credentialType = { "VerifiableCredential", "MyCustomType" };

        String vc = credentialIssuer.issueCredential(sc, credentialType, null, null,
                new EthereumAttestation2019Builder(), null);

        log.info("verificationCredential :\n {} ",vc);
        if (!vc.isEmpty()){
            log.info("SUCCESS");
        }
        assertNotNull(vc);

    } catch (Exception e) {
        e.printStackTrace();
        fail();
    }
}

Checking for a Verifiable credential validity

  • Previous setting
EthereumCredentialValidation credentialValidation;
{
    System.out.println("********************** Credential ValidationTest - Previous Setting ****************************");
    credentialValidation = new EthereumCredentialValidationImpl();
    try {
        credentialValidation.instance(rpcConnection, issuerPrivateKey, verificationRegistryContractAddress, new EthereumAttestation2019Builder());
        System.out.println("Verifiable credential is: " + vc + "\nIssued by " + (EthereumKeyUtils.getAddressFromPrivateKey(issuerPrivateKey)));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

It is time to check if a verifiable credential is valid or not, by checking if an issuer has registered a credential hash on the Verification Registry contract

public void credentialCheckingTest() {
    System.out.println("*****************************************************************************");
    System.out.println("********************** Credential ValidationTest ****************************");
    try {
        System.out.println("Verifying " + (EthereumKeyUtils.getAddressFromPrivateKey(issuerPrivateKey)) +" has emitted the verifiable credential and also the verifiable credential is not expired...");
        //Note that it is not necessary to have the private key but only the issuer address. 
        boolean isValidCredential = credentialValidation.verifyCredential(vc);//returns "true" if the verifiable credential is valid; otherwise "false";
        //in this case we are simply using the verifiable credential that was returned in the previous step.
        if (isValidCredential){
            log.info("SUCCESS");
        }
        assertTrue(isValidCredential);
    } catch (Exception e) {
        e.printStackTrace();
        fail();
    }
}