Persona Class
Overview
The Persona
class represents locally created and maintained cryptographic identities in the Keychain system. A persona manages two separate cryptographic keychains (one for encryption, one for signing) and provides methods for encrypting, decrypting, signing, and verifying data.
Package: keychain.identity.persona
from keychain.identity.persona import Persona
Class Definition
class Persona(KeychainObject):
"""Represents a locally created and maintained cryptographic identity."""
Constructor
def __init__(self, c_pointer) -> None
Initialize a Persona object with a C library pointer. Personas are typically created through Gateway.create_persona()
methods rather than direct construction.
Parameters:
-
c_pointer
- C library pointer to the persona object
Properties
Basic Properties
name
@property
def name(self) -> str
Get the primary name of the persona.
Returns: Primary name string
Configuration Properties
auto_renew
@property
def auto_renew(self) -> bool
Check if the persona automatically renews certificates.
Returns: True
if auto-renewal is enabled
encryption_algorithm
@property
def encryption_algorithm(self) -> EncryptionScheme
Get the encryption algorithm used by this persona.
Returns: EncryptionScheme
enumeration value
encryption_key_size
@property
def encryption_key_size(self) -> int
Get the encryption key size in bits.
Returns: Key size in bits
signature_algorithm
@property
def signature_algorithm(self) -> SignatureScheme
Get the signature algorithm used by this persona.
Returns: SignatureScheme
enumeration value
Status Methods
is_null()
def is_null(self) -> bool
Check if the persona is null (uninitialized).
Returns: True
if persona is null
is_mature()
def is_mature(self) -> bool
Check if the persona is mature (ready for cryptographic operations).
Returns: True
if persona is mature
Example:
if persona.is_mature():
print("Persona is ready for operations")
else:
print("Waiting for persona to mature...")
gateway.await_persona_maturity(persona)
Keychain Access Methods
keychain(keychain_type)
def keychain(self, keychain_type: KeychainType) -> Keychain
Get a specific keychain from the persona.
Parameters:
-
keychain_type
(KeychainType
) - Type of keychain (ENCRYPT or SIGN)
Returns: Keychain
object
Contact Management Methods
find_contact(name, subname)
def find_contact(self, name: str, subname: str) -> Contact
Find a contact by name and subname.
Parameters:
-
name
(str
) - Primary name of the contact -
subname
(str
) - Secondary name of the contact
Returns: Contact
object if found
Raises: KeychainNotFoundError
if contact not found
Example:
try:
bob_contact = persona.find_contact("bob", "company.com")
print(f"Found contact: {bob_contact.name}.{bob_contact.subname}")
except KeychainNotFoundError:
print("Contact not found")
get_contact(index)
def get_contact(self, index: int) -> Contact
Get a contact by index.
Parameters:
-
index
(int
) - Index of the contact in the contacts list
Returns: Contact
object
Raises: IndexError
if index is out of range
add_contact(name, subname, did)
def add_contact(self, name: str, subname: str, did: PersonaDID) -> Contact
Add a new contact to this persona.
Parameters:
-
name
(str
) - Primary name of the contact -
subname
(str
) - Secondary name of the contact -
did
(PersonaDID
) - Contact’s decentralized identifier
Returns: New Contact
object
Example:
# Add a new contact
new_contact = persona.add_contact(
name="charlie",
subname="partner.org",
did=charlie_did
)
Lifecycle Operations
Cryptographic Operations
encrypt(cleartext, recipients)
def encrypt(
self,
cleartext: Union[str, bytes],
recipients: List[Contact]
) -> EncryptedData
Encrypt data for specified recipients using envelope encryption.
Parameters:
-
cleartext
(str
orbytes
) - Data to encrypt -
recipients
(List[Contact]
) - List of recipient contacts
Returns: EncryptedData
object
Example:
# Encrypt a message for multiple recipients
recipients = [bob_contact, charlie_contact]
encrypted = persona.encrypt("Confidential message", recipients)
decrypt(ciphertext)
def decrypt(self, ciphertext: EncryptedData) -> Tuple[Union[str, bytes], CharEncoding]
Decrypt encrypted data using this persona’s private key.
Parameters:
-
ciphertext
(EncryptedData
) - Encrypted data to decrypt
Returns: Tuple of (decrypted data, character encoding)
Example:
# Decrypt received message
decrypted_data, encoding = persona.decrypt(encrypted_message)
print(f"Received: {decrypted_data}")
add_decrypt_access(encrypted_data, new_recipient)
def add_decrypt_access(
self,
encrypted_data: EncryptedData,
new_recipient: Contact
) -> EncryptedData
Grant decrypt access to an additional recipient.
Parameters:
-
encrypted_data
(EncryptedData
) - Existing encrypted data -
new_recipient
(Contact
) - New recipient to grant access to
Returns: Updated EncryptedData
object
sign(cleartext, is_approval, tags, variables)
def sign(
self,
cleartext: SerializedData,
is_approval: bool = False,
tags: Optional[TagSet] = None,
variables: Optional[TagSet] = None
) -> VerifiableData
Create verifiable (signed) data using this persona’s private key.
Parameters:
-
cleartext
(SerializedData
) - Data to sign -
is_approval
(bool
) - Whether this is an approval signature -
tags
(TagSet
, optional) - Metadata tags -
variables
(TagSet
, optional) - Variable metadata
Returns: VerifiableData
object
Example:
from keychain.core.serialized_data import SerializedData
from keychain.constants import DataType
# Create and sign a document
document = SerializedData.from_string(
"Contract agreement terms",
DataType.UTF8_STRING
)
signed_document = persona.sign(
cleartext=document,
is_approval=True
)
Credential Operations
create_credential(credential_id, credential_type, subject_id, start_timestamp, end_timestamp, claims, tags, variables)
def create_credential(
self,
credential_id: str,
credential_type: str,
subject_id: str,
start_timestamp: int,
end_timestamp: int,
claims: TagSet,
tags: Optional[TagSet] = None,
variables: Optional[TagSet] = None
) -> Credential
Create and sign a W3C verifiable credential.
Parameters:
-
credential_id
(str
) - Unique credential identifier -
credential_type
(str
) - Type of credential -
subject_id
(str
) - Subject’s identifier -
start_timestamp
(int
) - Validity start time (milliseconds since epoch) -
end_timestamp
(int
) - Validity end time (milliseconds since epoch) -
claims
(TagSet
) - Credential claims -
tags
(TagSet
, optional) - Metadata tags -
variables
(TagSet
, optional) - Variable metadata
Returns: Credential
object
Example:
import time
from keychain.core.tag_set import TagSet
# Create employee credential
claims = TagSet()
claims.set_tag_value("", "employee_id", "12345")
claims.set_tag_value("", "name", "Alice Smith")
claims.set_tag_value("", "department", "Engineering")
claims.set_tag_value("", "role", "Senior Developer")
now = int(time.time() * 1000)
one_year = now + (365 * 24 * 60 * 60 * 1000)
credential = hr_persona.create_credential(
credential_id="emp-alice-12345",
credential_type="EmployeeCredential",
subject_id="did:keychain:alice.company.com",
start_timestamp=now,
end_timestamp=one_year,
claims=claims
)
create_transaction(consensus_algorithm, quorum, tags, base_variables)
def create_transaction(
self,
consensus_algorithm: ConsensusAlgorithm,
quorum: TagSet,
tags: Optional[TagSet] = None,
base_variables: Optional[TagSet] = None
) -> Transaction
Create and sign a consensus transaction.
Parameters:
-
consensus_algorithm
(ConsensusAlgorithm
) - Consensus algorithm to use -
quorum
(TagSet
) - Participant definitions -
tags
(TagSet
, optional) - Metadata tags -
base_variables
(TagSet
, optional) - Initial variables
Returns: Transaction
object
add_signature_to_verifiable_data(verifiable_data, is_approval, tags, variables)
def add_signature_to_verifiable_data(
self,
verifiable_data: VerifiableData,
is_approval: bool = False,
tags: Optional[TagSet] = None,
variables: Optional[TagSet] = None
) -> VerifiableData
Add this persona’s signature to existing verifiable data.
Parameters:
-
verifiable_data
(VerifiableData
) - Existing verifiable data -
is_approval
(bool
) - Whether this is an approval signature -
tags
(TagSet
, optional) - Metadata tags -
variables
(TagSet
, optional) - Variable metadata
Returns: Updated VerifiableData
object
add_signature_to_credential(credential, is_approval, tags, variables)
def add_signature_to_credential(
self,
credential: Credential,
is_approval: bool = False,
tags: Optional[TagSet] = None,
variables: Optional[TagSet] = None
) -> Credential
Add this persona’s signature to an existing credential.
Parameters:
-
credential
(Credential
) - Existing credential -
is_approval
(bool
) - Whether this is an approval signature -
tags
(TagSet
, optional) - Metadata tags -
variables
(TagSet
, optional) - Variable metadata
Returns: Updated Credential
object
add_signature_to_transaction(transaction, is_approval, tags, variables)
def add_signature_to_transaction(
self,
transaction: Transaction,
is_approval: bool = False,
tags: Optional[TagSet] = None,
variables: Optional[TagSet] = None
) -> Transaction
Add this persona’s signature to an existing transaction.
Parameters:
-
transaction
(Transaction
) - Existing transaction -
is_approval
(bool
) - Whether this is an approval signature -
tags
(TagSet
, optional) - Metadata tags -
variables
(TagSet
, optional) - Variable metadata
Returns: Updated Transaction
object
Verification Operations
verify_verifiable_data(verifiable_data)
def verify_verifiable_data(self, verifiable_data: VerifiableData) -> VerificationResult
Verify verifiable data signatures using this persona’s contact information.
Parameters:
-
verifiable_data
(VerifiableData
) - Data to verify
Returns: VerificationResult
object
verify_credential(credential)
def verify_credential(self, credential: Credential) -> VerificationResult
Verify credential signatures using this persona’s contact information.
Parameters:
-
credential
(Credential
) - Credential to verify
Returns: VerificationResult
object
verify_transaction(transaction)
def verify_transaction(self, transaction: Transaction) -> VerificationResult
Verify transaction signatures using this persona’s contact information.
Parameters:
-
transaction
(Transaction
) - Transaction to verify
Returns: VerificationResult
object
verify(data)
def verify(self, data: Union[VerifiableData, Credential, Transaction]) -> VerificationResult
Generic verification method for any verifiable data type.
Parameters:
-
data
(VerifiableData
,Credential
, orTransaction
) - Data to verify
Returns: VerificationResult
object
Example:
# Verify different types of signed data
vdata_result = persona.verify(signed_document)
cred_result = persona.verify(employee_credential)
tx_result = persona.verify(consensus_transaction)
for result in [vdata_result, cred_result, tx_result]:
if result.is_verified():
signer = result.signer()
print(f"Valid signature from {signer.name}.{signer.subname}")
else:
print("Invalid signature")
Comparison Methods
eq(other)
def __eq__(self, other: object) -> bool
Test equality with another persona.
Parameters:
-
other
(Persona
) - Persona to compare with
Returns: True
if personas are equal
Example:
# Check if two persona references are the same
if persona1 == persona2:
print("Same persona")
else:
print("Different personas")
Example: Complete Persona Workflow
from keychain.gateway import Gateway
from keychain.constants import SecurityLevel, DataType, KeychainType
from keychain.core.serialized_data import SerializedData
from keychain.core.tag_set import TagSet
from keychain.exceptions import KeychainNotFoundError
import time
# Initialize gateway
settings = Gateway.init("keychain.config")
gateway = Gateway(settings)
try:
# Create personas
alice = gateway.create_persona(
name="alice",
subname="company.com",
security_level=SecurityLevel.HIGH,
auto_renew=True
)
bob = gateway.create_persona(
name="bob",
subname="company.com",
security_level=SecurityLevel.HIGH,
auto_renew=True
)
# Wait for personas to mature
if not alice.is_mature():
print("Waiting for Alice's persona to mature...")
alice.await_maturity()
if not bob.is_mature():
print("Waiting for Bob's persona to mature...")
bob.await_maturity()
print(f"Alice's persona: {alice.name}.{alice.subname}")
print(f" Encryption: {alice.encryption_algorithm} ({alice.encryption_key_size} bits)")
print(f" Signature: {alice.signature_algorithm} ({alice.signature_key_size} bits)")
print(f" Cipher: {alice.cipher}")
print(f" Auto-renew: {alice.auto_renew}")
# Add Bob as a contact for Alice
bob_contact = alice.add_contact(
name="bob",
subname="company.com",
did=bob.did
)
# Add Alice as a contact for Bob
alice_contact = bob.add_contact(
name="alice",
subname="company.com",
did=alice.did
)
print(f"Alice has {len(alice.contacts)} contacts")
print(f"Bob has {len(bob.contacts)} contacts")
# Alice encrypts a message for Bob
message = "Confidential project status update"
encrypted = alice.encrypt(message, [bob_contact])
print("Message encrypted by Alice")
# Bob decrypts the message
decrypted_data, encoding = bob.decrypt(encrypted)
print(f"Bob decrypted: {decrypted_data}")
# Alice signs a document
document_content = "Important contract agreement"
document = SerializedData.from_string(document_content, DataType.UTF8_STRING)
signed_document = alice.sign(
cleartext=document,
is_approval=True
)
print("Document signed by Alice")
# Bob verifies Alice's signature
verification_result = bob.verify(signed_document)
if verification_result.is_verified():
signer = verification_result.signer()
print(f"✓ Signature verified! Signed by: {signer.name}.{signer.subname}")
else:
print("✗ Signature verification failed")
# Alice creates a credential for Bob
claims = TagSet()
claims.set_tag_value("", "employee_id", "54321")
claims.set_tag_value("", "name", "Bob Johnson")
claims.set_tag_value("", "department", "Marketing")
claims.set_tag_value("", "clearance_level", "Standard")
now = int(time.time() * 1000)
six_months = now + (180 * 24 * 60 * 60 * 1000)
credential = alice.create_credential(
credential_id="emp-bob-54321",
credential_type="EmployeeCredential",
subject_id=str(bob.did),
start_timestamp=now,
end_timestamp=six_months,
claims=claims
)
print("Employee credential created for Bob")
# Bob verifies the credential
cred_verification = bob.verify(credential)
if cred_verification.is_verified():
print("✓ Credential verified")
else:
print("✗ Credential verification failed")
# Demonstrate contact management
print("\nContact Management:")
print(f"Alice's contacts:")
for i, contact in enumerate(alice.contacts):
print(f" {i}: {contact.name}.{contact.subname}")
# Find specific contact
try:
found_contact = alice.find_contact("bob", "company.com")
print(f"Found Bob's contact: {found_contact.name}.{found_contact.subname}")
except KeychainNotFoundError:
print("Bob's contact not found")
# Access keychains
print(f"\nKeychain Information:")
enc_keychain = alice.encryption_keychain()
sig_keychain = alice.signature_keychain()
print(f"Alice has encryption and signature keychains")
# Certificate renewal
print(f"\nCertificate Management:")
print(f"Alice auto-renew: {alice.auto_renew}")
# Manually renew if needed
alice.renew_certificate()
print("Certificate renewal initiated for Alice")
finally:
# Cleanup
Gateway.close()
Error Handling
Persona methods can raise various exceptions:
-
KeychainNotFoundError
- Contact or resource not found -
KeychainSecurityError
- Cryptographic operation failures -
KeychainValidationError
- Input validation errors -
KeychainMemoryError
- Memory allocation failures
Always wrap persona operations in appropriate try-catch blocks.
See Also
-
Gateway Class - Main API interface
-
Contact Class - External identities
-
PersonaDID Class - Persona identifiers
-
VerificationResult Class - Verification results
-
Exception Classes - Error handling