Anima Cryptographic Identity Protocol

Table of Contents

1. Overview

1.1. Rationale

TODO

1.2. Terminology

Persona: a "Persona" in this document, when capitalized, refers to a consistent, cryptographically verifiable identity. This identity may be strongly linked to a real person or other real entity, or it may be anonymous. A person may have one or many Personas.

Endorsement: an "Endorsement" in this document, when capitalized, refers to a cryptographic signature generated by another third-party Persona based on a public key, which is used to "endorse" the authenticity of the public key, i.e. supporting the claim that this key does in fact correspond to a private key owned by the alleged Persona. Endorsements, especially from people you personally trust, add veracity to authentication via public keys. Endorsements are similar to "keysigning" in OpenPGP.

1.3. Persona Authentication

The Persona authentication process begins with a LUCID URI as described in Part 2.2. These URIs will be attached to anything that one might feasibly want to verify the authorship of. The format of the URIs themselves is defined, but the way in which they are provided is not. They may be included in JSON data, appended in plain text after a message, or any other technique which makes the URI easily accessible.

Next, the full public key, identity proofs, and endorsements for the Persona must be located. Note that LUCID URIs are Uniform Resource Identifiers, not Uniform Resource Locators. The significance of this distinction lies in the fact that this specification does not define a canonical method for resolving LUCID URIs to Personas ("locating" them). It is intentionally left undefined and intended to be open-ended and implementation-specific, though other specifications for LUCID URI resolution may be created in the future.

When the canonical home of the Persona has been located, several resources are collected: the Persona's full public key, a list of ownership proofs (links to - or single proofs as found on - sites such as Keyoxide or Keybase), and a list of Endorsements for that public key. All of this information is stored locally by the client, along with notes about what Persona the key belongs to, for future authentication purposes. All keys found this way should always have at least one Endorsement, from the key owner themselves. This Endorsement obviously doesn't mean anything for the trustworthiness of the key, but it does provide a baseline level of cryptographic integrity.

Once the public key has been stored, any future messages that include an attached fingerprint matching the key can be cryptographically verified using that stored public key, allowing subsequent authentication based on the fingerprint alone.

1.4. Web of Trust

Anima is based on a decentralized trust model known as the "web of trust". The basic principle is that although you can't be expected to know everyone in the world personally, there can be a few people you trust, who have a few people they trust, who have a few people they trust, and so on, forming a giant "web of trust" that can provide some sense of the trustworthiness of a stranger based on who else trusts them, and how many trust-hops away from you they are in the web. Anima has a trust system similar to OpenPGP's but with more fine-grained trust distinctions and more amenable to numeric analysis of complex trust chains. The trust system is outlined in Part 4.

1.5. Encryption for Confidentiality

TODO - key exchange, communication via symmetric cipher

1.6. Compliance

When marked in small caps, the terms must, must not, required, should, should not, may, optional, recommended, and not recommended are to be interpreted as described in RFC 2119. The small caps term not required is equivalent to the term optional as defined in RFC 2119.

2. Keys and Fingerprints

2.1. Fingerprints

Key fingerprints are compact identifiers that can be liberally attached to messages and media with minimal usage of bandwidth or storage. Fingerprints are calculated from a public key using SHA3-512/192, that is, hashed using the SHA-3 hashing algorithm with an output size of 512 bits, which is then truncated to 192 bits. These fingerprints are commonly represented by a string of 32 Base64 characters, e.g. k79dnQ7BwEabPeqqXyZlvyEJ3exz4eVF. These may be displayed to the user in groups of 4 for readability (such as k79d nQ7B wEab Peqq XyZl vyEJ 3exz 4eVF) but they must be stored and transmitted without any such padding. (TODO: is 512/192 actually stronger than 224/192 or simply 192?)

Fingerprints serve as a globally unique identifier for a Persona. They are resilient to collision or preimage attacks but must not be considered equivalent to a public key. Messages with only a fingerprint attached should not be trusted for anything important. Important messages should always contain a cryptographic signature alongside the fingerprint, so that the full public key matching the fingerprint can be used to properly verify the contents. Even in the event of a successful collision attack in the future, users who already have the fingerprint's original public key stored would be unaffected.

Malicious public keys generated with colliding fingerprints may try to claim that they are the correct Persona for the fingerprint, which could trick users who haven't received the original, genuine public key. This is not currently computationally feasible, but it could become so in the future. The only way to solve this problem is socially, i.e. by making it publically known that there is an impersonator with your fingerprint out there. A new keypair could be generated and endorsements for it received again, and then revoke the original key/fingerprint, which would alleviate the impersonator problem, but this is potentially a very difficult and time-consuming task and so cannot be considered an acceptable solution. In the event that fingerprints become easily compromised in the future, later versions of the protocol may use more secure fingerprints, and systems will need to be able to handle upgrading to these new fingerprints at that time.

In an abundance of caution, entire public keys could be attached to messages instead of fingerprints. With some ECC-based algorithms, the full public key is fairly short (an Ed25519 public key is 64 characters in Base64). However, this practice is currently not recommended unless viable attacks on the SHA3 hash are discovered.

2.2. LUCID URIs

The perferred identifier for a Persona is a Uniform Resource Identifier (URI) (as per RFC 3986) with a lucid scheme (not yet registered with IANA). LUCID stands for Lightweight Unique Cryptographic IDentifier.

lucid URIs must be formatted as follows: lucid:<version>:<fingerprint>?<query>#<fragment>

<version> is a string starting with "v" followed by an integer representing the LUCID URI version. Currently, only version 1 exists, written as v1. The "v" is case-insensitive.

<fingerprint> is a SHA3-512/192 fingerprint as described above, encoded in Base64.

<query> and <fragment> are a query component and fragment identifier respectively, as defined in RFC 3986. They currently have no defined use, but may be used in the future for purposes such as supplying parameters to identity queries or identifying sub-resources. Compliant implementations must accept and be able to parse LUCID URIs with query strings or fragments, though currently they are not required to do anything with that data.

The lucid: scheme, <version>, and <fingerprint> are required in a valid LUCID URI. <query> and <fragment> are optional. Examples of a valid LUCID URIs are:

2.3. Endorsements

Version 1 (the current and only version) Endorsements consist of five pieces of information: the Endorsement algorithm version number, the fingerprint of the endorser, the trust level associated with the Endorsement, a timestamp indicating when the endorsement was made, and a cryptographic signature. The signature is generated from the concatenation of the following:

This stream of bytes is then signed using the endorser's private key, and the resulting signature is used for the Endorsement. Note that the type of public key used is irrelevant. As long as both the endorser and the verifier use the same byte stream, the result will be the same, regardless of the format or size of the public key. Future Endorsement versions are guaranteed to contain a version number, but all other fields may be different.

Security when obtaining the other Persona's original public key is crucial - all other verifications are based on this key. By contrast, security when issuing Endorsements is a non-issue, since they're generated cryptographically with your secret private key, the other Persona's public key (which should be cached locally), and the related Endorsement information, so intercepting them in transit provides no added value to an attacker. Cryptographically invalid Endorsement signatures are rejected, and if the attacker wants to issue their own Endorsement, they can already do that - the weight of that endorsement depends on their own trustworthiness.

3. Message Data

3.1. Data Types

Number

A numeric quantity. Any restrictions on the field (bounds, integers only, etc) will be in the field description.

String

A string of UTF-8 characters.

Base64

Raw byte data, encoded as a Base64 string.

Timestamp

A date and time corresponding to an event. Must be a string in the specific YYYY-MM-DDThh:mm:ssZ format as defined by ISO 8601. Timestamps must always be in UTC, with the Z suffix.

Array of T

A list of values of a certain type T. Arrays may be homogenous or heterogenous, and may or may not be empty.

Object

A composite type consisting of a set of named fields and their values.

HashAlgorithm

A supported hash algorithm, represented as a String. Must be one of: The capitalizations shown are the preferred representation, but a HashAlgorithm value is case-insensitive.

CompressionAlgorithm

A supported compression algorithm, represented as a String. Must be one of: The capitalizations shown are the preferred representation, but a CompressionAlgorithm value is case-insensitive.

SymmetricCipher

A supported symmetric key cipher, represented as a String. Must be one of: The capitalizations shown are the preferred representation, but a SymmetricCipher value is case-insensitive.

AsymmetricCipher

A supported asymmetric key cipher, represented as a String. Must be one of: The capitalizations shown are the preferred representation, but a AsymmetricCipher value is case-insensitive.

MessageType

Denotes a type of message, represented as a String. Valid options are: The capitalizations shown are the preferred representation, but a MessageType value is case-insensitive.

SignatureType

Denotes a type of signature, represented as a String. Valid options are: The capitalizations shown are the preferred representation, but a SignatureType value is case-insensitive.

3.2. Endorsement Message

The canonical form for an endorsement data packet is a JSON-compatible map with the following keys and fields:

{
    "version": 1,
    "trustLevel": "Known",
    "signerFingerprint": "k79dnQ7BwEabPeqqXyZlvyEJ3exz4eVF",
    "timestamp": "2022-02-10T12:34:56Z",
    "signature": "TODO"
}

These values are valid for a signer public key of TODO and a target public key of TODO. You can verify it yourself. Note that these values cannot be used to verify the endorsement as is. The Base64 strings will need to be converted to raw bytes and the trust level and timestamp into a numeric value. See Part 2.3 for details on calculating Endorsement signatures.

4. Trust System

4.1. Trust Levels

Every Persona is able to apply a "trust level" to every other Persona they know of by way of Endorsements. Each Endorsement is associated with a trust level ranging from explicitly distrusted, to neutral, to trusted, to a special level reserved for keys you own the private key for, and therefore don't need to "trust" ownership of at all.

Below is the list of trust levels and their associated descriptions. To the left are the numeric values for each level in parentheses, and in square brackets are possible letters or symbols used to represent them in user interfaces. These are only suggestions; implementations may use whatever abbreviated depiction they want so long as the full-word label is identical to those listed below. This system works best when assigned trust levels are honest and accurate, so give some thought to these before chosing one for someone.

5. Cipher Suite

5.1. Hashing Algorithms

5.1.1. Allowed Hashing Algorithms

Note that public key fingerprints must always be generated with SHA3-512 truncated to 192 bits as defined in Part 2.1.

SHA2-512/256

SHA version 2 using an internal state size of 512 (8×64) bits, truncated to 256 bits. Thanks to the use of truncation, this method is resistant to length extension attacks.

SHA2-384

SHA version 2 using an internal state size of 512 (8×64) bits, truncated to 384 bits. Less resistant against length extension attacks than SHA2-512/256, but better collision resistance.

SHA3-256

SHA version 3 using an internal state size of 1600 (5×5×64) bits, with an output size of 256 bits. Equivalent to SHA2-512/256 for collision resistance, significantly stronger against length extension attacks but more expensive to compute than SHA2.

SHA3-384

SHA version 3 using an internal state size of 1600 (5×5×64) bits, with an output size of 384 bits. Stronger than SHA3-256 but more expensive to compute.

SHA3-512

SHA version 3 using an internal state size of 1600 (5×5×64) bits, with an output size of 512 bits. Stronger than SHA3-384 but more expensive to compute.

BLAKE2s-256

BLAKE2 with an internal state size of 256 bits and an output size of 256 bits. Significantly better worst-case collision resistance than SHA2 or SHA3, while being faster than both. SHA2/3 are still included as they are more thoroughly tested.

BLAKE2b-384

BLAKE2 with an internal state size of 512 bits and an output size of 384 bits. Stronger variant of BLAKE2s-256.

BLAKE2b-512

BLAKE2 with an internal state size of 512 bits and an output size of 512 bits. Stronger variant of BLAKE2b-384.

5.1.2. Disallowed Hashing Algorithms

MD4 and MD5

Cryptographically broken and collisions can be generated in seconds.

MD2

Less vulnerable than MD4 or MD5 but still not considered secure. MD2 support has been removed from OpenSSL, GnuTLS, and NSS.

SHA0 and SHA1

Cryptographically broken; generating collisions for SHA-1 is computationally feasible, and takes only around an hour for SHA-0 on commodity hardware.

SHA2-224, SHA2-256, and SHA2-512

All are vulnerable against length extension attacks.

SHA3-224

Weaker than SHA3-256 but with nearly identical computation time.

5.1.3. TBD

SHAKE128/SHAKE256

Whirlpool

RIPEMD-160

5.2. Symmetric Ciphers

5.2.1. Allowed Symmetric Ciphers

AES-GCM-128

AES-CCM-128

ChaCha20-Poly1305

5.2.2. Disallowed Symmetric Ciphers

5.3. Asymmetric Ciphers

5.3.1. Allowed Asymmetric Ciphers

RSA2048

RSA4096

Ed25519

Ed448

NISTp256

NISTp384

NISTp521

5.3.2. Disallowed Asymmetric Ciphers

5.4. Compression Algorithms

5.4.1. zlib

(deflate + zlib wrapper)

5.4.2. brotli

5.4.3. lzma

5.4.4. zstd