Class persona
Description
persona
represents a cryptographic identity, the private keys of which are created and managed within the same local database used by the gateway
object that created the persona
. The cryptographic identity comprises of an encryption keychain and a signature keychain. The persona
class functions primarily as a handle for persona
objects that are established by the gateway
object.
Multiple personas
may be managed by the same gateway
object, and each persona
maps to a different set of contacts
. As such, persona
objects provide context for gateway
cryptographic operations such as encryption and signing.
The distinction between a persona
and a contact
is that a gateway
creates a persona
locally whereas a contact
is created by another device.
In fact, |
Since: v2.0
(significantly enhanced in v3.0
)
Property Methods
auto_renew()
bool auto_renew() const
Gets whether the persona is configured to renew key certificates automatically.
Returns: true
if the persona is configured to renew certificates automatically, false
otherwise
encryption_algorithm()
kc::encryption_scheme encryption_algorithm() const
Gets the asymmetric encryption algorithm being used to encrypt data with this persona.
Returns: The encryption algorithm scheme (e.g., ecies_ecp_secp256r1
, rsa_oaep_sha256
)
encryption_key_size()
size_t encryption_key_size() const
Gets the asymmetric encryption key size in bits.
Returns: The encryption key size in bits (e.g., 256, 2048, 4096)
signature_algorithm()
kc::signature_scheme signature_algorithm() const
Gets the asymmetric signature algorithm being used to sign data with this persona.
Returns: The signature algorithm scheme (e.g., ecdsa_ecp_secp256r1
, rsa_pss_sha256
)
Contact Management
contacts()
std::vector<kc::contact> contacts() const
Gets the list of contacts associated with this persona.
Returns: Vector of contact objects belonging to this persona
find_contact()
kc::contact find_contact(std::string name, std::string subname) const
Finds a contact with the given name and subname.
Parameters:
-
name
- The contact’s name -
subname
- The contact’s subname
Returns: The contact with matching name and subname (exact match)
Throws: Exception if no contact is found with the specified name and subname
add_contact()
kc::contact add_contact(
const std::string& name,
const std::string& sub_name,
const kc::persona_did& did
)
Adds a new contact to this persona by its DID. This method inserts a new contact into the database as a contact owned by this persona, then resolves the public key information from the DID using a method that is dependent on the DID method field (for example, looking up the PKI if necessary).
Parameters:
-
name
- The contact name -
sub_name
- The contact subname -
did
- The contact’s DID for key resolution
Returns: The newly created contact object
Lifecycle Management
refresh()
void refresh()
Refreshes this persona’s data from the database. This method looks up and updates the persona object with current persona state data from the database.
Note: Since persona objects are snapshots, always refresh before performing operations to ensure you have the latest state.
renew_certificate()
void renew_certificate()
Manually initiates key rollover for this persona. Note that key rollover proceeds asynchronously, and the rollover process usually completes at a time well after the return of this method.
Cryptographic Operations
encrypt()
kc::encrypted_data encrypt(
const kc::serialized_data& clear_text,
const std::vector<kc::contact>& recipients
)
Encrypts serialized data with the persona’s current public key and the recipients' current public keys. This method encrypts the cleartext with a symmetric cipher using envelope encryption.
Parameters:
-
clear_text
- The serialized data to encrypt -
recipients
- List of contacts who will be given decrypt access to the encrypted data
Returns: Encrypted data object, envelope encrypted so that only the persona and the recipients can decrypt
Note: For self-encryption (encrypt for storage), pass an empty recipients vector
add_decrypt_access()
kc::key_lock add_decrypt_access(
kc::encrypted_data& in_out_ciphertext,
const kc::contact& new_recipient,
bool attachable = true
)
Adds decrypt access to encrypted data with the specified new recipient’s current public keys. Upon successful execution, the encrypted data will be modified to include an additional key lock for the new recipient.
Parameters:
-
in_out_ciphertext
- The original encrypted data (modified in place) -
new_recipient
- The contact to which access will be granted -
attachable
- Whether the resulting key lock should contain additional metadata for reattachment (default:true
)
Returns: The key lock that was attached to the encrypted data
decrypt()
kc::serialized_data decrypt(const kc::encrypted_data& ciphertext)
Decrypts encrypted data with the persona’s private key that matches a public key in the access list of the ciphertext.
Parameters:
-
ciphertext
- The encrypted data to decrypt
Returns: The decrypted data as serialized data
Throws: Exception if the persona doesn’t have access to decrypt the data
generate_signature()
std::string generate_signature(const std::string& cleartext)
Generates a signature for plain text using the persona’s current private key.
Parameters:
-
cleartext
- The plain text to sign
Returns: The signature in hex-encoded DER format
sign()
kc::verifiable_data sign(
const kc::serialized_data& cleartext,
const bool approval = true,
const kc::tag_set& tags = kc::tag_set(),
const kc::tag_set& variables = kc::tag_set()
)
Signs (creates verifiable data from) serialized data using the persona’s current private key.
Parameters:
-
cleartext
- The serialized data to be signed -
approval
- Whether the signature represents approval (true
) or rejection (false
) (default:true
) -
tags
- Tags to add to the resulting attestation (default: empty) -
variables
- Variables to add to the resulting attestation (default: empty)
Returns: The signed, verifiable data signed with the persona’s most recently created signature key
create_verifiable_data()
kc::verifiable_data create_verifiable_data(
const kc::serialized_data& cleartext,
const bool is_approval = true,
const kc::tag_set& tags = kc::tag_set(),
const kc::tag_set& variables = kc::tag_set()
)
Alias for sign()
. Creates verifiable data from serialized data using the persona’s current private key.
Parameters:
-
cleartext
- The serialized data to be signed -
is_approval
- Whether the signature represents approval (true
) or rejection (false
) (default:true
) -
tags
- Tags to add to the resulting attestation (default: empty) -
variables
- Variables to add to the resulting attestation (default: empty)
Returns: The signed, verifiable data
verify()
std::vector<kc::verification_result> verify(const tkc::verifiable& signed_msg)
Verifies the signatures on a verifiable object using the persona’s current private key.
Parameters:
-
signed_msg
- The verifiable object (verifiable data, credential, or transaction)
Returns: A vector of verification results, one for each signature in the verifiable object
Advanced Operations
create_credential()
kc::credential create_credential(
const std::string& credential_id,
const std::string& type,
const std::string& subject,
kc::timestamp_t start_timestamp,
kc::timestamp_t end_timestamp,
const kc::tag_set& claims,
const kc::tag_set& tags = kc::tag_set(),
const kc::tag_set& variables = kc::tag_set()
)
Creates and signs a credential using the persona’s current private key. This creates a W3C-compatible verifiable credential.
Parameters:
-
credential_id
- The credential ID (as suggested by W3C) -
type
- The credential type (as suggested by W3C) -
subject
- An identifier for the credential subject (for example, a DID) -
start_timestamp
- The starting validity time -
end_timestamp
- The validity end time -
claims
- A set of claims for the subject -
tags
- Tags for the credential (default: empty) -
variables
- Variables for the credential (default: empty)
Returns: The signed credential
create_transaction()
kc::transaction create_transaction(
kc::consensus_algorithm consensus,
const kc::quorum& quorum,
const kc::tag_set& tags,
const kc::tag_set& variables
)
Creates and signs a ledger transaction using the persona’s current private key. Keychain ledger transactions are exchanged as part of the application-level consensus. Keychain ledger transactions and public-key infrastructure transactions (such as blockchain transactions) are distinct concepts.
Parameters:
-
consensus
- The consensus algorithm to use -
quorum
- The set of participants required to participate in the consensus -
tags
- Tags for the transaction -
variables
- Variables for the transaction
Returns: The signed transaction
add_signature()
kc::attestation add_signature(
tkc::verifiable& in_out_signed_verifiable,
bool is_approval = true,
const kc::tag_set& tags = kc::tag_set(),
const kc::tag_set& vars = tkc::tag_set()
)
Adds a signature to a verifiable object (verifiable data, credential, or transaction) using the persona’s current private key.
Parameters:
-
in_out_signed_verifiable
- The verifiable object (modified in place) -
is_approval
- Whether the signature represents approval (true
) or rejection (false
) (default:true
) -
tags
- Tags to add to the resulting attestation (default: empty) -
vars
- Variables to add to the resulting attestation (default: empty)
Returns: The resulting attestation that was also added to the input verifiable data
Example Usage
Basic Persona Operations
#include <keychain/keychain_headers.hpp>
int main() {
try {
// Assuming gateway is already initialized and persona exists
kc::persona alice = gateway.find_persona("alice", "personal");
// Check persona properties
std::cout << "Auto-renew: " << alice.auto_renew() << std::endl;
std::cout << "Encryption algorithm: " << (int)alice.encryption_algorithm() << std::endl;
std::cout << "Encryption key size: " << alice.encryption_key_size() << " bits" << std::endl;
std::cout << "Signature algorithm: " << (int)alice.signature_algorithm() << std::endl;
std::cout << "Signature key size: " << alice.signature_key_size() << " bits" << std::endl;
std::cout << "Cipher: " << (int)alice.cipher() << std::endl;
return 0;
} catch (const kc::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
}
Self-Encryption (Secure Storage)
// Create data to encrypt
std::string secret = "My confidential information";
kc::serialized_data data(secret);
// Encrypt for self (empty recipients list)
std::vector<kc::contact> recipients; // empty = self-encryption
kc::encrypted_data encrypted = alice.encrypt(data, recipients);
// Store encrypted data safely...
// Later: decrypt the data
kc::serialized_data decrypted = alice.decrypt(encrypted);
std::string recovered = decrypted.utf8_string();
std::cout << "Original: " << secret << std::endl;
std::cout << "Recovered: " << recovered << std::endl;
// Output: Original and recovered should match
Digital Signing and Verification
// Create document to sign
std::string document = "Important contract v1.2";
kc::serialized_data doc_data(document);
// Sign with approval
kc::verifiable_data signed_doc = alice.sign(doc_data, true);
// Add metadata tags
kc::tag_set tags;
tags.set_tag("document", "type", kc::serialized_data("contract"));
tags.set_tag("version", "number", kc::serialized_data("1.2"));
tags.set_tag("legal", "binding", kc::serialized_data(true));
kc::verifiable_data signed_with_metadata = alice.sign(doc_data, true, tags);
// Verify signature
std::vector<kc::verification_result> results = alice.verify(signed_doc);
for (const auto& result : results) {
if (result.is_verified()) {
std::cout << "✓ Valid signature" << std::endl;
std::cout << "Signer DID: " << result.signer_did().serialize() << std::endl;
} else {
std::cout << "✗ Invalid signature" << std::endl;
}
}
Multi-Recipient Encryption
// Add contacts to persona
kc::persona_did bob_did("did:keychain:bob:work");
kc::persona_did charlie_did("did:keychain:charlie:team");
kc::contact bob = alice.add_contact("bob", "work", bob_did);
kc::contact charlie = alice.add_contact("charlie", "team", charlie_did);
// Encrypt for multiple recipients
std::string message = "Team meeting at 3pm";
kc::serialized_data msg_data(message);
std::vector<kc::contact> team = {bob, charlie};
kc::encrypted_data team_encrypted = alice.encrypt(msg_data, team);
// Now alice, bob, and charlie can all decrypt this message
// (assuming they have access to their respective personas)
Contact Management
// List all contacts
std::vector<kc::contact> all_contacts = alice.contacts();
std::cout << "Alice has " << all_contacts.size() << " contacts:" << std::endl;
for (const auto& contact : all_contacts) {
std::cout << "- " << contact.name() << "." << contact.sub_name() << std::endl;
}
// Find specific contact
try {
kc::contact bob = alice.find_contact("bob", "work");
std::cout << "Found Bob: " << bob.did().serialize() << std::endl;
} catch (const kc::exception& e) {
std::cout << "Bob not found: " << e.what() << std::endl;
}
Persona Lifecycle Management
// Refresh persona state from database
alice.refresh();
// Check if automatic renewal is enabled
if (!alice.auto_renew()) {
std::cout << "Enabling auto-renewal for alice" << std::endl;
alice.set_property_auto_renew(true);
}
// Manually trigger certificate renewal
std::cout << "Initiating certificate renewal..." << std::endl;
alice.renew_certificate();
// Wait for persona to become mature (for new personas)
std::cout << "Waiting for persona maturity..." << std::endl;
alice.await_maturity();
std::cout << "Persona is now mature and ready for operations" << std::endl;
Creating Verifiable Credentials
// Create identity verification credential
kc::tag_set identity_claims;
identity_claims.set_tag("identity", "verified", kc::serialized_data(true));
identity_claims.set_tag("identity", "method", kc::serialized_data("government_id"));
identity_claims.set_tag("personal", "name", kc::serialized_data("Alice Smith"));
identity_claims.set_tag("personal", "date_of_birth", kc::serialized_data("1990-01-15"));
kc::credential identity_vc = alice.create_credential(
"https://issuer.example/credentials/identity/12345",
"IdentityCredential",
alice.did().serialize(), // subject is alice herself
time(nullptr), // valid from now
time(nullptr) + (5 * 365 * 24 * 60 * 60), // valid for 5 years
identity_claims
);
// Verify the credential
std::vector<kc::verification_result> vc_verification = alice.verify(identity_vc);
if (!vc_verification.empty() && vc_verification[0].is_verified()) {
std::cout << "✓ Credential is valid and self-signed" << std::endl;
}
Thread Safety and Best Practices
// Personas are snapshots - always refresh before critical operations
class SafePersonaOperations {
private:
kc::gateway& gateway_;
std::string persona_name_;
std::string persona_subname_;
public:
SafePersonaOperations(kc::gateway& gw, const std::string& name, const std::string& subname)
: gateway_(gw), persona_name_(name), persona_subname_(subname) {}
kc::encrypted_data safe_encrypt(const kc::serialized_data& data,
const std::vector<kc::contact>& recipients) {
// Always get fresh persona state
kc::persona current = gateway_.find_persona(persona_name_, persona_subname_);
current.refresh(); // Ensure latest state
return current.encrypt(data, recipients);
}
kc::verifiable_data safe_sign(const kc::serialized_data& data) {
// Always get fresh persona state
kc::persona current = gateway_.find_persona(persona_name_, persona_subname_);
current.refresh(); // Ensure latest state
return current.sign(data);
}
};
Methods inherited from class facade |
---|
|