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
[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
Claim is literal) can take several forms:
openpgp4fpr:3637202523e7c1309ab79e99ef2dc5827b445f4b(for later reference,
- Hashed URI:
[Verifying my cryptographic key: FINGERPRINT_URI]
- Profile URL:
- The above formats are for PGP keys. In these formats,
FINGERPRINTis the fingerprint of your public key (in lowercase?), and
Hashed URIis the hash of the URI using
- The other contents in the message are not important, the important part is that it contains
Profile URLis the profile page link provided by a specific
Keyoxideinstance, 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
Then, in the `notation` section, add a line with `[email protected]=CLAIM` and add some `Claims`.
Then upload the public key to
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
- algorithm: "EdDSA", curve: "Ed25519" (RFC8037)
- algorithm: "ES256", curve: "P-256"
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
Profile JWS payload, include the payload such as name, claims, description, etc. (refer to Ariadne Signature Profile v0 for the specific format).
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#
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
According to this exchange protocol, the client interacts with the server and uploads, updates, or deletes
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.
So the question is, how do you construct
ASP and how do you upload it to the server?
First, the domain
keyoxide.org 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
keyoxide.org (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.
ASPEserver, which can store and publicly provide
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.