Key Lock Functions
#include <keychain/keychain_headers.h>
Overview
Key lock functions work with encrypted symmetric keys used in envelope (hybrid) encryption. A key lock encapsulates the ciphertext of a public-key encrypted symmetric block cipher key along with its pertinent metadata, such as the public key used during encryption. Key locks enable secure sharing of encrypted data by allowing multiple recipients to decrypt the symmetric key using their private keys.
Object Lifecycle Functions
kc_key_lock_construct_from_serialized_string()
int kc_key_lock_construct_from_serialized_string(
kc_key_lock_t** out_key_lock_ptr,
const char* serialized_string,
const unsigned int serialized_string_size,
const tkc_serialization_format serialization_format
)
Deserializes a key lock from a string representation.
Parameters:
-
out_key_lock_ptr
- Pointer to key lock pointer (output, caller must free) -
serialized_string
- String serialization of the key lock -
serialized_string_size
- Number of bytes in the serialized string -
serialization_format
- Expected serialization format (JSON, XML, or PROTOBUF)
Returns: Error code (0 = success)
Example:
kc_key_lock_t* key_lock = NULL;
const char* serialized = "{\"cipherText\":\"...\",\"publicKey\":\"...\"}";
int result = kc_key_lock_construct_from_serialized_string(&key_lock,
serialized, strlen(serialized), TKC_SERIALIZATION_FORMAT_JSON);
if (result == 0) {
// Use key lock...
kc_key_lock_destruct(&key_lock);
}
kc_key_lock_construct_from_copy()
int kc_key_lock_construct_from_copy(
kc_key_lock_t** out_key_lock_ptr,
const kc_key_lock_t* rhs_key_lock_ptr
)
Creates a deep copy of a key lock object.
Parameters:
-
out_key_lock_ptr
- Pointer to new key lock pointer (output, caller must free) -
rhs_key_lock_ptr
- Key lock object to copy
Returns: Error code (0 = success)
Example:
kc_key_lock_t* original_lock = NULL;
kc_key_lock_t* copied_lock = NULL;
// ... create original_lock ...
int result = kc_key_lock_construct_from_copy(&copied_lock, original_lock);
if (result == 0) {
// Use copied key lock...
kc_key_lock_destruct(&copied_lock);
}
Cryptographic Data Access Functions
kc_key_lock_cipher_text()
int kc_key_lock_cipher_text(
const kc_key_lock_t* key_lock_ptr,
char** out_cipher_text,
unsigned int* out_size
)
Gets the raw binary ciphertext of the encrypted symmetric key.
Parameters:
-
key_lock_ptr
- Key lock object to query -
out_cipher_text
- Pointer to ciphertext buffer pointer (output, caller must free) -
out_size
- Pointer to ciphertext size (output)
Returns: Error code (0 = success)
Example:
char* cipher_text = NULL;
unsigned int cipher_size = 0;
int result = kc_key_lock_cipher_text(key_lock, &cipher_text, &cipher_size);
if (result == 0) {
printf("Encrypted key size: %u bytes\n", cipher_size);
kc_common_delete_buffer(&cipher_text);
}
kc_key_lock_public_key()
int kc_key_lock_public_key(
const kc_key_lock_t* key_lock_ptr,
char** out_public_key_hex,
unsigned int* out_size
)
Gets the public key used to encrypt the symmetric key.
Parameters:
-
key_lock_ptr
- Key lock object to query -
out_public_key_hex
- Pointer to public key string pointer (output, caller must free) -
out_size
- Pointer to public key string size (output)
Returns: Error code (0 = success)
Example:
char* public_key = NULL;
unsigned int key_size = 0;
int result = kc_key_lock_public_key(key_lock, &public_key, &key_size);
if (result == 0) {
printf("Recipient public key: %.*s\n", key_size, public_key);
kc_common_delete_buffer(&public_key);
}
kc_key_lock_public_key_hash()
int kc_key_lock_public_key_hash(
const kc_key_lock_t* key_lock_ptr,
char** out_public_key_hash_hex,
unsigned int* out_size
)
Gets a non-cryptographic hash of the public key for fast lookups.
Parameters:
-
key_lock_ptr
- Key lock object to query -
out_public_key_hash_hex
- Pointer to hash string pointer (output, caller must free) -
out_size
- Pointer to hash string size (output)
Returns: Error code (0 = success)
Example:
char* key_hash = NULL;
unsigned int hash_size = 0;
int result = kc_key_lock_public_key_hash(key_lock, &key_hash, &hash_size);
if (result == 0) {
printf("Public key hash (for lookup): %.*s\n", hash_size, key_hash);
kc_common_delete_buffer(&key_hash);
}
kc_key_lock_cipher_text_hash()
int kc_key_lock_cipher_text_hash(
const kc_key_lock_t* key_lock_ptr,
char** out_cipher_text_hash_hex,
unsigned int* out_size
)
Gets a cryptographic hash of the ciphertext for integrity verification.
Parameters:
-
key_lock_ptr
- Key lock object to query -
out_cipher_text_hash_hex
- Pointer to hash string pointer (output, caller must free) -
out_size
- Pointer to hash string size (output)
Returns: Error code (0 = success)
Example:
char* cipher_hash = NULL;
unsigned int hash_size = 0;
int result = kc_key_lock_cipher_text_hash(key_lock, &cipher_hash, &hash_size);
if (result == 0) {
printf("Ciphertext integrity hash: %.*s\n", hash_size, cipher_hash);
kc_common_delete_buffer(&cipher_hash);
}
Metadata Access Functions
kc_key_lock_algorithm()
int kc_key_lock_algorithm(
const kc_key_lock_t* key_lock_ptr,
tkc_encryption_scheme* out_algorithm
)
Gets the public-key encryption algorithm used to encrypt the symmetric key.
Parameters:
-
key_lock_ptr
- Key lock object to query -
out_algorithm
- Pointer to encryption scheme (output)
Returns: Error code (0 = success)
Example:
tkc_encryption_scheme algorithm;
int result = kc_key_lock_algorithm(key_lock, &algorithm);
if (result == 0) {
printf("Key encryption algorithm: %d\n", algorithm);
}
kc_key_lock_version()
int kc_key_lock_version(
const kc_key_lock_t* key_lock_ptr,
tkc_version* out_version
)
Gets the data format version of the key lock.
Parameters:
-
key_lock_ptr
- Key lock object to query -
out_version
- Pointer to version information (output)
Returns: Error code (0 = success)
kc_key_lock_data_type()
int kc_key_lock_data_type(
const kc_key_lock_t* key_lock_ptr,
tkc_data_type* out_data_type
)
Gets the data type value indicating this is a key lock.
Parameters:
-
key_lock_ptr
- Key lock object to query -
out_data_type
- Pointer to data type value (output)
Returns: Error code (0 = success)
Serialization Functions
kc_key_lock_serialize()
int kc_key_lock_serialize(
const kc_key_lock_t* key_lock_ptr,
char** out_serialized_string,
unsigned int* out_size
)
Serializes the key lock to a string in protobuf format.
Parameters:
-
key_lock_ptr
- Key lock object to serialize -
out_serialized_string
- 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_key_lock_serialize(key_lock, &serialized, &serialized_size);
if (result == 0) {
printf("Serialized key lock (%u bytes): %.*s\n",
serialized_size, serialized_size, serialized);
kc_common_delete_buffer(&serialized);
}
Query Functions
kc_key_lock_equals()
int kc_key_lock_equals(
const kc_key_lock_t* lhs_key_lock_ptr,
bool* out_is_equal,
const kc_key_lock_t* rhs_key_lock_ptr
)
Tests equality of two key lock objects.
Parameters:
-
lhs_key_lock_ptr
- First key lock to compare -
out_is_equal
- Pointer to equality result (output) -
rhs_key_lock_ptr
- Second key lock to compare
Returns: Error code (0 = success)
Example: Analyzing Encrypted Data Access Control
void analyze_encrypted_data_access(kc_encrypted_data_t* encrypted_data) {
// Get all key locks from the encrypted data
kc_key_lock_t** key_locks = NULL;
unsigned int lock_count = 0;
int result = kc_encrypted_data_key_locks(encrypted_data, &key_locks, &lock_count);
if (result != 0) {
printf("Failed to get key locks: %d\n", result);
return;
}
printf("Encrypted data has %u key locks (recipients):\n", lock_count);
for (unsigned int i = 0; i < lock_count; i++) {
kc_key_lock_t* lock = key_locks[i];
// Get recipient public key
char* public_key = NULL;
unsigned int key_size = 0;
kc_key_lock_public_key(lock, &public_key, &key_size);
// Get public key hash for identification
char* key_hash = NULL;
unsigned int hash_size = 0;
kc_key_lock_public_key_hash(lock, &key_hash, &hash_size);
// Get encryption algorithm
tkc_encryption_scheme algorithm;
kc_key_lock_algorithm(lock, &algorithm);
// Get ciphertext size
char* cipher_text = NULL;
unsigned int cipher_size = 0;
kc_key_lock_cipher_text(lock, &cipher_text, &cipher_size);
printf("\nRecipient #%u:\n", i + 1);
printf(" Public key hash: %.*s\n", hash_size, key_hash ? key_hash : "Unknown");
printf(" Public key: %.40s...\n", public_key ? public_key : "Unknown");
printf(" Encryption algorithm: %d\n", algorithm);
printf(" Encrypted key size: %u bytes\n", cipher_size);
// Cleanup
if (public_key) kc_common_delete_buffer(&public_key);
if (key_hash) kc_common_delete_buffer(&key_hash);
if (cipher_text) kc_common_delete_buffer(&cipher_text);
}
// Cleanup key locks array
if (key_locks) {
for (unsigned int i = 0; i < lock_count; i++) {
kc_key_lock_destruct(&key_locks[i]);
}
kc_common_delete_buffer_array((char**)&key_locks, lock_count);
}
printf("\nAccess control analysis complete.\n");
}
Example: Finding Key Lock for Specific Recipient
kc_key_lock_t* find_key_lock_for_recipient(kc_encrypted_data_t* encrypted_data,
const char* target_public_key_hash) {
kc_key_lock_t** key_locks = NULL;
unsigned int lock_count = 0;
kc_key_lock_t* found_lock = NULL;
// Get all key locks
int result = kc_encrypted_data_key_locks(encrypted_data, &key_locks, &lock_count);
if (result != 0) {
return NULL;
}
// Search for matching public key hash
for (unsigned int i = 0; i < lock_count; i++) {
char* key_hash = NULL;
unsigned int hash_size = 0;
result = kc_key_lock_public_key_hash(key_locks[i], &key_hash, &hash_size);
if (result == 0 && key_hash) {
// Compare with target hash
if (strlen(target_public_key_hash) == hash_size &&
memcmp(key_hash, target_public_key_hash, hash_size) == 0) {
// Found matching key lock - create copy before cleanup
kc_key_lock_construct_from_copy(&found_lock, key_locks[i]);
kc_common_delete_buffer(&key_hash);
break;
}
kc_common_delete_buffer(&key_hash);
}
}
// Cleanup search results
if (key_locks) {
for (unsigned int i = 0; i < lock_count; i++) {
kc_key_lock_destruct(&key_locks[i]);
}
kc_common_delete_buffer_array((char**)&key_locks, lock_count);
}
return found_lock;
}
void demonstrate_recipient_search(kc_encrypted_data_t* encrypted_data) {
const char* alice_key_hash = "a1b2c3d4e5f6"; // Example hash
kc_key_lock_t* alice_lock = find_key_lock_for_recipient(encrypted_data, alice_key_hash);
if (alice_lock) {
printf("Found key lock for Alice's public key\n");
// Get Alice's public key
char* public_key = NULL;
unsigned int key_size = 0;
int result = kc_key_lock_public_key(alice_lock, &public_key, &key_size);
if (result == 0) {
printf("Alice's public key: %.*s\n", key_size, public_key);
kc_common_delete_buffer(&public_key);
}
// Check encryption algorithm
tkc_encryption_scheme algorithm;
result = kc_key_lock_algorithm(alice_lock, &algorithm);
if (result == 0) {
printf("Encryption algorithm used: %d\n", algorithm);
}
kc_key_lock_destruct(&alice_lock);
} else {
printf("No key lock found for Alice's public key hash\n");
}
}
Example: Key Lock Integrity Verification
bool verify_key_lock_integrity(kc_key_lock_t* key_lock) {
// Get the ciphertext and its hash
char* cipher_text = NULL;
char* stored_hash = NULL;
unsigned int cipher_size = 0;
unsigned int hash_size = 0;
int result1 = kc_key_lock_cipher_text(key_lock, &cipher_text, &cipher_size);
int result2 = kc_key_lock_cipher_text_hash(key_lock, &stored_hash, &hash_size);
if (result1 != 0 || result2 != 0) {
if (cipher_text) kc_common_delete_buffer(&cipher_text);
if (stored_hash) kc_common_delete_buffer(&stored_hash);
return false;
}
// Compute fresh hash of ciphertext
char* computed_hash = NULL;
int computed_size = 0;
int result3 = kc_gateway_hash(&computed_hash, &computed_size,
cipher_text, cipher_size);
bool is_valid = false;
if (result3 == 0 && computed_hash) {
// Compare stored hash with computed hash
if (hash_size == computed_size &&
memcmp(stored_hash, computed_hash, hash_size) == 0) {
is_valid = true;
printf("Key lock integrity verification: PASSED\n");
} else {
printf("Key lock integrity verification: FAILED\n");
printf("Stored hash: %.*s\n", hash_size, stored_hash);
printf("Computed hash: %.*s\n", computed_size, computed_hash);
}
}
// Cleanup
if (cipher_text) kc_common_delete_buffer(&cipher_text);
if (stored_hash) kc_common_delete_buffer(&stored_hash);
if (computed_hash) kc_common_delete_buffer(&computed_hash);
return is_valid;
}
void demonstrate_integrity_checking(kc_encrypted_data_t* encrypted_data) {
kc_key_lock_t** key_locks = NULL;
unsigned int lock_count = 0;
int result = kc_encrypted_data_key_locks(encrypted_data, &key_locks, &lock_count);
if (result != 0) {
printf("Failed to get key locks for integrity check\n");
return;
}
printf("Verifying integrity of %u key locks:\n", lock_count);
unsigned int valid_count = 0;
for (unsigned int i = 0; i < lock_count; i++) {
printf("Key lock #%u: ", i + 1);
if (verify_key_lock_integrity(key_locks[i])) {
valid_count++;
}
}
printf("\nIntegrity check summary: %u/%u key locks are valid\n",
valid_count, lock_count);
// Cleanup
if (key_locks) {
for (unsigned int i = 0; i < lock_count; i++) {
kc_key_lock_destruct(&key_locks[i]);
}
kc_common_delete_buffer_array((char**)&key_locks, lock_count);
}
}
Example: Key Lock Serialization and Storage
void demonstrate_key_lock_persistence(kc_key_lock_t* key_lock) {
// Serialize key lock for storage
char* serialized = NULL;
unsigned int serialized_size = 0;
int result = kc_key_lock_serialize(key_lock, &serialized, &serialized_size);
if (result != 0) {
printf("Failed to serialize key lock: %d\n", result);
return;
}
printf("Serialized key lock (%u bytes)\n", serialized_size);
// Simulate storage to file
FILE* storage_file = fopen("/tmp/keylock_storage.dat", "wb");
if (storage_file) {
fwrite(serialized, 1, serialized_size, storage_file);
fclose(storage_file);
printf("Key lock saved to storage\n");
}
// Simulate retrieval from storage
storage_file = fopen("/tmp/keylock_storage.dat", "rb");
if (storage_file) {
fseek(storage_file, 0, SEEK_END);
long file_size = ftell(storage_file);
fseek(storage_file, 0, SEEK_SET);
char* loaded_data = malloc(file_size);
fread(loaded_data, 1, file_size, storage_file);
fclose(storage_file);
// Deserialize loaded key lock
kc_key_lock_t* loaded_lock = NULL;
result = kc_key_lock_construct_from_serialized_string(&loaded_lock,
loaded_data, file_size, TKC_SERIALIZATION_FORMAT_PROTOBUF);
if (result == 0) {
printf("Key lock loaded from storage\n");
// Verify it matches original
bool are_equal = false;
kc_key_lock_equals(key_lock, &are_equal, loaded_lock);
printf("Original and loaded key locks match: %s\n",
are_equal ? "Yes" : "No");
kc_key_lock_destruct(&loaded_lock);
} else {
printf("Failed to deserialize loaded key lock: %d\n", result);
}
free(loaded_data);
}
kc_common_delete_buffer(&serialized);
}
Memory Management
-
Use
kc_key_lock_destruct()
to free key lock objects -
Use
kc_common_delete_buffer()
for string outputs (public keys, hashes, ciphertext, serialized data) -
Use
kc_common_delete_buffer_array()
for arrays of key locks -
Always check return codes before using output parameters
-
Key locks are typically obtained from encrypted data objects
Security Considerations
-
Key locks contain encrypted symmetric keys - protect from tampering
-
Verify ciphertext integrity using
kc_key_lock_cipher_text_hash()
-
Use public key hashes for fast recipient lookup without exposing full keys
-
Ensure proper access control when storing or transmitting key locks
-
Validate encryption algorithms match expected security requirements
Best Practices
-
Check integrity of key locks before attempting decryption
-
Use public key hashes for efficient recipient identification
-
Store key locks securely alongside encrypted data
-
Verify encryption algorithms meet security policy requirements
-
Monitor access patterns to key locks for audit purposes
See Also
-
Encrypted Data - Objects that contain key locks
-
Gateway Cryptographic Operations - Encryption and decryption
-
Persona Functions - Key management and decryption
-
Enums - Encryption schemes and data types
-
C++ Key Lock Class - Object-oriented interface