# Introduction

## Getting started

Start developing your PAD application in three steps:

1. Join our waitlist at <https://www.pad.tech/>
2. Stay tuned and receive an Operator API key from us
3. Create your own PAD instance and integrate it into your app!

## Base URL

`https://api.pad.tech`

The only available API version is currently `v0`.

Check out the PAD API endpoint descriptions [here](/api_desc).


# How PAD Works

Here we describe the PAD protocol - the stuff that goes on behind the scenes of the API. This is the place to start if you want to understand the cryptography and mathematics behind the protocol before diving into code.

In this section we take some liberties in describing the protocol to make the main ideas easy to digest quickly. For all of the precise details, please see the comprehensive information in the **Code Samples** section of the documentation.

## Protagonists of the PAD protocol

* **Alice** is a user of the protocol, and she has a secret that she would like to make available to Bob under certain circumstances that are not well-defined in advance.
* **Bob** is the intended recipient of Alice's secret.
* **Trustees** respond to decryption requests - they do not judge whether a request is made at appropriate circumstances. To distribute trust and ensure that no secret is decrypted without Alice's knowledge, the PAD protocol makes use of multiple trustees. For any given secret to be decrypted, a threshold number of them must respond to Bob's decryption request.

## The lifecycle of PAD data

Here we describe how data flows through the PAD system.

### Secret generation and encryption

Let's imagine that Alice has an application built on the PAD API. She also has a secret, perhaps even a new one every second. There are no constraints on the secret - it could be a location, a passphrase, a document, or any other digital information. With her personal device, Alice generates a fresh symmetric key K and encrypts her secret with it. She then again encrypts that ciphertext using the public key of Bob. Next, the key K is split into shares using a cryptographic *secret sharing scheme*. This produces shares of the key K - one for each of the trustees. Finally, each share is encrypted using the public key of the trustee that the share is associated with.

Everything is now ready for storage with the PAD service.

### PAD-locking a secret

Alice assigns an arbitrary token value to reference her secret. Then, Alice's application sends all of the following to the PAD service using the API:

* Ciphertext encrypted with Bob's public key. This contains the encryption of her secret using the new symmetric key K.
* Encrypted shares of the key K: one share per trustee, with each share encrypted using a public key of the associated trustee.
* The hash of the token value.

The PAD service stores this data. Of course, Alice's secret remains safe because it is stored only in encrypted form with the PAD service. The trustees only need to store their own personal key pair.

Lastly, Alice sends Bob her token value. This is what he will use to request decryption of Alice's secret.

#### Updating data

If Alice has a new secret, she can repeat the above process. Alternatively, Alice may wish to update a secret previously secured with PAD and already associated with a token. This is convenient and straightforward as it doesn't require that she be in contact with Bob to provide a new token. To update a secret, Alice simply encrypts the new secret and submits this data to the PAD service again, using the same token hash.

### Submitting a decryption request

When Bob wishes to decrypt Alice's secret, he uses his application to send the token and its hash to the PAD service via the API. The PAD server then finds the information provided by Alice that has been associated with the token hash and publishes all of it on the PAD ledger.

The ledger now contains an encryption (under the symmetric key K and again under Bob's public key) of Alice's secret, and one encrypted secret share of K per trustee. This is when trustees participate in the decryption.

### The role of trustees

Trustees monitor the PAD ledger for decryption requests that require their action. When they see a ciphertext that has been encrypted with their public key, they decrypt and publish the result back to the ledger.

Each of the trustees publish a secret share of the decryption key K. Once a threshold number of the trustees have published the plaintext share, Alice knows Bob now has access to her secret.

### Recovering the original data

When a threshold number of trustees have responded to the data decryption request, Bob can access Alice's secret by taking the following steps:

1. Bob sees the ciphertext, which was encrypted to his public key. He decrypts to the plaintext, which itself is an encryption of Alice's secret using the symmetric key K.
2. Using the secret sharing scheme reconstruction procedure, Bob uses the trustee responses published on the ledger to compute K.
3. Using the ciphertext in (1) and the key in (2), Bob decrypts the ciphertext of Alice's secret. He now knows her secret.

### Transparency for Alice

The cornerstone of PAD is the accountability of its decryption: Alice will always know if and when her secret has been accessed. This accountability is provided by PAD's public immutable ledger which makes permanent Bob's decryption requests and the responses from trustees.

The way in which Alice has encrypted her secret requires that at least Bob and a threshold number of trustees are required to uncover her secret. In unusual circumstances, perhaps one or two trustees would be willing to work with Bob to decrypt a secret without checking that Bob's request is on the public immutable ledger. All such malicious efforts reveal nothing about Alice's secret unless a large coalition with a threshold number of trustees all operate maliciously. The threshold parameters can be tuned according to use case, either to emphasise security or high availability.

As long as there does not exist a malicious *threshold* of trustees, the PAD system provides both positive and negative proofs about whether an encryption has occurred. Ledger entries are proof positive. Their absence is proof that Bob has not decrypted.

### Ledger immutability

The PAD ledger is a privately managed Hyperledger Fabric (HLF) blockchain and anyone can use the API to query its state. Future updates of the PAD protocol will enable trustees to operate as a peer on any number of HLF channels. Presently, we use a different mechanism to guarantee and prove that the ledger is being maintained properly and is append-only. In addition to a key pair, trustees maintain a hash value that represents their current view of the PAD ledger based on the requests and responses that they have seen. Everytime a decryption request or trustee response is added to the ledger, trustees receive a hash chain proof that this update represents an append-only modification to the ledger state. To ensure that all trustees agree on the current state, trustees will occasionally attest to their current view by publishing the hash value on the ledger.

![PAD reference diagram](/files/aNv3ZuBDEdGHKda0AilV)

***

**Protocol in a nutshell** (slightly simplified - see code documentation for full details)

*Encrypting a secret*

* Let Alice's secret be $$s$$. Alice generates a brand new symmetric encryption key $$K$$ and uses it to encrypt her secret: $$C = Enc\_K(s)$$.
* Alice uses Bob's public key $$pkB$$ to encrypt again: $$C' = Enc\_{pkB}(C)$$.
* Suppose that there are $$n$$ trustees, holding public keys $$pkT\_1,\dots,pkT\_n$$. Alice's device uses a cryptographic *secret sharing scheme* to split $$K$$ into $$n$$ shares $$s\_1, \dots, s\_n$$. The secret sharing scheme reconstruction threshold is set to $$t$$, meaning that at least t-out-of-n shares are necessary and sufficient to reconstruct $$K$$.
* For each $$i = 1, \dots ,n$$, Alice encrypts the share $$s\_i$$ using the public key $$pkT\_i$$.
* Alice generates an arbitrary token value $$tkn$$ that is used to reference her secret. She sends $$(C', Enc\_{pkT\_1}(s\_1), \dots, Enc\_{pkT\_n}(s\_n), \mathrm{hash}(tkn))$$ to the PAD service.
* Alice sends $$tkn$$ to Bob.

*Decrypting a secret*

* Bob posts $$tkn$$ to the PAD ledger and in response, the PAD service publishes $$C'$$ and $$Enc\_{pkT\_i}(s\_i)$$ for each $$i = 1, \dots, n$$.
* For each $$i = 1,\dots,n$$, trustee $$i$$ decrypts $$Enc\_{pkT\_i}(s\_i)$$ and publishes $$s\_i$$ to the PAD ledger.
* Bob applies the secret sharing reconstruction procedure to at least $$t$$ of the published secret shares, deriving $$K$$.
* Bob can decrypt $$C'$$ to $$C = Enc\_K(s)$$ using his private key and decrypt $$C$$ to $$s$$ using $$K$$.

***


# Applying for a new PAD Instance


# Setting up a Trustee

Trustees are a core component of PAD. PAD relies on sufficient number of Trustees acting honestly. This is a means of decentralising trust. Given their essential role, Trustees should be run by trusted individuals.

We recommend running a Trustee on a Raspberry Pi. The Trustee software will then run as a daemon and periodically queries the PAD server and responds accordingly. The procedure is simple: download the scripts; edit the configuration file; then start the Trustee daemon.

In the following sections, we assume access to the Raspberry Pi is already set up, either with a monitor and mouse or in headless mode via secure shell (SSH) (See [this](https://jacobian.org/2021/jan/22/headless-rpi/) for a tutorial on setting up a headless Raspberry Pi).

## Clone the repository

```
pi@raspberry:~$ git clone https://github.com/sw7group/pad-trustee-node
```

The repository is currently private. Please email <padtrustees@sw7group.com> with your GitHub account name and we will send you a licence to provide access to the repo.

The repository consists of the installer script `install.sh`, the NodeJS source code of the Trustee, a template configuration file `config/pad-trustee.json` and a service file `service/pad-trustee.service` that makes the Trustee a daemon.

## Install node.js and npm

```
pi@raspberry:~$ sudo apt update
pi@raspberry:~$ sudo apt install nodejs npm
```

This will install Node.js and npm (Node Package Manager).

## Run the installer

with the command

```
pi@raspberry:~/pad-trustee-node$ ./install.sh
```

where `~/pad-trustee-node` is the location of the downloaded repository.

The script

* checks if nvm (Node Version Manager) is installed
  * if not, prompts to install nvm. The user can also manually install nvm.
* generates a random ID for the Trustee
* generates the decryption key and signing key
* creates directories that sit the configuration files and Trustee private keys, the source code and the service file
* generates a configuration file with the Trustee's ID and private keys
* installs NodeJS 14 and installs dependencies
* most importantly, display the public details of the Trustee

Copy the last step's output of the installer. This information is\
required to register the Trustee on the PAD server. This is a sample output of the installer:

```
Trustee ID:
trustee_3d552d143e0102e2
Trustee full name:
Trustee-3d552d143e0102e2
Trustee encryption key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwwvrAS7QgpRx7kWR/447
JY7UOZr7DdPRRuDN+zYE85kDh4EBgbgTTBbvk/5wSGg5x5QMR3coAy0HnEqT3Bxb
aDu/SH5ep+Ybn/Pfk6ddKjBoFt9j+nvVutprnskuBN5F+zb4YnQnGr9vygdhL74A
DLvp0njF3Ab6PZYtv990XrfsE7oBRaXZ+Lx4CV6KiyhDTaOHl7RI854G25O8IS3K
VLjjnNK1VTNttODXXJ5yOOk+zMhXHso7diz1fpbkUyg5Ez5Mwj7ksQ9PRFo7jn+P
HiAVFSIgd5jk5PSzxo3BozfGouigrjehmpp7HJRk7L5UWwUSUa8xYcPP40FxNZGp
YwIDAQAB
-----END PUBLIC KEY-----
Trustee verification key:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENkqLf3tg3OkCOsVws9c5ImjpKDPj
MuKz6R/aQ2PSwSvAOAiPRHZDwApnyr/v74JrY1DwEeqbaIWn2mVp/euhzw==
-----END PUBLIC KEY-----
```

## Register as a Trustee

Send the information above (Trustee ID, name, and the public keys) to <padtrustees@sw7group.com>. Until then, the PAD server will not process requests from the Trustee.

After registration, an Operator can nominate you to be a Trustee of their instance.

## Start the Trustee daemon

Reload the list of user services:

```
pi@raspberry:~/pad-trustee-node$ systemctl --user daemon-reload
```

Then, the Trustee daemon can be started:

```
pi@raspberry:~/pad-trustee-node$ systemctl --user start pad-trustee
```

The daemon should fail to start:

```
pi@raspberry:~/pad-trustee-node$ systemctl --user status pad-trustee

● pad-trustee.service - pad-trustee-node - Trustee service for Privacy-preserving Accountable Decryption (PAD)
     Loaded: loaded (...; disabled; vendor preset: enabled)
     Active: activating (auto-restart) since ...
    Process: ...
   Main PID: ...

start.sh[239579]:       [Symbol(kCapture)]: false,
start.sh[239579]:       [Symbol(kNeedDrain)]: false,
start.sh[239579]:       [Symbol(corked)]: 0,
start.sh[239579]:       [Symbol(kOutHeaders)]: [Object: null prototype]
start.sh[239579]:     },
start.sh[239579]:     data: { ok: false, message: 'Unauthorized' }
start.sh[239579]:   },
start.sh[239579]:   isAxiosError: true,
start.sh[239579]:   toJSON: [Function: toJSON]
start.sh[239579]: }
```

This is because we are using the template API key. We should obtain at least one working Trustee API key to get the daemon running properly.

## Obtain Trustee API keys

Whenever a PAD instance is created with you nominated as a Trustee, we will send you the instance name and a Trustee API key associated with the instance. You can choose to join and serve the instance or not.

To join a PAD instance as a Trustee, update the configuration file at `~/.pad-trustee/config/pad-trustee.yaml`. The `instances` section shows the list of instances the Trustee is serving. It is a dictionary where the key is the instance name and the value contains the API key.

Remove the template instance for the first time. Afterwards, add new entries in the dictionary with the corresponding instance name and API key.

For example, suppose two instances `my-pad-1.0` and `my-pad-2.0` have been created by Operators, and the Trustees' API key for them are `pad.api.key1` and `pad.api.key2`. This is how `instances` should look like in the configuration file:

```yaml
instances:
  my-pad-1.0:
    api_key: pad.api.key1
  my-pad-2.0:
    api_key: pad.api.key2
```

To apply the changes, restart the Trustee daemon:

```
pi@raspberry:~/pad-trustee-node$ systemctl --user restart pad-trustee
```

## Query Trustee status

You can query the Trustee daemon's status using `systemctl`:

```
pi@raspberry:~/pad-trustee-node$ systemctl --user status pad-trustee

● pad-trustee.service - pad-trustee-node - Trustee service for Privacy-preserving Accountable Decryption (PAD)
     Loaded: loaded (...; disabled; vendor preset: enabled)
     Active: active (running)
     ...
```

The status `Active: active (running)` shows that the daemon is running properly.

For a more detailed log of the daemon, you may use `journalctl`:

```
pi@raspberry:~/pad-trustee-node$ journalctl --user-unit pad-trustee
```

To see a live update of the log, use the `-f` flag. Press `Ctrl + C` to exit monitoring.

```
pi@raspberry:~/pad-trustee-node$ journalctl -f --user-unit pad-trustee
```

## Updating the Trustee code

To update the Trustee code, download/clone the repository again. Then run `patch.sh`.

The script will copy the up-to-date code over to the source directory of the Trustee daemon. It will then restart the daemon.

## (Optional) Enable Trustee daemon to start on boot

You may wish the Trustee daemon to start automatically on boot. To do this, simply use the `enable` command in `systemctl`:

```
pi@raspberry:~$ systemctl --user enable pad-trustee
```

## (Optional) Configure the Trustee daemon

* A PEM-encoded string may be used as the keys in the config file instead of specifying a path. For example, instead of having the section

```yaml
trustee:
  decryption_key_file: /path/to/decryption.pem
```

You may use a key directly like this:

```yaml
trustee:
  decryption_key: |-
    -----BEGIN PRIVATE KEY-----
    # ...
    -----END PRIVATE KEY-----
```

* You may change the list of instances the Trustee references in the `instances` section.
* You may change the `interval` in seconds in which the Trustee queries the PAD server.

> Do not set `interval` too small, otherwise some requests may be blocked by the server because of rate-limiting.

* You may change the path in which the states of the Trustee is stored at `storage.path`.


# Code Samples for Encryptor and Decryptor


# Node.js

## `cryptoUtil`

In the following sections, we will use different cryptographic primitives to implement parts of the PAD protocol. Here we provide a `cryptoUtil.js` Node.js script with these cryptographic primitives. (*Requires Node.js v14+*)

```javascript
// cryptoUtil.js
const crypto = require('crypto');

const EPHEMERAL_KEY_SIZE = 16;

/**
 * @typedef {Object} SymCiphertext
 * @property {string} ciphertext
 * @property {string} iv
 */
/**
 * @typedef {Object} HybridCiphertext
 * @property {SymCiphertext} encryptedMessage
 * @property {string} encryptedEphemeralKey
 */

/**
 * @param {object} options
 * @param {Object.<string, crypto.KeyObject>}
 */
exports.generateSigningKeyPair = (options={type: 'ec', namedCurve:'prime256v1'}) => {
  return crypto.generateKeyPairSync(options.type, options);
}

/**
 * @param {Buffer} data
 * @param {Buffer} symKey
 * @param {string} algorithm
 * @return {SymCiphertext}
 */
function encryptSym(data, symKey, algorithm='aes-128-cbc') {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv(algorithm, symKey, iv);
  let ciphertext = cipher.update(data);
  ciphertext = Buffer.concat([ciphertext, cipher.final()]);
  return {
    ciphertext: ciphertext.toString('base64'),
    iv: iv.toString('base64'),
  };
}
exports.encryptSym = encryptSym;

/**
 * @param {SymCiphertext} ciphertext
 * @param {symKey} string
 * @param {string} algorithm
 * @return {Buffer}
 */
function decryptSym(ciphertext, symKey, algorithm) {
  const iv = Buffer.from(ciphertext.iv, 'base64');
  const decipher = crypto.createDecipheriv(algorithm, symKey, iv);
  let data = decipher.update(Buffer.from(ciphertext.ciphertext, 'base64'));
  data = Buffer.concat([data, decipher.final()]);
  return data;
}
exports.decryptSym = decryptSym;

/**
 * @param {Buffer} data
 * @param {crypto.KeyLike} encKey
 * @return {Buffer | HybridCiphertext} the ciphertext as a bytes string
 */
function encryptAsym(data, encKey) {
  try {
    return crypto.publicEncrypt(encKey, data);
  } catch (err) {
    if (err.code === 'ERR_OSSL_RSA_DATA_TOO_LARGE_FOR_KEY_SIZE') {
      // avoid infinite recursive calls
      if (data.length <= EPHEMERAL_KEY_SIZE) {
        throw new Error('Ephemeral key size is too large for the encryption key type');
      }
      return encryptHybrid(data, encKey);
    }
    throw err;
  }
}
exports.encryptAsym = encryptAsym;

/**
 * @param {Buffer | HybridCiphertext} ciphertext
 * @param {crypto.KeyLike} decKey
 * @return {Buffer}
 */
function decryptAsym(ciphertext, decKey) {
  if (Buffer.isBuffer(ciphertext)) {
    return crypto.privateDecrypt(decKey, ciphertext);
  }
  return decryptHybrid(ciphertext, decKey);
}
exports.decryptAsym = decryptAsym;

/**
 * @param {Buffer} data
 * @param {crypto.KeyLike} encKey
 * @return {HybridCiphertext}
 */
function encryptHybrid(data, encKey) {
  const ephemeralKey = crypto.randomBytes(EPHEMERAL_KEY_SIZE);
  const encryptedMessage = encryptSym(data, ephemeralKey);
  const encryptedEphemeralKey = encryptAsym(ephemeralKey, encKey).toString('base64');
  // encryptedEphemeralKey must be returned by crypto.publicEncrypt, i.e. a Buffer
  return { encryptedMessage, encryptedEphemeralKey };
}
exports.encryptHybrid = encryptHybrid;

/**
 * @param {HybridCiphertext} ciphertext
 * @param {crypto.KeyLike} decKey
 * @return {Buffer}
 */
function decryptHybrid(ciphertext, decKey) {
  const encryptedEphemeralKey = Buffer.from(ciphertext.encryptedEphemeralKey, 'base64');
  const ephemeralKey = decryptAsym(encryptedEphemeralKey, decKey);
  const {encryptedMessage} = ciphertext;
  const data = decryptSym(encryptedMessage, ephemeralKey);
  return data;
}
exports.decryptHybrid = decryptHybrid;

/**
 * @param {string | Buffer} data
 * @param {crypto.KeyLike} signingKey
 * @param {string} algorithm
 * @return {Buffer}
 */
function sign(data, signingKey, algorithm='SHA256') {
  const sign = crypto.createSign(algorithm);
  sign.update(data);
  sign.end();
  const signature = sign.sign(signingKey);
  return signature;
}
exports.sign = sign;

/**
 * @param {string | Buffer} data
 * @param {crypto.KeyLike} verificationKey 
 * @param {string | Buffer} signature
 * @param {string} algorithm
 * @return {boolean}
 */
function verify(data, verificationKey, signature, algorithm='SHA256') {
  if (typeof signature === 'string') {
    signature = Buffer.from(signature, 'base64');
  }
  const verify = crypto.createVerify('SHA256');
  verify.update(data);
  verify.end();
  const verification = verify.verify(verificationKey, signature);
  return verification;
};
exports.verify = verify;

/**
 * @param {...(string | Buffer)} data
 * @return {Buffer}
 */
function hash(...data) {
  const sha256 = crypto.createHash('sha256');
  for (const d of data) {
    sha256.update(d);
  }
  return sha256.digest();
}
exports.hash = hash;

/**
 * @param {Buffer} a
 * @param {Buffer} b
 * @return {Buffer}
 */
function xor(a, b) {
  assert(a.length === b.length);
  const result = a.map((byte, i) => byte ^ b[i]);
  return Buffer.from(result);
}
exports.xor = xor;
```

* `EPHEMERAL_KEY_SIZE` (global variable): is the number of random bytes of the ephemeral keys used in a hybrid (symmetric & asymmetric) encryption.
* `encryptSym` (function): performs a symmetric encryption. Algorithm: `AES-128-CBC`.
* `decryptSym` (function): performs a symmetric decryption. Algorithm: `AES-128-CBC`
* `encryptAsym` (function): performs an asymmetric encryption. If the data to be encrypted is too large, it uses a hybrid encryption instead. Algorithm: depends on input key type
* `decryptAsym` (function): performs an asymmetric decryption. If the ciphertext is a result from a hybrid encryption, then it uses hybrid decryption; Otherwise, it uses asymmetric decryption. Algorithm: depends on input key type
* `encryptHybrid` (function): performs a hybrid encryption: performs a symmetric encryption on the data with an ephemeral key, then performs an asymmetric encryption on the ephemeral key with the encryption key.
* `decryptHybrid` (function): performs a hybrid decryption: retrieve the ephemeral key with an asymmetric decryption. Then it performs a symmetric decryption on the payload with the ephemeral key.
* `sign` (function): digitally signs a piece of data with a signing key. Algorithm: depends on input key type; data is first hashed with `SHA256`;
* `verify` (function): verifies if a signature matches with the alleged data and verification key. Algorithm: depends on input key type; data is first hashed with `SHA256`.
* `hash` (function): hashes the data in the argument list. Algorithm: `SHA256`
* `xor` (function): performs exclusive-or on two binary arrays

## Encrypting <a href="#encrypting" id="encrypting"></a>

An `Encryption` is a JSON object which has the following form:

```
{
    "description": string,
    "tokenHash": 256-bit-hex-string,
    "ciphertext": hybrid-ciphertext,
    "trusteeShares": {
        [trusteeId]: {
            "encrypted": base64-string,
            "hashed": 256-bit-hex-string,
        },
    },
    "validatorShares": {
        [validatorId]: {
            "encrypted": hybrid-ciphertext,
        },
    },
}
```

, where `hybrid-ciphertext` has the form

```
{
    "encryptedMessage": {
        "ciphertext": base64-string,
        "iv": base64-string,
    },
    "encryptedEphemeralKey": base64-string,
}
```

The encryption phase involves the encryptor sending an `Encryption` to the PAD server. Thus, it is essential to understand how it is created. We will go through its properties one by one.

* `"description"`: Description of the `encryption`. This can be an arbitrary string.
* `"tokenHash"`: Hased value of a `token`. `tokenHash = SHA256(token)`.
* `"ciphertext"`: The ciphertext of the secret encrypted with the decryptor's public key and the symmetric key `k`.
* `"trusteeShares"`: A dictionary containing all the encrypted and hashed trustee shares.
  * `[trusteeId]`: A dictionary entry where the key is a trustee's ID, and the value is an object of encrypted and hashed trustee shares.
    * `"encrypted"`: The trustee's share of the masked symmetric key `k \oplus R` used to encrypt the secret, encoded as a base64 string.
    * `"hashed"`: `SHA256` of the trustee's share, encoded as a hex string.
* `"validatorShares"`: A dictionary containing all the encrypted validator shares.
  * `[validatorId]`: A dictionary entry where the key is a validator's ID, and the value is an object of encrypted validator shares.
    * `"encrypted"`: The validator's share of the mask `R` to the symmetric key used to encrypt the secret together with the decryptor's public key. Since the public key is large, the validator's shares are large too. Thus, the encryption of a validator's share uses an ephemeral key as a symmetric key. `k` and decryptor's key.

### Creating `token` and `tokenHash`

A `token` is a random number sent from the encryptor to the decryptor for her to later request for a piece of encryptor's data. It is essential to keep it secret between the encryptor and decryptor until the data request phase. An `encryption`'s ID is `tokenHash`, the hash value of `token`. For portability and readability, both `token` and `tokenHash` are represented as hexadecimal strings.

> Important: note that `token` should be taken as a lowercase string when hashed into `tokenHash`.

```javascript
// create-token-and-hash.js
const crypto = require('crypto');
const {hash} = require('./cryptoUtil');

const token = crypto.randomBytes(16).toString('hex'); // 'd1fbe8b5f3ffd7a16a2aa400ebc0194f'
const tokenHash = hash(token).toString('hex'); // '5892a6c7ad71b358df760b4291a8adf974f77bd9d3f16c4fd38c58147e80f401'
```

### Creating `ciphertext`

The `ciphertext` part of an `encryption` should be encrypted with the symmetric key first, then the decryptor's encryption key. To ensure integrity, a digital signature from the encryptor against the ciphertext in the first encryption should be attached before the second encryption. In general, the first step creates the ciphertext $$c = SymEnc\_{k}(token, s)$$ Then the second step creates $$AsymEnc\_{Bek}(c, Sign\_{Ask}(c))$$ For example, suppose `secret = "my_secret"` is the encryptor's secret, the following code snippet generates `c`.

```javascript
// create-ciphertext-first-step.js
const crypto = require('crypto');
const {encryptSym} = require('./cryptoUtil');

const token = /* from create-token-and-hash.js */;
const secret = 'my_secret';
const dataJson = {token, secret};
const data = JSON.stringify(dataJson);

const k = crypto.randomBytes(16);
const c = encryptSym(data, k);
```

With `c`, the `ciphertext` can be created like this:

```javascript
// create-ciphertext-second-step.js
const crypto = require('crypto');
const fs = require('fs');
const {encryptAsym} = require('./cryptoUtil');

const c = /* from create-ciphertext-first-step.js */;
const encryptorSigningKey = fs.readFileSync('/path/to/encryptor/signing-key.pem');
const decryptorEncryptionKey = fs.readFileSync('/path/to/decryptor/encryption-key.pem');
const payload = JSON.stringify(c);
const signature = sign(payload, encryptorSigningKey).toString('base64');
const signedPayloadString = JSON.stringify({payload, signature});
const signedPayload = Buffer.from(signedPayloadString);

const ciphertext = encryptHybrid(signedPayload, decryptorEncryptionKey);
```

### Secret sharing

The essential part of creating `trusteeShares` and `validatorShares` is secret sharing. We use the library [secrets.js-grempe](https://github.com/grempe/secrets.js). In PAD, we also support 1 to be the thresholds. Moreover, we assumed the number of trustees and validators in instances is at most 256, it suffices to use 8 bits for secret sharing indices.

```javascript
// secret-sharing.js
const sss = require('secrets.js-grempe');

const BITS = '8';

/**
 * @param {Buffer} s
 * @param {number} n
 * @param {number} t
 * @return {Buffer[]}
 */
function split(s, n, t) {
  assert(n >= t);
  let sharesBytes;
  if (n === 1) {
    const id = Buffer.alloc(1,1);
    const prefix = Buffer.alloc(1,1);
    sharesBytes = [Buffer.concat([id, prefix, s])];
  } else {
    const sHex = s.toString('hex');
    const shares = sss.share(sHex, n, t);
    sharesBytes = shares.map((share) =>
      // remove 'bits' part with slice
      Buffer.from(share.slice(1), 'hex'),
    );
  }
  return sharesBytes;
}
exports.split = split;

/**
 * @param {Buffer[]} shares
 * @return {Buffer}
 */
function combine(shares) {
  const combinedHex = sss.combine(
    shares.map((share) => BITS + share.toString('hex')),
  );
  return Buffer.from(combinedHex, 'hex');
}
exports.combine = combine;
```

### Creating `trusteeShares`

To create `trusteeShares`, the encryptor should first have knowledge about the settings of the instance, including the trustee threshold and the list of trustees referencing the instance (check out GET /metadata and GET /all-trustees/{trustee-id}. These information are also in one of the first few blocks on the ledger). The symmetric key `k` is then masked with a random number. This masked symmetric key is the secret shared among the trustees. After that, each share of trustees' is encrypted with their individual encryption key (the mapping between secret sharing index and trustee does not matter, but we recommend following the order in the instance's metadata. For example, `trustee1` may hold a share of index `00` in an `encryption`, but hold another share of index `01` in another `encryption`). For auditing purposes, the hash of each share *before encrypting* should also be included, so that after a trustee post her share, consistency can be checked.

```javascript
const crypto = require('crypto');
const {encryptAsym, hash, xor} = require('./cryptoUtil');
const {split} = require('./secret-sharing');

/**
 * @param {Buffer} maskedSymKey
 * @param {object} trustees
 * @param {number} trusteeThreshold
 * @return {object}
 */
function createTrusteeShares(maskedSymKey, trustees, trusteeThreshold) {
  const n = Object.keys(trustees).length;
  const shares = split(maskedSymKey, n, trusteeThreshold);
  const trusteeShares = {};
  for (const [i, [trustee, {encryptionKey}]] of Object.entries(trustees).entries()) {
    const encryptedShare = encryptAsym(shares[i], encryptionKey);
    const hashedShare = hash(shares[i]);
    trusteeShares[trustee] = {
      encrypted: encryptedShare.toString('base64'),
      hashed: hashedShare.toString('hex'),
    };
  }
  return trusteeShares;
}

const k = /* from create-ciphertext-first-step.js */;
const R = crypto.randomBytes(16);

// the masked symmetric key maskedK is the secret to be shared
const maskedK = xor(k, R);

const trustees = {
  'trustee1': {
    encryptionKey: /* trustee1's encryption key */,
  },
  'trustee2': {
    encryptionKey: /* trustee2's encryption key */,
  },
};
const trusteeThreshold = 2;
const trusteeShares = createTrusteeShares(maskedK, trustees, trusteeThreshold);
```

### Creating `validatorShares`

This is similar to creating `trusteeShares`, except the secret shared among the validators is the mask `R` together with the decryptor's public key to identify him.

```javascript
const crypto = require('crypto');
const {split} = require('./secret-sharing');

/**
 * @param {Buffer} RAndBvkPayload
 * @param {object} validators
 * @param {number} validatorThreshold
 * @return {object}
 */
function createValidatorShares(RAndBvkPayload, validators, validatorThreshold) {
  const nPrime = Object.keys(validators).length;
  const shares = split(RAndBvkPayload, nPrime, validatorThreshold);
  const validatorShares = {};
  for (const [i, [validator, {encryptionKey}]] of Object.entries(validators).entries()) {
    const encryptedShare = encryptHybrid(shares[i], encryptionKey);
    validatorShares[validator] = {
      encrypted: encryptedShare,
    };
  }
  return validatorShares;
}

const R = /* from create-trustee-shares.js */;
const bvk = /* decryptor's verification key or identity */;

const RAndBvkJson = {
  mask: R.toString("base64"),
  decryptorIdentity: bvk.toString(),
};
const RAndBvkPayload = Buffer.from(JSON.stringify(RAndBvkJson));

const validators = {
  'validator1': {
    encryptionKey: /* validator1's encryption key */,
  },
  'validator2': {
    encryptionKey: /* validator2's encryption key */,
  },
};
const validatorThreshold = 2;

const validatorShares = createValidatorShares(RAndBvkPayload, validators, validatorThreshold);
```

### Creating `channelKey`

You will also need a signing key pair for creating the new channel. This ensures that only the encryptor can modify the `Encryption` object using endpoint for updating an `Encryption` in a channel.

This channel key pair should be generated freshly and must not be the key pair that identifies the encryptor. Only the public (verification) key is sent to the server. The encryptor should keep the private (signing) key so long as she would update the `Encryption` therein.

```javascript
// generate-channel-key.js
const {generateSigningKeyPair} = require('./cryptoUtil');

const channelKeyPair = generateSigningKeyPair();
const channelSigningKey = channelKeyPair.privateKey;
const channelKey = channelKeyPair.publicKey.export({type: 'spki', format: 'pem'});
```

That's it! We have gone through the steps of creating a new channel. Recall that the `encryption` is being sent to the PAD service server and the `token` is then shared with the decryptor out-of-band. The encryption channel allows the encryptor to update the secret which is useful in some use cases.

### Updating `Encryption` object

Using the channel signing key and the `token-hash`, the encryptor can update her `Encryption` object in the channel associated with the `token`. The following code snippets show how one create `encryptionPayload` and `signature` required for the operation.

```javascript
const {sign} = require('./cryptoUtil');

const channelSigningKey = /* from generate-channel-key.js */
const newEncryption = {
  // the new encryption content...
};

const encryptionPayload = JSON.stringify(newEncryption);
const signatureBuffer = sign(encryptionPayload, channelSigningKey);
const signature = signatureBuffer.toString('base64');
```

## Decrypting <a href="#decrypting" id="decrypting"></a>

The decryption phase happens after the encryption has been uploaded, a data request has been posted, and sufficient number of trustees and validators, respectivelly, have responded. At this stage, the decryptor has enough information to decrypt the encryptor's secret.

### Verifying responses correctness

It is important for the decryptor to check correctness and integrity of the trustee and validator responses. Checking correctness can be done by checking consistency between a response and its hash submitted by the encryptor at encryption time. Checking integrity involves verifying a signature against the response payload.

```javascript
/* verify-responses.js */
const {hash, verify} = require('./cryptoUtil');

/**
 * @typedef {Object} SignerMetadata
 * @property {string} id
 * @property {string} fullName
 * @property {'Trustee' | 'Validator' | 'Server'} role
 */ 
/**
 * @typedef {Object} SignedResponse
 * @property {string} payload
 * @property {{signerMetadata: SignerMetadata, payload: string}}
/**
 * @param {string} token
 * @param {Object<string, string>} trusteeVerificationKeys
 * @param {Object<string, SignedResponse>} trusteeResponses
 * @param {Object<string, string>} hashedTrusteeShares
 */
function verifyTrusteeResponses(token, trusteeVerificationKeys, trusteeResponses, hashedTrusteeShares) {
  for (const [trusteeId, signedTrusteeShare] of Object.entries(trusteeResponses)) {
    // check signature
    const trusteeResponsePayload = signedTrusteeShare.trusteeResponse;
    const vk = trusteeVerificationKeys[trusteeId];
    const signature = signedTrusteeShare.signature.payload;
    if (!verify(trusteeResponsePayload, vk, signature)) {
      throw new Error('Signature not match with payload');
    }

    const trusteeResponse = JSON.parse(trusteeResponsePayload);
    // check payload metadata
    if (trusteeResponse.token !== token) {
      throw new Error('Token mismatch');
    }
    if (trusteeResponse.type !== 'trustee_response') {
      throw new Error('Object type mismatch');
    }
    // check signer consistency
    const signer = signedTrusteeShare.signature.signerMetadata;
    if (signer.id !== trusteeId ||
      trusteeResponse.trusteeId !== trusteeId ||
      signer.role !== 'Trustee') {
      throw new Error('Wrong signer');
    }
    // check hash
    const {trusteeShare} = trusteeResponse;
    const hex = hash(Buffer.from(trusteeShare, 'base64')).toString('hex');
    if (hex !== hashedTrusteeShares[trusteeId]) {
      throw new Error('Wrong trustee share');
    }
  }
}

/**
 * @param {string} token
 * @param {Object<string, string>} validatorVerificationKeys
 * @param {Object<string, SignedResponse>} validatorResponses
 */
function verifyValidatorResponses(token, validatorVerificationKeys, validatorResponses) {
  for (const [validatorId, signedValidatorShare] of Object.entries(validatorResponses)) {
    // check signature
    const validatorResponsePayload = signedValidatorShare.validatorResponse;
    const vk = validatorVerificationKeys[validatorId];
    const signature = signedValidatorShare.signature.payload;
    if (!verify(validatorResponsePayload, vk, signature)) {
      throw new Error('Signature not match with payload');
    }

    const validatorResponse = JSON.parse(validatorResponsePayload);
    // check payload metadata
    if (validatorResponse.token !== token) {
      throw new Error('Token mismatch');
    }
    if (validatorResponse.type !== 'validator_response') {
      throw new Error('Object type mismatch');
    }
    // check signer consistency
    const signer = signedValidatorShare.signature.signerMetadata;
    if (signer.id !== validatorId ||
      validatorResponse.validatorId !== validatorId ||
      signer.role !== 'Validator') {
      throw new Error('Wrong signer');
    }
  }
}

const token = /* token */;
/* these verification keys can be cached/stored locally */
const trusteeVerificationKeys = {
  'trustee1': /* from GET /all-trustees/trustee1 */,
  /* ... */
};
const validatorVerificationKeys = {
  'validator1': /* from GET /all-validators/validator1 */,
  /* ... */
};
const {trusteeResponses} = /* from GET /data-requests/{token}/trustee-responses */;
/*
{
  "trustee100": {
    "payload": "{\"token\":\"e3b0c44298fc1c149afbf4c8996fb924\",\"trusteeShare\":\"0110\",\"type\":\"trustee_response\",\"trusteeId\":\"trustee100\"}",
    "signature": {
      "signerMetadata": {
        "id": "trustee100",
        "fullName": "Trustee-100",
        "role": "Trustee"
      },
      "payload": "MEUCIGUjs7m3ZaJxB7i9G2GjEI+LpkXcsed3fkVDdchB1W5WAiEAtUsM5m/ouA/eaJBk39DT0tDLc97TeM093s4vuws+fgc="
    },
    "submissionTime": "2021-09-13T11:42:50Z"
  }
}
*/
const {validatorResponses} = /* from GET /data-requests/{token}/validator-responses */;
const {hashedTrusteeShares} = /* from GET /encryptions/{token-hash}/hashed-trustee-shares */;
verifyTrusteeResponses(
  token,
  trusteeVerificationKeys,
  trusteeResponses,
  hashedTrusteeShares,
);
verifyValidatorResponses(
  token,
  validaotrVerificationKeys,
  validatorResponses,
);
```

### Verifying `ciphertext` integrity

Recall that the `ciphertext` payload includes the encryptor's signature before encrypted with decryptor's encryption key. This ensures that the payload is not modified by third party, including the PAD server. The signature needs to be verified before decrypting.

```javascript
/* verify-ciphertext.js */
const fs = require('fs');
const {decryptHybrid, verify} = require('./cryptoUtil');

/** @typedef {import ('crypto').KeyLike} KeyLike
/** @typedef {import ('./cryptoUtil').HybridCiphertext} HybridCiphertext
/** @typedef {import ('./cryptoUtil').SymCiphertext} SymCiphertext

/**
 * @param {HybridCiphertext} ciphertext
 * @param {KeyLike} decryptorDecryptionKey
 * @param {KeyLike} encryptorVerificationKey
 * @return {SymCiphertext}
 */
function decryptVerifyCiphertext(ciphertext, decryptorDecryptionKey, encryptorVerificationKey) {
  const decrypted = decryptHybrid(ciphertext, decryptorDecryptionKey);
  const signedPayloadString = decrypted.toString('utf8');
  const {payload, signature} = JSON.parse(signedPayloadString);
  if (!verify(payload, encryptorVerificationKey, signature)) {
    throw new Error('Signature not match with payload');
  }
  const innerCiphertext = JSON.parse(payload);
  return innerCiphertext;
}

const {ciphertext} = /* from GET /encryptions/{token-hash}/ciphertext */;
const decryptorDecryptionKey = fs.readFileSync('/path/to/decryptor/decryption-key.pem');
const encryptorVerificationKey = fs.readFileSync('/path/to/encryptor/verification-key.pem');

const c = decryptVerifyCiphertext(
  ciphertext,
  decryptorDecryptionKey,
  encryptorVerificationKey,
);
```

### Reconstructing masked symmetric key from trustees

To perform the symmetric decryption we need sufficient responses from trustees and validators, respectively. Then those will combine to the masked symmetric key and the masked. We show how to reconstruct the masked symmetric key from trustees' responses in this section. Obviously, it has redundancy with our [previous example](#verifying-responses-correctness). In actual implementation, these scripts can be merged. For example, parse the response, push the share to an array only if it is valid, then combine those later.

```javascript
/* reconstruct-masked-k.js */
const {combine} = require('./secret-sharing.js');

const {trusteeResponses} = /* from GET /data-requests/{token}/trustee-responses */;
const trusteeShares = Object.values(trusteeResponses).map((signed) => {
  const trusteeResponse = JSON.parse(signed.trusteeResponse);
  const share = Buffer.from(trusteeResponse.trusteeShare, 'base64');
  return share;
});
const maskedK = combine(trusteeShares);
```

### Reconstructing the mask from validators

```javascript
/* resconstruct-r.js */
const {combine} = require('./secret-sharing.js');

const {validatorResponses} = /* from GET /data-requests/{token}/validator-responses */;
const validatorShares = Object.values(validatorResponses).map((signed) => {
  const validatorResponse = JSON.parse(signed.validatorResponse);
  const share = Buffer.from(validatorResponse.validatorShare, 'base64');
  return share;
});
const RAndBvkPayload = combine(validatorShares);
const RAndBvkString = RAndBvkPayload.toString();
const RAndBvkJson = JSON.parse(RAndBvkString);
const R = Buffer.from(RAndBvkJson.mask, 'base64');
```

### Decrypting!

The decryptor now has everything to retrieve the encryptor's secret.

```javascript
const {xor, decryptSym} = require('./cryptoUtil');

const maskedK = /* from reconstruct-masked-k.js */;
const R = /* from reconstruct-r.js */;
const c = /* from verify-ciphertext.js */;

const k = xor(maskedK, R);
const decrypted = decryptSym(c, k);
const dataJson = JSON.parse(decrypted.toString('utf8'));
const {token, secret} = dataJson;
if (token !== /* token */) {
  throw new Error('Token mismatch');
}
console.log(secret); // my_secret
```


# React Native

## `cryptoUtil`

In the following sections, we will use different cryptographic primitives to implement parts of the PAD protocol. Here we provide a `cryptoUtil.js` script with these cryptographic primitives.

The secret sharing library is forked from [secrets.js-grempe](https://github.com/grempe/secrets.js), with slight modifications for react native. The source code is provided in the bottom of this page.

```javascript
import { RSA, KeyPair } from 'react-native-rsa-native';
import { NativeModules } from 'react-native';
import type { Aes as AesType } from 'react-native-aes-crypto';
import { encode as btoa } from 'base-64';
import { toByteArray, fromByteArray } from 'base64-js';
import * as sss from './secrets.js';

const Aes: any = NativeModules.Aes;
const EPHEMERAL_KEY_SIZE = 16;
const BITS = '8';

export async function split(
  secret: string,
  numShare: number,
  threshold: number,
): Promise<string[]> {
  return (await sss.split(secret, numShare, threshold)).map(share => share.substring(1));
}

export function combine(shares: string[]): string {
  return sss.combine(shares.map(share => BITS + share));
}

export interface SymCiphertext {
  ciphertext: string;
  iv: string;
}

export interface HybridCiphertext {
  encryptedMessage: SymCiphertext;
  encryptedEphemeralKey: string;
}

export function randomBytes(length: number): Promise<string> {
  return Aes.randomKey(length);
}

function generateRsaKeyPair(keySize: number = 4096): Promise<KeyPair> {
  return RSA.generateKeys(keySize);
}

export function generateEncryptionKeyPair(
  options: { type: 'rsa'; keySize: number } = { type: 'rsa', keySize: 4096 },
): Promise<KeyPair> {
  if (options.type === 'rsa') {
    return generateRsaKeyPair(options.keySize);
  }
  throw new Error(`Unsupported type ${options.type}`);
}

export function generateSigningKeyPair(
  options: { type: 'rsa'; keySize: number } = { type: 'rsa', keySize: 4096 },
): Promise<KeyPair> {
  return generateEncryptionKeyPair(options);
}

export async function encryptSym(
  data: string,
  symKey: string,
  algorithm: AesType.Algorithms = 'aes-128-cbc',
) {
  const iv = await Aes.randomKey(16);
  const ciphertext = await Aes.encrypt(data, symKey, iv, algorithm);
  return {
    ciphertext,
    iv: hexToBase64(iv),
  };
}

export function decryptSym(
  ciphertext: SymCiphertext,
  symKey: string,
  algorithm: AesType.Algorithms = 'aes-128-cbc',
): Promise<string> {
  const iv = base64ToHex(ciphertext.iv);
  return Aes.decrypt(ciphertext.ciphertext, symKey, iv, algorithm);
}

export async function encryptAsym(
  data: string,
  encKey: string,
): Promise<string | HybridCiphertext> {
  try {
    return await RSA.encrypt64(data, encKey);
  } catch (err: unknown) {
    // if error indicates plaintext too big
    // avoid infinite recursive calls
    if (data.length <= EPHEMERAL_KEY_SIZE) {
      throw new Error(
        'Ephemeral key size is too large for the encryption key type',
      );
    }
    return encryptHybrid(data, encKey);
  }
}

export function decryptAsym(
  ciphertext: string | HybridCiphertext,
  decKey: string,
): Promise<string> {
  if (typeof ciphertext === 'string') {
    return RSA.decrypt64(ciphertext, decKey);
  }
  return decryptHybrid(ciphertext, decKey);
}

export async function encryptHybrid(
  data: string,
  encKey: string,
): Promise<HybridCiphertext> {
  const ephemeralKey = await Aes.randomKey(EPHEMERAL_KEY_SIZE);
  const encryptedMessage = await encryptSym(data, ephemeralKey);
  const encryptedEphemeralKey = await encryptAsym(ephemeralKey, encKey);
  if (typeof encryptedEphemeralKey !== 'string') {
    throw new Error(
      'Ephemeral key size is too large for the encryption key type',
    );
  }
  // encryptedEphemeralKey must be returned by crypto.publicEncrypt, i.e. a Uint8Array
  return { encryptedMessage, encryptedEphemeralKey };
}

export async function decryptHybrid(
  ciphertext: HybridCiphertext,
  decKey: string,
): Promise<string> {
  const { encryptedEphemeralKey } = ciphertext;
  const ephemeralKey = await decryptAsym(encryptedEphemeralKey, decKey);
  const { encryptedMessage } = ciphertext;
  return decryptSym(encryptedMessage, ephemeralKey);
}

export function sign(data: string, signingKey: string): Promise<string> {
  return RSA.sign(data, signingKey);
}

export function verify(
  data: string,
  verificationKey: string,
  signature: string,
): Promise<boolean> {
  return RSA.verify(signature, data, verificationKey);
}

export function hash(...data: string[]): Promise<string> {
  return Aes.sha256(data.join(''));
}

export function xor(a: string, b: string): string {
  const bChunks = split2(b);
  return split2(a)
    .map((byteHex, i) =>
      // eslint-disable-next-line no-bitwise
      (parseInt(byteHex, 16) ^ parseInt(bChunks[i], 16))
        .toString(16)
        .padStart(2, '0'),
    )
    .join('');
}

function split2(str: string): string[] {
  const chunks = str.match(/\w{2}/g);
  if (chunks === null) {
    throw new Error('Invalid encoding');
  }
  return chunks;
}

export function hexToBase64(hex: string): string {
  const chunks = split2(hex);
  return btoa(
    chunks.map(byteHex => String.fromCharCode(parseInt(byteHex, 16))).join(''),
  );
}

export function base64ToHex(b64: string): string {
  return binToHex(toByteArray(b64));
}

export function hexToBin(hex: string): Uint8Array {
  const chunks = split2(hex);
  return Uint8Array.from(chunks.map(byteHex => parseInt(byteHex, 16)));
}

export function binToHex(bin: Uint8Array): string {
  return bin.reduce(
    (str, byte) => str + byte.toString(16).padStart(2, '0'),
    '',
  );
}

export { toByteArray as base64ToBin, fromByteArray as BinToBase64 };

export function hexToUtf8(hex: string): string {
  return sss.hex2str(hex);
}

export function utf8ToHex(a: string): string {
  return sss.str2hex(a);
}

export function binToUtf8(bin: Uint8Array): string {
  return String.fromCharCode(...bin);
}

export function utf8ToBin(a: string): Uint8Array {
  return Uint8Array.from(a.split('').map(byte => byte.charCodeAt(0)));
}

export function base64ToUtf8(b64: string): string {
  return binToUtf8(toByteArray(b64));
}

export function utf8ToBase64(a: string): string {
  return fromByteArray(utf8ToBin(a));
}
```

* `EPHEMERAL_KEY_SIZE` (global variable): is the number of random bytes of the ephemeral keys used in a hybrid (symmetric & asymmetric) encryption.
* `randomBytes` (function): generates random bytes encoded in hexidecimal.
* `generateEncryptionKeyPair` (function): generates fresh encryption key pairs.
* `generateSigningKeyPair` (function): generates fresh signing key pairs.
* `encryptSym` (function): performs a symmetric encryption. Algorithm: `AES-128-CBC`.
* `decryptSym` (function): performs a symmetric decryption. Algorithm: `AES-128-CBC`
* `encryptAsym` (function): performs an asymmetric encryption. If the data to be encrypted is too large, it uses a hybrid encryption instead. Algorithm: RSA
* `decryptAsym` (function): performs an asymmetric decryption. If the ciphertext is a result from a hybrid encryption, then it uses hybrid decryption; Otherwise, it uses asymmetric decryption. Algorithm: RSA
* `encryptHybrid` (function): performs a hybrid encryption: performs a symmetric encryption on the data with an ephemeral key, then performs an asymmetric encryption on the ephemeral key with the encryption key.
* `decryptHybrid` (function): performs a hybrid decryption: retrieve the ephemeral key with an asymmetric decryption. Then it performs a symmetric decryption on the payload with the ephemeral key.
* `sign` (function): digitally signs a piece of data with a signing key. Algorithm: depends on input key type; data is first hashed with `SHA512`;
* `verify` (function): verifies if a signature matches with the alleged data and verification key. Algorithm: depends on input key type; data is first hashed with `SHA512`.
* `hash` (function): hashes the data in the argument list. Algorithm: `SHA256`
* `xor` (function): performs exclusive-or on two binary arrays
* `hexToBase64` (function): transforms the encoding of binary data from hexidecimal to base64
* `base64ToHex` (function): transforms the encoding of binary data from base64 to hexidecimal
* `hexToBin` (function): decodes a hexidecimal-encoded string to a `Uint8Array`
* `binToHex` (function): encodes a `Uint8Array` to hexidecimal
* `base64ToBin` (function): decodes a base64-encoded string to a `Uint8Array`
* `binToBase64` (function): encodes a `Uint8Array` to base64

## Encrypting <a href="#encrypting" id="encrypting"></a>

An `Encryption` is a JSON object that has the following form:

```
{
    "description": string,
    "tokenHash": 256-bit-hex-string,
    "ciphertext": hybrid-ciphertext,
    "trusteeShares": {
        [trusteeId]: {
            "encrypted": base64-string,
            "hashed": 256-bit-hex-string,
        },
    },
    "validatorShares": {
        [validatorId]: {
            "encrypted": hybrid-ciphertext,
        },
    },
}
```

, where `hybrid-ciphertext` has the form

```
{
    "encryptedMessage": {
        "ciphertext": base64-string,
        "iv": base64-string,
    },
    "encryptedEphemeralKey": base64-string,
}
```

The encryption phase involves the encryptor sending an `Encryption` to the PAD server. Thus, it is essential to understand how it is created. We will go through its properties one by one.

* `"description"`: Description of the `encryption`. This can be an arbitrary string.
* `"tokenHash"`: Hased value of a `token`. `tokenHash = SHA256(token)`.
* `"ciphertext"`: The ciphertext of the secret encrypted with the decryptor's public key and the symmetric key `k`.
* `"trusteeShares"`: A dictionary containing all the encrypted and hashed trustee shares.
  * `[trusteeId]`: A dictionary entry where the key is a trustee's ID, and the value is an object of encrypted and hashed trustee shares.
    * `"encrypted"`: The trustee's share of the masked symmetric key `k \oplus R` used to encrypt the secret, encoded as a base64 string.
    * `"hashed"`: `SHA256` of the trustee's share, encoded as a hex string.
* `"validatorShares"`: A dictionary containing all the encrypted validator shares.
  * `[validatorId]`: A dictionary entry where the key is a validator's ID, and the value is an object of encrypted validator shares.
    * `"encrypted"`: The validator's share of the mask `R` to the symmetric key used to encrypt the secret together with the decryptor's public key. Since the public key is large, the validator's shares are large too. Thus, the encryption of a validator's share uses an ephemeral key as a symmetric key. `k` and decryptor's key.

### Creating `token` and `tokenHash`

A `token` is a random number sent from the encryptor to the decryptor for her to later request for a piece of encryptor's data. It is essential to keep it secret between the encryptor and decryptor until the data request phase. An `encryption`'s ID is `tokenHash`, the hash value of `token`. For portability and readability, both `token` and `tokenHash` are represented as hexadecimal strings.

> Important: note that `token` should be taken as a lowercase string when hashed into `tokenHash`.

```typescript
// create-token-and-hash.js
import {randomBytes, hash} from './cryptoUtil';

const token: string = await randomBytes(16); // 'd1fbe8b5f3ffd7a16a2aa400ebc0194f'
const tokenHash: string = await hash(token); // '5892a6c7ad71b358df760b4291a8adf974f77bd9d3f16c4fd38c58147e80f401'
```

### Creating `ciphertext`

The `ciphertext` part of an `encryption` should be encrypted with the symmetric key first, then the decryptor's encryption key. To ensure integrity, a digital signature from the encryptor against the ciphertext in the first encryption should be attached before the second encryption. In general, the first step creates the ciphertext $$c = SymEnc\_{k}(token, s)$$ Then the second step creates $$AsymEnc\_{Bek}(c, Sign\_{Ask}(c))$$ For example, suppose `secret = "my_secret"` is the encryptor's secret, the following code snippet generates `c`.

```typescript
// create-ciphertext-first-step.js
import {randomBytes, encryptSym} from './cryptoUtil';

const token: string = /* from create-token-and-hash.js */;
const secret: string = 'my_secret';
const dataJson = {token, secret};
const data: string = JSON.stringify(dataJson);

const k: string = await randomBytes(16);
const c: string = await encryptSym(data, k);
```

With `c`, the `ciphertext` can be created like this:

```javascript
// create-ciphertext-second-step.js
import {sign, encryptHybrid, SymCiphertext, HybridCiphertext} from './cryptoUtil';

const c: SymCiphertext = /* from create-ciphertext-first-step.js */;
const encryptorSigningKey: string = /* from some keystore */;
const decryptorEncryptionKey: string = /* from some keystore */;
const payload: string = JSON.stringify(c);
const signature: string = await crypto.sign(payload, encryptorSigningKey);
const signedPayload: string = JSON.stringify({payload, signature});

const ciphertext: HybridCiphertext = await encryptHybrid(signedPayload, decryptorEncryptionKey);
```

### Creating `trusteeShares`

To create `trusteeShares`, the encryptor should first have knowledge about the settings of the instance, including the trustee threshold and the list of trustees referencing the instance (check out GET /metadata and GET /all-trustees/{trustee-id}. These information are also in one of the first few blocks on the ledger). The symmetric key `k` is then masked with a random number. This masked symmetric key is the secret shared among the trustees. After that, each share of trustees' is encrypted with their individual encryption key (the mapping between secret sharing index and trustee does not matter, but we recommend following the order in the instance's metadata. For example, `trustee1` may hold a share of index `00` in an `encryption`, but hold another share of index `01` in another `encryption`). For auditing purposes, the hash of each share *before encrypting* should also be included, so that after a trustee post her share, consistency can be checked.

```typescript
import {
  split,
  hexToBase64,
  hexToUtf8,
  encryptAsym,
  isHybridCiphertext,
  hash,
  Shares } from './cryptoUtil';

type TrusteeShares = {
  [trusteeId: string]: {
    encrypted: string,
    hashed: string,
  },
};

async function createTrusteeShares(maskedSymKey: string, trustees: Object, trusteeThreshold: number): Promise<TrusteeShares> {
  const n = Object.keys(trustees).length;
  const shares: Shares = await split(maskedSymKey, n, trusteeThreshold);
  const trusteeShares: TrusteeShares = {};
  for (const [i, [trusteeId, {encryptionKey}]] of Object.entries(trustees).entries()) {
    const shareBase64 = hexToBase64(shares[i]);
    const shareUtf8 = hexToUtf8(shares[i]);
    const encryptedShare = await encryptAsym(shareBase64, encryptionKey);
    if (isHybridCiphertext(encryptedShare)) {
      throw new Error('share is too large');
    }
    const hashedShare = await hash(shareUtf8);
    trusteeShares[trusteeId] = {
      encrypted: encryptedShare,
      hashed: hashedShare,
    };
  }
  return trusteeShares;
}

const k = /* from create-ciphertext-first-step.js */;
const R = crypto.randomBytes(16);

// the masked symmetric key maskedK is the secret to be shared
const maskedK = xor(k, R);

const trustees = {
  'trustee1': {
    encryptionKey: /* trustee1's encryption key */,
  },
  'trustee2': {
    encryptionKey: /* trustee2's encryption key */,
  },
};
const trusteeThreshold = 2;
const trusteeShares = await createTrusteeShares(maskedK, trustees, trusteeThreshold);
```

### Creating `validatorShares`

This is similar to creating `trusteeShares`, except the secret shared among the validators is the mask `R` together with the decryptor's public key to identify him.

```typescript
import {
  split,
  hexToBase64,
  hexToUtf8,
  encryptHybrid,
  utf8ToHex,
  hash,
  Shares } from './cryptoUtil';

type ValidatorShares = {
  [validatorId: string]: {
    encrypted: string,
  },
};

async function createValidatorShares(RAndBvkPayload: string, validators: Object, validatorThreshold: number): Promise<ValidatorShares> {
  const nPrime = Object.keys(validators).length;
  const shares: Shares = await split(RAndBvkPayload, nPrime, validatorThreshold);
  const validatorShares: ValidatorShares = {};
  for (const [i, [validatorId, {encryptionKey}]] of Object.entries(validators).entries()) {
    const shareBase64 = hexToBase64(shares[i]);
    const encryptedShare = await encryptHybrid(shareBase64, encryptionKey);
    validatorShares[validatorId] = {
      encrypted: encryptedShare,
    };
  }
  return validatorShares;
}

const R = /* from create-trustee-shares.js */;
const bvk = /* decryptor's verification key or identity */;

const RAndBvkJson = {
  mask: hexToBase64(R),
  decryptorIdentity: bvk,
};
const RAndBvkPayload = utf8ToHex(JSON.stringify(RAndBvkJson));

const validators = {
  'validator1': {
    encryptionKey: /* validator1's encryption key */,
  },
  'validator2': {
    encryptionKey: /* validator2's encryption key */,
  },
};
const validatorThreshold = 2;

const validatorShares = await createValidatorShares(RAndBvkPayload, validators, validatorThreshold);
```

### Creating `channelKey`

You will also need a signing key pair for creating the new channel. This ensures that only the encryptor can modify the `Encryption` object using endpoint for updating an `Encryption` in a channel.

This channel key pair should be generated freshly and must not be the key pair that identifies the encryptor. Only the public (verification) key is sent to the server. The encryptor should keep the private (signing) key so long as she would update the `Encryption` therein.

```typescript
// generate-channel-key.js
import {generateSigningKeyPair} from './cryptoUtil';

const {private: channelSigningKey, public: channelKey} = await generateSigningKeyPair();
```

That's it! We have gone through the steps of creating a new channel. Recall that the `encryption` is being sent to the PAD service server and the `token` is then shared with the decryptor out-of-band. The encryption channel allows the encryptor to update the secret which is useful in some use cases.

### Updating `Encryption` object

Using the channel signing key and the `token-hash`, the encryptor can update her `Encryption` object in the channel associated with the `token`. The following code snippets show how one create `encryptionPayload` and `signature` required for the operation.

```typescript
import {sign} from './cryptoUtil';

const channelSigningKey = /* from generate-channel-key.js */
const newEncryption = {
  // the new encryption content...
};

const encryptionPayload = JSON.stringify(newEncryption);
const signature = await sign(encryptionPayload, channelSigningKey);
```

## Decrypting <a href="#decrypting" id="decrypting"></a>

The decryption phase happens after the encryption has been uploaded, a data request has been posted, and sufficient number of trustees and validators, respectivelly, have responded. At this stage, the decryptor has enough information to decrypt the encryptor's secret.

### Verifying responses correctness

It is important for the decryptor to check correctness and integrity of the trustee and validator responses. Checking correctness can be done by checking consistency between a response and its hash submitted by the encryptor at encryption time. Checking integrity involves verifying a signature against the response payload.

```typescript
/* verify-responses.js */
// Work in progress
```

### Verifying `ciphertext` integrity

Recall that the `ciphertext` payload includes the encryptor's signature before encrypted with decryptor's encryption key. This ensures that the payload is not modified by third party, including the PAD server. The signature needs to be verified before decrypting.

```typescript
/* verify-ciphertext.js */
import {decryptHybrid, verify, HybridCiphertext, SymCiphertext} from './cryptoUtil';

function decryptVerifyCiphertext(ciphertext: HybridCiphertext, decryptorDecryptionKey: string, encryptorVerificationKey: string): SymCiphertext {
  const decrypted = decryptHybrid(ciphertext, decryptorDecryptionKey);
  const {payload, signature} = JSON.parse(decrypted);
  if (!verify(payload, encryptorVerificationKey, signature)) {
    throw new Error('Signature not match with payload');
  }
  const innerCiphertext = JSON.parse(payload);
  return innerCiphertext;
}

const {ciphertext} = /* from GET /encryptions/{token-hash}/ciphertext */;
const decryptorDecryptionKey = /* from some key store */;
const encryptorVerificationKey = /* from some key store */;

const c = decryptVerifyCiphertext(
  ciphertext,
  decryptorDecryptionKey,
  encryptorVerificationKey,
);
```

### Reconstructing masked symmetric key from trustees

To perform the symmetric decryption we need sufficient responses from trustees and validators, respectively. Then those will combine to the masked symmetric key and the masked. We show how to reconstruct the masked symmetric key from trustees' responses in this section. Obviously, it has redundancy with our [previous example](#verifying-responses-correctness). In actual implementation, these scripts can be merged. For example, parse the response, push the share to an array only if it is valid, then combine those later.

```typescript
/* reconstruct-masked-k.js */
import {base64ToHex, combine} from './cryptoUtil';

const {trusteeResponses} = /* from GET /data-requests/{token}/trustee-responses */;
const trusteeShares = Object.values(trusteeResponses).map((signed) => {
  const trusteeResponse = JSON.parse(signed.trusteeResponse);
  const share = base64ToHex(trusteeResponse.trusteeShare);
  return share;
});
const maskedK = combine(trusteeShares);
```

### Reconstructing the mask from validators

```typescript
/* resconstruct-r.js */
import {base64ToHex, hexToUtf8, combine} from './cryptoUtil';

const {validatorResponses} = /* from GET /data-requests/{token}/validator-responses */;
const validatorShares = Object.values(validatorResponses).map((signed) => {
  const validatorResponse = JSON.parse(signed.validatorResponse);
  const share = base64ToHex(validatorResponse.validatorShare);
  return share;
});
const RAndBvkPayload = combine(validatorShares);
const RAndBvkString = hexToUtf8(RAndBvkPayload)();
const RAndBvkJson = JSON.parse(RAndBvkString);
const R = base64ToHex(RAndBvkJson.mask);
```

### Decrypting!

The decryptor now has everything to retrieve the encryptor's secret.

```javascript
import {xor, decryptSym} from './cryptoUtil';

const maskedK = /* from reconstruct-masked-k.js */;
const R = /* from reconstruct-r.js */;
const c = /* from verify-ciphertext.js */;

const k = xor(maskedK, R);
const decrypted = decryptSym(c, k);
const dataJson = JSON.parse(decrypted);
const {token, secret} = dataJson;
if (token !== /* token */) {
  throw new Error('Token mismatch');
}
console.log(secret); // my_secret
```


# Code Samples for Auditor


# Node.js

The Auditor is a cautious observer of the ledger that routinely checks the ledger's integrity.

For example, instead of requesting transaction-by-transaction (a transaction in PAD means either a data request or a Trustee/Validator response), an Auditor would request the ledger as raw blocks, which can be used to verify the integrity of the ledger. Trustee attestations allow the Auditor to confirm they have been provided with the same ledger used by the Trustees.

## Computing digest of a ledger

The Auditor computes a succinct representation of the ledger, which can then be tested for consistency against the Trustee attestations. Since the ledger forms a blockchain, we define this succinct representation as *the hash of the most recent block in the blockchain*.

Occasionally, an Auditor may want to check on the transaction details. In the following sections, we will show how an Auditor can:

* Compute hash of a block
* Compute hash of a block's data section
* Extract transactions from a block's data

### Computing hash of a block

A block is composed of a header and a data section. The block header section contains the block number, previous block's hash, and the hash of the current block's data section.

**Example**

```json
{
    "header": {
        "number": "1",
        "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
        "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
    },
}
```

When we say "hash" of a block, we mean the hash of its header section. Below is a Node.js example of how to compute the hash given a JSON representation of the header. The dependency `cryptoUtil` is defined [here](https://github.com/sw7group/PAD-Dev-Docs/blob/main/code_samples_auditor/code_samples_enc_dec/README.md#cryptoutil).

```javascript
const asn1 = require('asn1.js');

const cryptoUtil = require('./cryptoUtil');

/**
 * @typedef {Object} Header
 * @property {string|number} [number]
 * @property {string|Buffer} [previousHash]
 * @property {string|Buffer} dataHash
 */
/**
 * @param {Header} header
 * @return {Buffer}
 */
function computeBlockHash(header) {
  const body = function() {
    this.seq().obj(
      this.key('number').int(),
      this.key('previousHash').octstr(),
      this.key('dataHash').octstr(),
    );
  };
  const headerAsn1 = asn1.define('headerAsn1', body);
  let {number, previousHash, dataHash} = header;
  if (previousHash == null) {
    previousHash = '';
  }
  if (typeof(number) !== 'number') {
    number = parseInt(number);
  }
  if (!Buffer.isBuffer(previousHash)) {
    previousHash = Buffer.from(previousHash, 'hex');
  }
  if (!Buffer.isBuffer(dataHash)) {
    dataHash = Buffer.from(dataHash, 'hex');
  }
  const encoded = headerAsn1.encode({
    number,
    previousHash,
    dataHash,
  });
  const hash = cryptoUtil.hash(encoded);
  return hash;
}

const header1 = {
  dataHash: "af34032c92ef85b976db007fa339293253bc4e58f144cf648c6ffcd5a1150791",
};
console.log(computeBlockHash(header1).toString('hex'));
// 1c2cf6ed047ab1d35b2ed3bfbba376d99626db2213632dd4b955ceb4c05f3ba8

const header2 = {
    number: 1,
    previousHash: "1c2cf6ed047ab1d35b2ed3bfbba376d99626db2213632dd4b955ceb4c05f3ba8",
    dataHash: "cf8289074798c7e8e1d267f0c0fb83acde339fb3007ff5246fb6745a94d55883",
};
console.log(computeBlockHash(header2).toString('hex'));
// 1af3275c9db7305fc85a3ded00a7829b5d6a99deacd35ed48cd31b79c8689275
```

### Computing data hash

When a user has utilised the data section of a block (for example, he/she extracted a data request and used it for some business logic), it is crucial for him/her to check its consistency against the `dataHash` entry in the block header.

The data section is an array of base64-encoded strings. Its hash is defined as the hash on the concatenation of these binary data. Below is a sample script for computing the data hash of a block:

```javascript
const cryptoUtil = require('./cryptoUtil');

/**
 * @param {string[]} data
 * @return {Buffer}
 */
function computeDataHash(data) {
  const dataArray = data.map((d) => {
    return Buffer.from(d, 'base64');
  });
  return cryptoUtil.hash(...dataArray);
}

const block = {
  header: {
    dataHash: "4a148a98c3f5216c480bed070e267186751da47d3782a4282b2c383879097c80",
  },
  data: {
    data: ["datum1==", "datum2=="], // fake data
  },
};

const dataHashHex = block.header.dataHash;
const dataHash = Buffer.from(dataHashHex, 'hex');

const data = block.data.data;
console.log(computeDataHash(data).equals(dataHash)); // true
```

## Extracting transactions from block data

### Functions and parameters

There are 4 smart contract functions that write on the ledger. Their parameters are as follows:

* `Init`: writes metadata of the instance
  1. stringified Trustee public keys
  2. trustee threshold
  3. stringified Validator public keys
  4. validator threshold
* `PostDataRequest`: posts a data request
  1. a token
* `PostTrusteeResponse`: posts a Trustee response
  1. Trustee response payload
  2. Trustee's digital signature on 1
* `PostValidatorResponse`: posts a Validator response
  1. Validator response payload
  2. Validator's digital signature on 1

A piece of block data may contain one of these functions' invocations and their parameters.

### Extracting the transactions

It is possible to extract the invoked smart contract functions and parameters from block data. The resulting value is an array of arrays of strings where the first strings in the inner arrays are the functions and the succeeding strings are the parameters. Since the blocks are protocol-buffer-encoded, we need to use a library [`protobufjs`](https://www.npmjs.com/package/protobufjs) for decoding.

```javascript
const {Type, Field} = require('protobufjs');

const protoChaincodeInput = new Type('ChaincodeInput')
    .add(new Field('args', 1, 'string', 'repeated'));

const protoChaincodeSpec = new Type('ChaincodeSpec')
    .add(new Field('input', 3, 'ChaincodeInput')).add(protoChaincodeInput);

const protoChaincodeProposalPayloadInput = new Type('ChaincodeProposalPayloadInput')
    .add(new Field('chaincodeSpec', 1, 'ChaincodeSpec')).add(protoChaincodeSpec);

const protoChaincodeProposalPayload = new Type('ChaincodeProposalPayload')
    .add(new Field('input', 1, 'ChaincodeProposalPayloadInput')).add(protoChaincodeProposalPayloadInput);

const protoChaincodeActionPayload = new Type('ChaincodeActionPayload')
    .add(new Field('chaincodeProposalPayload', 1, 'ChaincodeProposalPayload')).add(protoChaincodeProposalPayload);

const protoTransactionAction = new Type('TransactionAction')
    .add(new Field('payload', 2, 'ChaincodeActionPayload')).add(protoChaincodeActionPayload);

const protoTransaction = new Type('Transaction')
    .add(new Field('actions', 1, 'TransactionAction', 'repeated')).add(protoTransactionAction);

const protoPayload = new Type('Payload')
    .add(new Field('data', 2, 'Transaction')).add(protoTransaction);

const protoEnvelope = new Type('Envelope')
    .add(new Field('payload', 1, 'Payload')).add(protoPayload);

function getTransactions(bytes) {
  const txs = [];
  const envelope = protoEnvelope.decode(bytes);
  const actions = envelope.toJSON().payload.data.actions;
  for (const action of actions) {
    txs.push(action.payload.chaincodeProposalPayload
        .input.chaincodeSpec.input.args);
  }
  return txs;
}

const block = {
  header: {
    // ...
  },
  data: {
    data: [
      'CpsDEpgDCpUDEpIDCo8DCowDCokDGoYDChNQb3N0VHJ1c3RlZVJlc3BvbnNlCrIBeyJ0eXBlIjoidHJ1c3RlZV9yZXNwb25zZSIsInBhZE5hbWUiOiJteS1wYWQtMS4wIiwidHJ1c3RlZUlkIjoidHJ1c3RlZTEiLCJ0b2tlbiI6ImYxMzQxZmM5MDU5Zjg1N2MyMThmNTEwNzcxZTJjODlmIiwidHJ1c3RlZVNoYXJlIjoiQWtGdVdiQUcxU2NjbDY5UlduMnhIU2lRUGRsaFlvbVpuRnF5SE81bFFEZGwifQq5AXsic2lnbmVyTWV0YWRhdGEiOnsiaWQiOiJ0cnVzdGVlMSIsImZ1bGxOYW1lIjoiVHJ1c3RlZS0xIiwicm9sZSI6IlRydXN0ZWUifSwicGF5bG9hZCI6Ik1FWUNJUUNCMHJFa2FvZGR6VWQ0eXVJUmFuTlZ5ZVlDK21JZmxPSm5Mdm82RnF0QXRBSWhBSys3cWxtenJnZ1diRTEzVDJvcUErNS9wSUdiZmluZFl3OEFTbU1xV21vNSJ9',
      'CkESPwo9EjsKOQo3CjUaMwoPUG9zdERhdGFSZXF1ZXN0CiAyMWJmNTdkZDUyYTNiODEzMjhmZTEzOGFjNGU4ZWQxYg==',
    ],
  },
}
const blockData = block.data.data;

const data0B64 = blockData[0];
const data0 = Buffer.from(data0B64, 'base64');

console.log(getTransactions(data0));
// [
//   [
//     'PostTrusteeResponse',
//     '{"type":"trustee_response","padName":"my-pad-1.0","trusteeId":"trustee1","token":"f1341fc9059f857c218f510771e2c89f","trusteeShare":"AkFuWbAG1Sccl69RWn2xHSiQPdlhYomZnFqyHO5lQDdl"}',
//     '{"signerMetadata":{"id":"trustee1","fullName":"Trustee-1","role":"Trustee"},"payload":"MEYCIQCB0rEkaoddzUd4yuIRanNVyeYC+mIflOJnLvo6FqtAtAIhAK+7qlmzrggWbE13T2oqA+5/pIGbfindYw8ASmMqWmo5"}'
//   ]
// ]

const data1B64 = blockData[1];
const data1 = Buffer.from(base1B64, 'base64');

console.log(getTransactions(data1));
// [
//   [
//     'PostTrusteeResponse',
//     '21bf57dd52a3b81328fe138ac4e8ed1b'
//   ]
// ]
```

### Examples of transactions and parameters

Coming soon!


# API Description

***

This session describes endpoints of the PAD API. The endpoints may appear in subsessions more than once as they are titled by a role of PAD. A description of an endpoint consists of its method, URI, request parameters and response statuses, with examples.

## Base URL and version

Base URL: <https://api.pad.tech>

The only version available now is `v0`. To access the URI `/trustees`, for example, the URL will be <https://api.pad.tech/v0/trustees>.

## Types

"Primitive" types are written in lowercase. Examples:

* integer
* number
* string
* object (JSON object)
* array
* dict (dictionary/key-value pair where values have the same type)
* enum

Arrays are written in the form array\<T> which indicates it is an array where items are all in type T.

Dictionaries are written in the form dict\<KeyT, ValueT> which indicates it is an object where the keys are in type KeyT and the values are in type ValueT.

Stringified objects are written like string\<T>. A string of this type should be able to parse as an object of type T.

Defined types are capitalised. Examples:

* Encryption
* Token
* TrusteeId
* DataRequest


# Authentication

PAD-as-a-Service API uses API keys to authenticate users. All API keys have the prefix `pad`. Each API key identifies a *role* in a particular *instance*. There are 6 roles:

* `Operator`
* `Encryptor`
* `Decryptor`
* `Trustee`
* `Validator`
* `Auditor`

For example, a trustee referencing 3 different instances should have at least 3 different `Trustee` API keys for each instance. He cannot access some of the endpoints disallowed for a `Trustee` role (e.g. uploading an encryption).

## Using an API key

API keys should be provided in the request header `X-API-KEY` field. Making a request missing an API key or with an invalid API key will get a `401 Unauthorized` response.

## Access control list

| URI                                                             | HTTP Method | Operator             | Encryptor            | Decryptor            | Trustee              | Auditor              | Validator            |
| --------------------------------------------------------------- | ----------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- |
| /PADs                                                           | `POST`      | :heavy\_check\_mark: |                      |                      |                      |                      |                      |
| /all-trustees                                                   | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |
| /all-trustees/:trusteeId                                        | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |
| /all-validators                                                 | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |
| /all-validators/:validatorId                                    | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |
| /metadata                                                       | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |
| /encryptions                                                    | `POST`      | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |                      |                      |                      |
| /encryptions                                                    | `PUT`       | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |                      |                      |                      |
| /encryptions/:tokenHash/status                                  | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |
| /encryptions/:tokenHash/ciphertext                              | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |                      |                      |
| /encryptions/:tokenHash/encrypted-trustee-shares/:trusteeId     | `GET`       | :heavy\_check\_mark: |                      | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |                      |
| /encryptions/:tokenHash/hashed-trustee-shares                   | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |
| /encryptions/:tokenHash/encrypted-validator-shares/:validatorId | `GET`       | :heavy\_check\_mark: |                      | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |                      |
| /data-requests                                                  | `POST`      | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |                      |                      |                      |
| /data-requests                                                  | `GET`       | :heavy\_check\_mark: |                      | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |
| /data-requests/:token/trustee-responses                         | `POST`      | :heavy\_check\_mark: |                      | :heavy\_check\_mark: |                      |                      |                      |
| /data-requests/:token/trustee-responses                         | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |                      |
| /data-requests/:token/validator-responses                       | `POST`      | :heavy\_check\_mark: |                      |                      | :heavy\_check\_mark: |                      |                      |
| /data-requests/:token/validator-responses                       | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |                      |                      |                      |
| /trustee-attestations/:trusteeId                                | `PUT`       | :heavy\_check\_mark: |                      | :heavy\_check\_mark: |                      |                      |                      |
| /trustee-attestations/:trusteeId                                | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |
| /digest                                                         | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |
| /ledger                                                         | `GET`       | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: | :heavy\_check\_mark: |

## Rate limiting

We have 2 rate limiting policies: `IP + API_key` and `API_key`. Both have a limit of 100 requests per minute. In the `IP + API_key` policy, if an invalid API key is provided, only the IP is recorded usage of the API. Because of the `API_key` policy, distinct users of the same *role* of an instance should use different API keys. For example, `Trustee-1` and `Trustee-2` who both reference the same instance could use the same API key for serving the instance properly, but this would trigger rate limiting for the API key because the trustees are sharing quotas.

## https

All requests should be made with https protocol. Requests made with http protocol will get a [`301 Moved Permanantly`](https://datatracker.ietf.org/doc/html/rfc7231#section-6.4.2) response directed to https.


# Operator

## Create a new instance <a href="#op-create-instance" id="op-create-instance"></a>

`POST /PADs`

### Description

Operator creates an instance. The request body consists of the Operator's choice of the instance name, the list of trustees referencing the instance, and the corresponding threshold. All validators will be nominated automatically, with a threshold $$\lfloor#\mathrm{validators}/2\rfloor + 1$$. This endpoint also binds the API key to the instance, i.e. the API key can only access endpoints associated to the created instance afterwards.

> Choose the parameters carefully. They cannot be changed once the instance is created.

> The instance is not fully functional after creation. It takes time for the trustees and validators to realise this change. They may choose not to serve this instance as well.

### Parameters

| Name       | In   | Type                                   | Required | Description                                                     |
| ---------- | ---- | -------------------------------------- | -------- | --------------------------------------------------------------- |
| padName    | body | [PadName](#schema-pad-name)            | true     | The ID of the instance chosen by the Operator                   |
| trusteeIds | body | array<[TrusteeId](#schema-trustee-id)> | true     | The IDs of the trustees nominated by the Operator               |
| t          | body | integer                                | true     | The minimum number of trustee responses needed for a decryption |

**Example**

```json
{
    "padName": "my-pad-1.0",
    "trusteeIds": ["trustee1", "trustee2", "trustee3"],
    "t": 2,
}
```

### Responses

| Status | Meaning                                                                 | Description                                                                        | Schema                              |
| ------ | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------- |
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)            | Succeeded                                                                          | [ApiResponse](#schema-api-response) |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)        | Invalid instance ID, non-existing trustee or invalid trustee threshold is provided | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1)         | API key is missing or invalid                                                      | [ApiResponse](#schema-api-response) |
| 403    | [Forbidden](https://tools.ietf.org/html/rfc7235#section-6.5.3)          | User does not have permission for this request                                     | [ApiResponse](#schema-api-response) |
| 409    | [Conflict](https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.8) | Instance with the same name already exists                                         | [ApiResponse](#schema-api-response) |

#### 201 Created

The instance is successfully created. This response is returned *after* the instance is created. The creation process could take up to 30 seconds.

**Example**

```json
{
    "ok": true,
    "message": "Successfully created PAD instance",
}
```

#### 400 Bad Request

The request is malformed. Check that:

* The PAD instance name is valid. See [the PadName schema](#schema-pad-name) for details.
* All the trustee IDs are valid. Check out [this endpoint](#op-get-trustee-universe) which retrieves all the registered trustees.
* The trustee threshold is valid. It should be a positive integer at most the number of trustees nominated.

**Example1**

```json
{
  "ok": false,
  "message": "The trustee trustee4 does not exist",
}
```

**Example2**

```json
{
  "ok": false,
  "message": "invalid value at body.t. Expected: <= 3; given: 4",
}
```

#### 401 Unauthorized

Api key is missing or invalid.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

#### 403 Forbidden

User does not have permission to make this request.

**Example**

```json
{
  "ok": false,
  "message": "Forbidden",
}
```

#### 409 Conflict

A PAD instance of the same name already existed.

**Example**

```json
{
  "ok": false,
  "message": "the instance has already been created",
}
```

## Get the Trustee universe <a href="#op-get-trustee-universe" id="op-get-trustee-universe"></a>

`GET /all-trustees`

### Description

Retrieve all the registered Trustees - their IDs, descriptive names and public keys.

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the Trustees.

**Schema**

| Name            | Type                                                             | Required | Restrictions | Description |
| --------------- | ---------------------------------------------------------------- | -------- | ------------ | ----------- |
| ok              | boolean                                                          | true     | none         | none        |
| trusteeUniverse | dict<[TrusteeId](#schema-trustee-id),[Trustee](#schema-trustee)> | true     | none         | none        |

**Example**

```json
{
  "ok": true,
  "trusteeUniverse": {
    "trustee1": {
      "id": "trustee1",
      "fullName": "Trustee-1",
      "role": "Trustee",
      "encryptionKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvAnBzaNLM8/iIxP0Rz88\nQk7mj+TW1U1C2BQAaOAQfRTRrEsNDVPpAZB8LTfs8wZEhok5VzSMA4dPTkQE8Su8\np/eQJthOTCmBq2t8dgx0+uX3IhdwXgmWCh0OQ8NJ94rXA+/rWqjeNXZ4ShFlNDeu\nkv9OGLh4bvSTUHWzDi6M4qxlq8fJ/O+lTvJzf6cb6n7pKpT7/ppdGik/Hi8EcQiY\nSL9lbAkKJpgrfqWNDo7HX/2GffZdd316123stOqrBTZS81Ow/Z/rqiPvzBV1HxEv\nabfIFd1LefWgBfECoXOpvYaBuL4N6fchX9gAis7J66WFDQVZsnJ/J3Bzl0ECRgVp\n8QIDAQAB\n-----END PUBLIC KEY-----",
      "verificationKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELZyXL9AOgZrIsWrDkY0ohQuvMsVa\n+3eJSfsV+a1HW0M34lZInCVPgule/a9HqnqpDtXEBclgeeKS1YT7jVjpTg==\n-----END PUBLIC KEY-----",
      },
    },
  },
}
```

#### 401 Unauthorized

Api key is missing or invalid.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

**Example**

## Get the Validator universe <a href="#op-get-validator-universe" id="op-get-validator-universe"></a>

`GET /all-validators`

### Description

Retrieve all the registered Validators - their IDs, descriptive names and public keys.

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the Validators.

**Schema**

| Name              | Type                                                                     | Required | Restrictions | Description |
| ----------------- | ------------------------------------------------------------------------ | -------- | ------------ | ----------- |
| ok                | boolean                                                                  | true     | none         | none        |
| validatorUniverse | dict<[ValidatorId](#schema-validator-id),[Validator](#schema-validator)> | true     | none         | none        |

**Example**

```json
{
  "ok": true,
  "validatorUniverse": {
    "validator1": {
      "id": "validator1",
      "fullName": "Validator-1",
      "role": "Validator",
      "encryptionKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvAnBzaNLM8/iIxP0Rz88\nQk7mj+TW1U1C2BQAaOAQfRTRrEsNDVPpAZB8LTfs8wZEhok5VzSMA4dPTkQE8Su8\np/eQJthOTCmBq2t8dgx0+uX3IhdwXgmWCh0OQ8NJ94rXA+/rWqjeNXZ4ShFlNDeu\nkv9OGLh4bvSTUHWzDi6M4qxlq8fJ/O+lTvJzf6cb6n7pKpT7/ppdGik/Hi8EcQiY\nSL9lbAkKJpgrfqWNDo7HX/2GffZdd316123stOqrBTZS81Ow/Z/rqiPvzBV1HxEv\nabfIFd1LefWgBfECoXOpvYaBuL4N6fchX9gAis7J66WFDQVZsnJ/J3Bzl0ECRgVp\n8QIDAQAB\n-----END PUBLIC KEY-----",
      "verificationKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELZyXL9AOgZrIsWrDkY0ohQuvMsVa\n+3eJSfsV+a1HW0M34lZInCVPgule/a9HqnqpDtXEBclgeeKS1YT7jVjpTg==\n-----END PUBLIC KEY-----",
      },
    },
  },
}
```

#### 401 Unauthorized

Api key is missing or invalid.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

## Schemas

### PadName <a href="#schema-pad-name" id="schema-pad-name"></a>

ID of a PAD instance. Its length must be inclusively between 4 and 30. It should contains only lowercase letters, digits, periods (`.`) or dashes (`-`). It must start with a lowercase letter.

It is seldom used as a request parameter because the API key in the request already identifies a PAD instance.

**Example**

```json
"my-pad-1.0"
```

#### Schema

| Type   | Restrictions              |
| ------ | ------------------------- |
| string | `/[a-z][a-z0-9.-]{3,29}/` |

### TrusteeId <a href="#schema-trustee-id" id="schema-trustee-id"></a>

ID of a trustee. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

**Example**

```
trustee1
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### Trustee <a href="#schema-trustee" id="schema-trustee"></a>

An object listing details of a trustee, including its ID, human-readable description/name, its role (`Trustee`) and its public keys.

**Example**

```json
{
  "id": "trustee1",
  "fullName": "Trustee-1",
  "role": "Trustee",
  "encryptionKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvAnBzaNLM8/iIxP0Rz88\nQk7mj+TW1U1C2BQAaOAQfRTRrEsNDVPpAZB8LTfs8wZEhok5VzSMA4dPTkQE8Su8\np/eQJthOTCmBq2t8dgx0+uX3IhdwXgmWCh0OQ8NJ94rXA+/rWqjeNXZ4ShFlNDeu\nkv9OGLh4bvSTUHWzDi6M4qxlq8fJ/O+lTvJzf6cb6n7pKpT7/ppdGik/Hi8EcQiY\nSL9lbAkKJpgrfqWNDo7HX/2GffZdd316123stOqrBTZS81Ow/Z/rqiPvzBV1HxEv\nabfIFd1LefWgBfECoXOpvYaBuL4N6fchX9gAis7J66WFDQVZsnJ/J3Bzl0ECRgVp\n8QIDAQAB\n-----END PUBLIC KEY-----\n",
  "verificationKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELZyXL9AOgZrIsWrDkY0ohQuvMsVa\n+3eJSfsV+a1HW0M34lZInCVPgule/a9HqnqpDtXEBclgeeKS1YT7jVjpTg==\n-----END PUBLIC KEY-----"
}
```

#### Schema

| Name            | Type                            | Required | Restrictions              | Description                                                                               |
| --------------- | ------------------------------- | -------- | ------------------------- | ----------------------------------------------------------------------------------------- |
| id              | [TrusteeId](#schema-trustee-id) | true     | `/[0-9a-zA-Z-_]{3,30}/`   | none                                                                                      |
| fullName        | string                          | true     | `/Trustee-[0-9a-zA-Z_]+/` | none                                                                                      |
| role            | enum                            | true     | none                      | none                                                                                      |
| encryptionKey   | string                          | true     | none                      | PEM-encoded (public) encryption key of the trustee. Used by encryptors at encryption time |
| verificationKey | string                          | true     | none                      | PEM-encoded (public) verification key of trustee                                          |

### Validator <a href="#schema-validator" id="schema-validator"></a>

An object listing details of a validator, including its ID, human-readable description/name, its role (`Validator`) and its public keys.

**Example**

```json
{
  "id": "validator1",
  "fullName": "Validator1",
  "role": "Validator",
  "encryptionKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvAnBzaNLM8/iIxP0Rz88\nQk7mj+TW1U1C2BQAaOAQfRTRrEsNDVPpAZB8LTfs8wZEhok5VzSMA4dPTkQE8Su8\np/eQJthOTCmBq2t8dgx0+uX3IhdwXgmWCh0OQ8NJ94rXA+/rWqjeNXZ4ShFlNDeu\nkv9OGLh4bvSTUHWzDi6M4qxlq8fJ/O+lTvJzf6cb6n7pKpT7/ppdGik/Hi8EcQiY\nSL9lbAkKJpgrfqWNDo7HX/2GffZdd316123stOqrBTZS81Ow/Z/rqiPvzBV1HxEv\nabfIFd1LefWgBfECoXOpvYaBuL4N6fchX9gAis7J66WFDQVZsnJ/J3Bzl0ECRgVp\n8QIDAQAB\n-----END PUBLIC KEY-----\n",
  "verificationKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELZyXL9AOgZrIsWrDkY0ohQuvMsVa\n+3eJSfsV+a1HW0M34lZInCVPgule/a9HqnqpDtXEBclgeeKS1YT7jVjpTg==\n-----END PUBLIC KEY-----"
}
```

#### Schema

| Name            | Type                                | Required | Restrictions                | Description                                                                                 |
| --------------- | ----------------------------------- | -------- | --------------------------- | ------------------------------------------------------------------------------------------- |
| id              | [ValidatorId](#schema-validator-id) | true     | -                           | none                                                                                        |
| fullName        | string                              | true     | `/Validator-[0-9a-zA-Z_]+/` | none                                                                                        |
| role            | enum                                | true     | none                        | none                                                                                        |
| encryptionKey   | string                              | true     | none                        | PEM-encoded (public) encryption key of the validator. Used by encryptors at encryption time |
| verificationKey | string                              | true     | none                        | PEM-encoded (public) verification key of validator                                          |

### ApiResponse <a href="#schema-api-response" id="schema-api-response"></a>

**Example**

```json
{
  "ok": true,
  "message": "string"
}
```

#### Schema

| Name    | Type    | Required | Description                      |
| ------- | ------- | -------- | -------------------------------- |
| ok      | boolean | true     | The request is successful or not |
| message | string  | true     | none                             |


# Encryptor

## Create a channel for a secret and upload an encryption <a href="#op-upload-encryption" id="op-upload-encryption"></a>

`POST /encryptions`

### Description

Secrets are secured within a channel of a PAD instance. To create an encryption `Channel`, you must upload an `Encryption` object to the server. At any time, the decryptor can retrieve the `Encryption` object using the hash of the token value, which acts as an identifier of the channel. The decryptor may choose to retrieve the `Encryption` object immediately in order to independently store the encrypted values, or may only do so when a decryption is requested. In any case, no decryption can occur unless the decryptor has posted a data request and sufficient trustees and validators have responded. Read [the code samples section](https://github.com/sw7group/PAD-Dev-Docs/blob/main/code_samples_enc_dec.md#encrypting) for details and information about how to construct `Encryption` objects.

To facilitate updating the `Encryption` object securely in some use cases (Find-me, for example), you can send a channel key along with this request. This ensures only you who has the private key counterpart of the channel key can change the `Encryption` object in this channel.

### Parameters

| Name         | In   | Type                             | Required | Description                                             |
| ------------ | ---- | -------------------------------- | -------- | ------------------------------------------------------- |
| `encryption` | body | [Encryption](#schema-encryption) | true     | none                                                    |
| `channelKey` | body | string                           | true     | A PEM-encoded (public) verification key for the channel |

**Example**

```json
{
  "encryption": {
    "description": "string",
    "tokenHash": "d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4",
    "ciphertext": {
      "encryptedMessage": {
        "ciphertext": "base64_encoded_data",
        "iv": "base64_encoded_data"
      },
      "encryptedEphemeralKey": "base64_encoded_data"
    },
    "trusteeShares": {
      "trustee1": {
        "encrypted": "base64_encoded_data",
        "hashed": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
      }
    },
    "validatorShares": {
      "validator1": {
        "encrypted": {
          "encryptedMessage": {
            "ciphertext": "base64_encoded_data",
            "iv": "base64_encoded_data"
          },
          "encryptedEphemeralKey": "base64_encoded_data"
        }
      }
    },
  },
  "channelKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5fYv3lbLtDjR5IxAurWF6TMfhNZB\nPUn2DLapmjLWvZXYjqSrflJx4TemksjRyMDi+CwWP0PkunBB6wUdCDmdWA==\n-----END PUBLIC KEY-----"
}
```

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |
| 409    | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)   | Conflict                      | [ApiResponse](#schema-api-response) |

#### 200 OK

The encryption has been successfully uploaded onto the server.

**Example**

```json
{
  "ok": true,
  "message": "Successfully uploaded encryption",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

#### 409 Conflict

A channel with the same token already exists. The client should use another token or [update the encryption](#op-update-encryption) on the channel.

**Example**

```json
{
  "ok": false,
  "message": "The encryption with token hash ${tokenHash} already exists. Update it with PUT request or renew the token.",
}
```

## Get encryption status <a href="#op-get-encryption-status" id="op-get-encryption-status"></a>

`GET /encryptions/{token-hash}/status`

### Description

This retrieves the status of an `encryption`, namely whether or not the data has been requested by the decryptor. If a request has been made, then this status also gives which trustees and validators have responded to the data request. This information is retrieved and provided by the PAD server. To eliminate the need to trust the PAD service, this data should be checked for consistency with trustee attestations of the ledger state.

### Parameters

| Name         | In   | Type                     | Required | Description                            |
| ------------ | ---- | ------------------------ | -------- | -------------------------------------- |
| `token-hash` | path | [Sha256](#schema-sha256) | true     | Hash value of the token in hexadecimal |

#### Example

`GET /encryptions/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/status`

### Responses

| Status | Meaning                                                         | Description                                                   | Schema                              |
| ------ | --------------------------------------------------------------- | ------------------------------------------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                                                     | Inline                              |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid; Or the client lacks permission | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the status of an `Encryption`.

**Schema**

| Name                    | Type                                       | Required | Restrictions | Description |
| ----------------------- | ------------------------------------------ | -------- | ------------ | ----------- |
| `ok`                    | boolean                                    | true     | none         | none        |
| `encryptionStatus`      | object                                     | true     | none         | none        |
| » `tokenHash`           | [Sha256](#schema-sha256)                   | true     | none         | none        |
| » `requested`           | boolean                                    | true     | none         | none        |
| » `token`               | [Token](#schematoken)                      | false    | none         | none        |
| » `requestTime`         | [DateTime](#schemadatetime)                | false    | none         | none        |
| » `respondedTrustees`   | array<[TrusteeId](#schema-trustee-id)>     | false    | none         | none        |
| » `respondedValidators` | array<[ValidatorId](#schema-validator-id)> | false    | none         | none        |

**Example**

```json
{
  "ok": true,
  "encryptionStatus": {
    "tokenHash": "d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4",
    "requested": true,
    "token": "0fe5ff17c6ee6efa8ca385587b1e1ac2",
    "requestTime": "2021-05-05T13:53:19.275Z",
    "respondedTrustees": [
      "trustee1"
    ],
    "respondedValidators": [
      "validator1"
    ]
  }
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

## Update encryption <a href="#op-update-encryption" id="op-update-encryption"></a>

`PUT /encryptions/{token-hash}`

### Description

In some use cases (e.g. Find-me), secrets may be generated as a stream of data and the decryptor can make a request for only the most recent secret. This endpoint allows the encryptor to update the `Encryption` after [establishing an encryption channel](#op-upload-encryption).

To ensure only you can use this endpoint, you must sign the `Encryption` object with the channel private key.

### Parameters

| Name                | In   | Type                                     | Required | Description                                                            |
| ------------------- | ---- | ---------------------------------------- | -------- | ---------------------------------------------------------------------- |
| `token-hash`        | path | [Sha256](#schema-sha256)                 | true     | Hash value of the token                                                |
| `encryptionPayload` | body | string<[Encryption](#schema-encryption)> | true     | The new, stringified encryption object                                 |
| `signature`         | body | [Base64](#schema-base64)                 | true     | The signature with the channel private key against `encryptionPayload` |

#### Example

`PUT /encryptions/d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4`

```json
{
  "encryptionPayload": "{\"description\":\"string\",\"tokenHash\":\"d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4\",\"ciphertext\":{\"encryptedMessage\":{\"ciphertext\":\"base64_encoded_data\",\"iv\":\"base64_encoded_data\"},\"encryptedEphemeralKey\":\"base64_encoded_data\"},\"trusteeShares\":{\"trustee1\":{\"encrypted\":\"base64_encoded_data\",\"hashed\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"}},\"validatorShares\":{\"validator1\":{\"encrypted\":{\"encryptedMessage\":{\"ciphertext\":\"base64_encoded_data\",\"iv\":\"base64_encoded_data\"},\"encryptedEphemeralKey\":\"base64_encoded_data\"}}}}",
  "signature": "MEQCIGuYVL9wh/4TawM1bFSB5MmF4FkqJPcppj66xc2+MRdHAiBNEF8w77J6SLq3UtxgIRw5Hl8C2JKVUwaKHLflkoaI0w=="
}
```

### Responses

| Status | Meaning                                                         | Description                                                   | Schema                              |
| ------ | --------------------------------------------------------------- | ------------------------------------------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                                                     | [ApiResponse](#schema-api-response) |
| 400    | Bad Request                                                     | Tokens in path and body are inconsistent                      | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid; Or the client lacks permission | [ApiResponse](#schema-api-response) |

#### 200 OK

The `Encryption` is successfully updated.

**Example**

```json
{
  "ok": true,
  "message": "Successfully updated encryption"
}
```

#### 400 Bad Request

The request failed because tokens in path and body are inconsistent.

**Example**

```json
{
  "ok": false,
  "message": "Token hashes in path and body must be consistent",
}
```

#### 401 Unauthorized

Api key is missing or incorrect.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

## Schemas

### TrusteeId <a href="#schema-trustee-id" id="schema-trustee-id"></a>

ID of a trustee. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

**Example**

```
my_trustee-1
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### ValidatorId <a href="#schema-validator-id" id="schema-validator-id"></a>

ID of a validator. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

#### Example

```
my_validator-2
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### Encryption <a href="#schema-encryption" id="schema-encryption"></a>

An `Encryption` is identified by `tokenHash` and the instance in which it lives. It contains the ciphertext encrypted by both the decryptor's key and a fresh symmetric key `k`. It also contains the encrypted shares of `k` for the trustees and validators. For more details, read the [code samples page](/code_samples_enc_dec).

**Example**

```json
{
  "description": "string",
  "tokenHash": "hex_encoded_string",
  "ciphertext": {
    "encryptedMessage": {
      "ciphertext": "base64_encoded_string",
      "iv": "base64_encoded_string",
    },
    "encryptedEphemeralKey": "base64_encoded_string",
  },
  "trusteeShares": {
    "trustee1": {
      "encrypted": "base64_encoded_string",
      "hashed": "hex_encoded_string",
    },
  },
  "validatorShares": {
    "validator1": {
      "encrypted": {
        "encryptedMessage": {
          "ciphertext": "base64_encoded_string",
          "iv": "base64_encoded_string",
        },
        "encryptedEphemeralKey": "base64_encoded_string",
      },
    },
  },
}
```

#### Schema

| Name                   | Type                                              | Required | Description |
| ---------------------- | ------------------------------------------------- | -------- | ----------- |
| `description`          | string                                            | true     | none        |
| `tokenHash`            | [Sha256](#schema-sha256)                          | true     | none        |
| `trusteeShares`        | dict<[TrusteeId](#schema-trustee-id), object>     | true     | none        |
| » **\[`trusteeId`]**   | object                                            | true     | none        |
| »» `encrypted`         | string                                            | true     | none        |
| »» `hashed`            | [Sha256](#schema-sha256)                          | true     | none        |
| `validatorShares`      | dict<[ValidatorId](#schema-validator-id), object> | true     | none        |
| » **\[`validatorId`]** | object                                            | true     | none        |
| »» `encrypted`         | [Ciphertext](#schema-ciphertext)                  | true     | none        |
| `ciphertext`           | [Ciphertext](#schema-ciphertext)                  | true     | none        |

### Sha256 <a href="#schema-sha256" id="schema-sha256"></a>

A Sha256 hash value as a hexidecimal string.

**Example**

```json
"d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-F]{64}/` |

### DateTime <a href="#schema-date-time" id="schema-date-time"></a>

A timestamp in ISO 8601 format.

**Example**

```json
"2021-05-05T13:53:19.275Z"
```

#### Schema

| Type   | Restrictions |
| ------ | ------------ |
| string | -            |

### Trustee <a href="#schema-trustee" id="schema-trustee"></a>

An object listing details of a trustee, including its ID, human-readable description/name, its role (`Trustee`) and its public keys.

**Example**

```json
{
  "id": "trustee1",
  "fullName": "Trustee-1",
  "role": "Trustee",
  "encryptionKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvAnBzaNLM8/iIxP0Rz88\nQk7mj+TW1U1C2BQAaOAQfRTRrEsNDVPpAZB8LTfs8wZEhok5VzSMA4dPTkQE8Su8\np/eQJthOTCmBq2t8dgx0+uX3IhdwXgmWCh0OQ8NJ94rXA+/rWqjeNXZ4ShFlNDeu\nkv9OGLh4bvSTUHWzDi6M4qxlq8fJ/O+lTvJzf6cb6n7pKpT7/ppdGik/Hi8EcQiY\nSL9lbAkKJpgrfqWNDo7HX/2GffZdd316123stOqrBTZS81Ow/Z/rqiPvzBV1HxEv\nabfIFd1LefWgBfECoXOpvYaBuL4N6fchX9gAis7J66WFDQVZsnJ/J3Bzl0ECRgVp\n8QIDAQAB\n-----END PUBLIC KEY-----\n",
  "verificationKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELZyXL9AOgZrIsWrDkY0ohQuvMsVa\n+3eJSfsV+a1HW0M34lZInCVPgule/a9HqnqpDtXEBclgeeKS1YT7jVjpTg==\n-----END PUBLIC KEY-----",
}
```

#### Schema

| Name              | Type                            | Required | Restrictions              | Description                                                                               |
| ----------------- | ------------------------------- | -------- | ------------------------- | ----------------------------------------------------------------------------------------- |
| `id`              | [TrusteeId](#schema-trustee-id) | true     | `/[0-9a-zA-Z-_]{3,30}/`   | none                                                                                      |
| `fullName`        | string                          | true     | `/Trustee-[0-9a-zA-Z_]+/` | none                                                                                      |
| `role`            | enum                            | true     | none                      | none                                                                                      |
| `encryptionKey`   | string                          | true     | none                      | PEM-encoded (public) encryption key of the trustee. Used by encryptors at encryption time |
| `verificationKey` | string                          | true     | none                      | PEM-encoded (public) verification key of trustee                                          |

#### Enumerated Values

| Property | Value     |
| -------- | --------- |
| role     | `Trustee` |

### Validator <a href="#schema-validator" id="schema-validator"></a>

An object listing details of a validator, including its ID, human-readable description/name, its role (`Validator`) and its public keys.

**Example**

```json
{
  "id": "validator1",
  "fullName": "Validator1",
  "role": "Validator",
  "encryptionKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvAnBzaNLM8/iIxP0Rz88\nQk7mj+TW1U1C2BQAaOAQfRTRrEsNDVPpAZB8LTfs8wZEhok5VzSMA4dPTkQE8Su8\np/eQJthOTCmBq2t8dgx0+uX3IhdwXgmWCh0OQ8NJ94rXA+/rWqjeNXZ4ShFlNDeu\nkv9OGLh4bvSTUHWzDi6M4qxlq8fJ/O+lTvJzf6cb6n7pKpT7/ppdGik/Hi8EcQiY\nSL9lbAkKJpgrfqWNDo7HX/2GffZdd316123stOqrBTZS81Ow/Z/rqiPvzBV1HxEv\nabfIFd1LefWgBfECoXOpvYaBuL4N6fchX9gAis7J66WFDQVZsnJ/J3Bzl0ECRgVp\n8QIDAQAB\n-----END PUBLIC KEY-----\n",
  "verificationKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELZyXL9AOgZrIsWrDkY0ohQuvMsVa\n+3eJSfsV+a1HW0M34lZInCVPgule/a9HqnqpDtXEBclgeeKS1YT7jVjpTg==\n-----END PUBLIC KEY-----",
}
```

#### Schema

| Name              | Type                                | Required | Restrictions                | Description                                                                                 |
| ----------------- | ----------------------------------- | -------- | --------------------------- | ------------------------------------------------------------------------------------------- |
| `id`              | [ValidatorId](#schema-validator-id) | true     | -                           | none                                                                                        |
| `fullName`        | string                              | true     | `/Validator-[0-9a-zA-Z_]+/` | none                                                                                        |
| \`role            | enum\`                              | true     | none                        | none                                                                                        |
| `encryptionKey`   | string                              | true     | none                        | PEM-encoded (public) encryption key of the validator. Used by encryptors at encryption time |
| `verificationKey` | string                              | true     | none                        | PEM-encoded (public) verification key of validator                                          |

#### Enumerated Values

| Property | Value       |
| -------- | ----------- |
| role     | `Validator` |

### Base64 <a href="#schema-base64" id="schema-base64"></a>

A base64-encoded binary data.

**Example**

```json
"aGVsbG8gd29ybGQ="
```

#### Schema

| Type   | Restrictions |
| ------ | ------------ |
| string | none         |

### Ciphertext <a href="#schema-ciphertext" id="schema-ciphertext"></a>

A piece of asymmetrically encrypted ciphertext. It is created by first generating a symmetric ephemeral key, encrypt symmetrically the message using the ephemeral key, then encrypt asymmetrically the ephemeral key by an encryption key. All binary data are encoded in base64. For details, read [the code samples](/code_samples_enc_dec).

**Example**

```json
{
  "encryptedMessage": {
    "ciphertext": "base64_encoded_data=",
    "iv": "base64_encoded_data=",
  },
  "encryptedEphemeralKey": "base64_encoded_data=",
}
```

#### Schema

| Name                    | Type                     | Required | Restrictions | Description                                                 |
| ----------------------- | ------------------------ | -------- | ------------ | ----------------------------------------------------------- |
| `encryptedMessage`      | object                   | true     | none         | Cipher of a message encrypted with an ephemeral key         |
| » `ciphertext`          | [Base64](#schema-base64) | true     | none         | none                                                        |
| » `iv`                  | [Base64](#schema-base64) | true     | none         | none                                                        |
| `encryptedEphemeralKey` | [Base64](#schema-base64) | true     | none         | The ephemeral key encrypted by an asymmetric encryption key |

### PadInstanceMetadata <a href="#schema-pad-instance-metadata" id="schema-pad-instance-metadata"></a>

Information about a PAD instance. That includes the instance name, its list of trustees, the trustee threshold, the list of validators and the validator threshold.

**Example**

```json
{
  "padName": "my-pad-1.0",
  "trusteeIds": [
    "trustee1",
    "trustee2",
  ],
  "t": 1,
  "validatorIds": [
    "validator1",
    "validator2",
  ],
  "tPrime": 1,
}
```

#### Schema

| Name           | Type                                       | Required | Restrictions | Description |
| -------------- | ------------------------------------------ | -------- | ------------ | ----------- |
| `padName`      | [PadName](#schema-pad-name)                | true     | none         | none        |
| `trusteeIds`   | array<[TrusteeId](#schema-trustee-id)>     | true     | none         | none        |
| `t`            | integer                                    | true     | none         | none        |
| `validatorIds` | array<[ValidatorId](#schema-validator-id)> | true     | none         | none        |
| `tPrime`       | integer                                    | true     | none         | none        |

### ApiResponse <a href="#schema-api-response" id="schema-api-response"></a>

**Example**

```json
{
  "ok": true,
  "message": "string",
}
```

#### Schema

| Name      | Type    | Required | Description                      |
| --------- | ------- | -------- | -------------------------------- |
| `ok`      | boolean | true     | The request is successful or not |
| `message` | string  | true     | none                             |

### Token <a href="#schema-token" id="schema-token"></a>

A 128-bit random string kept secret between the encryptor and decryptor after encryption stage and before data request stage. It identifies a data request. Its hash value identifies an `encryption`. The decryptor posts it on the ledger at data request stage.

**Example**

```
"0fe5ff17c6ee6efa8ca385587b1e1ac2"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-Z]{32}/` |

### PadName <a href="#schema-pad-name" id="schema-pad-name"></a>

ID of a PAD instance. Its length must be inclusively between 4 and 30. It should contains only lowercase letters, digits, periods (`.`) or dashes (`-`). It must start with a lowercase letter.

It is seldom used as a request parameter because the API key in the request already identifies a PAD instance.

**Example**

```json
"my-pad-1.0"
```

#### Schema

| Type   | Restrictions              |
| ------ | ------------------------- |
| string | `/[a-z][a-z0-9.-]{3,29}/` |


# Decryptor

## Post data request <a href="#op-post-data-request" id="op-post-data-request"></a>

`POST /data-requests`

### Description

Decryptor requests encryptor's data by posting a data request to the ledger through this endpoint. After sufficient number of trustees and validators observe the data request and have responded to it, the decryptor will be able to decrypt the secret.

### Parameters

| Name | In   | Type                                | Required | Description |
| ---- | ---- | ----------------------------------- | -------- | ----------- |
| -    | body | [DataRequest](#schema-data-request) | true     | none        |

**Example**

```json
{
  "token": "0fe5ff17c6ee6efa8ca385587b1e1ac2",
}
```

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | [ApiResponse](#schema-api-response) |
| 400    | Bad Request                                                     | Invalid token                 | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |
| 409    | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)   | Conflict                      | [ApiResponse](#schema-api-response) |

#### 200 OK

The data request is successfully posted on the ledger.

**Example**

```json
{
  "ok": true,
  "message": "Successfully posted data request",
}
```

#### 400 Bad Request

Input is malformed. Check that:

* `token` is a string
* `token` is a 128-bit hex string

**Example 1**

```json
{
  "ok": false,
  "message": "Wrong type at body.token",
}
```

**Example 2**

```json
{
  "ok": false,
  "message": "wrong length at body.token. Expected: 32; given: 64",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

#### 409 Conflict

The data request has already been posted.

**Example**

```json
{
  "ok": false,
  "message": "Data request has been posted before",
}
```

## Get ciphertext <a href="#op-get-ciphertext" id="op-get-ciphertext"></a>

`GET /encryptions/{token-hash}/ciphertext`

### Description

Retrieve the ciphertext part of an `Encryption`. After decrypting it with decryptor's decryption key, one should find a payload encrypted with a symmetric key together with a digital signature by the encryptor. The decryptor will not have sufficient information to further decrypt unless there are anough trustees and validators who have responded to the data request. See [the code samples](/code_samples_enc_dec) to see how decryptions are done.

### Parameters

| Name       | In   | Type                     | Required | Description             |
| ---------- | ---- | ------------------------ | -------- | ----------------------- |
| token-hash | path | [Sha256](#schema-sha256) | true     | Hash value of the token |

**Example**

`GET /encryptions/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/ciphertext`

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |
| 404    | Not found                                                       | Encryption not found          | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the ciphertext from the `encryption`.

**Schema**

| Name       | Type                             | Required | Restrictions | Description |
| ---------- | -------------------------------- | -------- | ------------ | ----------- |
| ok         | boolean                          | true     | none         | none        |
| ciphertext | [Ciphertext](#schema-ciphertext) | true     | none         | none        |

**Example**

```json
{
  "ok": true,
  "ciphertext": {
    "encryptedMessage": {
      "ciphertext": "base64_encoded_data",
      "iv": "base64_encoded_data",
    },
    "encryptedEphemeralKey": "base64_encoded_data",
  },
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

#### 404 Not found

The encryption does not exist.

**Example**

```json
{
  "ok": false,
  "message": "Encryption with token hash d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4 not found",
}
```

## Get trustee responses <a href="#op-get-trustee-responses" id="op-get-trustee-responses"></a>

`GET /data-requests/{token}/trustee-responses`

### Description

Retrieves all trustee responses for a data request signed by the corresponding Trustee. Sufficient number of individual trustees' responses reconstruct to a masked symmetric key. See [code samples](/code_samples_enc_dec) for details.

> Note 1: The path parameter is the token which should be kept secret until the data request related to the token has been posted. Therefore, this endpoint should be called only after the data request is posted onto the ledger.

> Note 2: This endpoint returns successful status even if not enough trustees have responded. User should check if the number of responses is at least the secret sharing threshold before attempting to reconstruct the secret. Otherwise a garbage value will be reconstructed.

### Parameters

| Name  | In   | Type                   | Required | Description |
| ----- | ---- | ---------------------- | -------- | ----------- |
| token | body | [Token](#schema-token) | true     | none        |

**Example**

`GET /data-requests/{token}/trustee-responses`

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 400    | Bad Request                                                     | Token is invalid in format    | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |
| 404    | Not found                                                       | Encryption not found          | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved trustee responses for a data request.

**Schema**

| Name             | Type                                                                                            | Required | Restrictions | Description |
| ---------------- | ----------------------------------------------------------------------------------------------- | -------- | ------------ | ----------- |
| ok               | boolean                                                                                         | true     | none         | none        |
| trusteeResponses | dict<[TrusteeId](#schema-trustee-id), [SignedTrusteeResponse](#schema-signed-trustee-response)> | true     | none         | none        |

**Example**

```json
{
  "ok": true,
  "trusteeResponses": {
    "trustee1": {
      "trusteeResponse": "{\"padName\":\"my-pad-1.0\",\"token\":\"e3b0c44298fc1c149afbf4c8996fb924\",\"trusteeShare\":\"Ad8WqKbFL3ft1cCRYJE8Yh2Tb6UqbEVfErg/RF5RoXQA\",\"type\":\"trustee_response\",\"trusteeId\":\"trustee1\"}",
      "signature": {
        "signerMetdata": {
          "id": "trustee1",
          "fullName": "Trustee-1",
          "role": "Trustee",
        },
      },
    },
  },
}
```

#### 400 Bad Request

Request is malformed.

**Example**

```json
{
  "ok": false,
  "message": "wrong length at path.token. Expected: 32; given 31",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

#### 404 Not found

The data request does not exist.

**Example**

```json
{
  "ok": false,
  "message": "Data request not found",
}
```

## Get validator responses <a href="#op-get-validator-responses" id="op-get-validator-responses"></a>

`GET /data-requests/{token}/validator-responses`

### Description

Retrieves all validator responses for a data request signed by the corresponding Validator. Sufficient number of individual validators' responses reconstruct to a mask that together with trustees' responses reveals a symmetric key. The combined results also reveals the decryptor's identity. See [code samples](/code_samples_enc_dec)

> Note 1: The path parameter is the token which should be kept secret until the data request related to the token has been posted. Therefore, this endpoint should be called only after the data request is posted onto the ledger.

> Note 2: This endpoint returns successful status even if not enough validators have responded. User should check if the number of responses is at least the secret sharing threshold before attempting to reconstruct the secret. Otherwise a garbage value will be reconstructed.

### Parameters

| Name  | In   | Type                   | Required | Description |
| ----- | ---- | ---------------------- | -------- | ----------- |
| token | body | [Token](#schema-token) | true     | none        |

**Example**

`GET /data-requests/{token}/validator-responses`

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 400    | Bad Request                                                     | Token is invalid in format    | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |
| 404    | Not found                                                       | Encryption not found          | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved validator responses for a data request.

**Schema**

| Name               | Type                                                                                       | Required | Restrictions | Description |
| ------------------ | ------------------------------------------------------------------------------------------ | -------- | ------------ | ----------- |
| ok                 | boolean                                                                                    | true     | none         | none        |
| validatorResponses | dict<[ValidatorId](#schema-validator-id), [ValidatorResponse](#schema-validator-response)> | true     | none         | none        |

**Example**

```json
{
  "ok": true,
  "validatorResponses": {
    "validator1": {
      "validatorResponse": ,
      "signature": {
        "signerMetdata": {
          "id": "validator1",
          "fullName": "Validator-1",
          "role": "Validator",
        },
      },
    },
  },
}
```

#### 400 Bad Request

Request is malformed.

**Example**

```json
{
  "ok": false,
  "message": "wrong length at path.token. Expected: 32; given 31",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

#### 404 Not found

The data request does not exist.

**Example**

```json
{
  "ok": false,
  "message": "Data request not found",
}
```

## Schemas

### DataRequest <a href="#schema-data-request" id="schema-data-request"></a>

A data request, containing a token whose hash value was provided by the encryptor at encryption time.

**Example**

```json
{
  "token": "0fe5ff17c6ee6efa8ca385587b1e1ac2",
}
```

#### Schema

| Name  | Type                   | Required | Restrictions | Description |
| ----- | ---------------------- | -------- | ------------ | ----------- |
| token | [Token](#schema-token) | true     | none         | none        |

### Ciphertext <a href="#schema-ciphertext" id="schema-ciphertext"></a>

A piece of asymmetrically encrypted ciphertext. It is created by first generating a symmetric ephemeral key, encrypt symmetrically the message using the ephemeral key, then encrypt asymmetrically the ephemeral key by an encryption key. All binary data are encoded in base64. For details, read [the code samples](/code_samples_enc_dec).

**Example**

```json
{
  "encryptedMessage": {
    "ciphertext": "base64_encoded_data=",
    "iv": "base64_encoded_data="
  },
  "encryptedEphemeralKey": "base64_encoded_data=",
}
```

#### Schema

| Name                  | Type                     | Required | Restrictions | Description                                                 |
| --------------------- | ------------------------ | -------- | ------------ | ----------------------------------------------------------- |
| encryptedMessage      | object                   | true     | none         | Cipher of a message encrypted with an ephemeral key         |
| » ciphertext          | [Base64](#schema-base64) | true     | none         | none                                                        |
| » iv                  | [Base64](#schema-base64) | true     | none         | none                                                        |
| encryptedEphemeralKey | [Base64](#schema-base64) | true     | none         | The ephemeral key encrypted by an asymmetric encryption key |

### Base64 <a href="#schema-base64" id="schema-base64"></a>

A base64-encoded binary data.

**Example**

```json
"aGVsbG8gd29ybGQ="
```

#### Schema

| Type   | Restrictions |
| ------ | ------------ |
| string | none         |

### Token <a href="#schema-token" id="schema-token"></a>

A 128-bit random string kept secret between the encryptor and decryptor after encryption stage and before data request stage. It identifies a data request. Its hash value identifies an `encryption`. The decryptor posts it on the ledger at data request stage.

**Example**

```
"0fe5ff17c6ee6efa8ca385587b1e1ac2"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-Z]{32}/` |

### Sha256 <a href="#schema-sha256" id="schema-sha256"></a>

A Sha256 hash value as a hexidecimal string.

**Example**

```json
"d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-F]{64}/` |

### TrusteeId <a href="#schema-trustee-id" id="schema-trustee-id"></a>

ID of a trustee. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

**Example**

```
my_trustee-1
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### ValidatorId <a href="#schema-validator-id" id="schema-validator-id"></a>

ID of a validator. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

#### Example

```
my_validator-2
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### ApiResponse <a href="#schema-api-response" id="schema-api-response"></a>

**Example**

```json
{
  "ok": true,
  "message": "string"
}
```

#### Schema

| Name    | Type    | Required | Description                      |
| ------- | ------- | -------- | -------------------------------- |
| ok      | boolean | true     | The request is successful or not |
| message | string  | true     | none                             |

### TrusteeResponse <a href="#schema-trustee-response" id="schema-trustee-response"></a>

A trustee response to a data request. It contains the decrypted trustee share for the decryptor to perform a full decryption on a secret. It also consists of metadata for identifying the corresponding data request.

**Example**

```json
{
    "padName": "my-pad-1.0",
    "token": "e3b0c44298fc1c149afbf4c8996fb924",
    "trusteeShare": "0110",
    "type": "trustee_response",
    "trusteeId": "trustee1",
}
```

#### Schema

| Name         | Type                            | Required | Restrictions | Description                                   |
| ------------ | ------------------------------- | -------- | ------------ | --------------------------------------------- |
| padName      | [PadName](#schema-pad-name)     | true     | none         | The instance where the data request is posted |
| token        | [Token](#schema-token)          | true     | none         | The ID of the data request                    |
| trusteeShare | [Base64](#schema-base64)        | true     | none         | The decrypted trustee share                   |
| type         | enum                            | true     | none         | Type of response                              |
| trusteeId    | [TrusteeId](#schema-trustee-id) | true     | none         | ID of the responding trustee                  |

#### Enumerated Values

| Property | Value                |
| -------- | -------------------- |
| type     | `"trustee_response"` |

### SignedTrusteeResponse <a href="#schema-signed-trustee-response" id="schema-signed-trustee-response"></a>

A trustee response attached with a digital signature for everyone to validate the response's integrity.

Note that the trustee response is represented as a string (instead of an object). This ensures that there is a unified way to verify the signature.

**Example**

```json
{
  "trusteeResponse": "{\"padName\":\"my-pad-1.0\",\"token\":\"e3b0c44298fc1c149afbf4c8996fb924\",\"trusteeShare\":\"0110\",\"type\":\"trustee_response\",\"trusteeId\":\"trustee1\"}",
  "signature": {
    "signerMetadata": {
      "id": "trustee1",
      "fullName": "Trustee-1",
      "role": "Trustee"
    },
    "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ=="
  },
}
```

### Schema

| Name            | Type                                                | Required | Description |
| --------------- | --------------------------------------------------- | -------- | ----------- |
| trusteeResponse | string<[TrusteeResponse](#schema-trustee-response)> | true     | none        |
| signature       | [Signature](#schema-signature)                      | true     | none        |

### Signature <a href="#schema-signature-href-schema-signature-href-schema-signature" id="schema-signature-href-schema-signature-href-schema-signature"></a>

A digital signature. It consists of the metadata of the signer, including its ID, and the signature payload encoded in base64.

**Schema**

```json
{
  "signerMetadata": {
    "id": "string",
    "fullName": "string",
    "role": "Trustee",
  },
  "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ==",
}
```

#### Schema

| Name           | Type                               | Required | Description |
| -------------- | ---------------------------------- | -------- | ----------- |
| signerMetadata | [Participant](#schema-participant) | false    | none        |
| payload        | [Base64](#schema-base64)           | false    | none        |

### Participant <a href="#schema-participant-href-schema-participant-href-schema-participant" id="schema-participant-href-schema-participant-href-schema-participant"></a>

Metadata of a participant in PAD. It can currently be used to describe a trustee or a validator.

**Example**

```json
{
  "id": "my_trustee-1",
  "fullName": "Trustee-1",
  "role": "Trustee"
}
```

#### Schema

| Name     | Type                                                                   | Required | Description                                              |
| -------- | ---------------------------------------------------------------------- | -------- | -------------------------------------------------------- |
| id       | [TrusteeId](#schema-trustee-id) or [ValidatorId](#schema-validator-id) | true     | `/[0-9a-zA-Z-_]{3,30}/`                                  |
| fullName | string                                                                 | true     | `/Trustee-[0-9a-zA-Z_]+/` or `/Validator-[0-9a-zA-Z_]+/` |
| role     | enum                                                                   | true     | none                                                     |

#### Enumerated Values

| Property | Value     |
| -------- | --------- |
| role     | Trustee   |
| role     | Validator |
| role     | Server    |


# Trustee

## Get latest data requests <a href="#op-get-data-requests" id="op-get-data-requests"></a>

`GET /data-requests`

### Description

Retrieve the latest block headers. If at least one data request is present in a block, the block data is also returned. The notion of "latest" is determined by the query parameter `oldBlockHeight` and the ledger's current height. Trustees use this endpoint to get the latest relevant blocks, extract the data requests in them, and respond to the data requests accordingly.

Using the block data, one can compute the data hash and verify consistency of the block header. In addition, using the block headers, one can verify the blocks are chained.

### Parameters

| Name           | In    | Type    | Required | Description                                        |
| -------------- | ----- | ------- | -------- | -------------------------------------------------- |
| oldBlockHeight | query | integer | true     | Number of blocks the trustee has already processed |

**Example**

`GET /data-requests?oldBlockHeight=1`

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 400    | Bad Request                                                     | Request is invalid            | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the blocks and block data which contain data requests.

**Schema**

| Name   | Type                                                              | Required | Restrictions | Description |
| ------ | ----------------------------------------------------------------- | -------- | ------------ | ----------- |
| ok     | boolean                                                           | true     | none         | none        |
| blocks | dict<[BlockNumber](#schema-block-number), [Block](#schema-block)> | true     | none         | none        |

**Example**

```json
{
    "ok": true,
    "blocks": {
        "1": {
            "header": {
                "number": "1",
                "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
                "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
            },
        },
        "2": {
            "header": {
                "number": "2",
                "previousHash": "78aecc3976f7b2151ce0574278f816b8e5983e18229fde7b6e7c3ebdf5147baf",
                "dataHash": "3ec339eae416289f4ddd7dc2b69e8edf12ac013089207732ad6156e02dc21fb5",
            },
            "data": {
                "data": ["datum1==", "datum2=="],
            },
        },
    },
}
```

#### 400 Bad Request

Request is malformed. Make sure:

* `oldBlockHeight` is present in query parameter
* `oldBlockHeight` is a non-negative number
* `oldBlockHeight` is an integer
* `oldBlockHeight` is valid - no larger than the current block height of the ledger

**Example 1**

```json
{
    "ok": false,
    "message": "query.oldBlockHeight must be a non-negative integer",
}
```

**Example 2**

```json
{
    "ok": false,
    "message": "Invalid valid at query.oldBlockHeight. Expected: <=5; given: 10",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
    "ok": false,
    "message": "Unauthorized",
}
```

## Get encrypted trustee share in an `Encryption` <a href="#op-get-encrypted-trustee-share" id="op-get-encrypted-trustee-share"></a>

`GET /encryptions/{token-hash}/encrypted-trustee-shares/{trustee-id}`

### Description

Retrieves a encrypted trustee share from an `Encryption`. After detecting a new data request, a trustee should use this endpoint to get its encrypted share from the corresponding `Encryption`, decrypt it with its decryption key, then post the result with [postTrusteeResponse](#opPostTrusteeResponse).

### Parameters

| Name       | In   | Type                            | Required | Description             |
| ---------- | ---- | ------------------------------- | -------- | ----------------------- |
| token-hash | path | [Sha256](#schema-sha256)        | true     | Hash value of the token |
| trustee-id | path | [TrusteeId](#schema-trustee-id) | true     | Trustee's ID            |

**Example**

`GET /encryptions/d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4/encrypted-trustee-shares/trustee1`

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 400    | Bad Request                                                     | Request is invalid            | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |
| 404    | Not Found                                                       | Encryption not found          | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the encrypted trustee share.

**Schema**

| Name                  | Type                     | Required | Description                 |
| --------------------- | ------------------------ | -------- | --------------------------- |
| ok                    | boolean                  | true     | none                        |
| encryptedTrusteeShare | [Base64](#schema-base64) | true     | The encrypted trustee share |

**Example**

```json
{
  "ok": true,
  "encryptedTrusteeShare": "base64_encoded_data"
}
```

#### 400 Bad Request

Trustee does not exist or does not reference this PAD instance.

**Example**

```json
{
    "ok": false,
    "message": "Trustee with ID trustee1 does not exist in the PAD instance",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
    "ok": false,
    "message": "Unauthorized",
}
```

#### 404 Not Found

The encryption does not exist.

**Example**

```json
{
    "ok": false,
    "message": "Encryption with token hash d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4 not found",
}
```

## Post trustee response <a href="#op-post-trustee-response" id="op-post-trustee-response"></a>

`POST /data-requests/{token}/trustee-responses`

### Description

Posts a trustee response to the ledger.

After retrieving and finish decrypting its share, the trustee needs to post the result back to the ledger so that eventually, the decryptor can decrypt a secret.

### Parameters

| Name  | In   | Type                                                     | Required | Description                                                                          |
| ----- | ---- | -------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------ |
| token | path | [Token](#schema-token)                                   | true     | ID of the data request                                                               |
| -     | body | [SignedTrusteeResponse](#schema-signed-trustee-response) | true     | The decrypted share, along with a digital signature of the trustee and some metadata |

**Example**

`POST /data-requests/e3b0c44298fc1c149afbf4c8996fb924/trustee-responses`

```json
{
  "trusteeResponse": "{\"padName\":\"my-pad-1.0\",\"token\":\"e3b0c44298fc1c149afbf4c8996fb924\",\"trusteeShare\":\"0110\",\"type\":\"trustee_response\",\"trusteeId\":\"trustee1\"}",
  "signature": {
    "signerMetadata": {
      "id": "trustee1",
      "fullName": "Trustee-1",
      "role": "Trustee"
    },
    "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ=="
  }
}
```

### Responses

| Status | Meaning                                                         | Description                                        | Schema                              |
| ------ | --------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                                          | [ApiResponse](#schema-api-response) |
| 400    | Bad Request                                                     | Data request and trustee response are inconsistent | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid                      | [ApiResponse](#schema-api-response) |
| 403    | Forbidden                                                       | Trustee is not in the instance                     | [ApiResponse](#schema-api-response) |
| 404    | Not found                                                       | Data request not found                             | [ApiResponse](#schema-api-response) |
| 409    | Conflict                                                        | Response has been made before                      | [ApiResponse](#schema-api-response) |

#### 200 OK

The trustee response is successfully posted.

**Example**

```json
{
    "ok": true,
    "message": "Successfully posted trustee response",
}
```

#### 400 Bad request

Request is invalid. Make sure that :

* `padName` in `TrusteeResponse` is consistent with the PAD instance to which the API key is pointing
* `token` in path and `TrusteeResponse` are consistent
* `trusteeId` in `TrusteeResponse` and `signature` are consistent
* `role` is `Trustee` in `signature`
* signature in `signature` is consistent with the payload `TrusteeResponse`

**Example 1**

```json
{
    "ok": false,
    "message": "Inconsistent trustee ID",
}
```

**example 2**

```json
{
    "ok": false,
    "message": "Inconsistent PAD instance name",
}
```

**example 3**

```json
{
    "ok": false,
    "message": "Invalid signature",
}
```

#### 401 Unauthorized

Api key is missing or invalid.

**Example**

```json
{
    "ok": false,
    "message": "Unauthorized",
}
```

#### 403 Forbidden

The trustee is not part of the instance. Recall that the list of trustees is determined by the *Operator* at instance creation time.

**Example**

```json
{
    "ok": false,
    "message": "Not a trustee of the instance",
}
```

#### 404 Not Found

The server cannot find a data request pointed by the token in the path parameter.

**Example**

```json
{
    "ok": false,
    "message": "Data request not found",
}
```

#### 409 Conflict

A response from the same trustee has been made for the same data request before.

**Example**

```json
{
    "ok": false,
    "message": "Trustee response has been made for this request",
}
```

## Post trustee attestation <a href="#op-post-trustee-attestation" id="op-post-trustee-attestation"></a>

`PUT /trustee-attestations/{trustee-id}`

### Description

Trustee posts its view of the ledger\* with a digital signature. This allows other users to convince themselves that they are seeing the same ledger as trustees, who are the ones handling the data requests. Trustees should attest to the ledger regularly even there is no update on the ledger.

> \*The ledger view of the trustee includes the ID/name of the PAD instance, the height of the ledger, the current block hash of the ledger and a timestamp when the trustee construct the attestation.

### Parameters

| Name       | In   | Type                                              | Required | Description                                                                          |
| ---------- | ---- | ------------------------------------------------- | -------- | ------------------------------------------------------------------------------------ |
| trustee-id | path | [TrusteeId](#schema-trustee-id)                   | true     | ID of the trustee                                                                    |
| -          | body | [TrusteeAttestation](#schema-trustee-attestation) | true     | The decrypted share, along with a digital signature of the trustee and some metadata |

**Example**

`PUT /trustee-attestations/trustee1`

```json
{
  "ledgerDigest": "{\"ledgerId\":\"my-pad-1.0\",\"height\":10,\"currentHash\":\"54c0639eb43fcc52cfc4d05546ee35984210a2d3d977e83600288aa\",\"timestamp\":\"2021-09-19T12:41:17.368Z\"}",
  "signature": {
    "signerMetadata": {
      "id": "trustee1",
      "fullName": "Trustee-1",
      "role": "Trustee"
    },
    "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ=="
  }
}
```

### Responses

| Status | Meaning                                                         | Description                                        | Schema                              |
| ------ | --------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                                          | [ApiResponse](#schema-api-response) |
| 400    | Bad Request                                                     | Data request and trustee response are inconsistent | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid                      | [ApiResponse](#schema-api-response) |
| 403    | Forbidden                                                       | Trustee is not in the instance                     | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully posted trustee attestation.

**Example**

```json
{
    "ok": true,
    "message": "Successfully posted trustee attestation",
}
```

#### 400 Bad request

Request is malformed. Check that:

* Trustee IDs in attestation and path parameter are consistent.
* `padName` in attestation is consistent with the PAD instance to which the API key is pointing
* The signature is correct
* The attestation is correct, in the sense that:
  * The block height is non-negative and at most even with the ledger
  * `currentHash` is the block hash at `height`

**Example 1**

```json
{
    "ok": false,
    "message": "Inconsistent trustee ID"
}
```

**Example 2**

```json
{
    "ok": false,
    "message": "height (10) in attestation is too large; Expected <= 5"
}
```

**Example 3**

```json
{
    "ok": false,
    "message": "currentHash in attestation is <some_hash>; Expected <some_other_hash>"
}
```

#### 401 Unauthorized

Api key is missing or invalid.

**Example**

```json
{
    "ok": false,
    "message": "Unauthorized",
}
```

#### 403 Forbidden

The trustee is not part of the instance. Recall that the list of trustees is determined by the *Operator* at instance creation time.

**Example**

```json
{
    "ok": false,
    "message": "Not a trustee of the instance",
}
```

***

## Schemas

### ApiResponse <a href="#schema-api-response" id="schema-api-response"></a>

**Example**

```json
{
  "ok": true,
  "message": "string"
}
```

#### Schema

| Name    | Type    | Required | Description                      |
| ------- | ------- | -------- | -------------------------------- |
| ok      | boolean | true     | The request is successful or not |
| message | string  | true     | none                             |

### BlockNumber <a href="#schema-block-number" id="schema-block-number"></a>

ID of a block. It is an incremental index starting from 0. For example, if a ledger has height 10, then it has blocks 0, 1, ..., 9. The next block has block number 10.

#### Schema

| Type    | Restrictions |
| ------- | ------------ |
| integer | Non-negative |

### Block <a href="#schema-block" id="schema-block"></a>

Blocks are put sequentially as a blockchain to form a ledger. It consists of the header (which contains the chaining information) and optionally the data (from which data requests and trustee and validator responses can be extracted).

**Example 1**

```json
{
    "header": {
        "number": "1",
        "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
        "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
    },
}
```

**Example 2**

```json
{
    "header": {
        "number": "2",
        "previousHash": "78aecc3976f7b2151ce0574278f816b8e5983e18229fde7b6e7c3ebdf5147baf",
        "dataHash": "3ec339eae416289f4ddd7dc2b69e8edf12ac013089207732ad6156e02dc21fb5",
    },
    "data": {
        "data": ["datum1==", "datum2=="],
    },
}
```

#### Schema

| Name   | Type                                | Required | Description |
| ------ | ----------------------------------- | -------- | ----------- |
| header | [BlockHeader](#schema-block-header) | true     | none        |
| data   | [BlockData](#schema-block-data)     | false    | none        |

### BlockHeader <a href="#schema-block-header" id="schema-block-header"></a>

Block header contains metadata of a block. They are sufficient to prove the blocks form a chain without the need of block data, because the `previousHash` field in the schema refers to the hash of the previous block header, instead of the entire previous block. Thus, if the block data is irrelevant (for example not containing any data request when one is asking for them), it can be skipped.

If the block number is 0, the `number` and `previousHash` fields are empty. `dataHash` is computed with the same block's data. Refer to code samples on how to compute hash of a block header.

**Example 1**

```json
{
    "dataHash": "b24fd1a8c0c37f388f67ce6583710e3b1e5cfa79e652f764e92ee412299ac6c5",
}
```

**Example 2**

```json
{
    "number": "1",
    "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
    "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
}
```

#### Schema

| Name         | Type                                | Required | Description                         |
| ------------ | ----------------------------------- | -------- | ----------------------------------- |
| number       | [BlockNumber](#schema-block-number) | false    | Block number of the current block   |
| previousHash | [Sha256](#schema-sha256)            | false    | Hash of the previous block's header |
| dataHash     | [Sha256](#schema-sha256)            | true     | Hash of this block's data           |

### BlockData <a href="#schema-block-data" id="schema-block-data"></a>

Block data contains "transactions". In PAD, these are the data requests and trustee and validator responses. See code samples to see how block data are decoded.

**Example**

```json
{
    "data": ["datum1==", "datum2=="],
}
```

#### Schema

| Name | Type                            | Required | Description |
| ---- | ------------------------------- | -------- | ----------- |
| data | array<[Base64](#schema-base64)> | true     | none        |

### Base64

A base64-encoded binary data.

**Example**

```json
"aGVsbG8gd29ybGQ="
```

#### Schema

| Type   | Restrictions |
| ------ | ------------ |
| string | none         |

### Sha256

A Sha256 hash value as a hexidecimal string.

**Example**

```json
"d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-F]{64}/` |

### TrusteeId <a href="#schema-trustee-id" id="schema-trustee-id"></a>

ID of a trustee. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

**Example**

```
trustee1
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### Token <a href="#schema-token" id="schema-token"></a>

A 128-bit random string kept secret between the encryptor and decryptor after encryption stage and before data request stage. It identifies a data request. Its hash value identifies an `encryption`. The decryptor posts it on the ledger at data request stage.

**Example**

```
"0fe5ff17c6ee6efa8ca385587b1e1ac2"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-Z]{32}/` |

### PadName <a href="#schema-pad-name" id="schema-pad-name"></a>

ID of a PAD instance. Its length must be inclusively between 4 and 30. It should contains only lowercase letters, digits, periods (`.`) or dashes (`-`). It must start with a lowercase letter.

It is seldom used as a request parameter because the API key in the request already identifies a PAD instance.

**Example**

```json
"my-pad-1.0"
```

#### Schema

| Type   | Restrictions              |
| ------ | ------------------------- |
| string | `/[a-z][a-z0-9.-]{3,29}/` |

### TrusteeResponse <a href="#schema-trustee-response" id="schema-trustee-response"></a>

A trustee response to a data request. It contains the decrypted trustee share for the decryptor to perform a full decryption on a secret. It also consists of metadata for identifying the corresponding data request.

**Example**

```json
{
    "padName": "my-pad-1.0",
    "token": "e3b0c44298fc1c149afbf4c8996fb924",
    "trusteeShare": "0110",
    "type": "trustee_response",
    "trusteeId": "trustee1",
}
```

#### Schema

| Name         | Type                            | Required | Restrictions | Description                                   |
| ------------ | ------------------------------- | -------- | ------------ | --------------------------------------------- |
| padName      | [PadName](#schema-pad-name)     | true     | none         | The instance where the data request is posted |
| token        | [Token](#schema-token)          | true     | none         | The ID of the data request                    |
| trusteeShare | [Base64](#schema-base64)        | true     | none         | The decrypted trustee share                   |
| type         | enum                            | true     | none         | Type of response                              |
| trusteeId    | [TrusteeId](#schema-trustee-id) | true     | none         | ID of the responding trustee                  |

#### Enumerated Values

| Property | Value                |
| -------- | -------------------- |
| type     | `"trustee_response"` |

### SignedTrusteeResponse <a href="#schema-signed-trustee-response" id="schema-signed-trustee-response"></a>

A trustee response attached with a digital signature for everyone to validate the response's integrity.

Note that the trustee response is represented as a string (instead of an object). This ensures that there is a unified way to verify the signature.

**Example**

```json
{
  "trusteeResponse": "{\"padName\":\"my-pad-1.0\",\"token\":\"e3b0c44298fc1c149afbf4c8996fb924\",\"trusteeShare\":\"0110\",\"type\":\"trustee_response\",\"trusteeId\":\"trustee1\"}",
  "signature": {
    "signerMetadata": {
      "id": "string",
      "fullName": "string",
      "role": "Trustee"
    },
    "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ=="
  }
}
```

### Schema

| Name            | Type                                                | Required | Description |
| --------------- | --------------------------------------------------- | -------- | ----------- |
| trusteeResponse | string<[TrusteeResponse](#schema-trustee-response)> | true     | none        |
| signature       | [Signature](#schema-signature)                      | true     | none        |

### Participant <a href="#schema-participant" id="schema-participant"></a>

Metadata of a participant in PAD. It can currently be used to describe a trustee or a validator.

**Example**

```json
{
  "id": "trustee1",
  "fullName": "Trustee-1",
  "role": "Trustee"
}
```

#### Schema

| Name     | Type                                                                   | Required | Description                                              |
| -------- | ---------------------------------------------------------------------- | -------- | -------------------------------------------------------- |
| id       | [TrusteeId](#schema-trustee-id) or [ValidatorId](#schema-validator-id) | true     | `/[0-9a-zA-Z-_]{3,30}/`                                  |
| fullName | string                                                                 | true     | `/Trustee-[0-9a-zA-Z_]+/` or `/Validator-[0-9a-zA-Z_]+/` |
| role     | enum                                                                   | true     | none                                                     |

#### Enumerated Values

| Property | Value     |
| -------- | --------- |
| role     | Trustee   |
| role     | Validator |
| role     | Server    |

### Signature <a href="#schema-signature" id="schema-signature"></a>

A digital signature. It consists of the metadata of the signer, including its ID, and the signature payload encoded in base64.

**Schema**

```json
{
  "signerMetadata": {
    "id": "string",
    "fullName": "string",
    "role": "Trustee",
  },
  "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ==",
}
```

#### Schema

| Name           | Type                              | Required | Description |
| -------------- | --------------------------------- | -------- | ----------- |
| signerMetadata | [Participant](#schemaparticipant) | false    | none        |
| payload        | [Base64](#schema-base64)          | false    | none        |

### DateTime <a href="#schema-date-time" id="schema-date-time"></a>

A timestamp in ISO 8601 format.

**Example**

```json
"2021-05-05T13:53:19.275Z"
```

#### Schema

| Type   | Restrictions |
| ------ | ------------ |
| string | -            |

### LedgerDigest <a href="#schema-ledger-digest" id="schema-ledger-digest"></a>

A succinct representation of the ledger, which consists of the PAD instance name, the height and the then block hash of its ledger, and the timestamp when this digest is generated.

**Example**

```json
{
    "ledgerId": "my-pad-1.0",
    "height": 10,
    "currentHash": "54c0639eb43fcc52cfc4d05546ee35984210a2d3d977e83600288aa",
    "timestamp":"2021-09-19T12:41:17.368Z",
}
```

#### Schema

| Name        | Type                                | Required | Restrictions | Description                                 |
| ----------- | ----------------------------------- | -------- | ------------ | ------------------------------------------- |
| ledgerId    | [PadName](#schema-pad-name)         | true     | none         | The PAD instance's name                     |
| height      | [BlockHeight](#schema-block-height) | true     | none         | Block height of the ledger                  |
| currentHash | [Sha256](#schema-sha256)            | true     | none         | Hash of the block at `height` on the ledger |
| timestamp   | [DateTime](#schema-date-time)       | true     | none         | Time at which this digest is generated      |

### TrusteeAttestation <a href="#schema-trustee-attestation" id="schema-trustee-attestation"></a>

A trustee's succinct view of the ledger, along with a digital signature of it. The succinct view consists of the PAD instance ID, height and latest block hash of its ledger, and the latest timestamp when the attestation is created.

A collection of trustee attestations proves to a user that she and the trustees are seeing the same ledger.

Note that the ledger digest is represented as a string (instead of an object). This ensures that there is a unified way to verify the signature.

**Example**

```json
{
  "ledgerDigest": "{\"ledgerId\":\"my-pad-1.0\",\"height\":10,\"currentHash\":\"54c0639eb43fcc52cfc4d05546ee35984210a2d3d977e83600288aa\",\"timestamp\":\"2021-09-19T12:41:17.368Z\"}",
  "signature": {
    "signerMetadata": {
      "id": "trustee1",
      "fullName": "Trustee-1",
      "role": "Trustee"
    },
    "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ=="
  }
}
```

#### Schema

| Name         | Type                                          | Required | Restrictions | Description                                |
| ------------ | --------------------------------------------- | -------- | ------------ | ------------------------------------------ |
| ledgerDigest | string<[LedgerDigest](#schema-ledger-digest)> | true     | none         | A succinct representation of the ledger    |
| signature    | [Signature](#schemasignature)                 | true     | none         | A digital signature against `ledgerDigest` |


# Validator

## Get latest data requests <a href="#op-get-data-requests" id="op-get-data-requests"></a>

`GET /data-requests`

### Description

Retrieve the latest block headers. If at least one data request is present in a block, the block data is also returned. The notion of "latest" is determined by the query parameter `oldBlockHeight` and the ledger's current height. Validators use this endpoint to get the latest relevant blocks, extract the data requests in them, and respond to the data requests accordingly.

Using the block data, one can compute the data hash and verify consistency of the block header. In addition, using the block headers, one can verify the blocks are chained.

### Parameters

| Name           | In    | Type    | Required | Description                                          |
| -------------- | ----- | ------- | -------- | ---------------------------------------------------- |
| oldBlockHeight | query | integer | true     | Number of blocks the validator has already processed |

**Example**

`GET /data-requests?oldBlockHeight=1`

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 400    | Bad Request                                                     | Request is invalid            | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the blocks and block data which contain data requests.

**Schema**

| Name   | Type                                                              | Required | Restrictions | Description |
| ------ | ----------------------------------------------------------------- | -------- | ------------ | ----------- |
| ok     | boolean                                                           | true     | none         | none        |
| blocks | dict<[BlockNumber](#schema-block-number), [Block](#schema-block)> | true     | none         | none        |

**Example**

```json
{
    "ok": true,
    "blocks": {
        "1": {
            "header": {
                "number": "1",
                "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
                "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
            },
        },
        "2": {
            "header": {
                "number": "2",
                "previousHash": "78aecc3976f7b2151ce0574278f816b8e5983e18229fde7b6e7c3ebdf5147baf",
                "dataHash": "3ec339eae416289f4ddd7dc2b69e8edf12ac013089207732ad6156e02dc21fb5",
            },
            "data": {
                "data": ["datum1==", "datum2=="],
            },
        },
    },
}
```

#### 400 Bad Request

Request is malformed. Make sure:

* `oldBlockHeight` is present in query parameter
* `oldBlockHeight` is a non-negative number
* `oldBlockHeight` is an integer
* `oldBlockHeight` is valid - no larger than the current block height of the ledger

**Example 1**

```json
{
    "ok": false,
    "message": "query.oldBlockHeight must be a non-negative integer",
}
```

**Example 2**

```json
{
    "ok": false,
    "message": "Invalid valid at query.oldBlockHeight. Expected: <=5; given: 10",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
    "ok": false,
    "message": "Unauthorized",
}
```

## Get hashed trustee shares in an `Encryption` <a href="#op-get-hashed-trustee-shares" id="op-get-hashed-trustee-shares"></a>

`GET /encryptions/{token-hash}/hashed-trustee-shares`

### Description

Retrieves all the hashed trustee share from an `Encryption`. After receiving a new data request, before the validator attempt to respond to it, it should check if the threshold number of trustees have correctly responded to the data request. It can do this by checking consistent the shares and their hashes uploaded by the encryptor at encryption time. The former are the return values of this endpoint.

### Parameters

| Name       | In   | Type                     | Required | Description             |
| ---------- | ---- | ------------------------ | -------- | ----------------------- |
| token-hash | path | [Sha256](#schema-sha256) | true     | Hash value of the token |

**Example**

`GET /encryptions/d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4/hashed-trustee-shares`

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |
| 404    | Not Found                                                       | Encryption not found          | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the hashed trustee shares.

**Schema**

| Name               | Type                                                            | Required | Description                                     |
| ------------------ | --------------------------------------------------------------- | -------- | ----------------------------------------------- |
| ok                 | boolean                                                         | true     | none                                            |
| hashedTrusteeShare | dict<[TrusteeId](#schema-trustee-id), [Sha256](#schema-sha256)> | true     | A mapping from a trustee ID to its hashed share |

**Example**

```json
{
  "ok": true,
  "hashedTrusteeShare": {
      "trustee1": "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
      "my_trustee-2": "486ea46224d1bb4fb680f34f7c9ad96a8f24ec88be73ea8e5a6c65260e9cb8a7",
  },
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
    "ok": false,
    "message": "Unauthorized",
}
```

#### 404 Not Found

The encryption does not exist.

**Example**

```json
{
    "ok": false,
    "message": "Encryption with token hash d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4 not found",
}
```

## Get encrypted validator share in an `Encryption` <a href="#op-get-encrypted-validator-share" id="op-get-encrypted-validator-share"></a>

`GET /encryptions/{token-hash}/encrypted-validator-shares/{validator-id}`

### Description

Retrieves an encrypted validator share from an `Encryption`. After receiving a new data request, a validator should use this endpoint to get its encrypted share from the corresponding `Encryption`, decrypt it with its decryption key, then post the result with [postValidatorResponse](#opPostValidatorResponse).

### Parameters

| Name         | In   | Type                                | Required | Description             |
| ------------ | ---- | ----------------------------------- | -------- | ----------------------- |
| token-hash   | path | [Sha256](#schema-sha256)            | true     | Hash value of the token |
| validator-id | path | [ValidatorId](#schema-validator-id) | true     | The validator's ID      |

**Example**

`GET /encryptions/d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4/encrypted-validator-shares/validator1`

### Responses

| Status | Meaning                                                         | Description                   | Schema                              |
| ------ | --------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                     | Inline                              |
| 400    | Bad Request                                                     | Request is invalid            | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid | [ApiResponse](#schema-api-response) |
| 404    | Not Found                                                       | Encryption not found          | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the encrypted validator share.

**Schema**

| Name                    | Type                     | Required | Description                   |
| ----------------------- | ------------------------ | -------- | ----------------------------- |
| ok                      | boolean                  | true     | none                          |
| encryptedValidatorShare | [Base64](#schema-base64) | true     | The encrypted validator share |

**Example**

```json
{
  "ok": true,
  "encryptedValidatorShare": "base64_encoded_data"
}
```

#### 400 Bad Request

Validator does not exist or does not reference this PAD instance.

**Example**

```json
{
    "ok": false,
    "message": "Validator with ID validator1 does not exist in the PAD instance",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
    "ok": false,
    "message": "Unauthorized",
}
```

#### 404 Not Found

The encryption does not exist.

**Example**

```json
{
    "ok": false,
    "message": "Encryption with token hash d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4 not found",
}
```

## Post validator response <a href="#op-post-validator-response" id="op-post-validator-response"></a>

`POST /data-requests/{token}/validator-responses`

### Description

Posts a validator response to the ledger.

After retrieving and finish decrypting its share, the validator needs to post the result back to the ledger so that eventually, the decryptor can decrypt a secret. The validator shares combining also reveals the identity of the decryptor.

### Parameters

| Name  | In   | Type                                                         | Required | Description                                                                            |
| ----- | ---- | ------------------------------------------------------------ | -------- | -------------------------------------------------------------------------------------- |
| token | path | [Token](#schema-token)                                       | true     | ID of the data request                                                                 |
| -     | body | [SignedValidatorResponse](#schema-signed-validator-response) | true     | The decrypted share, along with a digital signature of the validator and some metadata |

**Example**

`POST /data-requests/e3b0c44298fc1c149afbf4c8996fb924/validator-responses`

```json
{
  "validatorResponse": "{\"padName\":\"my-pad-1.0\",\"token\":\"e3b0c44298fc1c149afbf4c8996fb924\",\"validatorShare\":\"0110\",\"type\":\"validator_response\",\"validatorId\":\"validator1\"}",
  "signature": {
    "signerMetadata": {
      "id": "validator1",
      "fullName": "Validator-1",
      "role": "Validator"
    },
    "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ=="
  }
}
```

### Responses

| Status | Meaning                                                         | Description                                        | Schema                              |
| ------ | --------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                                          | [ApiResponse](#schema-api-response) |
| 400    | Bad Request                                                     | Data request and trustee response are inconsistent | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid                      | [ApiResponse](#schema-api-response) |
| 403    | Forbidden                                                       | Trustee is not in the instance                     | [ApiResponse](#schema-api-response) |
| 404    | Not found                                                       | Data request not found                             | [ApiResponse](#schema-api-response) |
| 409    | Conflict                                                        | Response has been made before                      | [ApiResponse](#schema-api-response) |

#### 200 OK

Validator response is successfully post.

**Example**

```json
{
    "ok": true,
    "message": "Successfully posted validator response",
}
```

#### 400 Bad request

Request is invalid. Make sure that :

* `padName` in `ValidatorResponse` is consistent with the PAD instance to which the API key is pointing
* `token` in path and `ValidatorResponse` are consistent
* `validatorId` in `ValidatorResponse` and `signature` are consistent
* `role` is `Validator` in `signature`
* signature in `signature` is consistent with the payload `ValidatorResponse`

**Example 1**

```json
{
    "ok": false,
    "message": "Inconsistent validator ID",
}
```

**example 2**

```json
{
    "ok": false,
    "message": "Inconsistent PAD instance name",
}
```

**example 3**

```json
{
    "ok": false,
    "message": "Invalid signature",
}
```

#### 401 Unauthorized

Api key is missing or invalid.

**Example**

```json
{
    "ok": false,
    "message": "Unauthorized",
}
```

#### 403 Forbidden

The validator is not part of the instance. Recall that the list of validators is determined by the *Operator* at instance creation time.

**Example**

```json
{
    "ok": false,
    "message": "Not a validator of the instance",
}
```

#### 404 Not Found

The server cannot find a data request pointed by the token in the path parameter.

**Example**

```json
{
    "ok": false,
    "message": "Data request not found",
}
```

#### 409 Conflict

A response from the same validator has been made for the same data request before.

**Example**

```json
{
    "ok": false,
    "message": "Validator response has been made for this request",
}
```

## Schemas

### ApiResponse <a href="#schema-api-response" id="schema-api-response"></a>

**Example**

```json
{
  "ok": true,
  "message": "string"
}
```

#### Schema

| Name    | Type    | Required | Description                      |
| ------- | ------- | -------- | -------------------------------- |
| ok      | boolean | true     | The request is successful or not |
| message | string  | true     | none                             |

### BlockNumber <a href="#schema-block-number" id="schema-block-number"></a>

ID of a block. It is an incremental index starting from 0. For example, if a ledger has height 10, then it has blocks 0, 1, ..., 9. The next block has block number 10.

#### Schema

| Type    | Restrictions |
| ------- | ------------ |
| integer | Non-negative |

### Block <a href="#schema-block" id="schema-block"></a>

Blocks are put sequentially as a blockchain to form a ledger. It consists of the header (which contains the chaining information) and optionally the data (from which data requests and trustee and validator responses can be extracted).

**Example 1**

```json
{
    "header": {
        "number": "1",
        "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
        "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
    },
}
```

**Example 2**

```json
{
    "header": {
        "number": "2",
        "previousHash": "78aecc3976f7b2151ce0574278f816b8e5983e18229fde7b6e7c3ebdf5147baf",
        "dataHash": "3ec339eae416289f4ddd7dc2b69e8edf12ac013089207732ad6156e02dc21fb5",
    },
    "data": {
        "data": ["datum1==", "datum2=="],
    },
}
```

#### Schema

| Name   | Type                                | Required | Description |
| ------ | ----------------------------------- | -------- | ----------- |
| header | [BlockHeader](#schema-block-header) | true     | none        |
| data   | [BlockData](#schema-block-data)     | false    | none        |

### BlockHeader <a href="#schema-block-header" id="schema-block-header"></a>

Block header contains metadata of a block. They are sufficient to prove the blocks form a chain without the need of block data, because the `previousHash` field in the schema refers to the hash of the previous block header, instead of the entire previous block. Thus, if the block data is irrelevant (for example not containing any data request when one is asking for them), it can be skipped.

If the block number is 0, the `number` and `previousHash` fields are empty. `dataHash` is computed with the same block's data. Refer to code samples on how to compute hash of a block header.

**Example 1**

```json
{
    "dataHash": "b24fd1a8c0c37f388f67ce6583710e3b1e5cfa79e652f764e92ee412299ac6c5",
}
```

**Example 2**

```json
{
    "number": "1",
    "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
    "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
}
```

#### Schema

| Name         | Type                                | Required | Description                         |
| ------------ | ----------------------------------- | -------- | ----------------------------------- |
| number       | [BlockNumber](#schema-block-number) | false    | Block number of the current block   |
| previousHash | [Sha256](#schema-sha256)            | false    | Hash of the previous block's header |
| dataHash     | [Sha256](#schema-sha256)            | true     | Hash of this block's data           |

### BlockData <a href="#schema-block-data" id="schema-block-data"></a>

Block data contains "transactions". In PAD, these are the data requests and trustee and validator responses. See code samples to see how block data are decoded.

**Example**

```json
{
    "data": ["datum1==", "datum2=="],
}
```

#### Schema

| Name | Type                            | Required | Description |
| ---- | ------------------------------- | -------- | ----------- |
| data | array<[Base64](#schema-base64)> | true     | none        |

### Base64

A base64-encoded binary data.

**Example**

```json
"aGVsbG8gd29ybGQ="
```

#### Schema

| Type   | Restrictions |
| ------ | ------------ |
| string | none         |

### Sha256

A Sha256 hash value as a hexidecimal string.

**Example**

```json
"d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-F]{64}/` |

### TrusteeId <a href="#schema-trustee-id" id="schema-trustee-id"></a>

ID of a trustee. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

**Example**

```
trustee1
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### ValidatorId <a href="#schema-validator-id" id="schema-validator-id"></a>

ID of a validator. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

**Example**

```
validator1
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### Token <a href="#schema-token" id="schema-token"></a>

A 128-bit random string kept secret between the encryptor and decryptor after encryption stage and before data request stage. It identifies a data request. Its hash value identifies an `encryption`. The decryptor posts it on the ledger at data request stage.

**Example**

```
"0fe5ff17c6ee6efa8ca385587b1e1ac2"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-Z]{32}/` |

### PadName <a href="#schema-pad-name" id="schema-pad-name"></a>

ID of a PAD instance. Its length must be inclusively between 4 and 30. It should contains only lowercase letters, digits, periods (`.`) or dashes (`-`). It must start with a lowercase letter.

It is seldom used as a request parameter because the API key in the request already identifies a PAD instance.

**Example**

```json
"my-pad-1.0"
```

#### Schema

| Type   | Restrictions              |
| ------ | ------------------------- |
| string | `/[a-z][a-z0-9.-]{3,29}/` |

### ValidatorResponse <a href="#schema-validator-response" id="schema-validator-response"></a>

A validator response to a data request. It contains the decrypted validator share for the decryptor to perform a full decryption on a secret. It also consists of metadata for identifying the corresponding data request.

**Example**

```json
{
    "padName": "my-pad-1.0",
    "token": "e3b0c44298fc1c149afbf4c8996fb924",
    "validatorShare": "0110",
    "type": "validator_response",
    "validatorId": "validator1",
}
```

#### Schema

| Name           | Type                                | Required | Restrictions | Description                                   |
| -------------- | ----------------------------------- | -------- | ------------ | --------------------------------------------- |
| padName        | [PadName](#schema-pad-name)         | true     | none         | The instance where the data request is posted |
| token          | [Token](#schema-token)              | true     | none         | The ID of the data request                    |
| validatorShare | [Base64](#schema-base64)            | true     | none         | The decrypted validator share                 |
| type           | enum                                | true     | none         | Type of response                              |
| validatorId    | [ValidatorId](#schema-validator-id) | true     | none         | ID of the responding validator                |

#### Enumerated Values

| Property | Value                  |
| -------- | ---------------------- |
| type     | `"validator_response"` |

### SignedValidatorResponse <a href="#schema-signed-validator-response" id="schema-signed-validator-response"></a>

A validator response attached with a digital signature for everyone to validate the response's integrity.

Note that the validator response is represented as a string (instead of an object). This ensures that there is a unified way to verify the signature.

**Example**

```json
{
  "validatorResponse": "{\"padName\":\"my-pad-1.0\",\"token\":\"e3b0c44298fc1c149afbf4c8996fb924\",\"validatorShare\":\"0110\",\"type\":\"validator_response\",\"validatorId\":\"validator1\"}",
  "signature": {
    "signerMetadata": {
      "id": "validator1",
      "fullName": "Validator-1",
      "role": "Validator"
    },
    "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ=="
  }
}
```

### Schema

| Name              | Type                                                    | Required | Description |
| ----------------- | ------------------------------------------------------- | -------- | ----------- |
| validatorResponse | string<[ValidatorResponse](#schema-validator-response)> | true     | none        |
| signature         | [Signature](#schema-signature)                          | true     | none        |

### Participant <a href="#schema-participant" id="schema-participant"></a>

Metadata of a participant in PAD. It can currently be used to describe a trustee or a validator.

**Example**

```json
{
  "id": "validator1",
  "fullName": "Validator-1",
  "role": "Validator"
}
```

#### Schema

| Name     | Type                                                                   | Required | Description                                              |
| -------- | ---------------------------------------------------------------------- | -------- | -------------------------------------------------------- |
| id       | [TrusteeId](#schema-trustee-id) or [ValidatorId](#schema-validator-id) | true     | `/[0-9a-zA-Z-_]{3,30}/`                                  |
| fullName | string                                                                 | true     | `/Trustee-[0-9a-zA-Z_]+/` or `/Validator-[0-9a-zA-Z_]+/` |
| role     | enum                                                                   | true     | none                                                     |

#### Enumerated Values

| Property | Value     |
| -------- | --------- |
| role     | Trustee   |
| role     | Validator |
| role     | Server    |

### Signature <a href="#schema-signature" id="schema-signature"></a>

A digital signature. It consists of the metadata of the signer, including its ID, and the signature payload encoded in base64.

**Schema**

```json
{
  "signerMetadata": {
    "id": "string",
    "fullName": "string",
    "role": "Trustee",
  },
  "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ==",
}
```

#### Schema

| Name           | Type                              | Required | Description |
| -------------- | --------------------------------- | -------- | ----------- |
| signerMetadata | [Participant](#schemaparticipant) | false    | none        |
| payload        | [Base64](#schema-base64)          | false    | none        |


# Auditor

## Get ledger <a href="#op-get-ledger" id="op-get-ledger"></a>

`GET /ledger`

### Description

Retrieve the ledger as raw HyperLedger Fabric blocks in one of the three modes:

* Get a block with its block number (`blockNumber`)
* Get latest blocks after a block height (`oldBlockHeight`)
* Get blocks between two block numbers, inclusively (`start`, `end`)

One can verify the integrity of the ledger by verifying that:

1. `dataHash` in the block header matches with the hash of the block data; and
2. `previousHash` in the block header matches with the hahs of the previous block header for every block; and
3. the Trustee attestations match with the ledger Check out the code samples for Auditors for more details.

### Parameters

| Name           | In    | Type                                | Required | Description |
| -------------- | ----- | ----------------------------------- | -------- | ----------- |
| blockNumber    | query | [BlockNumber](#schema-block-number) | false    | none        |
| oldblockHeight | query | [BlockHeight](#schema-block-height) | false    | none        |
| start          | query | [BlockNumber](#schema-block-number) | false    | none        |
| end            | query | [BlockNumber](#schema-block-number) | false    | none        |

**Example 1**

`GET /ledger?blockNumber=3`

**Example 2**

`GET /ledger?start=1&end=2`

### Responses

| Status | Meaning                                                         | Description                                  | Schema                              |
| ------ | --------------------------------------------------------------- | -------------------------------------------- | ----------------------------------- |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Succeeded                                    | Inline                              |
| 400    | Bad Request                                                     | Missing or incorrect use of query parameters | [ApiResponse](#schema-api-response) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1) | API key is missing or invalid                | [ApiResponse](#schema-api-response) |

#### 200 OK

Successfully retrieved the ledger blocks.

**Schema**

| Name   | Type                                                              | Required | Restrictions | Description |
| ------ | ----------------------------------------------------------------- | -------- | ------------ | ----------- |
| ok     | boolean                                                           | true     | none         | none        |
| blocks | dict<[BlockNumber](#schema-block-number), [Block](#schema-block)> | true     | none         | none        |

**Example**

```json
{
    "ok": true,
    "blocks": {
        "1": {
            "header": {
                "number": "1",
                "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
                "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
            },
        },
        "2": {
            "header": {
                "number": "2",
                "previousHash": "78aecc3976f7b2151ce0574278f816b8e5983e18229fde7b6e7c3ebdf5147baf",
                "dataHash": "3ec339eae416289f4ddd7dc2b69e8edf12ac013089207732ad6156e02dc21fb5",
            },
            "data": {
                "data": ["datum1==", "datum2=="],
            },
        },
    },
}
```

#### 400 Bad Request

Query parameter is missing or misused. Suppose the ledger current height is `h`, then:

* `blockNumber` should be in `[0, h-1]`;
* `oldBlockHeight` should be in `[0, h]`;
* `start` should be in `[0, h-1]` and `end` should be in `[start, h-1]`.

Only one of `blockNumber`, `oldBlockHeight` or `start`/`end` should be used.

**Example 1**

```json
{
   "ok": false,
   "message": "Missing oldBlockHeight or blockNumber or start/end in query",
}
```

**Example 2**

```json
{
   "ok": false,
   "message": "start must be use in conjunction with end in query",
}
```

#### 401 Unauthorized

API key is missing or incorrect.

**Example**

```json
{
  "ok": false,
  "message": "Unauthorized",
}
```

## Get Trustee attestations <a href="#op-get-trustee-attestations" id="op-get-trustee-attestations"></a>

`GET /attestations`

### Description

Retrieve all the latest Trustee attestations in the instance. An attestation is a signed digest of the ledger (with a timestamp). See the Auditor code samples for how to verify integrity of the ledger by Trustee attestations.

> Note that the trustee attestations may attest to the ledger at different height, since Trustees update their attestations once in a while.

### Parameters

No parameter for this endpoint.

### Responses

| Status | Meaning                                                 | Description | Schema |
| ------ | ------------------------------------------------------- | ----------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Succeeded   | Inline |

#### 200 OK

Successfully retrieved the trustee attestations.

**Schema**

| Name         | Type                                                                                     | Required | Restrictions | Description |
| ------------ | ---------------------------------------------------------------------------------------- | -------- | ------------ | ----------- |
| ok           | boolean                                                                                  | true     | none         | none        |
| attestations | dict<[TrusteeId](#schema-trustee-id), [TrusteeAttestation](#schema-trustee-attestation)> | true     | none         | none        |

**Example**

```json
{
   "ok": true,
   "attestations": {
      "trustee1": {
         "ledgerDigest": "{\"ledgerId\":\"my-pad-1.0\",\"height\":10,\"currentHash\":\"54c0639eb43fcc52cfc4d05546ee35984210a2d3d977e83600288aa\",\"timestamp\":\"2021-09-19T12:41:17.368Z\"}",
         "signature": {
            "signerMetadata": {
               "id": "trustee1",
               "fullName": "Trustee-1",
               "role": "Trustee",
            },
            "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ==",
         },
      },
      "trustee2": {
         "ledgerDigest": "{\"ledgerId\":\"my-pad-1.0\",\"height\":8,\"currentHash\":\"854e0426ce76242087ecff0f8cebada226b9adb4806b6f93811879074312283a\",\"timestamp\":\"2021-09-19T12:41:17.368Z\"}",
         "signature": {
            "signerMetadata": {
               "id": "trustee2",
               "fullName": "Trustee-2",
               "role": "Trustee",
            },
            "payload": "MEYCIQCZ93GjVw4Vd1TJu3jagx5KCwQ3uXyClmKfUagdu4zwqwIhAI8nuJmdxD9Cum7KFYq0CnEQ6+OfcFakC3kpPCMgzlCC",
         },
      },
   },
}
```

## Get ledger digest\* <a href="#op-get-digest" id="op-get-digest"></a>

`GET /digest`

### Description

Retrieve the current digest of the ledger. A digest is a succinct representation of the ledger, which consists of the ledger ID (same as the instance ID in current implementation), the block height, the hash of the latest block and the timestamp at which the digest is created.

> \*For reference only. The preferred way is to compute the digest with ledger blocks. Check out the Auditor sample code for this.

### Parameters

No parameter for this endpoint.

### Responses

| Status | Meaning                                                 | Description | Schema |
| ------ | ------------------------------------------------------- | ----------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Succeeded   | Inline |

#### 200 OK

**Schema**

| Name   | Type                                  | Required | Restrictions | Description |
| ------ | ------------------------------------- | -------- | ------------ | ----------- |
| ok     | boolean                               | true     | none         | none        |
| digest | [LedgerDigest](#schema-ledger-digest) | true     | none         | none        |

**Example**

```json
{
   "ok": true,
   "digest": {
      "ledgerId": "my-pad-1.0",
      "height": 11,
      "currentHash": "b360336a86799863f5d7041fafc655a0df38e0738dae10eaed6546c9be7ecc17",
      "timestamp": "2021-09-19T12:45:42.165Z",
   },
}
```

## Schemas

### BlockNumber <a href="#schema-block-number" id="schema-block-number"></a>

ID of a block. It is an incremental index starting from 0. For example, if a ledger has height 10, then it has blocks 0, 1, ..., 9. The next block has block number 10.

#### Schema

| Type    | Restrictions |
| ------- | ------------ |
| integer | Non-negative |

### BlockHeight <a href="#schema-block-height" id="schema-block-height"></a>

Number of blocks on the ledger. For example, the digest of a ledger shows that the block height is 10, that means the ledger has 10 blocks.

It is also used to describe the status of a trustee/validator. When a trustee has finished processed a ledger of block height 10, the "block height of trustee" is 10. This indicates the trustee has processed 10 blocks from the ledger. In the mean time, the ledger itself could have a block height greater than 10.

#### Schema

| Type    | Restrictions |
| ------- | ------------ |
| integer | Non-negative |

### Block

Blocks are put sequentially as a blockchain to form a ledger. It consists of the header (which contains the chaining information) and optionally the data (from which data requests and trustee and validator responses can be extracted).

**Example 1**

```json
{
    "header": {
        "number": "1",
        "previousHash": "0ede53fd38d632f3a7d849f8ba8f70c851d772b53cecbc9d858fe7c8af03a858",
        "dataHash": "ee967360a911deb8f6bd77cbb49b334e1837c006c9b6cb2d59d8acd41964a6ac",
    },
}
```

**Example 2**

```json
{
    "header": {
        "number": "2",
        "previousHash": "78aecc3976f7b2151ce0574278f816b8e5983e18229fde7b6e7c3ebdf5147baf",
        "dataHash": "3ec339eae416289f4ddd7dc2b69e8edf12ac013089207732ad6156e02dc21fb5",
    },
    "data": {
        "data": ["datum1==", "datum2=="],
    },
}
```

#### Schema

| Name   | Type                                | Required | Description |
| ------ | ----------------------------------- | -------- | ----------- |
| header | [BlockHeader](#schema-block-header) | true     | none        |
| data   | [BlockData](#schema-block-data)     | false    | none        |

### ApiResponse <a href="#schema-api-response" id="schema-api-response"></a>

**Example**

```json
{
  "ok": true,
  "message": "string"
}
```

#### Schema

| Name    | Type    | Required | Description                      |
| ------- | ------- | -------- | -------------------------------- |
| ok      | boolean | true     | The request is successful or not |
| message | string  | true     | none                             |

### TrusteeId <a href="#schema-trustee-id" id="schema-trustee-id"></a>

ID of a trustee. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

**Example**

```
my_trustee-1
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### TrusteeAttestation <a href="#schema-trustee-attestation" id="schema-trustee-attestation"></a>

A trustee's succinct view of the ledger, along with a digital signature of it. The succinct view consists of the PAD instance ID, height and latest block hash of its ledger, and the latest timestamp when the attestation is created.

A collection of trustee attestations proves to a user that she and the trustees are seeing the same ledger.

Note that the ledger digest is represented as a string (instead of an object). This ensures that there is a unified way to verify the signature.

**Example**

```json
{
  "ledgerDigest": "{\"ledgerId\":\"my-pad-1.0\",\"height\":10,\"currentHash\":\"54c0639eb43fcc52cfc4d05546ee35984210a2d3d977e83600288aa\",\"timestamp\":\"2021-09-19T12:41:17.368Z\"}",
  "signature": {
    "signerMetadata": {
      "id": "string",
      "fullName": "string",
      "role": "Trustee"
    },
    "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ=="
  }
}
```

#### Schema

| Name         | Type                                          | Required | Restrictions | Description                                |
| ------------ | --------------------------------------------- | -------- | ------------ | ------------------------------------------ |
| ledgerDigest | string<[LedgerDigest](#schema-ledger-digest)> | true     | none         | A succinct representation of the ledger    |
| signature    | [Signature](#schemasignature)                 | true     | none         | A digital signature against `ledgerDigest` |

### LedgerDigest <a href="#schema-ledger-digest" id="schema-ledger-digest"></a>

A succinct representation of the ledger, which consists of the PAD instance name, the height and the then block hash of its ledger, and the timestamp when this digest is generated.

**Example**

```json
{
    "ledgerId": "my-pad-1.0",
    "height": 10,
    "currentHash": "54c0639eb43fcc52cfc4d05546ee35984210a2d3d977e83600288aa",
    "timestamp":"2021-09-19T12:41:17.368Z",
}
```

#### Schema

| Name        | Type                                | Required | Restrictions | Description                                 |
| ----------- | ----------------------------------- | -------- | ------------ | ------------------------------------------- |
| ledgerId    | [PadName](#schema-pad-name)         | true     | none         | The PAD instance's name                     |
| height      | [BlockHeight](#schema-block-height) | true     | none         | Block height of the ledger                  |
| currentHash | [Sha256](#schema-sha256)            | true     | none         | Hash of the block at `height` on the ledger |
| timestamp   | [DateTime](#schema-date-time)       | true     | none         | Time at which this digest is generated      |

### PadName <a href="#schema-pad-name" id="schema-pad-name"></a>

ID of a PAD instance. Its length must be inclusively between 4 and 30. It should contains only lowercase letters, digits, periods (`.`) or dashes (`-`). It must start with a lowercase letter.

It is seldom used as a request parameter because the API key in the request already identifies a PAD instance.

**Example**

```json
"my-pad-1.0"
```

#### Schema

| Type   | Restrictions              |
| ------ | ------------------------- |
| string | `/[a-z][a-z0-9.-]{3,29}/` |

### Sha256

A Sha256 hash value as a hexidecimal string.

**Example**

```json
"d033713dd14552c060c55746afdb989cfee8e624ae94a932d79fd25630f728a4"
```

#### Schema

| Type   | Restrictions        |
| ------ | ------------------- |
| string | `/[0-9a-fA-F]{64}/` |

### DateTime <a href="#schema-date-time" id="schema-date-time"></a>

A timestamp in ISO 8601 format.

**Example**

```json
"2021-05-05T13:53:19.275Z"
```

#### Schema

| Type   | Restrictions |
| ------ | ------------ |
| string | -            |

### Signature <a href="#schema-signature" id="schema-signature"></a>

A digital signature. It consists of the metadata of the signer, including its ID, and the signature payload encoded in base64.

**Schema**

```json
{
  "signerMetadata": {
    "id": "string",
    "fullName": "string",
    "role": "Trustee",
  },
  "payload": "MEQCIDbFV8FH8ZTbM0wrKPHSk0lrkiIFsP3/GcU4htiGc6XOAiBOqJZgbeUKxPXgIOZGek6ryoJ+jhmwbcJh0+mSHsSiTQ==",
}
```

#### Schema

| Name           | Type                              | Required | Description |
| -------------- | --------------------------------- | -------- | ----------- |
| signerMetadata | [Participant](#schemaparticipant) | false    | none        |
| payload        | [Base64](#schema-base64)          | false    | none        |

### Participant <a href="#schema-participant" id="schema-participant"></a>

Metadata of a participant in PAD. It can currently be used to describe a trustee or a validator.

**Example**

```json
{
  "id": "my_trustee-1",
  "fullName": "Trustee-1",
  "role": "Trustee"
}
```

#### Schema

| Name     | Type                                                                   | Required | Description                                              |
| -------- | ---------------------------------------------------------------------- | -------- | -------------------------------------------------------- |
| id       | [TrusteeId](#schema-trustee-id) or [ValidatorId](#schema-validator-id) | true     | `/[0-9a-zA-Z-_]{3,30}/`                                  |
| fullName | string                                                                 | true     | `/Trustee-[0-9a-zA-Z_]+/` or `/Validator-[0-9a-zA-Z_]+/` |
| role     | enum                                                                   | true     | none                                                     |

#### Enumerated Values

| Property | Value     |
| -------- | --------- |
| role     | Trustee   |
| role     | Validator |
| role     | Server    |

### ValidatorId <a href="#schema-validator-id" id="schema-validator-id"></a>

ID of a validator. It contains only alphanumerical characters, underscores (\_) and dashes (-). It has length inclusively between 3 and 30.

#### Example

```
my_validator-2
```

#### Schema

| Type   | Restrictions          |
| ------ | --------------------- |
| string | `[a-zA-Z0-9-_]{3,30}` |

### Base64

A base64-encoded binary data.

**Example**

```json
"aGVsbG8gd29ybGQ="
```

#### Schema

| Type   | Restrictions |
| ------ | ------------ |
| string | none         |


# Building a Find Me App With PAD

Your location is quite a private matter - it can reveal where you live and work, who your friends are, what shops you frequent, and whether you are travelling or at home.

But still, there are times when you wish to share your whereabouts. You call your friend to inform them of which restaurant you are dining at. Less lightheartedly, you inform the fire department of your address in the event of a fire.

We all share our location from time to time - this is an unavoidable fact of life. But sensibly, few are willing to continuously share their current location at all times just in case there is a need for someone to have that information.

### Why PAD?

We see a gap in technology. Solutions for location tracking are generally all-or-nothing: you opt not to share your location, or you let your phone track where you are and it shares this information with a nominated person.

With PAD, it’s possible to share the ability to access your location with a trusted person, without needing to share your actual location at all times. If needed, your sharing partner can find you, but this action will immediately notify you that your whereabouts have been decrypted.

**Using a ‘find-me’ application built on PAD, you no longer share your location either all the time or not at all. Instead, only the** *ability* **to access your location is shared. Your location is revealed only when needed, and you are guaranteed to be alerted when this happens.**

The trusted party that you nominate can retrieve your location at any time, whether the request is appropriate or not. This is crucial because many of the times you would want to share your location are when you would be unable to explicitly allow it - for example if you are injured during an outdoor activity. If you find that your trust is being abused and your location is accessed at inappropriate times, you will be aware of this and can change who you have entrusted with the ability to access your location.

### User experience

Here is how we envision find-me being used. Following cryptographic tradition, we use Alice to represent the user who will share the ability to see location data and Bob to denote her trusted sharing partner who will be able to request a decryption of her location.

1. Alice downloads an application on her phone.
2. Within the application, she agrees to share her data with Bob, whom she identifies with a phone number. Bob gets a notification of this on his phone, which he accepts.
3. Alice can choose the frequency with which her location is updated, for example every ten minutes. She may opt to let Bob decrypt one or more of her most recent locations on a rolling basis. That’s all for Alice - she can now let her app continuously monitor for her whether her secret has been decrypted.
4. Inside Bob's application, he can see who has shared with him (which includes Alice and possibly other people) and can choose to locate one of these people with a single tap.
5. If he does make this request, he sees the location data and Alice gets a notification that Bob has chosen to access her present location. The record of Bob's action is placed in an immutable blockchain so that Alice can always prove what occurred to any party.

## How to build it

It is easy to build a find-me application with PAD. The PAD API handles everything related to the cryptography and immutable records of decryption - leaving you free to tailor your application to your purpose.

### Set up a new PAD instance

* You need a PAD accountability ledger dedicated to your application. To get one, [open a PAD instance](/apply). Once you have done this, you will be the [operator](/glossary#operator) of a new instance and receive an operator API key.
* Using your operator API key, you can see a list of available [trustees](/glossary#trustees). You can create new trustees, if desired, and then choose to add new and/or already existing trustees to your PAD instance. As the operator, you also make the choice of decryption threshold. This is the number of trustees that must respond to a decryption request in order to Bob to decrypt.

### Enable encryption

We assume that your application already can integrate with a messaging service (such as whatsapp) and can access the device's GPS location.

* Your application needs to encrypt a user's location in a way that is compatible with the PAD protocol. The documentation [here](https://github.com/sw7group/PAD-Dev-Docs/blob/main/code_samples_enc_dec.md#encrypting) explains precisely how to take this data and turn it into an `Encryption` object. You are free to reuse the code seen in the documentation; this will do almost all of your work in this step for you.
* The application needs to be able to create a signing key pair and tokens, which are a reference to a particular secret. The sample code for that is provided entirely [here](https://github.com/sw7group/PAD-Dev-Docs/blob/main/code_samples_enc_dec.md). Once this functionalitiy is included you will need to provide a way for tokens and verification keys to be communicated securely to a recipient, perhaps using an end-to-end encrypted messaging service. For your application, you can determine precisely how Alice picks Bob and ensures that he is aware of this and able to receive necessary data from Alice.
* Now you are ready to implement your application-specific logic. At set-up, the device location is encrypted for the first time. The resulting `Encryption` object is sent to the PAD service using the API. A token is generated and sent to Bob. The find-me app runs a loop in the background where at every time interval, the secret is updated using an API call to contain the latest location data.
* You can enable Alice to revoke her sharing arrangement, by interrupting this loop upon Alice's request.
* Finally, the application will monitor the ledger for data requests that were shared by the user. Notifactions of each request will be pushed to Alice. She can discontinue the sharing (either with Bob or entirely) at any time if she finds that Bob is abusing his privilege.

### Enable decryption

* Your application will need to store tokens that Bob has received from each person who has decided to share their location with him. He will be able to access a list of these users and be able to click a button that creates a decryption request that is sent using the PAD API.
* Once a decryption request has been made, the application will make requests to the ledger to see when a threshold number of trustees have responded to the request. Bob may be able to see a progress bar that indicates to him how many trustees have responded and how many are needed. (However, we expect that each request should be fulfilled very quickly!)
* The decryption side of the application will then handle all cryptographic operations to reconstruct Alice's location for Bob and display this in human-readable form. The code for how to reconstruct a secret from trustee responses is provided [here](https://github.com/sw7group/PAD-Dev-Docs/blob/main/code_samples_enc_dec.md#decrypting).

## Future directions

In some uses of PAD, it may make sense for the role of trustee to be handled by dedicated entities that provide the trustee service but do not make encryptions or decryptions. The find-me use case presents an opportunity to realise a much different model that is more egalitarian.

We imagine a group of individuals who have some level of mutual trust - this could be an extended family or a hiking club. Everyone in the group could opt to act as a trustee in a PAD instance supporting the group. Users could also choose to allow anyone in the group to have the right to access their location, but this is not necessary.

In this scenario, and perhaps in others, a find-me application may wish to incorporate some of these extra features:

* Support page for running a hardware or software-based trustee within the find-me application
* A trustee rating mechanism that provides information about the reliability of a trustee and their average response time
* The ability for an encryptor to choose which trustees are designated to help decrypt a given secret

The PAD protocol enables a new model of data sharing that is naturally suited for the contextual sharing of location data to a trusted partner. Here we have sketched how such a find-me application could be built on top of our API. We are excited not only about this use case, so we hope you will check this blog in the future for additional posts on other ways that PAD can make your life easier as a developer!


# Glossary

### Asymmetric encryption scheme

### Attestation

### Channel

A channel refers to the part of the PAD service that handles a single secret. Each PAD instance consists of one channel per secret stored with the instance. One can think of a PAD channel as a channel between secret owner and secret recipient - the channel opens when the decryptor chooses to access the secret and posts a request to the instance ledger.

### Data/Decryption request

### Decryptor

Anyone who has been chosen by an encryptor to have the right to make a decryption request.

### Digital signature

### Encryptor

Any user who secures a secret with the PAD system.

### Instance (or PAD instance)

Abstractly, the PAD protocol uses a public append-only ledger to store decryption requests - this is what makes decryption accountable. In practice, it is unnecessary and unwieldy to have a single monolithic ledger for all users of PAD across all use-cases. Therefore, PAD offers a new ledger to whoever wants one: each of these ledgers is a PAD instance. For example, a developer may wish to build an application that uses PAD. They will open a new instance that serves all decryption requests made through their application.

### Operator

An operator is an owner of a PAD instance. To become an operator, you make a request to the PAD team. Operators have the right to set properties of a PAD instance: they choose trustees and set the decryption threshold.

### Secret

Any piece of information that is secured by the PAD system for potential sharing with a designated decryptor.

### Secret sharing scheme

A cryptographic protocol that splits a secret into a number of pieces, called secret shares. Any one of these shares - or indeed any small group of shares - reveals no information about the original secret. However when a threshold number of shares are combined, it is possible to easily reconstruct the secret.

### Service (or PAD service)

We use this to denote the entire PAD protocol and API. The PAD service works behind the scenes of every PAD instance.

### Symmetric encryption scheme

### Token

### Trustee attestation

Refers to [attestation](#attestation)

### Trustees

To ensure that a decryption request is only successful if it appears on the PAD ledger, each PAD instance makes use of a number of trustees. Trustees may either be dedicated to a single instance or may offer their services to multiple instances. We use threshold cryptography (a secret sharing scheme) to distribute the means of decryption across multiple trustees, ensuring that no single trustee (or small group of them) needs to be trusted. Trustees observe the ledger for access requests and share information on the ledger in response to requests that allow only the decryptor to retrieve a secret. The job of a trustee is to respond to requests - they do not judge whether a data request is made at an appropriate time.

### Validators

Validators are similar to trustees, except that they have additional responsibilities that help detect misbehaving or faulty trustees.


