Encrypted Data Functions
#include <keychain/keychain_headers.h>
Overview
Encrypted data functions work with envelope (hybrid) encrypted data objects. These objects encapsulate encrypted content along with access control lists specifying which public keys can decrypt the data.
Object Lifecycle Functions
kc_encrypted_data_construct_from_serialized_data()
int kc_encrypted_data_construct_from_serialized_data(
kc_encrypted_data_t** out_encrypted_data_ptr,
const kc_serialized_data_t* serialized_data_ptr
)
Deserializes encrypted data from a serialized data object. Encrypted data encapsulates envelope (hybrid) encryption of a given cleartext.
Parameters:
-
out_encrypted_data_ptr
- Pointer to encrypted data pointer (output, caller must free) -
serialized_data_ptr
- Serialized data containing encrypted data
Returns: Error code (0 = success)
Example:
kc_serialized_data_t* serialized = NULL;
kc_encrypted_data_t* encrypted = NULL;
// Assume serialized contains encrypted data...
int result = kc_encrypted_data_construct_from_serialized_data(&encrypted, serialized);
if (result == 0) {
// Use encrypted data...
kc_encrypted_data_destruct(&encrypted);
}
kc_encrypted_data_construct_from_serialized_string()
int kc_encrypted_data_construct_from_serialized_string(
kc_encrypted_data_t** out_encrypted_data_ptr,
const char* serialized_string,
const unsigned int serialized_string_size,
const tkc_serialization_format serialization_format
)
Deserializes encrypted data from a string.
Parameters:
-
out_encrypted_data_ptr
- Pointer to encrypted data pointer (output, caller must free) -
serialized_string
- String containing serialized encrypted data -
serialized_string_size
- Length of the string -
serialization_format
- Format of the serialization (JSON, XML, or PROTOBUF)
Returns: Error code (0 = success)
Serialization Functions
kc_encrypted_data_serialize()
int kc_encrypted_data_serialize(
const kc_encrypted_data_t* encrypted_data_ptr,
kc_serialized_data_t** out_serialized_data_ptr
)
Serializes encrypted data to a serialized data object.
Parameters:
-
encrypted_data_ptr
- Encrypted data to serialize -
out_serialized_data_ptr
- Pointer to serialized data pointer (output, caller must free)
Returns: Error code (0 = success)
Example:
kc_serialized_data_t* serialized = NULL;
int result = kc_encrypted_data_serialize(encrypted, &serialized);
if (result == 0) {
// Can now transmit or store the serialized data
kc_serialized_data_destruct(&serialized);
}
kc_encrypted_data_serialize_to_string()
int kc_encrypted_data_serialize_to_string(
const kc_encrypted_data_t* encrypted_data_ptr,
char** out_content,
unsigned int* out_size,
const tkc_serialization_format serialization_format
)
Serializes encrypted data to a string in the specified format.
Parameters:
-
encrypted_data_ptr
- Encrypted data 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)
Content Access Functions
kc_encrypted_data_iv()
int kc_encrypted_data_iv(
const kc_encrypted_data_t* encrypted_data_ptr,
char** out_iv_hex,
unsigned int* out_size
)
Gets the initialization vector (IV) used for symmetric encryption.
Parameters:
-
encrypted_data_ptr
- Encrypted data to query -
out_iv_hex
- Pointer to IV hex string pointer (output, caller must free) -
out_size
- Pointer to string size (output)
Returns: Error code (0 = success)
Example:
char* iv = NULL;
unsigned int iv_size = 0;
int result = kc_encrypted_data_iv(encrypted, &iv, &iv_size);
if (result == 0) {
printf("IV: %.*s\n", iv_size, iv);
kc_common_delete_buffer(&iv);
}
kc_encrypted_data_ciphertext()
int kc_encrypted_data_ciphertext(
const kc_encrypted_data_t* encrypted_data_ptr,
char** out_ciphertext,
unsigned int* out_size
)
Gets the encrypted ciphertext of the cleartext.
Parameters:
-
encrypted_data_ptr
- Encrypted data to query -
out_ciphertext
- Pointer to ciphertext pointer (output, caller must free) -
out_size
- Pointer to ciphertext size (output)
Returns: Error code (0 = success)
kc_encrypted_data_algorithm()
int kc_encrypted_data_algorithm(
const kc_encrypted_data_t* encrypted_data_ptr,
tkc_cipher* out_algorithm
)
Gets the symmetric cipher algorithm used for encryption.
Parameters:
-
encrypted_data_ptr
- Encrypted data to query -
out_algorithm
- Pointer to cipher algorithm (output)
Returns: Error code (0 = success)
Example:
tkc_cipher cipher_alg;
int result = kc_encrypted_data_algorithm(encrypted, &cipher_alg);
if (result == 0) {
printf("Encrypted with cipher: %d\n", cipher_alg);
if (cipher_alg == TKC_CIPHER_AES_256_GCM) {
printf("Using AES-256-GCM encryption\n");
}
}
Access Control Functions
kc_encrypted_data_num_key_locks()
int kc_encrypted_data_num_key_locks(
const kc_encrypted_data_t* encrypted_data_ptr,
unsigned int* out_count
)
Gets the number of key locks (access control entries) in the encrypted data.
Parameters:
-
encrypted_data_ptr
- Encrypted data to query -
out_count
- Pointer to key lock count (output)
Returns: Error code (0 = success)
kc_encrypted_data_key_lock()
int kc_encrypted_data_key_lock(
const kc_encrypted_data_t* encrypted_data_ptr,
kc_key_lock_t** out_key_lock_ptr,
const unsigned int index
)
Gets a specific key lock by index.
Parameters:
-
encrypted_data_ptr
- Encrypted data to query -
out_key_lock_ptr
- Pointer to key lock pointer (output, caller must free) -
index
- Zero-based index of the key lock to retrieve
Returns: Error code (0 = success)
Example:
unsigned int lock_count = 0;
int result = kc_encrypted_data_num_key_locks(encrypted, &lock_count);
if (result == 0) {
printf("Encrypted data has %u recipients\n", lock_count);
// Examine each key lock
for (unsigned int i = 0; i < lock_count; i++) {
kc_key_lock_t* key_lock = NULL;
result = kc_encrypted_data_key_lock(encrypted, &key_lock, i);
if (result == 0) {
// Process key lock...
kc_key_lock_destruct(&key_lock);
}
}
}
Query Functions
kc_encrypted_data_equals()
int kc_encrypted_data_equals(
const kc_encrypted_data_t* lhs_ptr,
bool* out_is_equal,
const kc_encrypted_data_t* rhs_ptr
)
Tests equality of two encrypted data objects.
Parameters:
-
lhs_ptr
- First encrypted data to compare -
out_is_equal
- Pointer to equality result (output) -
rhs_ptr
- Second encrypted data to compare
Returns: Error code (0 = success)
kc_encrypted_data_is_null()
int kc_encrypted_data_is_null(
const kc_encrypted_data_t* encrypted_data_ptr,
bool* out_is_null
)
Checks whether the encrypted data is null.
Parameters:
-
encrypted_data_ptr
- Encrypted data to check -
out_is_null
- Pointer to null status (output)
Returns: Error code (0 = success)
Example: Working with Encrypted Data
void analyze_encrypted_data(kc_encrypted_data_t* encrypted) {
// Check if data is valid
bool is_null = false;
int result = kc_encrypted_data_is_null(encrypted, &is_null);
if (result != 0 || is_null) {
printf("Encrypted data is null or invalid\n");
return;
}
// Get encryption algorithm
tkc_cipher cipher_alg;
result = kc_encrypted_data_algorithm(encrypted, &cipher_alg);
if (result == 0) {
printf("Encryption algorithm: ");
switch (cipher_alg) {
case TKC_CIPHER_AES_256_GCM:
printf("AES-256-GCM\n");
break;
case TKC_CIPHER_AES_128_GCM:
printf("AES-128-GCM\n");
break;
case TKC_CIPHER_CHACHA20_POLY1305:
printf("ChaCha20-Poly1305\n");
break;
default:
printf("Algorithm %d\n", cipher_alg);
}
}
// Get IV
char* iv_hex = NULL;
unsigned int iv_size = 0;
result = kc_encrypted_data_iv(encrypted, &iv_hex, &iv_size);
if (result == 0) {
printf("IV (%u bytes): %.*s\n", iv_size/2, iv_size, iv_hex);
kc_common_delete_buffer(&iv_hex);
}
// Get ciphertext size
char* ciphertext = NULL;
unsigned int ciphertext_size = 0;
result = kc_encrypted_data_ciphertext(encrypted, &ciphertext, &ciphertext_size);
if (result == 0) {
printf("Ciphertext size: %u bytes\n", ciphertext_size);
kc_common_delete_buffer(&ciphertext);
}
// Check access control
unsigned int recipient_count = 0;
result = kc_encrypted_data_num_key_locks(encrypted, &recipient_count);
if (result == 0) {
printf("Number of authorized recipients: %u\n", recipient_count);
// List each recipient
for (unsigned int i = 0; i < recipient_count; i++) {
kc_key_lock_t* key_lock = NULL;
result = kc_encrypted_data_key_lock(encrypted, &key_lock, i);
if (result == 0) {
printf(" Recipient %u: ", i + 1);
// Get public key from key lock
char* pubkey = NULL;
unsigned int pubkey_size = 0;
if (kc_key_lock_public_key(key_lock, &pubkey, &pubkey_size) == 0) {
printf("Public key: %.16s...\n", pubkey);
kc_common_delete_buffer(&pubkey);
}
kc_key_lock_destruct(&key_lock);
}
}
}
}
Example: Encryption and Decryption Workflow
// Complete encryption/decryption example
void demonstrate_encryption_workflow(kc_gateway_t* gateway) {
kc_persona_t* alice = NULL;
kc_persona_t* bob = NULL;
kc_contact_t* bob_contact = NULL;
// Get personas and contacts (implementation omitted)
// ...
// Create data to encrypt
const char* secret_message = "Confidential: Project Phoenix launch date is March 15";
kc_serialized_data_t* plaintext = NULL;
int result = kc_serialized_data_construct_from_string(&plaintext,
secret_message, strlen(secret_message), TKC_DATA_TYPE_UTF8_STRING);
if (result != 0) {
printf("Failed to create serialized data\n");
return;
}
// Alice encrypts for Bob
kc_encrypted_data_t* encrypted = NULL;
const kc_contact_t* recipients[] = {bob_contact};
result = kc_gateway_encrypt(gateway, &encrypted, alice, plaintext, recipients, 1);
if (result == 0) {
printf("Message encrypted successfully\n");
// Analyze the encrypted data
analyze_encrypted_data(encrypted);
// Serialize for transmission
char* encrypted_json = NULL;
unsigned int json_size = 0;
result = kc_encrypted_data_serialize_to_string(encrypted, &encrypted_json,
&json_size,
TKC_SERIALIZATION_FORMAT_JSON);
if (result == 0) {
printf("\nEncrypted data as JSON (%u bytes):\n", json_size);
printf("%.200s...\n", encrypted_json); // Show first 200 chars
// Bob receives and reconstructs the encrypted data
kc_encrypted_data_t* received_encrypted = NULL;
result = kc_encrypted_data_construct_from_serialized_string(
&received_encrypted, encrypted_json, json_size,
TKC_SERIALIZATION_FORMAT_JSON);
if (result == 0) {
// Bob decrypts the message
kc_serialized_data_t* decrypted = NULL;
result = kc_gateway_decrypt(gateway, &decrypted, bob, received_encrypted);
if (result == 0) {
char* decrypted_text = NULL;
unsigned int text_size = 0;
kc_serialized_data_content(decrypted, &decrypted_text, &text_size);
printf("\nBob decrypted message: %.*s\n", text_size, decrypted_text);
kc_common_delete_buffer(&decrypted_text);
kc_serialized_data_destruct(&decrypted);
} else {
printf("Bob failed to decrypt message\n");
}
kc_encrypted_data_destruct(&received_encrypted);
}
kc_common_delete_buffer(&encrypted_json);
}
kc_encrypted_data_destruct(&encrypted);
} else {
printf("Encryption failed: %d\n", result);
}
// Cleanup
kc_serialized_data_destruct(&plaintext);
if (alice) kc_persona_destruct(&alice);
if (bob) kc_persona_destruct(&bob);
if (bob_contact) kc_contact_destruct(&bob_contact);
}
Memory Management
-
Use
kc_encrypted_data_destruct()
to free encrypted data objects -
Use
kc_key_lock_destruct()
for key lock objects -
Use
kc_serialized_data_destruct()
for serialized data objects -
Use
kc_common_delete_buffer()
for string outputs -
Always check return codes before using output parameters
Security Considerations
-
Encrypted data uses envelope encryption for efficiency with multiple recipients
-
Each recipient has their own key lock containing the encrypted symmetric key
-
The actual data is encrypted once with a symmetric cipher
-
Always verify recipient lists before encryption
-
Protect encrypted data during transmission and storage
See Also
-
Serialized Data - Data serialization
-
Gateway Cryptographic Operations - Encryption/decryption
-
Persona Functions - Encryption operations
-
C++ Encrypted Data Class - Object-oriented interface