# Chain of signatures

# Definition

A signature chain is a series of ordered blocks, each consisting of a transaction and its signature.

  • Each transaction contains an operation, as well as its position in the chain, its creation timestamp and the hash of the previous transaction.
  • Each block signature contains the hash of the associated transaction, and the signature of that hash.

# Objectives

Each user account is associated with a signature chain, in which all operations concerning the keys of this account are recorded.
This allows any user to verify the integrity of the keys of any account, without having to trust a third party. Thus, even if Seald are ever compromised, the integrity of user accounts is protected.

# Protocol

Each block in the Seald signature chain consists of a transaction, a signature, and possibly additional information. The hash function used for the signature chain is SHA-256. Each transaction contains one operation, which can be the creation, renewal, or revocation of a key. Keys have a validity period. This period is up to five years. By default, Seald uses a validity period of three years.

The signature chain is initialized as soon as the account is created. A transaction is created at position 0, containing a creation operation, and must be signed by the signature key of the new device.

The following transactions can be the creation or revocation of a device, or the renewal of its private keys. The creation and renewal must be signed by a key already registered in the chain, and during its validity period.

When adding or renewing a key, the public signing key must be provided in the "extras" part of the block.

Revocation operations can be unsigned, if they are performed by the Team's administrator, or by the server (for example in case of expiry)

# Transaction

A transaction consists of two parts: some chain of signature properties, and the key operation.

# Properties

The chain of signature properties are :

  • position : the position in the chain.
  • previous_hash : the hash of the previous transaction.
  • timestamp : the timestamp of the transaction creation, in seconds since the UNIX epoch.
  • created_at : the timestamp of the transaction creation, in seconds since the UNIX epoch.
  • expire_at : the expiry timestamp of the key, in seconds.
  • sign :
    • user: The signer id.
    • device_id: The id of the key used to sign.

# Operation

An operation is composed of :

  • type : the type of operation, among "creation", "renewal" and "revocation".
  • device :
    • id : The id of the key concerned by the operation.
    • encryption_pubkey_hash : The hash of the public encryption key concerned.
    • signing_pubkey_hash : The hash of the public signing key concerned.

For a key addition or renewal operation, it is necessary to provide the full signing public key, encoded in base 64, in the transaction extras part.

# Signature

  • protocol : the signature protocol.
  • hash : the hash of the associated transaction.
  • signature : the signature of the hash, by the key specified in the transaction properties.

# Block example

{
  "transaction": {
    "properties": {
      "position": {"type": "integer"},
      "previous_hash": {"type": "string"},
      "timestamp": {"type": "string"},
      "signer": {
        "user": {"type": "string"},
        "device_id": {"type": "string"}
      },
      "created_at": {"type": "integer"},
      "expire_at": {"type": "integer"},
      "operation": {
        "type": {"type": "string", "enum": ["creation", "renewal", "revocation"]},
        "device": {
          "id": {"type": "string"},
          "encryption_pubkey_hash": {"type": "string"},
          "signing_pubkey_hash": {"type": "string"}
        }
      }
    }
  },
  "signature": {
    "protocol": {"type": "string"},
    "hash": {"type": "string"},
    "signature": {"type": "string"}
  },
  "extras": {
    "pubkeys": {"type": "string"}
  }
}