PHPackages                             craftcms/http-message-signatures - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. craftcms/http-message-signatures

ActiveLibrary[HTTP &amp; Networking](/categories/http)

craftcms/http-message-signatures
================================

PSR-7 compliant PHP 8.1+ implementation of HTTP Message Signatures (RFC 9421)

1.x-dev(1mo ago)118MITPHPPHP ^8.1

Since Feb 26Pushed 1mo agoCompare

[ Source](https://github.com/craftcms/http-message-signatures-php)[ Packagist](https://packagist.org/packages/craftcms/http-message-signatures)[ RSS](/packages/craftcms-http-message-signatures/feed)WikiDiscussions 1.x Synced 1w ago

READMEChangelogDependencies (10)Versions (5)Used By (0)

HTTP Message Signatures (RFC 9421)
==================================

[](#http-message-signatures-rfc-9421)

A PHP 8.4+ implementation of [HTTP Message Signatures](https://www.rfc-editor.org/rfc/rfc9421.html) as specified in RFC 9421.

Features
--------

[](#features)

- ✅ Full RFC 9421 compliance
- ✅ **PSR-7 compliant** - Works with any PSR-7 HTTP message implementation
- ✅ Support for multiple signature algorithms:
    - HMAC-SHA256
    - RSA-SHA256
    - Ed25519
- ✅ Signature creation and verification
- ✅ Structured fields parsing for `signature-input` and `signature` headers
- ✅ Component derivation (headers, query parameters, request target, etc.)
- ✅ Immutable message handling (respects PSR-7 immutability)

Installation
------------

[](#installation)

```
composer require craftcms/http-message-signatures
```

Requirements
------------

[](#requirements)

- PHP 8.4 or higher
- PSR-7 HTTP message implementation (e.g., `guzzlehttp/psr7`, `nyholm/psr7`, `slim/psr7`)

Dependencies
------------

[](#dependencies)

This package uses well-maintained, industry-standard libraries:

- **[bakame/http-structured-fields](https://packagist.org/packages/bakame/http-structured-fields)** - For parsing and formatting HTTP Structured Fields (RFC 8941) used in signature headers

Usage
-----

[](#usage)

### Creating a Signature

[](#creating-a-signature)

```
use HttpMessageSignatures\Signer;
use HttpMessageSignatures\Algorithm\HmacSha256;
use GuzzleHttp\Psr7\Request;

// Create a PSR-7 request
$request = new Request(
    'POST',
    'https://api.example.com/resource',
    [
        'Host' => 'api.example.com',
        'Content-Type' => 'application/json',
        'Date' => gmdate('D, d M Y H:i:s \G\M\T'),
    ],
    '{"data":"value"}'
);

// Create signer with HMAC-SHA256 algorithm
$signer = new Signer(new HmacSha256('your-secret-key'));

// Sign the request (returns a new immutable PSR-7 message)
$signedRequest = $signer->sign(
    $request,
    ['@method', '@path', '@authority', 'content-type', 'date'],
    [
        'keyid' => 'my-key-id',
        'signatureId' => 'sig1',
        'created' => time(),
        'expires' => time() + 300, // Optional: 5 minutes
    ]
);

// The original request is unchanged (PSR-7 immutability)
// $signedRequest is a new instance with Signature and Signature-Input headers
```

### Verifying a Signature

[](#verifying-a-signature)

```
use HttpMessageSignatures\Verifier;
use HttpMessageSignatures\Algorithm\HmacSha256;
use HttpMessageSignatures\Exception\VerificationException;

$verifier = new Verifier(new HmacSha256('your-secret-key'));

try {
    // Verify the signature (returns true if valid)
    $isValid = $verifier->verify($signedRequest);

    if ($isValid) {
        echo "Signature is valid!\n";
    }
} catch (VerificationException $e) {
    echo "Verification failed: " . $e->getMessage() . "\n";
}
```

### Using RSA-SHA256

[](#using-rsa-sha256)

```
use HttpMessageSignatures\Signer;
use HttpMessageSignatures\Algorithm\RsaSha256;

// Load your private key (for signing)
$privateKey = file_get_contents('/path/to/private-key.pem');

// Optionally provide public key (for verification)
$publicKey = file_get_contents('/path/to/public-key.pem');

$signer = new Signer(new RsaSha256($privateKey, $publicKey));

$signedRequest = $signer->sign(
    $request,
    ['@method', '@path', '@authority', 'content-type'],
    ['keyid' => 'rsa-key-1']
);
```

### Using Ed25519

[](#using-ed25519)

```
use HttpMessageSignatures\Signer;
use HttpMessageSignatures\Algorithm\Ed25519;

// Ed25519 requires the sodium extension
$privateKey = sodium_crypto_sign_seed_keypair(...);
$publicKey = sodium_crypto_sign_publickey($privateKey);

$signer = new Signer(new Ed25519($privateKey, $publicKey));

$signedRequest = $signer->sign(
    $request,
    ['@method', '@path', '@authority'],
    ['keyid' => 'ed25519-key-1']
);
```

### Available Components

[](#available-components)

The following components can be included in signatures:

**Derived Components:**

- `@method` - HTTP method
- `@path` - Request path
- `@query` - Query string
- `@authority` - Host and port
- `@scheme` - URI scheme
- `@target-uri` - Full URI
- `@request-target` - Request target
- `@status` - Response status code (for responses)

**Headers:**

- Any header name (e.g., `content-type`, `date`, `authorization`)

**Query Parameters:**

- `@query-param;name="paramname"` - Specific query parameter

PSR-7 Compliance
----------------

[](#psr-7-compliance)

This package is fully PSR-7 compliant:

- Works with any PSR-7 implementation (`guzzlehttp/psr7`, `nyholm/psr7`, `slim/psr7`, etc.)
- Respects PSR-7 immutability - all methods return new message instances
- Uses only PSR-7 interfaces (`MessageInterface`, `RequestInterface`, `ResponseInterface`)
- No direct dependencies on specific PSR-7 implementations

Testing
-------

[](#testing)

```
composer test
```

Code Quality
------------

[](#code-quality)

```
# Run all checks (lint + PHPStan + tests)
composer check

# Lint code
composer lint

# Auto-fix lint issues
composer fix

# Static analysis
composer phpstan
```

License
-------

[](#license)

MIT

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance93

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

34d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3ccdf8b493035de2343c55bd889513e3af5c04d5823482a2b186ad16adb1c3e3?d=identicon)[brandonkelly](/maintainers/brandonkelly)

---

Top Contributors

[![timkelty](https://avatars.githubusercontent.com/u/18329?v=4)](https://github.com/timkelty "timkelty (13 commits)")

---

Tags

httpsecuritysignatureAuthenticationrfc9421

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/craftcms-http-message-signatures/health.svg)

```
[![Health](https://phpackages.com/badges/craftcms-http-message-signatures/health.svg)](https://phpackages.com/packages/craftcms-http-message-signatures)
```

###  Alternatives

[guzzlehttp/psr7

PSR-7 message implementation that also provides common utility methods

7.9k1.1B3.7k](/packages/guzzlehttp-psr7)[tempest/framework

The PHP framework that gets out of your way.

2.2k31.1k11](/packages/tempest-framework)[amphp/http-client

An advanced async HTTP client library for PHP, enabling efficient, non-blocking, and concurrent requests and responses.

7318.5M183](/packages/amphp-http-client)[mezzio/mezzio-authentication-oauth2

OAuth2 (server) authentication middleware for Mezzio and PSR-7 applications.

28545.4k3](/packages/mezzio-mezzio-authentication-oauth2)[laudis/neo4j-php-client

Neo4j-PHP-Client is the most advanced PHP Client for Neo4j

185671.3k41](/packages/laudis-neo4j-php-client)[mezzio/mezzio

PSR-15 Middleware Microframework

3893.8M118](/packages/mezzio-mezzio)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
