# 6. Credentials

A credential is a set of signed information provided by an Issuer, representing digital credentials which can be used to prove yourself.
Credential issuance implemented using Camenisch Lysyanskaya signature schema.
During the credential issuance process, the Issuer signs a digital credential that the Holder processes and saves into Mobile SDK wallet thereby only the Holder can use it.
Mobile SDK can receive an unlimited number of credential in this way.

There are two roles in the connection establishing process: **Issuer** and **Holder**.
* The Issuer is the party that can sign some sort of reliable digital credentials. [Verity SDK](https://github.com/evernym/verity-sdk) can be used as an **Issuer**.
* The Holder is the party that accepts and stores digital credentials which can use later to prove yourself. **Mobile SDK** represents the **Holder** party. Bellow in this document we will explain which steps need to be taken in order to accept a Credential on the **Holder** side using Mobile SDK.

> **NOTE:** library should be initialized before using credentials API. See [initialization documentation](3.Initialization.md)

> **NOTE:** there must be established connection between Issuer and Holder. See [connections document](5.Connections.md)

To complete this section read through the following sections:

1. [Responding to Credential Offers](#responding-to-credential-offers)
1. [Deleting Credentials](#deleting-credentials)
1. [Cache data for Proof generation](#cache-data-for-proof-generation---optional)
1. [Credential with attachments](#credential-with-attachments)

## Responding to Credential Offers

Aries Credential Issuance protocol consists of several messages exchange:
* Issuer sends `Credential Offer` message to Holder
* Holder handles `Credential Offer` message and sends `Credential Request` message to Issuer
* Issuer handles `Credential Request` message and sends `Credential` message to Holder
* Holder handles `Credential Request` message and sends `Credential Ack` message (if requested) to Issuer

### Steps overview

In order to handle a `Credential Offer` a Holder (client) need to take the following steps:

1. Download and Parse Credential Offer message received from the Pairwise Cloud Agent.
2. Create Credential state object using parsed Credential Offer message.\
    1.1. Serialize Credential state object and save serialized representation.\
    1.2. Update Credential Offer message status on the Agent as reviewed.
3. Accept Credential Offer\
    3.1. Deserialize associated Connection state object\
    3.2. Deserialize Credential state object\
    3.3. Send Credential Request message\
    3.4. Await Credential status is completed\
    3.5. Serialize Credential state object and save serialized representation
4. Reject Credential Offer\
    4.1. Deserialize associated Connection state object\
    4.2. Deserialize Credential state object\
    4.3. Send Credential Reject message\
    4.4. Serialize Credential state object and save serialized representation

### 0. Credential Application object

As we mentioned before in the [Storage](./2.Storage.md) document SDK does not save state objects, so the application must care about it.
It is up to the developer regarding what data to store in the application.  
On of the possible formats may match the following structure:
```
{
    "pwDid" - string, // reference to the connection from which credential offer was received 
    "serialized" - string, // serialized representation of SDK Credential state object
    "threadId" - string, // Identifier of credential issuance protocol. 
                         // This is needed to match the following messages related to the protocol instance.

    // metadata to show on the UI
    "name": string, // credential name
    "attributes": { // credential attributes
        <name>: <value>, // attribute: value
        ...
    },
    
    // optionally
    "connectionName": string // name of the connection from which Crdential Offer was received 
    "connectionLogo": string // logo of the connection from which Crdential Offer was received 
    
    "timestamp": int // optional, time of receiving a credential (it can be shown on the UI and used for sorting) 
                     // it must be set when actual credential is received.
    "status" - string, // credential status (pending / issued)
}
```
Later in this document, we will show how to get each of these fields.

### 1. Get Credential Offer from pending messages

1. Download pending messages (see [messages documentation](4.MessagesFlow.md) for messages downloading information). Pending messages with `credential-offer` type should be used.  Extract credential offer JSON string from the downloaded message (value of `decryptedPayload` field).
    
    #### Example of Credential Offer
    
    ```json
    {
       "@id":"6269f643-beb2-4e98-92f1-b9683fa1cb36",
       "@type":"did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/offer-credential",
       "comment":"DEMO-Transcript",
       "credential_preview":{
          "@type":"did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/credential-preview",
          "attributes":[
             {
                "name":"DEMO-College Name",
                "value":"Faber College"
             },
             {
                "name":"DEMO-Degree",
                "value":"Computer Science"
             },
             {
                "name":"DEMO-GPA",
                "value":"4.0"
             },
             {
                "name":"DEMO-Major",
                "value":"SSI Software Engineering"
             },
             {
                "name":"DEMO-Student Name",
                "value":"Alice Andersen"
             }
          ]
       },
       "offers~attach":[
          {
             "@id":"libindy-cred-offer-0",
             "data":{
                "base64":" "
             },
             "mime-type":"application/json"
          }
       ],
       "~thread": { // (Optional) maybe omitted
          "thid": string, 
       }  
    }
    ```

The following data can be taken from the **Credential Offer** to fill the application Credential object we defined before:
* `comment` - name of the credential.
* `credential_preview.attributes` - array containing objects with offered attributes and their values.
* `~thread.thid` or else `@id` - Identifier of issue credential protocol. This value is needed to determine the next protocol message after offer acceptance.

  > In order to fill `pwDid` field you need to take `pairwiseDID` value from the downloaded message.

### 2. Create Credential state object using received Credential Offer

1. Create Credential state object

    ### iOS

    ```objc
    [appDelegate.sdkApi credentialCreateWithOffer: sourceId
            offer: message
            completion:^(NSError *error, NSInteger credentialHandle) {
                // ...
            }];
    ```

    ### Android
    ```java
    int credentialHandle = CredentialApi.credentialCreateWithOffer(sourceId, message).get();
    ```
    
    `sourceId` - any string\
    `message` - message downloaded on step 1.


2. Serialize Credential state object

    #### iOS
    ```objc
    [appDelegate.sdkApi credentialSerialize: credentialHandle
            completion:^(NSError *error, NSString *state) {
                // ...
            }];
    ```
    
    #### Android
    ```java
    String serializedCredential = CredentialApi.credentialSerialize(credentialHandle).get();
    ```

2. Save `serialized` sdk credential state object into your application connection object.

3. The `status` of the credential is considered as `pending` at this step.

4. Every time in the future you want to perform some operations using the created credential object you first need to fetch Credential object from the storage and next deserialize SDK object from its serialized representation (receive a new handle).

5. Update status of correspondent message on the Agent. See [messages documentation](4.MessagesFlow.md) for message update information.

### 3. Accept Credential Offer

If a user agreed to receive a credential related to the received offer, the following steps should be done in order to receive the actual credential.

#### 1. Deserialize Connection state object associated with received Credential Offer

#### iOS
```objC
[appDelegate.sdkApi connectionDeserialize:serializedConnection
        completion:^(NSError *error, NSInteger connectionHandle) {
            // ...
        }];
```

#### Android
```java
int connectionHandle = ConnectionApi.connectionDeserialize(serializedConnection).get();
```

#### 2. Deserialize Credential state object associated with accepted Credential Offer

#### iOS
```objC
[appDelegate.sdkApi credentialDeserialize:serializedCredential
        completion:^(NSError *error, NSInteger credentialHandle) {
            // ...
        }];
```

#### Android
```java
int credOfferHandle = CredentialApi.credentialDeserialize(serializedCredOffer).get();
```

#### 3. Send `Credential Request` message to the Issuer.

* `Credential Request` message contains a blinding factor which Issuer must use during Credential signing. If someone later intercepts Credential message intended to the Holder he will not be able to use it without knowledge of the key which was used by the Holder to generate the blinding factor.

* The private key used for credentials blinding is generated once on the first Mobile SDK initialization and stored in Mobile SDK wallet in encrypted form. The private key cannot be read from the wallet.

      #### iOS
    ```objc
    [appDelegate.sdkApi credentialSendRequest:credentialHandle
            connectionHandle:connectionHandle
            paymentHandle:0
            completion:^(NSError *error) {
                // ...
            }];
    ```
    
    #### Android
    ```java
    CredentialApi.credentialSendRequest(credOfferHandle, connectionHandle, 0).get()
    ```

#### 4. Serialize Credential state object and store in the application storage. 

Theoretical, processing of the `Credential Request` message on the Issuer side may take a while and User can just close the application before completion.\
It's better to store the credential state machine (received after sending `Credential Request`) into the applicaiton storage to avoid data loss.
> If you wish, you can skip storing for now and do it only after the credential will be completed (after step 5).

  1. Serialize Credential state object
      
       #### iOS
        ```objc
        [appDelegate.sdkApi credentialSerialize: credentialHandle
                completion:^(NSError *error, NSString *state) {
                    // ...
                }];
        ```
    
       #### Android
        ```java
        String serializedCredential = CredentialApi.credentialSerialize(credentialHandle).get();
        ```

  2. Update `serialized` value from the corresponding record stored in the application storage.

#### 5. Await Credential received.

   When `Credential` message will be received from the Issuer the state of the Credential object will be equal `4` (`Accepted`).  Mobile SDK unbind actual Credential and stores it into Mobile SDK wallet in encrypted form. The credential signature cannot be read from the wallet.

   There are two options regarding how to await `Credential` message depending on the messages receiving strategy you use:

   1. Polling - call `credentialUpdateState` function in loop until returned state is not equal `4` (`Accepted`).
    
        * Call following code in a loop until the returned state is not equal `4` (`Accepted`).

            #### iOS
        
            ```objc
            while(1) {
                [appDelegate.sdkApi credentialUpdateState:(NSInteger) credentialHandle
                                                  message:(NSString *) message         
                                               completion:^(NSError *error, NSInteger state)) {
                            if (state == 4){
                                break;
                            }
                        }];
            }
            ```
        
            #### Android
        
            ```java
            int state = -1
            while (state != 4){
                state = CredentialApi.credentialUpdateState(handle).get();
            }
            ```

        * These functions do the following things internally:
            * Downloads all pending messages from the Cloud Agent related to the connection
            * Find matching `Credential` message
            * If message found -> updates state machine with it and update message status on the Cloud Agent as read.

   2. Push notifications - as push notification doesn't contain the type of received message we can download all messages and analyze them:
        * Use common `downloadPendingMessages` function to download messages.
         * Find matching `Credential` message. The following conditions must met:
            * value of `["decryptedPayload"]["@type"]` field must ends with `issue-credential`
            * value of `["decryptedPayload"]["~thread"]["thid"]` field must match to the value of `@id` field from Credential Offer.

        * Update Credential state object with received `Credential` message:
    
           #### iOS
        
            ```objc
                [appDelegate.sdkApi credentialUpdateStateWithMessage:connectionHandle
                                                             message:message
                                                      withCompletion:^(NSError *error, NSInteger state) {
                    // ....
                }
            ```
        
           #### Android
        
            ```java
            int state = CredentialApi.credentialUpdateStateWithMessage(connectionHandle, message).get();
            ```
    
        * Update status of the message as read. See [messages documentation](./4.MessagesFlow.md) for message update information.
          #### iOS
          ```objC
          [appDelegate.sdkApi updateMessages:messageStatus
                  pwdidsJson:handledMessage
                  completion:^(NSError *error) {
                      // ...
                  }];
          ```

          #### Android
            ```java
            UtilsApi.vcxUpdateMessages(messageStatus, handledMessage).get()  
            ```

#### 6. Serialize Credential object and store in the application storage.

1. Once we get the credential completed (it means that internal representation of SDK credential state object changed) we need to update the corresponding record in the application storage to contain the latest serialized credential state.

    #### iOS
    ```objC
    [appDelegate.sdkApi credentialSerialize:credentialHandle
            completion:^(NSError *error, NSString *state)) {
                // ...
            }];
    ```
    
    #### Android
    ```java
    String serializedCredential = CredentialApi.credentialSerialize(credentialHandle).get();
    ```

1. The `status` of the credential is considered as `issued` at this step.

1. You also can save the `timestamp` of credential receiving.

1. Update a related record in the storage with the latest value.

### 4. Reject Credential Offer

If a user does not want to receive a credential related to the received offer, the following steps should be done in order to explicitly reject offer (notify Issuer).

#### 1. Deserialize Connection state object associated with rejected Credential Offer

    #### iOS
    ```objC
    [appDelegate.sdkApi connectionDeserialize:serializedConnection
            completion:^(NSError *error, NSInteger connectionHandle) {
                // ...
            }];
    ```
    
    #### Android
    ```java
    int connectionHandle = ConnectionApi.connectionDeserialize(serializedConnection).get();
    ```

#### 2. Deserialize Credential state object associated with rejected Credential Offer

    #### iOS
    ```objC
    [appDelegate.sdkApi credentialDeserialize:serializedCredential
            completion:^(NSError *error, NSInteger credentialHandle) {
                // ...
            }];
    ```
    
    #### Android
    ```java
    int credentialHandle = CredentialApi.credentialDeserialize(serializedCredOffer).get();
    ```

#### 3. Send `Credential Reject` message to the issuer

    #### iOS
    ```objc
    [appDelegate.sdkApi credentialReject:credentialHandle
            connectionHandle:connectionHandle
            comment:@"Rejection comment"
            completion:^(NSError *error) {
                // ...
            }];
    ```
    
    #### Android
    ```java
    CredentialApi.credentialReject(credOfferHandle, connectionHandle, "Rejection comment").get()
    ```

#### 4. Serialize Credential state object

   #### iOS
    ```objC
    [appDelegate.sdkApi credentialSerialize:credentialHandle
            completion:^(NSError *error, NSString *state)) {
                // ...
            }];
    ```

   #### Android
    ```java
    String serializedCredential = CredentialApi.credentialSerialize(credentialHandle).get();
    ```

#### 5. Update a related record in the storage with the latest value of the serialized Credential state object.

## Deleting Credentials

It may happen that after some time a User wants to delete credential that are no longer need to him.
In order to delete a credential you need to perform the next steps:

### 1. Delete a Credential stored in the Mobile SDK wallet

* 1.1. Deserialize existing Credential state object

       #### iOS
        ```objC
        [appDelegate.sdkApi credentialDeserialize:serializedCredential
                completion:^(NSError *error, NSInteger credentialHandle) {
                    // ...
                }];
        ```
    
       #### Android
        ```java
        int credentialHandle = CredentialApi.credentialDeserialize(serializedCredOffer).get();
        ```

* 1.2. Delete Credential from the Mobile SDK wallet

       #### iOS
        ```objC
        [appDelegate.sdkApi deleteCredential:credentialHandle
                withCompletion:^(NSError *error) {
                    // ...
                }];
        ```
    
       #### Android
        ```java
         CredentialApi.deleteCredential(credentialHandle).get();
        ```

### 2. Delete credential data from the application storage.

## Cache data for Proof generation - Optional

The first time SDK generates Proof using a specific credential it fetches the credential's public Credential Definition and Schema from the Ledger.
These operations take some time that increases the overall time taken to present proof to the remote side.
In order to decrease that time your application can fetch and cache these public entities right after receiving a credential.
Furthermore, it makes the Proof presentation independent of the Ledger connectivity as well.

### Steps

Assume you received Credential.

1. Assume that you just received and stored Credential, and the state of the Credential object is 4.

2. Fetch public Credential Definition and Schema associated with stored in the wallet credentials from the Ledger.

> **NOTE:** This function checks that data fetched and cached for all stored in the Wallet credentials

> **NOTE:** The recommended way is to call it in a separate thread as it may take several seconds.

#### iOS
    ```objC
    [appDelegate.sdkApi fetchPublicEntities:^(NSError *error, NSString *state)) {
                // ...
            }];
    ```

#### Android
    ```java
    UtilsApi.vcxFetchPublicEntities().get();
    ```

## Credential with attachments

Credentials with attachments can be issued and attachments can be shown in client application.

For example, attachments can be represented as base64 encoded strings, please refer to [Credentials with attachments example](CredentialsWithAttachments.md).

> **NOTE**: base64 encoded strings is just a representation of attachment, any other ways are valid and up to your system architecture.


## Next Step

Now your application is able to receive and store verifiable credentials.
You are ready to read how to [fill proof requests](7.Proofs.md) using credentials in your wallet.
