Skip to content

AgentCardVerifier

The AgentCardVerifier class provides methods for verifying signed A2A Agent Cards using Sigstore.

Overview

from sigstore_a2a import AgentCardVerifier

verifier = AgentCardVerifier(
    oidc_issuer="https://token.actions.githubusercontent.com"
)
result = verifier.verify_file("signed-card.json")

if result.valid:
    print("Signature verified!")

API Reference

AgentCardVerifier

AgentCardVerifier(
    identity: str | None = None,
    oidc_issuer: str | None = None,
    staging: bool = False,
    trust_config: Path | None = None,
)

Verifies signed A2A Agent Cards using Sigstore.

Initialize the Agent Card verifier.

PARAMETER DESCRIPTION
identity

The expected identity that has signed the model

TYPE: str | None DEFAULT: None

oidc_issuer

The expected OpenID Connect issuer that provided the certificate used for the signature

TYPE: str | None DEFAULT: None

staging

Use Sigstore staging environment

TYPE: bool DEFAULT: False

trust_config

A path to a custom trust configuration

TYPE: Path | None DEFAULT: None

Source code in sigstore_a2a/verifier.py
def __init__(
    self,
    identity: str | None = None,
    oidc_issuer: str | None = None,
    staging: bool = False,
    trust_config: Path | None = None,
):
    """Initialize the Agent Card verifier.

    Args:
        identity: The expected identity that has signed the model
        oidc_issuer: The expected OpenID Connect issuer that provided
            the certificate used for the signature
        staging: Use Sigstore staging environment
        trust_config: A path to a custom trust configuration
    """
    self.identity = identity
    self.oidc_issuer = oidc_issuer
    self.staging = staging
    self.trust_config = trust_config

    self._verifier: Verifier | None = None

verify_signed_card

verify_signed_card(
    signed_card: (
        SignedAgentCard | dict[str, Any] | str | Path
    ),
    constraints: IdentityConstraints | None = None,
) -> VerificationResult

Verify a signed Agent Card.

PARAMETER DESCRIPTION
signed_card

Signed agent card to verify

TYPE: SignedAgentCard | dict[str, Any] | str | Path

constraints

Optional identity constraints

TYPE: IdentityConstraints | None DEFAULT: None

RETURNS DESCRIPTION
VerificationResult

Verification result

Source code in sigstore_a2a/verifier.py
def verify_signed_card(
    self,
    signed_card: SignedAgentCard | dict[str, Any] | str | Path,
    constraints: IdentityConstraints | None = None,
) -> VerificationResult:
    """Verify a signed Agent Card.

    Args:
        signed_card: Signed agent card to verify
        constraints: Optional identity constraints

    Returns:
        Verification result
    """

    try:
        # Parse signed card input
        if isinstance(signed_card, str | Path):
            if Path(signed_card).exists():
                with open(signed_card) as f:
                    card_data = json.load(f)
            else:
                card_data = json.loads(str(signed_card))
        elif isinstance(signed_card, dict):
            card_data = signed_card
        elif isinstance(signed_card, SignedAgentCard):
            card_data = signed_card.model_dump(by_alias=True)
        else:
            return VerificationResult(valid=False, errors=[f"Invalid signed card type: {type(signed_card)}"])

        # Validate signed card structure
        try:
            parsed_signed_card = SignedAgentCard.model_validate(card_data)
        except Exception as e:
            return VerificationResult(valid=False, errors=[f"Invalid signed card structure: {e}"])

        # Extract agent card and signature bundle
        agent_card = parsed_signed_card.agent_card
        sig_bundle = parsed_signed_card.attestations.signature_bundle

        # Sigstore verification
        verifier = self._get_verifier()
        try:
            from sigstore.verify.policy import OIDCIssuer

            policy = AnyOf([OIDCIssuer(constraints.identity_provider)])

            # Verify the bundle
            subject, payload = verifier.verify_dsse(sig_bundle, policy)
        except Exception as e:
            # If verification fails, include the actual identity for debugging
            try:
                actual_identity = self._extract_identity(sig_bundle.signing_certificate)
                error_msg = f"Signature verification failed: {e}"
                if actual_identity:
                    error_msg += f" (Certificate identity: issuer={actual_identity.get('issuer')}, subject={actual_identity.get('subject')})"
                return VerificationResult(valid=False, errors=[error_msg])
            except Exception:
                return VerificationResult(valid=False, errors=[f"Signature verification failed: {e}"])

        # Extract identity from certificate
        identity = self._extract_identity(sig_bundle.signing_certificate)

        constraint_errors = []
        constraint_errors = self._check_constraints(identity, constraints)

        if constraint_errors:
            return VerificationResult(
                valid=False,
                agent_card=agent_card,
                certificate=sig_bundle.signing_certificate,
                identity=identity,
                errors=constraint_errors,
            )

        return VerificationResult(
            valid=True, agent_card=agent_card, certificate=sig_bundle.signing_certificate, identity=identity
        )

    except Exception as e:
        return VerificationResult(valid=False, errors=[f"Verification failed: {e}"])

verify_file

verify_file(
    file_path: str | Path,
    constraints: IdentityConstraints | None = None,
) -> VerificationResult

Verify a signed Agent Card file.

PARAMETER DESCRIPTION
file_path

Path to signed Agent Card file

TYPE: str | Path

constraints

Optional identity constraints

TYPE: IdentityConstraints | None DEFAULT: None

RETURNS DESCRIPTION
VerificationResult

Verification result

Source code in sigstore_a2a/verifier.py
def verify_file(self, file_path: str | Path, constraints: IdentityConstraints | None = None) -> VerificationResult:
    """Verify a signed Agent Card file.

    Args:
        file_path: Path to signed Agent Card file
        constraints: Optional identity constraints

    Returns:
        Verification result
    """
    return self.verify_signed_card(file_path, constraints)

IdentityConstraints

IdentityConstraints(
    repository: str | None = None,
    workflow: str | None = None,
    identity: str | None = None,
    identity_provider: str | None = None,
)

Identity constraints for signature verification.

Initialize identity constraints.

PARAMETER DESCRIPTION
repository

Required repository (e.g., "owner/repo")

TYPE: str | None DEFAULT: None

workflow

Required workflow name or path

TYPE: str | None DEFAULT: None

identity

Required identity

TYPE: str | None DEFAULT: None

identity_provider

Required OIDC issuer

TYPE: str | None DEFAULT: None

Source code in sigstore_a2a/verifier.py
def __init__(
    self,
    repository: str | None = None,
    workflow: str | None = None,
    identity: str | None = None,
    identity_provider: str | None = None,
):
    """Initialize identity constraints.

    Args:
        repository: Required repository (e.g., "owner/repo")
        workflow: Required workflow name or path
        identity: Required identity
        identity_provider: Required OIDC issuer
    """
    self.repository = repository
    self.workflow = workflow
    self.identity = identity
    self.identity_provider = identity_provider

VerificationResult

VerificationResult(
    valid: bool,
    agent_card: AgentCard | None = None,
    certificate: Certificate | None = None,
    identity: dict[str, Any] | None = None,
    errors: list[str] | None = None,
)

Result of Agent Card verification.

Initialize verification result.

PARAMETER DESCRIPTION
valid

Whether verification succeeded

TYPE: bool

agent_card

Verified agent card (if valid)

TYPE: AgentCard | None DEFAULT: None

certificate

Signing certificate

TYPE: Certificate | None DEFAULT: None

identity

Extracted identity information

TYPE: dict[str, Any] | None DEFAULT: None

errors

List of verification errors

TYPE: list[str] | None DEFAULT: None

Source code in sigstore_a2a/verifier.py
def __init__(
    self,
    valid: bool,
    agent_card: AgentCard | None = None,
    certificate: x509.Certificate | None = None,
    identity: dict[str, Any] | None = None,
    errors: list[str] | None = None,
):
    """Initialize verification result.

    Args:
        valid: Whether verification succeeded
        agent_card: Verified agent card (if valid)
        certificate: Signing certificate
        identity: Extracted identity information
        errors: List of verification errors
    """
    self.valid = valid
    self.agent_card = agent_card
    self.certificate = certificate
    self.identity = identity or {}
    self.errors = errors or []

__bool__

__bool__() -> bool

Return True if verification was successful.

Source code in sigstore_a2a/verifier.py
def __bool__(self) -> bool:
    """Return True if verification was successful."""
    return self.valid

Usage Examples

Basic Verification

from sigstore_a2a import AgentCardVerifier

verifier = AgentCardVerifier(
    oidc_issuer="https://token.actions.githubusercontent.com"
)

result = verifier.verify_file("signed-card.json")

if result.valid:
    print("✓ Signature verified!")
    print(f"  Agent: {result.agent_card.name}")
    print(f"  Signed by: {result.identity.get('subject')}")
else:
    print("✗ Verification failed:")
    for error in result.errors:
        print(f"  - {error}")

Verification with Constraints

from sigstore_a2a import AgentCardVerifier
from sigstore_a2a.verifier import IdentityConstraints

verifier = AgentCardVerifier(
    oidc_issuer="https://token.actions.githubusercontent.com"
)

# Define constraints
constraints = IdentityConstraints(
    repository="sigstore/sigstore-a2a",
    workflow="Release"
)

result = verifier.verify_file("signed-card.json", constraints)

Verifying with Google Identity

verifier = AgentCardVerifier(
    identity="user@example.com",
    oidc_issuer="https://accounts.google.com"
)

result = verifier.verify_file("signed-card.json")

Using Staging Environment

verifier = AgentCardVerifier(
    oidc_issuer="https://token.actions.githubusercontent.com",
    staging=True
)

Using Custom Trust Configuration

from pathlib import Path

verifier = AgentCardVerifier(
    oidc_issuer="https://my-idp.example.com",
    trust_config=Path("/path/to/trust-config.json")
)

Extracting Identity Information

result = verifier.verify_file("signed-card.json")

if result.valid:
    identity = result.identity

    print(f"Issuer: {identity.get('issuer')}")
    print(f"Subject: {identity.get('subject')}")
    print(f"Repository: {identity.get('github_workflow_repository')}")
    print(f"Workflow: {identity.get('github_workflow_name')}")
    print(f"Commit SHA: {identity.get('github_workflow_sha')}")

Identity Providers

Common OIDC issuers for verification:

Provider Issuer URL
GitHub Actions https://token.actions.githubusercontent.com
Google https://accounts.google.com
Microsoft https://login.microsoftonline.com/{tenant}/v2.0
GitLab https://gitlab.com