Skip to main content

1 DID

1.1 General Form

An Identifier (VaultysId) is composed with

  • a type (1 byte) type
  • a version (1 byte) v = 0
  • a proof (32 byte) p
  • a signing public key (variable) s
  • an encrypting public key (variable) e

1.1.1 Serialization and deserialization

We use messagepack serialization. MessagePack is a sort of JSON compressor https://msgpack.org/. The choice for this design is driven by the following consideration:

  • we don't need a very small footprint for the data as storage size is not an issue
  • we want to be friendly enough for third party implementation, above all
  • This serialization is also used for saltpack https://saltpack.org/ in order to stream encrypted data and this can be leveraged for the encryption part.

Caveats: Implementation can vary, i.e., VaultysId can vary if another implementation is used. Also, it is possible to alter some part of the messagePack data and still deserialize to the same data. (see tests)

VaultysId = type | messagepack({v, p, s, e})

warning

 Order of parameters of the message pack is important as it can influence the definition of the fingerprinting.

warning

Fingerprints may depend on message pack implementation.

warning

Fingerprints should NEVER be used at the protocol level. It can be used as a way to index a list of VaultysId. It is not recommended to use fingerprints as key exchange verification (like in PGP key exchange).

1.1.2 Fingerprint

Fingerprint = the first 40 characters of sha256(VaultysId)

1.1.3 DiD

Decentralized Id = did:vaultys:<fingerprint>

1.1.4 Secret

In order to backup VaultysId secrets, the following serialization is used secret = type | messagepack({v, p, ss, se}) where:

  • ss is the secret of public key s
  • se is the secret of public key e

2.2 Defined Type

There are 3 defined Types in the current state of the protocol type = 0: identifying a device (server, computer, etc...) type = 1: identifying a person. type = 3: identifying a person through a Fido2 device.

1.2.1 Type 3 serializations

As there is no proof concept for Fido2, the following parameters are set:

  • p = 0000...0000
  • s = COSE PublicKey as extracted by Fido2 Attestation
  • e is generated not handled by Fido2 device

As there is no backup from Fido2 device as recommended by certification, the following secret is used in order to port the VaultysId on various devices: secret = type | messagepack({v, fid, t, s, se}) where:

  • fid is the Fido2 id given by the attestation at creation
  • t is the webauthn transport used to connect to the device (in order to prevent from complex UI handling for the webauthn interface). t = hybrid | ble | nfc | usb Terms hybrid, ble, nfc, usb are the ones found in Fido2 specifications. for instance t = 0011 means that the Fido2 device can be reached only using NFC and USB transport

For information, our implementation for attestation creation is used with the following parameters:

navigator.credentials.create({
publicKey: {
challenge: randomBytes(32),
rp: {
name: "Vaultys ID",
},
user: {
id: Buffer.from("Vaultys ID", "utf-8"),
name: "Vaultys ID",
displayName: "Vaultys Wallet ID",
},
attestation: safari ? "none" : "direct",
authenticatorSelection: {
authenticatorAttachment: "cross-platform",
userVerification: "preferred"
},
pubKeyCredParams: [
{
"type": "public-key",
"alg": -7, // P256
},
{
"type": "public-key",
"alg": -8, // Ed25519/EdDSA
},
]
}
})

1.2.2 Type 3 signatures

Webauthn signatures have their own payload, we use attestation for