Loading proofofbrain-blog...

coinZdense deep Dive: Signature Structure

Signing Keys
index
Least/less authority

Signature Structure



In this post, we are going to describe the structure of the coinZdense post-quantum signatures. The first thing you will notice when looking just at the structure, is that coinZdense signatures have variable length and have the potential to become quite large, especially if we compare them to the small size of en ECDSA signature. The coinZdense signatures aren't designed to be the most compact hash-based signatures can be.

Remember the design goal priorities for the coinZdense project:

  1. Robust quantum resistant signatures
  2. Maximum parametrizability
  3. Support key-reuse-by-design utility chains and blockchain technology
  4. Maximize cross-language portability
  5. Support for privilege decomposition
  6. Support DEX chains

Signature size isn't in the list, and some of the priorities lead to somewhat larger signature sizes.

In the first MVP version, the size of signatures might be even huger. We plan to separate signature structure and signature serialization a bit in such a way that coinZdense will eventually support both JSON serialized signatures and binary signature serialization. It isn't decided yet if binary signatures are to be part of the MVP.

The exact binary signature serialization has not yet been decided on, and is thus not yet part of this post. For the JSON format, we don't use objects, only lists, integers and base64 encoded binary strings.

Before getting into the signature structure, please make sure you have read up on the rest of the deep dive posts up to this first. The structure is hard enough to follow with that knowledge and possibly close to impossible without. Here things will all come together, and you really need the foundation so see how things fit.

signature.gif

In JSON this structure will look something like this. The string would be longer base64 encoded strings, and the arrays, except for the pair of up/down values, will likely contain more entries than displayed here.

[
    "XX",
    ["XX"],
    0,
    64,
    0,
    17,
    "XX",
    "XX",
    ["XX"],
    [
       [
          ["XX"],
          [
             ["XX", "XX"]
          ]
       ]
    ] 
]

Note that once both serialization formats are implemented, JSON will remain the default for the API, but can be set explicitly to binary instead.

Now let's get into the structure. We start off by looking at the purple section of the diagram. To understand this section, we need to look back a bit at our parameterization file. Let's revisit our example hiveish.json file:

{
  "appname": "HIVEISH",
  "hashlen": 32,
  "otsbits": 5,
  "heights" : [9, 9, 8]
  "reserved": 12,
  "hierarchy": {
      "ACTIVE": {
          "POSTING": {
              "comment": {}   
          }
      },
      "recover_account": {}
  },
  "delegate_space": [
      {
          "name": "active",
          "allocate": 38,
          "reserved" : 5, 
      },
      {
          "name": "posting"
      },
      {
          "name": rare",
          "heights": [6, 6]
      }
  ]
}

To understand the app_id and privilege_id fields, we restructure the appname and hierarchy fields a bit into a single tree:

{
   "HIVEISH": {
      "ACTIVE": {
          "POSTING": {
              "comment": {}   
          }
      },
      "recover_account": {}
}

Or:

  • HIVEISH
    • ACTIVE
      • POSTING
        *comment
    • recover_account

We take the unsalted generic hash of the sting "HIVEISH". This will be the app_id and also the priviledge_id of the root-of-authority or owner key. Then we take this app_id and use it as key for the keyed hashing of the string "ACTIVE" to get the priviledge_id of the active key. We repeat this for the recover_account operation, and we get a priviledge_id representing the privilege just to use the recover_account operation in a transaction. Now we take the active key priviledge_id to hash the string "POSTING" and the result is the priviledge_id of the posting key. Finally we take the posting key priviledge_id as key and hash the string "comment" so we get the privilege id for just the comment operation.

At a top level, a signature consists of the app_id followed by an array of one or more signing-key signatures. The first entry will be the signing key that signed the transaction. If this key was the owner key, or if the client knows that this key is already stored somewhere retrievable on the blockchain, then this first signature may be the only one. If this isn't the owner key but some lower level key, then if this is the key's first use, if it's likely the blockchain hasn't recorded use of this key completely yet, or if the blockchain project opted not to implement this optimization, then following the signature of the transaction there will be signature of a higher privilege, signing the privilege delegation of the first key. This could be in a chain. There could be a third signature signing the privilege delegation of the second one, and so on.

This signing will use the following field of the signature before it:

  • priviledge_id[]
  • offset
  • allocation
  • key_type
  • pubkey[-1]

What this basically could do is:

  • Signature 1: Posting key signing a comment transaction.
  • Signature 2: Active key signing the posting key pubkey as having posting key privileges.
  • Signature 3: Owner key signing the active key pubkey as having active key privileges.

Or, departing from the limited HIVE privilege model:

  • Signature 1: Posting key signing a comment transaction.
  • Signature 2: Owner key signing a specialized bot key as having explicitly only comment and recover_account privileges.

Next up in our signature are the fields offset and allocation. The first one is a 64 bit unsigned integer value defining the offset of the signing key's index space. The allocation defines the allocation of key-space, starting at this offset, in bits. That is, an allocation of 20 for example would allocate 2^20 or an 1048576 indices index space.

Next up is the field key_type. Once again, a reference to the parameterization file. In this case, to the delegate_space field in this file. Note that for owner key signatures, this value will be zero, but that particular zero doesn't refer to the 0th element of the delegate_space.

On to the next section of the signature. This section pertains to the transaction or delegation signing. The idx field designates the index of the one-time key used for signing this operation. The salt is the random salt used in signing the transaction, and the digest is the generic hash using the salt as key value.

Next up in the signature is the pubkey array. This array consists of level-key pubkeys, depth first. So we start of with the pubkey of the deepest level key, and we end with the top level pubkey for the signing key.

The last part of the signing key signature, again this is an array with the same order as the pubkey array above. Where the pubkey array always contains all the pubkeys, the level-key signatures array will often contain less. Like at the signing keys level, a signature may be omitted if the signing party can assume the receiving side already has all the knowledge contained in the additional signatures. If there are more signatures, the first level-key signature signs the digest field of the larger signing-key signature and the remaining keys sign the pubkey of the level key one level down.

If we zoom in to the individual level-key signatures, these are made up by two parts. A Merkle header consisting of Merkle node values needed to get back to the level-key pubkey from the OTS pubkey, and of the OTS signature that is an array of up and down signing chunks as described before.

In our remaining few posts, we will look a bit more into the ideas behind some of the more advanced access controll hooks that coinZdens sets out to offer. We will be looking a bit closer into decomposition and revocation, two important building blocks for least authority based security setup. We must note that coinZdense aims to provide less authority, not least authority, but aims to do so in a way that could allow least authority infrastructure to be built on top of it. Decomposition and revocation. We already touched a bit on the first one. In the next post we shall look at both and how they fit together.

Signing Keys
index
Least/less authority

H2
H3
H4
3 columns
2 columns
1 column
1 Comment