Gateway Cryptographic Operations

#include <keychain/keychain_headers.h>

Overview

Gateway cryptographic functions provide high-level encryption, decryption, signing, and verification operations through the Keychain Core C API. These functions work with personas and contacts to perform secure cryptographic operations.

Encryption Operations

kc_gateway_encrypt()

int kc_gateway_encrypt(
    kc_gateway_t* gateway_ptr,
    kc_encrypted_data_t** out_encrypted_data,
    const kc_persona_t* persona,
    const kc_serialized_data_t* cleartext,
    const kc_contact_t** contact_array,
    const unsigned int contact_array_size
)

Encrypts serialized data using envelope (hybrid) encryption with the persona’s current public key and recipients' public keys.

Parameters:

  • gateway_ptr - Gateway instance

  • out_encrypted_data - Pointer to encrypted data object (output, caller must free)

  • persona - Encrypting persona

  • cleartext - Serialized data to encrypt

  • contact_array - Array of recipient contacts

  • contact_array_size - Number of recipients

Returns: Error code (0 = success)

Example:

kc_persona_t* alice = NULL;
kc_contact_t* bob = NULL;
kc_serialized_data_t* plaintext = NULL;
kc_encrypted_data_t* encrypted = NULL;

// Get persona and contact (assume they exist)
// Create serialized data from string
int result = kc_serialized_data_construct_from_string(&plaintext,
    "Confidential message", 20, TKC_DATA_TYPE_UTF8_STRING);

if (result == 0) {
    const kc_contact_t* recipients[] = {bob};
    result = kc_gateway_encrypt(gateway, &encrypted, alice, plaintext,
                               recipients, 1);
    if (result == 0) {
        printf("Data encrypted successfully\n");
        kc_encrypted_data_destruct(&encrypted);
    }
    kc_serialized_data_destruct(&plaintext);
}

kc_gateway_decrypt()

int kc_gateway_decrypt(
    kc_gateway_t* gateway_ptr,
    kc_serialized_data_t** out_cleartext,
    const kc_persona_t* persona,
    const kc_encrypted_data_t* ciphertext
)

Decrypts encrypted data using the persona’s private key that matches a public key in the ciphertext access list.

Parameters:

  • gateway_ptr - Gateway instance

  • out_cleartext - Pointer to decrypted data object (output, caller must free)

  • persona - Decrypting persona

  • ciphertext - Encrypted data to decrypt

Returns: Error code (0 = success)

Example:

kc_serialized_data_t* decrypted = NULL;
int result = kc_gateway_decrypt(gateway, &decrypted, alice, encrypted);
if (result == 0) {
    char* content = NULL;
    unsigned int content_size = 0;

    kc_serialized_data_content(decrypted, &content, &content_size);
    printf("Decrypted: %.*s\n", content_size, content);

    kc_common_delete_buffer(&content);
    kc_serialized_data_destruct(&decrypted);
}

Digital Signature Operations

kc_gateway_sign()

int kc_gateway_sign(
    kc_gateway_t* gateway_ptr,
    kc_verifiable_data_t** out_signed_data,
    const kc_persona_t* persona,
    const kc_serialized_data_t* cleartext,
    const bool is_approval,
    const kc_tag_set_t* tags,
    const kc_tag_set_t* vars
)

Creates verifiable (signed) data from serialized data using the persona’s current private key.

Parameters:

  • gateway_ptr - Gateway instance

  • out_signed_data - Pointer to signed data object (output, caller must free)

  • persona - Signing persona

  • cleartext - Serialized data to sign

  • is_approval - Whether this is an approval signature

  • tags - Metadata tags (can be NULL)

  • vars - Variable metadata (can be NULL)

Returns: Error code (0 = success)

Example:

kc_verifiable_data_t* signed_data = NULL;
kc_serialized_data_t* document = NULL;

// Create document to sign
int result = kc_serialized_data_construct_from_string(&document,
    "Legal contract content", 22, TKC_DATA_TYPE_UTF8_STRING);

if (result == 0) {
    result = kc_gateway_sign(gateway, &signed_data, alice, document,
                            false, NULL, NULL);
    if (result == 0) {
        printf("Document signed successfully\n");
        kc_verifiable_data_destruct(&signed_data);
    }
    kc_serialized_data_destruct(&document);
}

kc_gateway_verify()

int kc_gateway_verify(
    kc_gateway_t* gateway_ptr,
    kc_verification_result_t** out_result,
    const kc_persona_t* persona,
    const kc_verifiable_data_t* signed_data
)

Verifies a signed data object using contact information and PKI data.

Parameters:

  • gateway_ptr - Gateway instance

  • out_result - Pointer to verification result (output, caller must free)

  • persona - Verifying persona

  • signed_data - Signed data to verify

Returns: Error code (0 = success)

Example:

kc_verification_result_t* verify_result = NULL;
int result = kc_gateway_verify(gateway, &verify_result, bob, signed_data);
if (result == 0) {
    bool is_valid = false;
    kc_verification_result_is_valid(verify_result, &is_valid);
    printf("Signature verification: %s\n", is_valid ? "VALID" : "INVALID");
    kc_verification_result_destruct(&verify_result);
}

Hash Operations

kc_gateway_hash()

int kc_gateway_hash(
    char** out_hash_hex,
    unsigned int* out_hash_size,
    const char* input_data,
    const unsigned int input_data_size
)

Computes a SHA-256 hash of input data.

Parameters:

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

  • out_hash_size - Pointer to hash string length (output)

  • input_data - Data to hash

  • input_data_size - Length of input data

Returns: Error code (0 = success)

Example:

const char* document = "Important document content";
char* hash_result = NULL;
unsigned int hash_size = 0;

int result = kc_gateway_hash(&hash_result, &hash_size,
                            document, strlen(document));
if (result == 0) {
    printf("Document hash: %s (size: %u)\n", hash_result, hash_size);
    kc_common_delete_buffer(&hash_result);
} else {
    printf("Hash computation failed: %d\n", result);
}

Raw Signature Operations

kc_gateway_generate_signature_by_private_key()

int kc_gateway_generate_signature_by_private_key(
    char** out_signature_hex,
    unsigned int* out_signature_size,
    const char* cleartext,
    const unsigned int cleartext_size,
    const char* private_key_hex,
    const unsigned int private_key_size,
    tkc_signature_scheme algorithm
)

Generates a signature using an external private key.

Parameters:

  • out_signature_hex - Pointer to signature string pointer (output)

  • out_signature_size - Pointer to signature string length (output)

  • cleartext - Data to sign

  • cleartext_size - Length of cleartext

  • private_key_hex - Private key in hex format

  • private_key_size - Length of private key string

  • algorithm - Signature algorithm to use

Returns: Error code (0 = success)

kc_gateway_verify_raw_data()

int kc_gateway_verify_raw_data(
    bool* out_verified,
    const char* cleartext,
    const unsigned int cleartext_size,
    const char* public_key_hex,
    const unsigned int public_key_size,
    const char* signature_hex,
    const unsigned int signature_size,
    tkc_signature_scheme algorithm
)

Verifies a signature against a public key without persona/contact context.

Parameters:

  • out_verified - Pointer to verification flag (output, true = valid, false = invalid)

  • cleartext - Original signed data

  • cleartext_size - Length of cleartext

  • public_key_hex - Public key in hex format

  • public_key_size - Length of public key string

  • signature_hex - Signature in hex format

  • signature_size - Length of signature string

  • algorithm - Signature algorithm used

Returns: Error code (0 = success)

Complete Example: Secure Communication

// Demonstrates encryption and signing workflow
void demonstrate_secure_communication(kc_gateway_t* gateway) {
    kc_persona_t* alice = NULL;
    kc_persona_t* bob = NULL;
    kc_contact_t* bob_contact = NULL;
    kc_serialized_data_t* message = NULL;
    kc_encrypted_data_t* encrypted = NULL;
    kc_verifiable_data_t* signed_encrypted = NULL;

    // Get personas and contacts (assume they exist)
    // ... persona and contact retrieval code ...

    // Create message
    const char* msg = "Confidential project update";
    int result = kc_serialized_data_construct_from_string(&message,
        msg, strlen(msg), TKC_DATA_TYPE_UTF8_STRING);

    if (result != 0) goto cleanup;

    // Alice encrypts message for Bob
    const kc_contact_t* recipients[] = {bob_contact};
    result = kc_gateway_encrypt(gateway, &encrypted, alice, message,
                               recipients, 1);
    if (result != 0) {
        printf("Encryption failed: %d\n", result);
        goto cleanup;
    }

    printf("Message encrypted for Bob\n");

    // Convert encrypted data to serialized data for signing
    kc_serialized_data_t* encrypted_serialized = NULL;
    result = kc_encrypted_data_serialize(encrypted, &encrypted_serialized);
    if (result != 0) goto cleanup;

    // Alice signs the encrypted message
    result = kc_gateway_sign(gateway, &signed_encrypted, alice,
                            encrypted_serialized, false, NULL, NULL);
    if (result != 0) {
        printf("Signing failed: %d\n", result);
        kc_serialized_data_destruct(&encrypted_serialized);
        goto cleanup;
    }

    printf("Encrypted message signed by Alice\n");
    kc_serialized_data_destruct(&encrypted_serialized);

    // Bob verifies Alice's signature
    kc_verification_result_t* verify_result = NULL;
    result = kc_gateway_verify(gateway, &verify_result, bob, signed_encrypted);
    if (result == 0) {
        bool is_valid = false;
        kc_verification_result_is_valid(verify_result, &is_valid);
        printf("Signature verification: %s\n", is_valid ? "VALID" : "INVALID");

        if (is_valid) {
            // Extract encrypted data from verified message and decrypt
            // ... additional decryption code would go here ...
            printf("Message verified and ready for decryption\n");
        }

        kc_verification_result_destruct(&verify_result);
    }

cleanup:
    if (message) kc_serialized_data_destruct(&message);
    if (encrypted) kc_encrypted_data_destruct(&encrypted);
    if (signed_encrypted) kc_verifiable_data_destruct(&signed_encrypted);
    if (alice) kc_persona_destruct(&alice);
    if (bob) kc_persona_destruct(&bob);
    if (bob_contact) kc_contact_destruct(&bob_contact);
}

Memory Management

All cryptographic objects must be properly freed:

  • Use specific destruct functions: kc_encrypted_data_destruct(), kc_verifiable_data_destruct(), etc.

  • Use kc_common_delete_buffer() for string outputs

  • Always check return codes before using output parameters

Security Guidelines

  • Always verify signatures before trusting data

  • Use appropriate contact lists for encryption access control

  • Protect private keys with proper access controls

  • Validate all input parameters before cryptographic operations

See Also