Credential Functions

#include <keychain/keychain_headers.h>

Overview

Credential functions work with W3C Verifiable Credentials, which are signed data structures that make claims about a subject. Credentials inherit from verifiable data and add specific fields for issuer, subject, claims, and validity periods.

Object Lifecycle Functions

kc_credential_construct_from_serialized_data()

int kc_credential_construct_from_serialized_data(
    kc_credential_t** out_credential_ptr,
    const kc_serialized_data_t* serialized_data_ptr
)

Deserializes a credential from serialized data. A credential is signed (verifiable) data structured on the W3C verifiable credential data model.

Parameters:

  • out_credential_ptr - Pointer to credential pointer (output, caller must free)

  • serialized_data_ptr - Serialized data containing the credential

Returns: Error code (0 = success)

Example:

kc_serialized_data_t* serialized = NULL;
kc_credential_t* credential = NULL;

// Assume serialized contains credential data...
int result = kc_credential_construct_from_serialized_data(&credential, serialized);
if (result == 0) {
    // Use credential...
    kc_credential_destruct(&credential);
}

kc_credential_construct_from_serialized_string()

int kc_credential_construct_from_serialized_string(
    kc_credential_t** out_credential_ptr,
    const char* serialized_string,
    const unsigned int serialized_string_size,
    const tkc_serialization_format serialization_format
)

Deserializes a credential from a string.

Parameters:

  • out_credential_ptr - Pointer to credential pointer (output, caller must free)

  • serialized_string - String containing serialized credential

  • serialized_string_size - Length of the string

  • serialization_format - Format of the serialization (JSON, XML, or PROTOBUF)

Returns: Error code (0 = success)

Example:

const char* json_credential = "{\"@context\":[\"https://www.w3.org/2018/credentials/v1\"],"
                             "\"id\":\"credential-123\","
                             "\"type\":[\"VerifiableCredential\",\"IdentityCredential\"],"
                             "\"issuer\":\"did:keychain:alice\","
                             "\"subject\":{\"id\":\"did:keychain:bob\"}}";

kc_credential_t* credential = NULL;
int result = kc_credential_construct_from_serialized_string(&credential,
    json_credential, strlen(json_credential), TKC_SERIALIZATION_FORMAT_JSON);
if (result == 0) {
    printf("Credential loaded from JSON\n");
    kc_credential_destruct(&credential);
}

kc_credential_destruct()

int kc_credential_destruct(kc_credential_t** credential_ptr)

Destructs a credential object and frees its resources.

Parameters:

  • credential_ptr - Pointer to credential pointer (set to NULL on success)

Returns: Error code (0 = success)

Serialization Functions

kc_credential_serialize()

int kc_credential_serialize(
    const kc_credential_t* credential_ptr,
    kc_serialized_data_t** out_serialized_data_ptr
)

Serializes a credential to a serialized data object.

Parameters:

  • credential_ptr - Credential to serialize

  • out_serialized_data_ptr - Pointer to serialized data pointer (output, caller must free)

Returns: Error code (0 = success)

kc_credential_serialize_to_string()

int kc_credential_serialize_to_string(
    const kc_credential_t* credential_ptr,
    char** out_content,
    unsigned int* out_size,
    const tkc_serialization_format serialization_format
)

Serializes a credential to a string in the specified format.

Parameters:

  • credential_ptr - Credential to serialize

  • out_content - Pointer to string pointer (output, caller must free)

  • out_size - Pointer to string size (output)

  • serialization_format - Format for serialization (JSON, XML, or PROTOBUF)

Returns: Error code (0 = success)

Credential Property Functions

kc_credential_id()

int kc_credential_id(
    const kc_credential_t* credential_ptr,
    char** out_content,
    unsigned int* out_size
)

Gets the credential ID (W3C defined).

Parameters:

  • credential_ptr - Credential to query

  • out_content - Pointer to ID string pointer (output, caller must free)

  • out_size - Pointer to string size (output)

Returns: Error code (0 = success)

Example:

char* cred_id = NULL;
unsigned int id_size = 0;
int result = kc_credential_id(credential, &cred_id, &id_size);
if (result == 0) {
    printf("Credential ID: %.*s\n", id_size, cred_id);
    kc_common_delete_buffer(&cred_id);
}

kc_credential_issuer()

int kc_credential_issuer(
    const kc_credential_t* credential_ptr,
    char** out_content,
    unsigned int* out_size
)

Gets the identifier of the issuer as a string.

Parameters:

  • credential_ptr - Credential to query

  • out_content - Pointer to issuer string pointer (output, caller must free)

  • out_size - Pointer to string size (output)

Returns: Error code (0 = success)

kc_credential_issuer_name()

int kc_credential_issuer_name(
    const kc_credential_t* credential_ptr,
    char** out_content,
    unsigned int* out_size
)

Gets the name of the issuer (if available).

Parameters:

  • credential_ptr - Credential to query

  • out_content - Pointer to name string pointer (output, caller must free)

  • out_size - Pointer to string size (output)

Returns: Error code (0 = success)

kc_credential_type()

int kc_credential_type(
    const kc_credential_t* credential_ptr,
    char*** out_type_array,
    unsigned int* out_array_size
)

Gets the credential types as an array of strings.

Parameters:

  • credential_ptr - Credential to query

  • out_type_array - Pointer to string array pointer (output, caller must free)

  • out_array_size - Pointer to array size (output)

Returns: Error code (0 = success)

Example:

char** types = NULL;
unsigned int type_count = 0;
int result = kc_credential_type(credential, &types, &type_count);
if (result == 0) {
    printf("Credential types:\n");
    for (unsigned int i = 0; i < type_count; i++) {
        printf("  - %s\n", types[i]);
    }
    kc_common_delete_buffer_array(&types, type_count);
}

kc_credential_subject()

int kc_credential_subject(
    const kc_credential_t* credential_ptr,
    kc_tag_set_t** out_subject_ptr
)

Gets the credential subject as a tag set.

Parameters:

  • credential_ptr - Credential to query

  • out_subject_ptr - Pointer to tag set pointer (output, caller must free)

Returns: Error code (0 = success)

kc_credential_credential_subject_id()

int kc_credential_credential_subject_id(
    const kc_credential_t* credential_ptr,
    char** out_content,
    unsigned int* out_size
)

Gets the ID of the credential subject.

Parameters:

  • credential_ptr - Credential to query

  • out_content - Pointer to subject ID string pointer (output, caller must free)

  • out_size - Pointer to string size (output)

Returns: Error code (0 = success)

Validity Period Functions

kc_credential_issuance_timestamp()

int kc_credential_issuance_timestamp(
    const kc_credential_t* credential_ptr,
    uint64_t* out_timestamp
)

Gets the credential issuance timestamp in milliseconds since epoch.

Parameters:

  • credential_ptr - Credential to query

  • out_timestamp - Pointer to timestamp (output)

Returns: Error code (0 = success)

kc_credential_expiration_timestamp()

int kc_credential_expiration_timestamp(
    const kc_credential_t* credential_ptr,
    uint64_t* out_timestamp
)

Gets the credential expiration timestamp in milliseconds since epoch.

Parameters:

  • credential_ptr - Credential to query

  • out_timestamp - Pointer to timestamp (output)

Returns: Error code (0 = success)

Example:

uint64_t issued_at = 0;
uint64_t expires_at = 0;

int result = kc_credential_issuance_timestamp(credential, &issued_at);
if (result == 0) {
    kc_credential_expiration_timestamp(credential, &expires_at);

    // Convert to human-readable dates
    time_t issued_sec = issued_at / 1000;
    time_t expires_sec = expires_at / 1000;

    printf("Issued: %s", ctime(&issued_sec));
    printf("Expires: %s", ctime(&expires_sec));

    // Check if still valid
    uint64_t now = time(NULL) * 1000;
    if (now < expires_at) {
        printf("Credential is still valid\n");
    } else {
        printf("Credential has expired\n");
    }
}

Query Functions

kc_credential_equals()

int kc_credential_equals(
    const kc_credential_t* lhs_ptr,
    bool* out_is_equal,
    const kc_credential_t* rhs_ptr
)

Tests equality of two credentials.

Parameters:

  • lhs_ptr - First credential to compare

  • out_is_equal - Pointer to equality result (output)

  • rhs_ptr - Second credential to compare

Returns: Error code (0 = success)

kc_credential_is_null()

int kc_credential_is_null(
    const kc_credential_t* credential_ptr,
    bool* out_is_null
)

Checks whether the credential is null.

Parameters:

  • credential_ptr - Credential to check

  • out_is_null - Pointer to null status (output)

Returns: Error code (0 = success)

Example: Complete Credential Processing

void process_credential(kc_credential_t* credential) {
    // Check if credential is valid
    bool is_null = false;
    int result = kc_credential_is_null(credential, &is_null);
    if (result != 0 || is_null) {
        printf("Invalid credential\n");
        return;
    }

    // Get credential ID
    char* cred_id = NULL;
    unsigned int id_size = 0;
    result = kc_credential_id(credential, &cred_id, &id_size);
    if (result == 0) {
        printf("Credential ID: %.*s\n", id_size, cred_id);
        kc_common_delete_buffer(&cred_id);
    }

    // Get issuer information
    char* issuer = NULL;
    char* issuer_name = NULL;
    unsigned int issuer_size = 0, name_size = 0;

    result = kc_credential_issuer(credential, &issuer, &issuer_size);
    if (result == 0) {
        printf("Issued by: %.*s\n", issuer_size, issuer);

        // Try to get issuer name
        if (kc_credential_issuer_name(credential, &issuer_name, &name_size) == 0) {
            printf("Issuer name: %.*s\n", name_size, issuer_name);
            kc_common_delete_buffer(&issuer_name);
        }

        kc_common_delete_buffer(&issuer);
    }

    // Get credential types
    char** types = NULL;
    unsigned int type_count = 0;
    result = kc_credential_type(credential, &types, &type_count);
    if (result == 0) {
        printf("Credential types (%u):\n", type_count);
        for (unsigned int i = 0; i < type_count; i++) {
            printf("  - %s\n", types[i]);
        }
        kc_common_delete_buffer_array(&types, type_count);
    }

    // Get subject ID
    char* subject_id = NULL;
    unsigned int subject_id_size = 0;
    result = kc_credential_credential_subject_id(credential, &subject_id, &subject_id_size);
    if (result == 0) {
        printf("Subject: %.*s\n", subject_id_size, subject_id);
        kc_common_delete_buffer(&subject_id);
    }

    // Check validity period
    uint64_t issued_at = 0, expires_at = 0;
    kc_credential_issuance_timestamp(credential, &issued_at);
    kc_credential_expiration_timestamp(credential, &expires_at);

    uint64_t now = time(NULL) * 1000;
    if (now >= issued_at && now < expires_at) {
        printf("Credential is currently valid\n");

        // Calculate days until expiration
        uint64_t days_left = (expires_at - now) / (1000 * 60 * 60 * 24);
        printf("Expires in %llu days\n", days_left);
    } else if (now < issued_at) {
        printf("Credential is not yet valid\n");
    } else {
        printf("Credential has expired\n");
    }

    // Export to JSON for storage
    char* json_output = NULL;
    unsigned int json_size = 0;
    result = kc_credential_serialize_to_string(credential, &json_output, &json_size,
                                             TKC_SERIALIZATION_FORMAT_JSON);
    if (result == 0) {
        printf("\nCredential as JSON:\n%.*s\n", json_size, json_output);
        kc_common_delete_buffer(&json_output);
    }
}

Example: Creating and Verifying Credentials

// Example using gateway and persona to create a credential
void create_identity_credential(kc_gateway_t* gateway, kc_persona_t* issuer) {
    const char* cred_id = "https://example.com/credentials/identity/12345";
    const char* cred_type = "IdentityCredential";
    const char* subject_did = "did:keychain:bob.employee";

    // Set validity for 1 year
    uint64_t now = time(NULL) * 1000;
    uint64_t one_year_later = now + (365ULL * 24 * 60 * 60 * 1000);

    // Create claims
    kc_tag_set_t* claims = NULL;
    kc_tag_set_construct(&claims);
    kc_tag_set_add_string(claims, "name", "Bob Smith");
    kc_tag_set_add_string(claims, "employeeId", "EMP-12345");
    kc_tag_set_add_string(claims, "department", "Engineering");

    // Create credential
    kc_credential_t* credential = NULL;
    int result = kc_persona_create_credential(issuer, &credential,
        cred_id, strlen(cred_id),
        cred_type, strlen(cred_type),
        subject_did, strlen(subject_did),
        now, one_year_later,
        claims, NULL, NULL);

    if (result == 0) {
        printf("Identity credential created successfully\n");

        // Process the credential
        process_credential(credential);

        // Verify the credential
        kc_verification_result_t* verify_result = NULL;
        result = kc_gateway_verify(gateway, &verify_result, issuer,
                                 (kc_verifiable_data_t*)credential);
        if (result == 0) {
            bool is_valid = false;
            kc_verification_result_is_valid(verify_result, &is_valid);
            printf("Credential verification: %s\n", is_valid ? "VALID" : "INVALID");
            kc_verification_result_destruct(&verify_result);
        }

        kc_credential_destruct(&credential);
    }

    kc_tag_set_destruct(&claims);
}

Memory Management

  • Use kc_credential_destruct() to free credential objects

  • Use kc_common_delete_buffer() for string outputs

  • Use kc_common_delete_buffer_array() for string arrays

  • Use kc_tag_set_destruct() for tag sets

  • Always check return codes before using output parameters

See Also