Wind_Mask,technically me.

Keyoxide Introduction

About this service, it seems that it has not been introduced in the Chinese world yet, but it can be seen that users are using it on GitHub and some Fediverse platforms.
I didn't use a similar Keybase service before because it didn't support PGP subkeys or other PGP functions, but on the other hand, Keyoxide's design is more decentralized and autonomous.
I have done some work on this (including Chinese translation and implementation of its protocol in another language), so let me introduce it now.

For accurate details, documentation, and code, please refer to the official website Keyoxide.


As stated by the official website:

Keyoxide is a privacy-friendly tool to create and verify decentralized online identities.
Just like passports for real-life identities, Keyoxide can be used to verify the online identity of people to make sure one is interacting with whom they are supposed to be and not imposters.
Unlike real-life passports, Keyoxide works with online identities or "personas", meaning these identities can be anonymous and one can have multiple separate personas to protect their privacy, both online and in real life.

I explain it as: Keyoxide aims to establish consistency among various channels of an identity by using cryptography and decentralized hosting, allowing for proxy or self-verification to ensure the consistency of an identity across multiple channels.
It does not prove that you are you, but rather proves that multiple channels (or their controllers) can be controlled by the same key holder. In other words, it proves that a certain account on platform A and a certain account on platform B (channels can have more meanings, such as a domain name) belong to the same person.


In terms of the configuration of an identity, Keyoxide uses the Ariadne Spec to interpret the format of online identities.

Before delving into the details of the original link, you can also listen to my simple explanation: an online identity is a signed identity document using a key (refer to any popular science explanation of asymmetric cryptography), which consists of:

  • Metadata, indicating the cryptographic information used and that it is an online identity document.
  • Claims, which are declarations about the identity of some online channels or accounts, such as claiming that a domain belongs to this identity or a GitHub account belongs to this identity.
  • Personal information that the user is willing to record, such as email, profile, avatar, and links.

Then the document is signed and distributed.
So how do you verify that these channels do belong to this identity?
For various service providers and channels, there are different APIs or methods to publicly obtain information that only the owner can control. For example, for domains, there are TXT records in DNS, and for GitHub, there are public gists. In these pieces of information, the owner records specific proofs:

An identity proof may be:

  • an URI representation of a cryptographic key's identifier
  • a cryptographic hash of a URI representation of a cryptographic key's identifier
  • an URL pointing to a web representation of an Ariadne Identity Profile

In other words, the owner records the URI (similar to the fingerprint of a key) used to sign the profile document in the account, or the hash of this URI, or a link pointing to the profile document.
In this way, the person who obtains the signed profile document can check if the accounts associated with each claim have the required proofs placed according to the specification. If they are obtained, it proves that the corresponding channels do belong to the controller of this identity.


The format of a Claim is [email protected]=CLAIM, where CLAIM should follow the requirements in the Available claims/proofs.
The format of proof (the one placed in your various accounts, the proof@... in Claim is literal) can take several forms:

  • URI: openpgp4fpr:3637202523e7c1309ab79e99ef2dc5827b445f4b (for later reference, ASP is aspe:domain.tld:ASPFINGERPRINT)
  • Hashed URI: $argon2id$v=19$m=16,t=2,p=1$UElOT0ZIU09mSHlReE1lcg$2nJmgFL0s3DHPksuSE2enw
  • Message: [Verifying my cryptographic key: FINGERPRINT_URI]
  • Profile URL: or


  • The above formats are for PGP keys. In these formats, FINGERPRINT is the fingerprint of your public key (in lowercase?), and FINGERPRINT_URI is openpgp4fpr:FINGERPRINT.
  • Hashed URI is the hash of the URI using argon2 or bcrypt.
  • The other contents in the message are not important, the important part is that it contains FINGERPRINT_URI.
  • Profile URL is the profile page link provided by a specific Keyoxide instance, and it can also be redirected.

Usage under OpenPGP#

First, you need an OpenPGP key, which is not the focus of this article. Please refer to other guides.
Next, you need to:

gpg --edit-key FINGERPRINT
uid N
Then, in the `notation` section, add a line with `[email protected]=CLAIM` and add some `Claims`.

Then upload the public key to or Web Key Directory.
Please remember to update the information of your various channels according to the requirements in the Available claims/proofs, otherwise the verification will fail.
Then, you can search for your profile document on Keyoxide by entering your key ID fingerprint or email.

Ariadne Signature Profile#

In addition to OpenPGP, a separate specification is provided for signing the profile document. I personally think that adding annotations in the PGP public key is not the best choice, but the new format also has difficulties in promotion. Readers can consider it themselves.
This method uses JSON Web Signature (JWS) to sign the identity document, which allows for more widespread implementation without relying on specific OpenPGP implementations and supports more advanced cryptographic primitives.
According to the specification, ASP only uses the following combinations of signing algorithms and curves for JWS:

  • algorithm: "EdDSA", curve: "Ed25519" (RFC8037)
  • algorithm: "ES256", curve: "P-256"

And it uses a public key in the JWK format in the JWS.
To use the so-called Profile JWS, it must be serialized using the compact serialization defined in Section 3.1 of RFC7515.

In the Profile JWS header:
alg=the signing algorithm, see IANA-JOSE
jwk=the public key in the JWK format (a JSON representation of a public key)
kid=the fingerprint of the public key specific to this specification, see below

In the Profile JWS payload, include the payload such as name, claims, description, etc. (refer to Ariadne Signature Profile v0 for the specific format).

ASP fingerprint#

The fingerprint of ASP is calculated according to the method of calculating the fingerprint of JWK in RFC7638. The fingerprint is obtained by taking the first 16 bytes of the hash of the JWK fingerprint using the SHA512 hash algorithm, and then converting it to unpadded BASE32. The fingerprint can be in either uppercase or lowercase, but the code will convert it to uppercase.

ASPE Server and Client#

With ASP, as long as it can be publicly obtained, it can be verified using the same method as the identity document in OpenPGP.
The specification defines the Ariadne Signature Profile Exchange Protocol, assuming that a server that can interact via an API is available for uploading and storing publicly accessible ASP.
According to this exchange protocol, the client interacts with the server and uploads, updates, or deletes ASP.


Assuming you have successfully uploaded an ASP with a fingerprint of ASPFINGERPRINT and the ASPE server domain is domain.tld, you can verify it by entering the ASPE URI as aspe:domain.tldASPFINGERPRINT on Keyoxide.

ASP Usage#

So the question is, how do you construct ASP and how do you upload it to the server?
First, the domain is an ASPE server, which means that as long as you follow the protocol, you can interact with it.
First, there is an online web interface provided by asp.keyoxide that can be used to generate ASP and upload it to a specified domain server. However, it has limited support for claim channels (at least a few months ago when I checked), and customization is not fully available.
Second, there is kx-aspe-cli, but it also has limited design support.
If you want to customize ASP locally (but of course, you need to provide claims for service providers and edit the configuration file), or even generate your own keys, I previously wrote a command-line tool to achieve this: aspe-client-go. I have confirmed that it can interact with (including the server I will mention later).


If you are interested in promoting the use of this tool and protocol, you can participate in the hosting of its server, including:

  • An instance of Keyoxide, which can verify identity configuration documents.
  • An ASPE server, which can store and publicly provide ASP.
    For the guide on the former, please refer to Self-hosting Keyoxide.
    For the latter, there is aspe-server-rs, but it seems that data storage has not been integrated yet. I have implemented aspe-server-go, which should have implemented the API and storage.
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.