Keyoxide

Developer guides

Write an ASPE server

What does an ASPE server do?

An Ariadne Signature Profile (ASP) is a type of identity profile that services like Keyoxide can verify but which rely on basic cryptographic standards like EdDSA and ES256 instead of cryptographic tools like OpenPGP.

The ASP Exchange (ASPE) protocol refers to the set of HTTP requests by which people can upload and download ASPs to and from dedicated servers.

A public ASPE server will:

ASP profiles are encoded, stored and distributed as so-called profile JWSs, which in turn are sent to the ASPE server as part of so-called request JWSs.

Of course, an ASPE server could also be private, meaning people will not be able to upload their profiles to it — or only a list of pre-authorized people/profiles may do so — but the profiles that the server does store should still be publicly accessible.

Implementing an ASPE server

Now, let's try and implement an ASPE server! This will be a simple overview of the different required steps. For more implementation details, refer to the ASP specification.

I have already written a minimal ASPE server written in Rust, creatively named aspe-server-rs. I will be basing this guide on that repository, so feel free to inspect the code for more context.

Do you have a static web page? Follow the Implement ASPE on a static site guide instead.

Receiving ASPs

Let's begin the guide by looking at how ASPE servers receive ASPs.

An ASPE server has an endpoint dedicated to receiving ASPs:

POST ENDPOINT = '/.well-known/aspe/post'

This endpoint must use HTTPS and accept POST requests. POST requests must have a so-called request JWS as body (see the Request JWS section).

Upon receiving a POST request, the server must validate the request JWS by checking the different values it contains as well as validating the signature. These checks are all described in the Request JWS section.

The server must also check the validity of the profile JWS contained within the request JWS.

Luckily, there are many libraries and tools to help with this validation process, including jose (JS) and josekit (Rust).

If the request JWS is valid, the profile JWS it contains must be stored in a way the server implementation sees fit. See the Storing ASPs section. The request JWS must be discarded.

Request JWS

A request JWS is a JSON Web Signature (RFC7515) that is sent over HTTPS to transmit a so-called profile JWS (see the Profile JWS section).

To validate a request JWS, make sure that:

A reasonable amount of time is subjective and requires deliberate considation from the developer. A shorter amount of time helps protect profiles against replay attacks but punishes people living in regions with poor connectivity and flaky internet. The spec recommends accepting iat values within an hour of the moment that the server receives the request, both before and after.

Profile JWS

A profile JWS is a JSON Web Signature that contains all the information of an ASP profile.

To validate a profile JWS, make sure that:

Computing the fingerprint

To obtain the fingerprint associated with the ASP profile, one must create a specific JSON object based on the JWK-encoded public key, serialize it, hash it, truncate it and encode it. All the details for this process can be found in section 2.2 of the spec.

Storing ASPs

The server may store ASPs in any way it sees fit, as long as it does so in a queryable manner. After all, the sole purpose of storing ASPs is to subsequently retrieve and distribute them in response to a request.

ASPs can only be identified and requested by their URI:

URI = 'aspe:' domain ':' fingerprint

The domain is the one used to access the ASPE server.

The key's fingerprint is obtained as described in Computing the fingerprint. The fingerprint needs to be taken into consideration when implementing a storage layer for the ASPE server.

A simple Key-Value Database could suffice, where the fingerprint is the key and the profile JWS the value.

Distributing ASPs

The endpoint used to request ASPs from the server looks as follows:

GET ENDPOINT = '/.well-known/aspe/id/' fingerprint

Requests made to this endpoint must be GET requests.

If an ASP profile with the requested fingerprint was indeed stored by the ASP server and the profile is not expired (see Profile JWS), it should be sent as the response to the request; if not, the server should return a 404 NOT FOUND.

Allowing servers to update and delete ASPs

Updating and deleting ASPs are basically variations on the process of uploading ASPs!

When the ASPE server receives a request JWS with the http://ariadne.id/action property set to update, the server should check whether it indeed already has stored an ASP with the fingerprint of the incoming ASP and whether the keys perfectly match. If all checks are positive, the server can overwrite the existing ASP with the incoming ASP.

Likewise, if the request JWS has the http://ariadne.id/action property set to delete and the server has found an existing ASP with a matching fingerprint, it should remove said ASP from storage.

More information

All the information provided above is further elaborated on in the ASP specification.

Feel free to reach out to the community for questions and discussions.