# k2gl/in-toto-attestation

> Build and parse in-toto attestation Statements in PHP.

Wrap any predicate (SLSA provenance, SBOM, …) in the in-toto Statement format tools expect.

## Install

```bash
composer require k2gl/in-toto-attestation
```

## Requirements

- PHP >=8.1
- k2gl/dsse ^1.0

## Documentation

# k2gl/in-toto-attestation

[![CI](https://img.shields.io/github/actions/workflow/status/k2gl/in-toto-attestation/ci.yml?branch=main&label=CI&logo=github)](https://github.com/k2gl/in-toto-attestation/actions/workflows/ci.yml)
[![Latest Stable Version](https://img.shields.io/packagist/v/k2gl/in-toto-attestation?logo=packagist&logoColor=white)](https://packagist.org/packages/k2gl/in-toto-attestation)
[![Total Downloads](https://img.shields.io/packagist/dt/k2gl/in-toto-attestation?logo=packagist&logoColor=white)](https://packagist.org/packages/k2gl/in-toto-attestation)
[![PHPStan Level](https://img.shields.io/badge/PHPStan-level%209-2a5ea7?logo=php&logoColor=white)](https://phpstan.org)
[![License](https://img.shields.io/packagist/l/k2gl/in-toto-attestation?color=yellowgreen)](https://packagist.org/packages/k2gl/in-toto-attestation)

Build, sign and verify in-toto attestation Statements in PHP, both the current v1 and the
legacy v0.1 that many real-world bundles still carry. Signed and parsed over DSSE.

An in-toto attestation is a signed claim ("predicate") about one or more artifacts
("subjects"). The claim is a **Statement**, carried inside a DSSE envelope with payload
type `application/vnd.in-toto+json`. This package gives you typed, validated `Statement`
and `ResourceDescriptor` value objects plus the sign/parse glue to DSSE.

## Install

```bash
composer require k2gl/in-toto-attestation
```

Requires PHP 8.1+. Pulls in `k2gl/dsse`. The example signers use `ext-sodium`
(Ed25519) / `ext-openssl` (ECDSA), both bundled with PHP.

## Usage

### Build and sign a statement

```php
use K2gl\InToto\Statement;
use K2gl\InToto\ResourceDescriptor;
use K2gl\Dsse\Ed25519Signer;

$statement = new Statement(
    subject: [
        new ResourceDescriptor(
            name: 'pkg:composer/k2gl/dsse@1.0.0',
            digest: ['sha256' => '…'],
        ),
    ],
    predicateType: 'https://slsa.dev/provenance/v1',
    predicate: ['buildDefinition' => [/* … */], 'runDetails' => [/* … */]],
);

$envelope = $statement->sign($signer);   // a K2gl\Dsse\Envelope
echo $envelope->toJson();
```

### Verify and parse

```php
use K2gl\InToto\PredicateRegistry;
use K2gl\InToto\Statement;
use K2gl\Dsse\Envelope;
use K2gl\Dsse\Ed25519Verifier;

$envelope = Envelope::fromJson($json);

$envelope->verify($verifier);              // DSSE signature check (throws on failure)
$statement = Statement::fromEnvelope($envelope);

$statement->predicateType;                 // 'https://slsa.dev/provenance/v1'
$statement->subject[0]->digest;            // ['sha256' => '…']
$statement->subject[0]->hasDigest('sha256', $expectedHex);    // case-insensitive digest check
$statement->predicate(PredicateRegistry::default());          // typed Predicate when registered, else the raw array
```

`fromEnvelope()` checks the envelope's `payloadType` and decodes the payload — always
verify the envelope's signatures (via `k2gl/dsse`) before trusting the result.

### Statement versions

Real-world Sigstore bundles carry in-toto Statements in two schema versions: the current
`v1` and the legacy `v0.1` (often wrapping a SLSA Provenance `v0.2` predicate). `fromJson()`
and `fromEnvelope()` parse both and expose which one was decoded:

```php
use K2gl\InToto\StatementVersion;

$statement = Statement::fromEnvelope($envelope);
$statement->version === StatementVersion::V0_1;   // true for a legacy bundle
```

New statements default to `v1`. To build a `v0.1` statement, pass the version explicitly:

```php
$statement = new Statement(
    subject: [new ResourceDescriptor(name: 'app', digest: ['sha256' => '…'])],
    predicateType: 'https://slsa.dev/provenance/v0.2',
    predicate: [/* … */],
    version: StatementVersion::V0_1,
);
```

## Scope

This package models the **Statement** layer (the generic envelope payload). Concrete
predicate types — SLSA Provenance, SPDX/CycloneDX, etc. — are intentionally out of scope.
They can be read as the raw `predicate` array, or modelled by companion packages that
implement `Predicate` and register a factory in a `PredicateRegistry` (e.g.
`k2gl/slsa-provenance`); `Statement::predicate()` then returns the typed object.

## License

MIT — see [LICENSE](LICENSE). Independent, clean-room implementation of the in-toto
Attestation specification (Apache-2.0).

## API

### K2gl\InToto\Exception\InTotoException (interface)

_no public methods_

### K2gl\InToto\Exception\InvalidStatementException (class)

_no public methods_

### K2gl\InToto\Predicate (interface)

- `predicateType(): string`
- `toArray(): array`

### K2gl\InToto\PredicateRegistry (class)

- `register(string $predicateType, callable $factory): void`
- `has(string $predicateType): bool`
- `resolve(string $predicateType, array $predicate): ?Predicate`
- `default(): self`

### K2gl\InToto\ResourceDescriptor (class)

- `__construct( public readonly ?string $name = null, public readonly ?string $uri = null, public readonly array $digest = [], public readonly ?string $mediaType = null, public readonly ?string $downloadLocation = null, public readonly ?array $annotations = null, public readonly ?string $content = null, )`
- `toArray(): array`
- `digestFor(string $algorithm): ?string`
- `hasDigest(string $algorithm, string $hexValue): bool`
- `fromArray(array $data): self`

### K2gl\InToto\Statement (class)

- `__construct( public readonly array $subject, public readonly string $predicateType, public readonly array $predicate = [], public readonly StatementVersion $version = StatementVersion::V1, )`
- `sign(Signer ...$signers): Envelope`
- `predicate(?PredicateRegistry $registry = null): Predicate|array`
- `fromEnvelope(Envelope $envelope): self`
- `toArray(): array`
- `toJson(): string`
- `fromJson(string $json): self`
- `fromArray(array $data): self`

### K2gl\InToto\StatementVersion (enum)

_no public methods_

## Links

- GitHub: https://github.com/k2gl/in-toto-attestation
- Packagist: https://packagist.org/packages/k2gl/in-toto-attestation
