ActivityPub HTTP Signatures
A library for creating, parsing, and verifying HTTP signature headers, as per the Signing HTTP Messages draft 08 specification.
Basic use
Signing
The following example illustrates using the library to sign requests:
import { Sha256Signer } from 'activitypub-http-signatures';
import fetch from 'node-fetch';
// You should make the public key available at this URL
const publicKeyId = 'http://my-site.example/@paul#main-key';
const privateKey = `-----BEGIN RSA PRIVATE KEY-----
${process.env.PRIVATE_KEY}
-----END RSA PRIVATE KEY-----`;
export function getResource(url) {
// A dict of the headers used in your request. The host and
// date properties will be added to this object
// if they're missing, with the following default values:
const headers = {
host: new URL(url).host,
date: new Date().toUTCString()
}
const method = 'GET';
const signer = new Sha256Signer({ publicKeyId, privateKeyId });
// Generate the signature header
const signature = signer.sign({
url,
method,
headers
});
// Create the HTTP request with the generated header
return fetch(
url,
headers: {
...headers,
signature,
accept: 'application/ld+json'
}
)
}
Verifying
import parser from 'activitypub-http-signatures';
import fetch from 'node-fetch';
// Assuming we're dealing with a nodejs IncommingMessage
export async function verifyIncomingRequestSignature(req){
// Parse the fields from the signature header
// NB: If you're using express, you need to use originalUrl instead of url
const { url, method, headers } = req;
const signature = parser.parse({ url, method, headers });
// Get the public key object using the provided key ID
const keyRes = await fetch(
signature.keyId,
{
headers: {
accept: 'application/ld+json, application/json'
}
}
);
const { publicKey } = await keyRes.json();
// Verify the signature
const success = signature.verify(
publicKey.publicKeyPem, // The PEM string from the public key object
);
if(!success){
throw new Error('http signature validation failed')
} else {
return publicKey.owner
}
}
Changes in V2
Version 2 of this package has a completely new and hopefully simpler API.
All previous exports have been removed,
you now need to use Sha256Signer
to sign outgoing requests
and Parser
to parse and verify incoming requests.
See the examples above for details.
Dependencies
activitypub-http-signatures
Activitypub HTTP Signatures Based on HTTP Signatures draft 08
-
activitypub-http-signatures
-
default
⏏ - .Sha256Signer
-
.Parser
-
.parse(reqOptions) ⇒
Signature
-
.getSignatureClass(algorithm, options) ⇒
Signature
-
.parse(reqOptions) ⇒
-
.Sha256Signature
- new Sha256Signature(options)
-
.verify(key) ⇒
boolean
-
default
⏏
default Default export: new instance of Parser class
Sha256Signer
Kind: static class of default
new Sha256Signer(options)
Class for signing a request and returning the signature header
Param | Type | Description |
---|---|---|
options | object |
Config options |
options.publicKeyId | string |
URI for public key that must be used for verification |
options.privateKey | string |
Private key to use for signing |
options.headerNames | Array.<string> |
Names of headers to use in generating signature |
string
sha256Signer.sign(reqOptions) ⇒ Generate the signature header for an outgoing message
Kind: instance method of Sha256Signer
Returns: string
- Value for the signature header
Param | Type | Description |
---|---|---|
reqOptions | object |
Request options |
reqOptions.url | string |
The full URL of the request to sign |
reqOptions.method | string |
Method of the request |
reqOptions.headers | object |
Dict of headers used in the request |
Parser
Incoming request parser and Signature factory. If you wish to support more signature types you can extend this class and overide getSignatureClass.
Kind: static class of default
-
.Parser
-
.parse(reqOptions) ⇒
Signature
-
.getSignatureClass(algorithm, options) ⇒
Signature
-
.parse(reqOptions) ⇒
Signature
parser.parse(reqOptions) ⇒ Parse an incomming request's http signature header
Kind: instance method of Parser
Returns: Signature
- Object representing the signature
Throws:
-
UnkownAlgorithmError
If the algorithm used isn't one we know how to verify
Param | Type | Description |
---|---|---|
reqOptions | object |
Request options |
reqOptions.url | string |
The pathname (and query string) of the request URL |
reqOptions.method | string |
Method of the request |
reqOptions.headers | object |
Dict of headers used in the request |
Signature
parser.getSignatureClass(algorithm, options) ⇒ Construct the signature class for a given algorithm. Override this method if you want to support additional algorithms.
Kind: instance method of Parser
Throws:
-
UnkownAlgorithmError
If an unknown algorithm was used
Param | Type | Description |
---|---|---|
algorithm | string |
The algorithm used by the signed request |
options | object |
|
options.signature | Buffer |
The signature as a buffer |
options.string | string |
The string that was signed |
options.keyId | string |
The ID of the public key to be used for verification |
Sha256Signature
Kind: static class of default
new Sha256Signature(options)
Class representing the HTTP signature
Param | Type | Description |
---|---|---|
options | object |
|
options.signature | Buffer |
The signature as a buffer |
options.string | string |
The string that was signed |
options.keyId | string |
The ID of the public key to be used for verification |
boolean
sha256Signature.verify(key) ⇒ Verify the signature using a public key
Kind: instance method of Sha256Signature
Param | Type | Description |
---|---|---|
key | string |
The public key matching the signature's keyId |