VerificationResult Class

Overview

The VerificationResult class contains the results of cryptographic signature verification operations. It provides information about whether signatures are valid, who signed the data, and additional verification details.

Package: keychain.gateway

from keychain.gateway import VerificationResult

Class Definition

class VerificationResult(KeychainObject):
    """Contains the results of signature verification operations."""

Constructor

def __init__(self, c_pointer) -> None

Initialize a VerificationResult object with a C library pointer. VerificationResult objects are typically created through verification methods in Gateway, Persona, or Contact classes rather than direct construction.

Parameters:

  • c_pointer - C library pointer to the verification result object

Status Methods

is_verified()

def is_verified(self) -> bool

Check if the signature verification was successful.

Returns: True if the signature is valid, False otherwise

Example:

# Verify signed data
result = gateway.verify(persona, signed_data)

if result.is_verified():
    print("✓ Signature is valid")
else:
    print("✗ Signature verification failed")

signer_is_known()

def signer_is_known(self) -> bool

Check if the signer is known (exists in the verifying persona’s contact list).

Returns: True if the signer is a known contact, False otherwise

Example:

result = gateway.verify(persona, signed_data)

if result.is_verified():
    if result.signer_is_known():
        print("Signature from known contact")
    else:
        print("Signature from unknown signer")

Signer Information

signer()

def signer(self) -> Optional[Contact]

Get the contact object representing the signer (if known).

Returns: Contact object if signer is known, None otherwise

Example:

result = gateway.verify(persona, signed_data)

if result.is_verified() and result.signer_is_known():
    signer_contact = result.signer()
    if signer_contact:
        print(f"Signed by: {signer_contact.name}.{signer_contact.subname}")
        print(f"Signer DID: {signer_contact.did}")

Attestation Information

attestation

@property
def attestation(self) -> Optional[Attestation]

Get the attestation object from the verification result.

Returns: Attestation object if available, None otherwise

Example:

result = gateway.verify(persona, signed_data)

if result.is_verified():
    attestation = result.attestation
    if attestation:
        print("Attestation information available")
        # Access attestation details

Complete Verification Examples

Basic Verification Workflow

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

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

try:
    # Get or create personas
    alice = gateway.find_persona("alice", "company.com")
    bob = gateway.find_persona("bob", "company.com")

    # Alice adds Bob as a contact
    bob_contact = alice.add_contact("bob", "company.com", bob.did)

    # Bob adds Alice as a contact
    alice_contact = bob.add_contact("alice", "company.com", alice.did)

    # Alice signs a document
    document = SerializedData.from_string(
        "Important contract terms",
        DataType.UTF8_STRING
    )

    signed_document = alice.sign(
        cleartext=document,
        is_approval=True
    )

    print("Document signed by Alice")

    # Bob verifies Alice's signature
    result = bob.verify(signed_document)

    # Analyze verification result
    print("\n=== Verification Result ===")
    print(f"Signature valid: {result.is_verified()}")
    print(f"Signer known: {result.signer_is_known()}")

    if result.is_verified():
        if result.signer_is_known():
            signer = result.signer()
            if signer:
                print(f"Signed by: {signer.name}.{signer.subname}")
                print(f"Signer DID: {signer.did}")
                print(f"Signer algorithms: {signer.signature_algorithm}")
        else:
            print("Signature is valid but signer is unknown")

    # Check attestation details
    attestation = result.attestation
    if attestation:
        print("Attestation information is available")

finally:
    Gateway.close()

Advanced Verification Analysis

from keychain.gateway import Gateway
from keychain.core.tag_set import TagSet
import time

def analyze_verification_result(result: VerificationResult, operation_name: str):
    """Provide detailed analysis of verification result."""

    print(f"\n=== Verification Analysis: {operation_name} ===")

    # Basic verification status
    is_valid = result.is_verified()
    is_known = result.signer_is_known()

    print(f"Signature Status: {'VALID' if is_valid else 'INVALID'}")
    print(f"Signer Status: {'KNOWN' if is_known else 'UNKNOWN'}")

    if not is_valid:
        print("⚠️  Signature verification failed!")
        print("   - Document may have been tampered with")
        print("   - Signature may be forged")
        print("   - Cryptographic keys may be invalid")
        return False

    # Analyze signer information
    if is_known:
        signer = result.signer()
        if signer:
            print(f"✓ Verified signature from known contact:")
            print(f"   Name: {signer.name}.{signer.subname}")
            print(f"   DID: {signer.did}")
            print(f"   Encryption: {signer.encryption_algorithm} ({signer.encryption_key_size} bits)")
            print(f"   Signature: {signer.signature_algorithm} ({signer.signature_key_size} bits)")
            print(f"   Contact Status: Known={signer.is_known}, Mature={signer.is_mature}")
        else:
            print("⚠️  Signer marked as known but contact object unavailable")
    else:
        print("⚠️  Valid signature from unknown signer")
        print("   - Signer not in contact list")
        print("   - May need to add signer as a contact")

    # Analyze attestation
    attestation = result.attestation
    if attestation:
        print("✓ Attestation information available")
        # Note: Attestation methods would depend on actual implementation
    else:
        print("ℹ️  No attestation information available")

    return is_valid and is_known

def comprehensive_verification_workflow():
    """Demonstrate comprehensive verification workflows."""

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

    try:
        # Setup personas and contacts
        alice = gateway.create_persona("alice", "company.com", SecurityLevel.HIGH, True)
        bob = gateway.create_persona("bob", "company.com", SecurityLevel.HIGH, True)
        charlie = gateway.create_persona("charlie", "partner.org", SecurityLevel.MEDIUM, True)

        # Wait for maturity
        for persona in [alice, bob, charlie]:
            if not persona.is_mature():
                persona.await_maturity()

        # Setup contact relationships
        alice.add_contact("bob", "company.com", bob.did)
        alice.add_contact("charlie", "partner.org", charlie.did)

        bob.add_contact("alice", "company.com", alice.did)
        bob.add_contact("charlie", "partner.org", charlie.did)

        charlie.add_contact("alice", "company.com", alice.did)
        # Note: Charlie doesn't have Bob as a contact

        # Create different types of signed data
        document = SerializedData.from_string("Contract Agreement", DataType.UTF8_STRING)

        # 1. Alice signs a document
        alice_signed = alice.sign(document, is_approval=True)

        # 2. Create a credential signed by Alice
        claims = TagSet()
        claims.set_tag_value("", "role", "Manager")
        claims.set_tag_value("", "department", "Engineering")

        now = int(time.time() * 1000)
        one_year = now + (365 * 24 * 60 * 60 * 1000)

        credential = alice.create_credential(
            credential_id="mgr-001",
            credential_type="ManagerCredential",
            subject_id="did:keychain:bob.company.com",
            start_timestamp=now,
            end_timestamp=one_year,
            claims=claims
        )

        print("=== Verification Test Scenarios ===")

        # Scenario 1: Bob verifies Alice's signature (known signer)
        print("\n1. Bob verifies Alice's document signature:")
        result1 = bob.verify(alice_signed)
        success1 = analyze_verification_result(result1, "Known Signer Verification")

        # Scenario 2: Bob verifies Alice's credential (known issuer)
        print("\n2. Bob verifies Alice's credential:")
        result2 = bob.verify(credential)
        success2 = analyze_verification_result(result2, "Credential Verification")

        # Scenario 3: Charlie verifies Alice's signature (known signer)
        print("\n3. Charlie verifies Alice's document signature:")
        result3 = charlie.verify(alice_signed)
        success3 = analyze_verification_result(result3, "Cross-Organization Verification")

        # Scenario 4: Bob signs and Charlie verifies (unknown signer)
        bob_signed = bob.sign(document, is_approval=False)
        print("\n4. Charlie verifies Bob's signature (unknown signer):")
        result4 = charlie.verify(bob_signed)
        success4 = analyze_verification_result(result4, "Unknown Signer Verification")

        # Summary
        print(f"\n=== Verification Summary ===")
        scenarios = [
            ("Bob → Alice (known)", success1),
            ("Bob → Alice credential", success2),
            ("Charlie → Alice (known)", success3),
            ("Charlie → Bob (unknown)", success4)
        ]

        for scenario, success in scenarios:
            status = "✓ TRUSTED" if success else "⚠️  UNTRUSTED"
            print(f"  {scenario}: {status}")

        # Security recommendations
        print(f"\n=== Security Recommendations ===")
        if not success4:
            print("• Add Bob as a contact for Charlie to enable trusted verification")

        print("• Always check both is_verified() and signer_is_known() for security-critical operations")
        print("• Regularly refresh contact information to maintain up-to-date PKI data")
        print("• Use verification results to make authorization decisions")

    finally:
        Gateway.close()

if __name__ == "__main__":
    comprehensive_verification_workflow()

Verification Result Patterns

def verification_result_patterns():
    """Demonstrate common verification result patterns."""

    def handle_verification_result(result: VerificationResult, operation: str) -> bool:
        """Standard verification result handling pattern."""

        if not result.is_verified():
            print(f"❌ {operation}: Signature verification FAILED")
            return False

        if not result.signer_is_known():
            print(f"⚠️  {operation}: Valid signature from UNKNOWN signer")
            print("   Consider adding signer as a contact for future operations")
            return False  # Or True, depending on security policy

        signer = result.signer()
        if signer:
            print(f"✅ {operation}: Valid signature from {signer.name}.{signer.subname}")
            return True
        else:
            print(f"⚠️  {operation}: Signer marked as known but unavailable")
            return False

    # Example usage patterns
    settings = Gateway.init("keychain.config")
    gateway = Gateway(settings)

    try:
        # Setup test environment
        alice = gateway.find_persona("alice", "company.com")
        bob = gateway.find_persona("bob", "company.com")

        document = SerializedData.from_string("Test document", DataType.UTF8_STRING)
        signed_doc = alice.sign(document)

        # Pattern 1: Simple verification
        result = bob.verify(signed_doc)
        if handle_verification_result(result, "Document verification"):
            print("✓ Document is trusted - proceed with operation")
        else:
            print("✗ Document is not trusted - abort operation")

        # Pattern 2: Verification with fallback
        result = bob.verify(signed_doc)
        if result.is_verified():
            if result.signer_is_known():
                print("✅ Fully trusted signature")
                proceed = True
            else:
                print("⚠️  Valid but unknown signer - requesting manual approval")
                # In real app, might prompt user or check whitelist
                proceed = False  # Or prompt user
        else:
            print("❌ Invalid signature - rejecting")
            proceed = False

        # Pattern 3: Verification with signer details
        result = bob.verify(signed_doc)
        if result.is_verified() and result.signer_is_known():
            signer = result.signer()
            if signer:
                # Make decisions based on signer identity
                if signer.name == "alice" and signer.subname == "company.com":
                    print("✅ Authorized signer - high trust level")
                elif signer.subname == "company.com":
                    print("✅ Internal signer - medium trust level")
                else:
                    print("⚠️  External signer - low trust level")

        return True

    finally:
        Gateway.close()

Error Handling

VerificationResult methods generally don’t raise exceptions, but the underlying verification operations can fail:

Example:

from keychain.exceptions import KeychainSecurityError, KeychainValidationError

try:
    # Verification operation
    result = gateway.verify(persona, signed_data)

    # Safe to check result properties
    if result.is_verified():
        print("Signature is valid")

        if result.signer_is_known():
            signer = result.signer()
            # signer might be None even if signer_is_known() is True
            if signer:
                print(f"Signed by: {signer.name}.{signer.subname}")

except KeychainSecurityError as e:
    print(f"Cryptographic verification failed: {e}")
except KeychainValidationError as e:
    print(f"Input validation failed: {e}")
except Exception as e:
    print(f"Unexpected error during verification: {e}")

Security Considerations

  1. Always check both conditions: Verify both is_verified() and signer_is_known() for security-critical operations

  2. Handle unknown signers: Decide how to handle valid signatures from unknown signers based on your security policy

  3. Null signer objects: Even if signer_is_known() returns True, the signer() method might return None

  4. Attestation analysis: Examine attestation objects when available for additional verification context

See Also