Credential Class

Overview

The Credential class represents a W3C verifiable credential. It is signed (verifiable) data structured on the W3C verifiable credential data model, comprising credential data and a list of attestations (digital signatures).

Package: keychain.core.credential

from keychain.core.credential import Credential

Class Definition

class Credential(SerializableObject):
    """Represents a W3C verifiable credential."""

Constructor

def __init__(
    self,
    serialized_string: Optional[bytes] = None,
    serialization_format: SerializationFormat = SerializationFormat.PROTOBUF,
    serialized_data: Optional[SerializedData] = None,
    c_pointer: Optional[ctypes.c_void_p] = None,
) -> None

Initialize a Credential object. Credentials are typically created through Gateway.create_credential() or Persona.create_credential() methods.

Parameters:

  • serialized_string (bytes, optional) - Serialized credential bytes to deserialize

  • serialization_format (SerializationFormat) - Format of the serialized string (default: PROTOBUF)

  • serialized_data (SerializedData, optional) - SerializedData object to construct from

  • c_pointer (ctypes.c_void_p, optional) - Existing C pointer to wrap

Example:

# Create from serialized bytes
credential = Credential(serialized_string=credential_bytes)

# Create from existing C pointer (typically from library functions)
credential = Credential(c_pointer=existing_pointer)

Class Methods

from_copy(other)

@classmethod
def from_copy(cls, other: "Credential") -> "Credential"

Create a deep copy of an existing credential.

Parameters:

  • other (Credential) - The credential to copy

Returns: New Credential instance that is a deep copy

Example:

original_credential = gateway.create_credential(...)
copied_credential = Credential.from_copy(original_credential)

Properties

Basic Properties

id

@property
def id(self) -> str

Get the credential ID (W3C defined).

Returns: The credential ID string

type

@property
def type(self) -> str

Get the credential type (W3C defined).

Returns: The credential type string

issuer

@property
def issuer(self) -> str

Get the identifier of the issuer as a string.

Returns: The identifier of the issuer

subject

@property
def subject(self) -> str

Get an identifier for the subject.

Returns: An identifier of the subject

Timestamp Properties

timestamp

@property
def timestamp(self) -> int

Get the timestamp of the credential.

Returns: The timestamp in milliseconds since the Epoch

start_timestamp

@property
def start_timestamp(self) -> int

Get the timestamp for when the credential validity period starts.

Returns: The timestamp in milliseconds since the Epoch

end_timestamp

@property
def end_timestamp(self) -> int

Get the timestamp for when the credential validity period ends.

Returns: The timestamp in milliseconds since the Epoch

Metadata Properties

version

@property
def version(self) -> Version

Get the serialized data format version.

Returns: Version enumeration value

tags

@property
def tags(self) -> TagSet

Get the tags tag set containing metadata.

Returns: TagSet object with metadata tags

claims

@property
def claims(self) -> TagSet

Get the list of credential claims.

Returns: TagSet object containing the credential claims

base_variables

@property
def base_variables(self) -> TagSet

Get the original verifiable variable tag set (stack variables at time index 0).

Returns: TagSet object with the initial variable set

attestations

@property
def attestations(self) -> List[Attestation]

Get the attestations (digital signatures).

Returns: List of Attestation objects

Methods

stack_variables(time_index)

def stack_variables(self, time_index: int) -> TagSet

Get the current (merged) stack variables at the specified time index.

Parameters:

  • time_index (int) - Time index (0 = initial variables, 1 = after first attestation, etc.)

Returns: TagSet object with merged variables at the specified time

Example:

# Get initial variables
initial_vars = credential.stack_variables(0)

# Get variables after first attestation
updated_vars = credential.stack_variables(1)

copy()

def copy(self) -> "Credential"

Create a deep copy of this credential.

Returns: New Credential instance that is a deep copy

reattach_attachable_attestation(attestation)

def reattach_attachable_attestation(self, attestation: Attestation) -> None

Attach an attachable attestation to the credential.

Parameters:

  • attestation (Attestation) - The attestation to attach

Raises: KeychainError if the attestation cannot be attached

serialize()

def serialize(self) -> bytes

Serialize the credential to bytes.

Returns: Serialized credential in protobuf format

data_type()

def data_type(self) -> DataType

Get the data type.

Returns: DataType.CREDENTIAL

is_valid_at(timestamp)

def is_valid_at(self, timestamp: int) -> bool

Check if the credential is valid at a given timestamp.

Parameters:

  • timestamp (int) - Timestamp in milliseconds since epoch

Returns: True if the credential is valid at the given timestamp

is_currently_valid()

def is_currently_valid(self) -> bool

Check if the credential is currently valid.

Returns: True if the credential is valid at the current time

Example:

if credential.is_currently_valid():
    print("Credential is currently valid")
else:
    print("Credential has expired or not yet valid")

Comparison Methods

eq(other)

def __eq__(self, other: object) -> bool

Compare credentials for equality.

Parameters:

  • other (Credential) - The other credential to compare

Returns: True if credentials are equal

Example: Creating and Using Credentials

from keychain.gateway import Gateway
from keychain.core.tag_set import TagSet
from keychain.core.serialized_data import SerializedData
from keychain.constants import SecurityLevel, DataType
import time

# Initialize gateway
settings = Gateway.init("keychain.config")
gateway = Gateway(settings)

try:
    # Create issuer persona (HR department)
    hr_persona = gateway.create_persona(
        name="hr",
        subname="company.com",
        security_level=SecurityLevel.HIGH,
        auto_renew=True
    )

    # Wait for persona to mature
    if not hr_persona.is_mature():
        hr_persona.await_maturity()

    # Create employee claims
    claims = TagSet()
    claims.set_tag_value("", "employee_id",
                        SerializedData.from_string("12345", DataType.UTF8_STRING))
    claims.set_tag_value("", "name",
                        SerializedData.from_string("Alice Johnson", DataType.UTF8_STRING))
    claims.set_tag_value("", "department",
                        SerializedData.from_string("Engineering", DataType.UTF8_STRING))
    claims.set_tag_value("", "role",
                        SerializedData.from_string("Senior Developer", DataType.UTF8_STRING))
    claims.set_tag_value("", "clearance_level",
                        SerializedData.from_string("Standard", DataType.UTF8_STRING))

    # Set validity period (1 year)
    now = int(time.time() * 1000)
    one_year = now + (365 * 24 * 60 * 60 * 1000)

    # Create credential
    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
    )

    print("Employee credential created successfully")

    # Display credential information
    print(f"Credential ID: {credential.id}")
    print(f"Credential Type: {credential.type}")
    print(f"Issuer: {credential.issuer}")
    print(f"Subject: {credential.subject}")
    print(f"Created: {credential.timestamp}")
    print(f"Valid from: {credential.start_timestamp}")
    print(f"Valid until: {credential.end_timestamp}")
    print(f"Currently valid: {credential.is_currently_valid()}")

    # Access credential claims
    credential_claims = credential.claims
    employee_id = credential_claims.get_tag_value("", "employee_id")
    name = credential_claims.get_tag_value("", "name")
    department = credential_claims.get_tag_value("", "department")
    role = credential_claims.get_tag_value("", "role")

    print(f"\nClaims:")
    print(f"  Employee ID: {employee_id.content}")
    print(f"  Name: {name.content}")
    print(f"  Department: {department.content}")
    print(f"  Role: {role.content}")

    # Check attestations
    attestations = credential.attestations
    print(f"\nAttestations: {len(attestations)}")
    for i, attestation in enumerate(attestations):
        print(f"  Attestation {i+1}: Present")

finally:
    Gateway.close()

See Also