Keychain DID Functions
#include <keychain/keychain_headers.h>
Overview
Keychain DID functions work with keychain-specific DIDs that extend basic DID functionality with keychain-specific fields such as the public-key infrastructure network ID and the keychain type. These DIDs include additional metadata and network information specific to the Keychain ecosystem.
Object Lifecycle Functions
kc_keychain_did_construct_from_serialized_string()
int kc_keychain_did_construct_from_serialized_string(
kc_keychain_did_t** out_keychain_did_ptr,
const char* serialized_string,
const unsigned int serialized_string_size
)
Deserializes a keychain DID from a string representation in W3C format.
Parameters:
-
out_keychain_did_ptr
- Pointer to keychain DID pointer (output, caller must free) -
serialized_string
- Serialized DID as a character array -
serialized_string_size
- Number of bytes in the serialized string
Returns: Error code (0 = success)
Example:
kc_keychain_did_t* keychain_did = NULL;
const char* did_string = "did:keychain:mainnet:alice.example.com";
int result = kc_keychain_did_construct_from_serialized_string(&keychain_did,
did_string, strlen(did_string));
if (result == 0) {
// Use keychain DID...
kc_keychain_did_destruct(&keychain_did);
}
kc_keychain_did_construct_from_copy()
int kc_keychain_did_construct_from_copy(
kc_keychain_did_t** out_keychain_did_ptr,
const kc_keychain_did_t* rhs_keychain_did_ptr
)
Creates a deep copy of a keychain DID object.
Parameters:
-
out_keychain_did_ptr
- Pointer to new keychain DID pointer (output, caller must free) -
rhs_keychain_did_ptr
- Keychain DID object to copy
Returns: Error code (0 = success)
Example:
kc_keychain_did_t* original_did = NULL;
kc_keychain_did_t* copied_did = NULL;
// ... create original_did ...
int result = kc_keychain_did_construct_from_copy(&copied_did, original_did);
if (result == 0) {
// Use copied keychain DID...
kc_keychain_did_destruct(&copied_did);
}
Keychain-Specific Access Functions
kc_keychain_did_keychain_type()
int kc_keychain_did_keychain_type(
const kc_keychain_did_t* keychain_did_ptr,
unsigned int* out_keychain_type
)
Gets the keychain type from the keychain DID.
Parameters:
-
keychain_did_ptr
- Keychain DID object to query -
out_keychain_type
- Pointer to keychain type (output)
Returns: Error code (0 = success)
Example:
unsigned int keychain_type = 0;
int result = kc_keychain_did_keychain_type(keychain_did, &keychain_type);
if (result == 0) {
printf("Keychain type: %u\n", keychain_type);
}
kc_keychain_did_network()
int kc_keychain_did_network(
const kc_keychain_did_t* keychain_did_ptr,
char** out_network_str,
unsigned int* out_size
)
Gets the network ID from the keychain DID.
Parameters:
-
keychain_did_ptr
- Keychain DID object to query -
out_network_str
- Pointer to network string pointer (output, caller must free) -
out_size
- Pointer to network string size (output)
Returns: Error code (0 = success)
Example:
char* network = NULL;
unsigned int network_size = 0;
int result = kc_keychain_did_network(keychain_did, &network, &network_size);
if (result == 0) {
printf("Network: %.*s\n", network_size, network);
kc_common_delete_buffer(&network);
}
kc_keychain_did_network_specific_id()
int kc_keychain_did_network_specific_id(
const kc_keychain_did_t* keychain_did_ptr,
char** out_nsid,
unsigned int* out_size
)
Gets the network-specific identifier from the keychain DID.
Parameters:
-
keychain_did_ptr
- Keychain DID object to query -
out_nsid
- Pointer to network-specific ID string pointer (output, caller must free) -
out_size
- Pointer to ID string size (output)
Returns: Error code (0 = success)
Example:
char* nsid = NULL;
unsigned int nsid_size = 0;
int result = kc_keychain_did_network_specific_id(keychain_did, &nsid, &nsid_size);
if (result == 0) {
printf("Network-specific ID: %.*s\n", nsid_size, nsid);
kc_common_delete_buffer(&nsid);
}
Standard DID Component Access Functions
kc_keychain_did_scheme()
int kc_keychain_did_scheme(
const kc_keychain_did_t* keychain_did_ptr,
char** out_scheme,
unsigned int* out_size
)
Gets the DID scheme (always "did" for valid DIDs).
Parameters:
-
keychain_did_ptr
- Keychain DID object to query -
out_scheme
- Pointer to scheme string pointer (output, caller must free) -
out_size
- Pointer to scheme string size (output)
Returns: Error code (0 = success)
kc_keychain_did_method()
int kc_keychain_did_method(
const kc_keychain_did_t* keychain_did_ptr,
char** out_method,
unsigned int* out_size
)
Gets the DID method (should be "keychain" for keychain DIDs).
Parameters:
-
keychain_did_ptr
- Keychain DID object to query -
out_method
- Pointer to method string pointer (output, caller must free) -
out_size
- Pointer to method string size (output)
Returns: Error code (0 = success)
kc_keychain_did_id()
int kc_keychain_did_id(
const kc_keychain_did_t* keychain_did_ptr,
char** out_id,
unsigned int* out_size
)
Gets the method-specific identifier portion of the DID.
Parameters:
-
keychain_did_ptr
- Keychain DID object to query -
out_id
- Pointer to ID string pointer (output, caller must free) -
out_size
- Pointer to ID string size (output)
Returns: Error code (0 = success)
Serialization Functions
kc_keychain_did_serialize()
int kc_keychain_did_serialize(
const kc_keychain_did_t* keychain_did_ptr,
char** out_serialized_str,
unsigned int* out_size
)
Serializes the keychain DID to a string as defined in the W3C specification.
Parameters:
-
keychain_did_ptr
- Keychain DID object to serialize -
out_serialized_str
- Pointer to serialized string pointer (output, caller must free) -
out_size
- Pointer to string size (output)
Returns: Error code (0 = success)
Example:
char* serialized = NULL;
unsigned int serialized_size = 0;
int result = kc_keychain_did_serialize(keychain_did, &serialized, &serialized_size);
if (result == 0) {
printf("Serialized keychain DID: %.*s\n", serialized_size, serialized);
kc_common_delete_buffer(&serialized);
}
Metadata Functions
kc_keychain_did_data_type()
int kc_keychain_did_data_type(
const kc_keychain_did_t* keychain_did_ptr,
unsigned int* out_data_type
)
Gets the data type value indicating this is a keychain DID.
Parameters:
-
keychain_did_ptr
- Keychain DID object to query -
out_data_type
- Pointer to data type value (output)
Returns: Error code (0 = success)
Query Functions
kc_keychain_did_equals()
int kc_keychain_did_equals(
const kc_keychain_did_t* lhs_keychain_did_ptr,
bool* out_is_equal,
const kc_keychain_did_t* rhs_keychain_did_ptr
)
Tests equality of two keychain DID objects.
Parameters:
-
lhs_keychain_did_ptr
- First keychain DID to compare -
out_is_equal
- Pointer to equality result (output) -
rhs_keychain_did_ptr
- Second keychain DID to compare
Returns: Error code (0 = success)
Example: Keychain DID Analysis
void analyze_keychain_did(const char* did_string) {
kc_keychain_did_t* keychain_did = NULL;
printf("Analyzing keychain DID: %s\n", did_string);
// Parse the keychain DID
int result = kc_keychain_did_construct_from_serialized_string(&keychain_did,
did_string, strlen(did_string));
if (result != 0) {
printf("Failed to parse keychain DID: %d\n", result);
return;
}
// Get standard DID components
char* scheme = NULL;
char* method = NULL;
char* id = NULL;
unsigned int scheme_size = 0;
unsigned int method_size = 0;
unsigned int id_size = 0;
kc_keychain_did_scheme(keychain_did, &scheme, &scheme_size);
kc_keychain_did_method(keychain_did, &method, &method_size);
kc_keychain_did_id(keychain_did, &id, &id_size);
printf("\nStandard DID Components:\n");
printf(" Scheme: %.*s\n", scheme_size, scheme ? scheme : "Unknown");
printf(" Method: %.*s\n", method_size, method ? method : "Unknown");
printf(" Method-specific ID: %.*s\n", id_size, id ? id : "Unknown");
// Get keychain-specific components
unsigned int keychain_type = 0;
char* network = NULL;
char* nsid = NULL;
unsigned int network_size = 0;
unsigned int nsid_size = 0;
kc_keychain_did_keychain_type(keychain_did, &keychain_type);
kc_keychain_did_network(keychain_did, &network, &network_size);
kc_keychain_did_network_specific_id(keychain_did, &nsid, &nsid_size);
printf("\nKeychain-Specific Components:\n");
printf(" Keychain Type: %u\n", keychain_type);
printf(" Network: %.*s\n", network_size, network ? network : "Unknown");
printf(" Network-Specific ID: %.*s\n", nsid_size, nsid ? nsid : "Unknown");
// Get data type
unsigned int data_type = 0;
kc_keychain_did_data_type(keychain_did, &data_type);
printf(" Data Type: %u\n", data_type);
// Test serialization
char* serialized = NULL;
unsigned int serialized_size = 0;
result = kc_keychain_did_serialize(keychain_did, &serialized, &serialized_size);
if (result == 0) {
printf("\nSerialization Test:\n");
printf(" Original: %s\n", did_string);
printf(" Serialized: %.*s\n", serialized_size, serialized);
if (strlen(did_string) == serialized_size &&
memcmp(did_string, serialized, serialized_size) == 0) {
printf(" ✓ Round-trip serialization successful\n");
} else {
printf(" ✗ Round-trip serialization failed\n");
}
kc_common_delete_buffer(&serialized);
}
// Cleanup
if (scheme) kc_common_delete_buffer(&scheme);
if (method) kc_common_delete_buffer(&method);
if (id) kc_common_delete_buffer(&id);
if (network) kc_common_delete_buffer(&network);
if (nsid) kc_common_delete_buffer(&nsid);
kc_keychain_did_destruct(&keychain_did);
}
Example: Network-Based DID Operations
void demonstrate_network_operations() {
// Test different network configurations
const char* test_dids[] = {
"did:keychain:mainnet:alice.company.com",
"did:keychain:testnet:bob.development.local",
"did:keychain:private:charlie.internal.corp",
"did:keychain:staging:diana.staging.example.org"
};
printf("Analyzing DIDs by network:\n\n");
for (size_t i = 0; i < sizeof(test_dids) / sizeof(test_dids[0]); i++) {
kc_keychain_did_t* did = NULL;
int result = kc_keychain_did_construct_from_serialized_string(&did,
test_dids[i], strlen(test_dids[i]));
if (result == 0) {
char* network = NULL;
char* nsid = NULL;
unsigned int network_size = 0;
unsigned int nsid_size = 0;
unsigned int keychain_type = 0;
kc_keychain_did_network(did, &network, &network_size);
kc_keychain_did_network_specific_id(did, &nsid, &nsid_size);
kc_keychain_did_keychain_type(did, &keychain_type);
printf("DID %zu: %s\n", i + 1, test_dids[i]);
printf(" Network: %.*s\n", network_size, network ? network : "Unknown");
printf(" Entity: %.*s\n", nsid_size, nsid ? nsid : "Unknown");
printf(" Type: %u\n", keychain_type);
// Determine network characteristics
if (network && network_size == 7 && memcmp(network, "mainnet", 7) == 0) {
printf(" Environment: Production\n");
} else if (network && network_size == 7 && memcmp(network, "testnet", 7) == 0) {
printf(" Environment: Testing\n");
} else if (network && network_size == 7 && memcmp(network, "private", 7) == 0) {
printf(" Environment: Private/Internal\n");
} else if (network && network_size == 7 && memcmp(network, "staging", 7) == 0) {
printf(" Environment: Staging\n");
} else {
printf(" Environment: Unknown\n");
}
printf("\n");
if (network) kc_common_delete_buffer(&network);
if (nsid) kc_common_delete_buffer(&nsid);
kc_keychain_did_destruct(&did);
} else {
printf("Failed to parse DID %zu: %s\n", i + 1, test_dids[i]);
}
}
}
Example: DID Comparison and Filtering
bool is_same_network(kc_keychain_did_t* did1, kc_keychain_did_t* did2) {
char* network1 = NULL;
char* network2 = NULL;
unsigned int size1 = 0;
unsigned int size2 = 0;
int result1 = kc_keychain_did_network(did1, &network1, &size1);
int result2 = kc_keychain_did_network(did2, &network2, &size2);
bool same_network = false;
if (result1 == 0 && result2 == 0 && network1 && network2) {
if (size1 == size2 && memcmp(network1, network2, size1) == 0) {
same_network = true;
}
}
if (network1) kc_common_delete_buffer(&network1);
if (network2) kc_common_delete_buffer(&network2);
return same_network;
}
void filter_dids_by_network(const char** did_strings, size_t count,
const char* target_network) {
printf("Filtering DIDs for network: %s\n\n", target_network);
for (size_t i = 0; i < count; i++) {
kc_keychain_did_t* did = NULL;
int result = kc_keychain_did_construct_from_serialized_string(&did,
did_strings[i], strlen(did_strings[i]));
if (result == 0) {
char* network = NULL;
unsigned int network_size = 0;
kc_keychain_did_network(did, &network, &network_size);
if (network && strlen(target_network) == network_size &&
memcmp(network, target_network, network_size) == 0) {
char* nsid = NULL;
unsigned int nsid_size = 0;
kc_keychain_did_network_specific_id(did, &nsid, &nsid_size);
printf("✓ %s\n", did_strings[i]);
printf(" Entity: %.*s\n", nsid_size, nsid ? nsid : "Unknown");
if (nsid) kc_common_delete_buffer(&nsid);
}
if (network) kc_common_delete_buffer(&network);
kc_keychain_did_destruct(&did);
}
}
}
void demonstrate_did_filtering() {
const char* all_dids[] = {
"did:keychain:mainnet:alice.company.com",
"did:keychain:testnet:bob.development.local",
"did:keychain:mainnet:charlie.company.com",
"did:keychain:private:diana.internal.corp",
"did:keychain:testnet:eve.development.local",
"did:keychain:mainnet:frank.company.com"
};
size_t count = sizeof(all_dids) / sizeof(all_dids[0]);
// Filter by different networks
filter_dids_by_network(all_dids, count, "mainnet");
printf("\n");
filter_dids_by_network(all_dids, count, "testnet");
printf("\n");
filter_dids_by_network(all_dids, count, "private");
}
Example: DID Type and Configuration Analysis
void analyze_keychain_configuration(kc_keychain_did_t* did) {
unsigned int keychain_type = 0;
char* network = NULL;
unsigned int network_size = 0;
int result = kc_keychain_did_keychain_type(did, &keychain_type);
if (result != 0) {
printf("Failed to get keychain type\n");
return;
}
result = kc_keychain_did_network(did, &network, &network_size);
if (result != 0) {
printf("Failed to get network information\n");
return;
}
printf("Keychain Configuration Analysis:\n");
printf(" Type: %u", keychain_type);
// Interpret keychain type (assuming some standard values)
switch (keychain_type) {
case 1:
printf(" (Standard)\n");
break;
case 2:
printf(" (Enterprise)\n");
break;
case 3:
printf(" (Development)\n");
break;
default:
printf(" (Unknown)\n");
break;
}
printf(" Network: %.*s", network_size, network);
// Analyze network security implications
if (network && network_size == 7 && memcmp(network, "mainnet", 7) == 0) {
printf(" (Production - High Security)\n");
printf(" Security Level: Production\n");
printf(" Certificate Validation: Required\n");
printf(" Audit Logging: Enabled\n");
} else if (network && network_size == 7 && memcmp(network, "testnet", 7) == 0) {
printf(" (Testing - Medium Security)\n");
printf(" Security Level: Testing\n");
printf(" Certificate Validation: Optional\n");
printf(" Audit Logging: Limited\n");
} else if (network && network_size == 7 && memcmp(network, "private", 7) == 0) {
printf(" (Private - Custom Security)\n");
printf(" Security Level: Custom\n");
printf(" Certificate Validation: Internal CA\n");
printf(" Audit Logging: Internal\n");
} else {
printf(" (Custom Network)\n");
printf(" Security Level: Unknown\n");
printf(" Certificate Validation: Unknown\n");
printf(" Audit Logging: Unknown\n");
}
if (network) kc_common_delete_buffer(&network);
}
void demonstrate_configuration_analysis() {
const char* config_dids[] = {
"did:keychain:mainnet:prod.enterprise.com",
"did:keychain:testnet:dev.testing.local",
"did:keychain:private:internal.company.corp"
};
for (size_t i = 0; i < sizeof(config_dids) / sizeof(config_dids[0]); i++) {
kc_keychain_did_t* did = NULL;
int result = kc_keychain_did_construct_from_serialized_string(&did,
config_dids[i], strlen(config_dids[i]));
if (result == 0) {
printf("\n=== Configuration %zu ===\n", i + 1);
printf("DID: %s\n", config_dids[i]);
analyze_keychain_configuration(did);
kc_keychain_did_destruct(&did);
}
}
}
Memory Management
-
Use
kc_keychain_did_destruct()
to free keychain DID objects -
Use
kc_common_delete_buffer()
for string outputs (scheme, method, ID, network, network-specific ID, serialized data) -
Always check return codes before using output parameters
-
Keychain DIDs are immutable once created
Best Practices
-
Use appropriate networks for different environments (mainnet for production, testnet for development)
-
Validate network-specific IDs according to your naming conventions
-
Store keychain DIDs in their canonical string form for persistence
-
Use keychain type to categorize different kinds of entities
-
Implement network-based access controls and security policies
See Also
-
DID Functions - Basic DID functionality
-
Persona DID Functions - Persona-specific DID handling
-
Persona Functions - Using keychain DIDs with personas
-
Contact Functions - Using keychain DIDs with contacts
-
C++ Keychain DID Class - Object-oriented interface