This page provides a quick introduction to HTTP Signatures PHP library and introductory examples.
If you have not already installed HTTP Signatures PHP library head over to the Installation page.
Signing a message¶
Once you have a PSR-7 message ready to send, create a Context with:
- your chosen algorithm
- the list of headers to include in the signature
- the key you will use to sign the message
For these examples we will sign the method + URI (indicated by
(request-target) and the
Content-Type header. This provides a very
basic level of protection, and you should consider the headers you sign
in your application carefully. These may also be specified by the verifier
(most often a server hosting an API or web service).
Note also that this does not apply only to HTTP requests sent by a client. Servers can add a signature to responses that the client can verify.
Private Key Context (RSA)¶
This type of signature uses a private key known only to you, which can be verified using a public key that is known to anyone who wants to verify the message.
The key file is assumed to be an unencrypted private key in PEM format.
use HttpSignatures\Context; $context = new Context([ 'keys' => ['key43' => file_get_contents('/path/to/privatekeyfile')], 'algorithm' => 'rsa-sha256', 'headers' => ['(request-target)', 'Date', 'Accept'], ]);
Signing the Message:¶
Now $message contains the
$message->headers->get('Signature'); // keyId="examplekey",algorithm="hmac-sha256",headers="...",signature="..."
Adding a Digest header while signing¶
Digest header automatically when signing to also protect the
payload (body) of the message in addition to the request-target and headers:
$context->signer()->signWithDigest($message); $message->headers->get('digest'); // SHA-256=<base64SHA256Digest>
Verifying a Signed Message¶
Most parameters are derived from the Signature in the signed message, so the Context can be created with fewer parameters.
It is probably most useful to create a Context with multilpe keys/certificates. the signature verifier will look up the key using the keyId attribute of the Signature header and use that to validate the signature.
Verifying a HMAC signed message¶
A message signed with an hmac signature is verified using the same key as the one used to sign the original message:
use HttpSignatures\Context; $context = new HttpSignatures\Context([ 'keys' => ['key300' => 'some-other-secret', 'key12' => 'secret-here'] ]); $context->verifier()->isSigned($message); // true or false
Verifying a RSA signed message¶
An RSA signature is verified using the certificate associated with the Private Key that created the message. Create a context by importing the X.509 PEM format certificates in place of the ‘secret’:
use HttpSignatures\Context; $context = new HttpSignatures\Context([ 'keys' => ['key43' => file_get_contents('/path/to/certificate'), 'key87' => $someOtherCertificate], $context->verifier()->isSigned($message); // true or false ]);
Verifying a message digest¶
To confirm the body has a valid digest header and the header is a valid digest of the message body:
$context->verifier()->isValidDigest($message); // true or false
An all-in-one validation that the signature includes the digest, and the digest is valid for the message body:
$context->verifier()->isSignedWithDigest($message); // true or false
Symfony requests normalize query strings which means the resulting request target can be incorrect. See https://github.com/symfony/psr-http-message-bridge/pull/30
When creating PSR-7 requests you use withRequestTarget to ensure the request target is correct. For example
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory; use Symfony\Component\HttpFoundation\Request; $symfonyRequest = Request::create('/foo?b=1&a=2'); $psrRequest = (new DiactorosFactory()) ->createRequest($symfonyRequest) ->withRequestTarget($symfonyRequest->getRequestUri());