

# Manage quorum authentication (M of N access control) using CloudHSM CLI
<a name="key-quorum-auth-chsm-cli"></a>

The hardware security modules (HSMs) in your AWS CloudHSM cluster support quorum authentication, also known as M of N access control. With quorum authentication, no single user on the HSM can perform quorum-controlled operations. Instead, a minimum number of HSM users (at least 2) must cooperate to do these operations. Quorum authentication adds an extra layer of protection by requiring approvals from multiple HSM users.

Quorum authentication can control the following operations:
+ HSM key usage and management by a [crypto-user](understanding-users.md#crypto-user-chsm-cli) – Creating signatures with a key, or wrapping, unwrapping, sharing, unsharing, and setting an attribute of a key.

**Important considerations**
+ An HSM user can sign their own quorum token—that is, the requesting user can provide one of the required approvals for quorum authentication.
+ You choose the minimum number of quorum approvers for quorum-controlled operations. The smallest number you can choose is two (2), and the largest number you can choose is eight (8).
+ The HSM can store up to 1,024 quorum tokens. If the HSM already has 1,024 tokens when you try to create a new one, the HSM purges one of the expired tokens. By default, tokens expire ten minutes after their creation.
+ If multi-factor authentication (MFA) is enabled, the cluster uses the same key for quorum authentication and for MFA. For more information about using quorum authentication and MFA, see [Using CloudHSM CLI to manage MFA](login-mfa-token-sign.md).
+ Each HSM can only contain one token per Admin service at a time, but multiple tokens per Crypto User service.

The following topics provide more information about quorum authentication in AWS CloudHSM.

**Topics**
+ [Quorum authentication process for CloudHSM CLI](key-quorum-auth-chsm-cli-overview.md)
+ [Supported AWS CloudHSM service names and types for quorum authentication with CloudHSM CLI](key-quorum-auth-chsm-cli-service-names.md)
+ [Set up quorum authentication for AWS CloudHSM crypto-users using CloudHSM CLI](key-quorum-auth-chsm-cli-first-time.md)
+ [Key management and usage with quorum authentication enabled for AWS CloudHSM using CloudHSM CLI](key-quorum-auth-chsm-cli-crypto-user.md)

# Quorum authentication process for CloudHSM CLI
<a name="key-quorum-auth-chsm-cli-overview"></a>

The following steps summarize the quorum authentication processes for CloudHSM CLI. For the specific steps and tools, see [Key management and usage with quorum authentication enabled for AWS CloudHSM using CloudHSM CLI](key-quorum-auth-chsm-cli-crypto-user.md).

1. Each hardware security module (HSM) user creates an asymmetric key for signing. Users do this outside of the HSM, taking care to protect the key appropriately.

1. Each HSM user logs in to the HSM and registers the public part of their signing key (the public key) with the HSM.

1. When an HSM user wants to do a quorum-controlled operation, the same user logs in to the HSM and gets a *quorum token*.

1. The HSM user gives the quorum token to one or more other HSM users and asks for their approval.

1. The other HSM users approve by using their keys to cryptographically sign the quorum token. This occurs outside the HSM.

1. When the HSM user has the required number of approvals, the same user logs in to the HSM and runs the quorum-controlled operation with the **--approval** argument, supplying the signed quorum token file, which contains all necessary approvals (signatures).

1. The HSM uses the registered public keys of each signer to verify the signatures. If the signatures are valid, the HSM approves the token and the quorum-controlled operation is performed.

# Supported AWS CloudHSM service names and types for quorum authentication with CloudHSM CLI
<a name="key-quorum-auth-chsm-cli-service-names"></a>

**Admin Services**: Quorum authentication is used for admin privileged services like creating users, deleting users, changing user passwords, setting quorum values, and deactivating quorum and MFA capabilities.

**Crypto User Services**: Quorum authentication is used for crypto-user privileged services associated with a specific key like signing with a key, sharing/unsharing a key, wrapping/unwrapping a key, and setting a key's attribute. The quorum value of an associated key is configured when the key is generated, imported, or unwrapped. The quorum value must be equal to or less than the number of users that the key is associated with, which includes users that the key is shared with and the key owner.

Each service type is further broken down into a qualifying service name, which contains a specific set of quorum supported service operations that can be performed.


****  

| Service name | Service type | Service operations | 
| --- | --- | --- | 
| user | Admin |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/cloudhsm/latest/userguide/key-quorum-auth-chsm-cli-service-names.html)  | 
| quorum | Admin |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/cloudhsm/latest/userguide/key-quorum-auth-chsm-cli-service-names.html)  | 
| cluster1 | Admin |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/cloudhsm/latest/userguide/key-quorum-auth-chsm-cli-service-names.html)  | 
| key-management | Crypto User |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/cloudhsm/latest/userguide/key-quorum-auth-chsm-cli-service-names.html)  | 
| key-usage | Crypto User |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/cloudhsm/latest/userguide/key-quorum-auth-chsm-cli-service-names.html)  | 

[1] Cluster service is exclusively available on hsm2m.medium

# Set up quorum authentication for AWS CloudHSM crypto-users using CloudHSM CLI
<a name="key-quorum-auth-chsm-cli-first-time"></a>

These topics describe how to configure your CloudHSM for quorum authentication by [crypto-users](understanding-users.md#crypto-user-chsm-cli). Perform these steps once during initial setup. For subsequent key management and usage, refer to [Key management and usage with quorum authentication enabled for AWS CloudHSM using CloudHSM CLI](key-quorum-auth-chsm-cli-crypto-user.md).

**Topics**
+ [Prerequisites](#key-quorum-crypto-user-prerequisites)
+ [Step 1. Create and register a key for signing](#key-quorum-crypto-user-create-and-register-key)
+ [Step 2. Set the key quorum values during key generation](#key-quorum-admin-set-quorum-minimum-value-chsm-cli)

## Prerequisites
<a name="key-quorum-crypto-user-prerequisites"></a>
+ Familiarity with the [CloudHSM CLI](cloudhsm_cli.md)

## Step 1. Create and register a key for signing
<a name="key-quorum-crypto-user-create-and-register-key"></a>

To use quorum authentication, each crypto-user must complete *all* of the following steps: 

**Topics**
+ [Create an RSA key pair](#key-mofn-key-pair-create-chsm-cli)
+ [Create a registration token](#key-mofn-registration-token-chsm-cli)
+ [Sign the unsigned registration token](#key-mofn-sign-registration-token-chsm-cli)
+ [Register the public key with the HSM](#key-mofn-register-key-chsm-cli)

### Create an RSA key pair
<a name="key-mofn-key-pair-create-chsm-cli"></a>

There are many different ways to create and protect a key pair. The following examples show how to do it with [OpenSSL](https://www.openssl.org/).

**Example – Create a private key with OpenSSL**  
The following example demonstrates how to use OpenSSL to create a 2048-bit RSA key. To use this example, replace *<crypto\$1user1.key>* with the name of the file where you want to store the key.  

```
$ openssl genrsa -out <crypto_user1.key>
Generating RSA private key, 2048 bit long modulus
.....................................+++
.+++
e is 65537 (0x10001)
```

Next, generate the public key using the private key that you just created.

**Example – Create a public key with OpenSSL**  
The following example demonstrates how to use OpenSSL to create a public key from the private key you just created.  

```
$ openssl rsa -in crypto_user1.key -outform PEM -pubout -out crypto_user1.pub
writing RSA key
```

### Create a registration token
<a name="key-mofn-registration-token-chsm-cli"></a>

You create a token and sign it with the private key you just generated in the previous step.

**Create a registration token**

1. Use the following command to start the CloudHSM CLI:

------
#### [ Linux ]

   ```
   $ /opt/cloudhsm/bin/cloudhsm-cli interactive
   ```

------
#### [ Windows ]

   ```
   PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\cloudhsm-cli.exe" interactive
   ```

------

1. Create a registration token by running the [quorum token-sign generate](cloudhsm_cli-qm-token-gen.md) command:

   ```
   aws-cloudhsm > quorum token-sign generate --service registration --token /path/tokenfile
   {
     "error_code": 0,
     "data": {
       "path": "/path/tokenfile"
     }
   }
   ```

1. The [quorum token-sign generate](cloudhsm_cli-qm-token-gen.md) command generates a registration token at the specified file path. Inspect the token file:

   ```
   $ cat /path/tokenfile
   {
     "version": "2.0",
     "tokens": [
       {
         "approval_data": <approval data in base64 encoding>,
         "unsigned": <unsigned token in base64 encoding>,
         "signed": ""
       }
     ]
   }
   ```

   The token file consists of the following:
   + **approval\$1data**: A base64 encoded randomized data token whose raw data doesn’t exceed the maximum of 245 bytes.
   + **unsigned**: A base64 encoded and SHA256 hashed token of the approval\$1data.
   + **signed**: A base64 encoded signed token (signature) of the unsigned token, using the RSA 2048-bit private key previously generated with OpenSSL.

   You sign the unsigned token with the private key to demonstrate that you have access to the private key. You will need the registration token file fully populated with a signature and the public key to register the crypto-user as a quorum user with the AWS CloudHSM cluster.

### Sign the unsigned registration token
<a name="key-mofn-sign-registration-token-chsm-cli"></a>

1. Decode the base64 encoded unsigned token and place it into a binary file:

   ```
   $ echo -n '6BMUj6mUjjko6ZLCEdzGlWpR5sILhFJfqhW1ej3Oq1g=' | base64 -d > crypto_user.bin
   ```

1. Use OpenSSL and the private key to sign the now binary unsigned registration token and create a binary signature file:

   ```
   $ openssl pkeyutl -sign \
   -inkey crypto_user1.key \
   -pkeyopt digest:sha256 \
   -keyform PEM \
   -in crypto_user.bin \
   -out crypto_user.sig.bin
   ```

1. Encode the binary signature into base64:

   ```
   $ base64 -w0 crypto_user.sig.bin > crypto_user.sig.b64
   ```

1. Copy and paste the base64 encoded signature into the token file:

   ```
   {
     "version": "2.0",
     "tokens": [
       {
         "approval_data": <approval data in base64 encoding>,
         "unsigned": <unsigned token in base64 encoding>,
         "signed": <signed token in base64 encoding>
       }
     ]
   }
   ```

### Register the public key with the HSM
<a name="key-mofn-register-key-chsm-cli"></a>

After creating a key, the crypto-user must register the public key with the AWS CloudHSM cluster.

1. Start CloudHSM CLI:

------
#### [ Linux ]

   ```
   $ /opt/cloudhsm/bin/cloudhsm-cli interactive
   ```

------
#### [ Windows ]

   ```
   PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\cloudhsm-cli.exe" interactive
   ```

------

1. Sign in as the crypto-user whose public key you want to register.

   ```
   aws-cloudhsm > login --username crypto_user1 --role crypto-user
   Enter password:
   {
     "error_code": 0,
     "data": {
       "username": "crypto_user1",
       "role": "crypto-user"
     }
   }
   ```

1. Register the public key with the **[Register a user's token-sign quorum strategy using CloudHSM CLI](cloudhsm_cli-user-chqm-token-reg.md)**. For more information, see the following example or use the **help user change-quorum token-sign register** command.  
**Example – Register a public key with AWS CloudHSM cluster**  

   The following example shows how to use the **user change-quorum token-sign register** command in CloudHSM CLI to register a crypto-user public key with the HSM. To use this command, the crypto-user must be logged in to the HSM. Replace these values with your own:

   ```
   aws-cloudhsm > user change-quorum token-sign register --public-key </path/crypto_user.pub> --signed-token </path/tokenfile>
   {
     "error_code": 0,
     "data": {
       "username": "crypto_user1",
       "role": "crypto-user"
     }
   }
   ```
**Note**  
**/path/crypto\$1user.pub**: The filepath to the public key PEM file  
**Required**: Yes  
**/path/token\$1file**: The filepath with token signed by user private key  
**Required**: Yes

1. After all crypto-users register their public keys, the output from the **user list** command shows this in the quorum field, stating the enabled quorum strategy in use.

    In this example, the AWS CloudHSM cluster has two HSMs, each with the same crypto-users, as shown in the following output from the **user list** command. For more information about creating users, see [User management with CloudHSM CLI](manage-hsm-users-chsm-cli.md).

   ```
   aws-cloudhsm > user list
   {
     "error_code": 0,
     "data": {
       "users": [
         {
           "username": "admin",
           "role": "admin",
           "locked": "false",
           "mfa": [],
           "quorum": [],
           "cluster-coverage": "full"
         },
         {
           "username": "crypto_user1",
           "role": "crypto-user",
           "locked": "false",
           "mfa": [],
           "quorum": [
             {
               "strategy": "token-sign",
               "status": "enabled"
             }
           ],
           "cluster-coverage": "full"
         },
         {
           "username": "crypto_user2",
           "role": "crypto-user",
           "locked": "false",
           "mfa": [],
           "quorum": [
             {
               "strategy": "token-sign",
               "status": "enabled"
             }
           ],
           "cluster-coverage": "full"
         },
         {
           "username": "crypto_user3",
           "role": "crypto-user",
           "locked": "false",
           "mfa": [],
           "quorum": [
             {
               "strategy": "token-sign",
               "status": "enabled"
             }
           ],
           "cluster-coverage": "full"
         },
         {
           "username": "app_user",
           "role": "internal(APPLIANCE_USER)",
           "locked": "false",
           "mfa": [],
           "quorum": [],
           "cluster-coverage": "full"
         }
       ]
     }
   }
   ```

## Step 2. Set the key quorum values during key generation
<a name="key-quorum-admin-set-quorum-minimum-value-chsm-cli"></a>

To use quorum authentication, a crypto-user must log in to the HSM and then set the associated *key quorum values*. This is the minimum number of crypto-user approvals that are required to perform HSM key management/usage operations. For more information about the associated key commands associated with either key management or key usage, see [Supported services and types](key-quorum-auth-chsm-cli-service-names.md).

**Generate a key pair with key quorum values set**

1. Use the following command to start CloudHSM CLI:

------
#### [ Linux ]

   ```
   $ /opt/cloudhsm/bin/cloudhsm-cli interactive
   ```

------
#### [ Windows ]

   ```
   PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\cloudhsm-cli.exe" interactive
   ```

------

1. Using CloudHSM CLI, log in as a crypto-user.

   ```
   aws-cloudhsm > login --username crypto_user1 --role crypto-user
   Enter password:
   {
     "error_code": 0,
     "data": {
       "username": "crypto_user1",
       "role": "crypto-user"
     }
   }
   ```

This example generates an RSA key pair which has key quorum values of two (2) set for both key-management and key-usage operations. You can choose any value from zero (0) to eight (8), up to the total number of crypto-users on the HSM. In this example, the HSM has three (3) crypto-users, so the maximum possible value is three (3). Note that in this example we are sharing the key with *<crypto\$1user2>* during key generation. Also note that public keys do not have quorum values.

```
aws-cloudhsm > key generate-asymmetric-pair rsa \
--public-exponent 65537 \
--modulus-size-bits 2048 \
--public-label rsa-public-key-example \
--private-label rsa-private-key-example \
--public-attributes verify=true \
--private-attributes sign=true
--share-crypto-users crypto_user2 \
--manage-private-key-quorum-value 2 \
--use-private-key-quorum-value 2
{
  "error_code": 0,
  "data": {
    "public_key": {
      "key-reference": "0x0000000000640006",
      "key-info": {
        "key-owners": [
          {
            "username": "crypto_user",
            "key-coverage": "full"
          }
        ],
        "shared-users": [],
        "key-quorum-values": {
          "manage-key-quorum-value": 0,
          "use-key-quorum-value": 0
        },
        "cluster-coverage": "full"
      },
      "attributes": {
        "key-type": "rsa",
        "label": "rsa-public-key-example",
        "id": "0x",
        "check-value": "0x218f50",
        "class": "public-key",
        "encrypt": false,
        "decrypt": false,
        "token": true,
        "always-sensitive": false,
        "derive": false,
        "destroyable": true,
        "extractable": true,
        "local": true,
        "modifiable": true,
        "never-extractable": false,
        "private": true,
        "sensitive": false,
        "sign": false,
        "trusted": false,
        "unwrap": false,
        "verify": true,
        "wrap": false,
        "wrap-with-trusted": false,
        "key-length-bytes": 512,
        "public-exponent": "0x010001",
        "modulus": "0xbdf471a3d2a869492f51c767bece8780730ae6479a9a75efffe7cea3594fb28ca518630e7b1d988b45d2fedc830b7ab848448c24c476cacb73d1523278aed289551e07af0fbfabe4811cc4601678bd097b5c0a578249ed1eb0e4878a80ba1ed85ac46eb1fee60d2a8bdd322075196dec4b57fa2cd82af44ad068115ac219bc073ec65c19c97bd883cf26931408d7bc51e237626b8b9b8f2485425907a0eb42f2f4c40018c8dac7ceeb1b646305a2e537ab904346883e41d568264abee0137048e4657d2cf72801810f3212f662b7a7ae134848b922771f6a30aa76718008d9cc74ff8ddcd8d867b05c3d40020d1514999af96889911467191b9f390d8de07f83",
        "modulus-size-bits": 2048
      }
    },
    "private_key": {
      "key-reference": "0x0000000000640007",
      "key-info": {
        "key-owners": [
          {
            "username": "crypto_user",
            "key-coverage": "full"
          }
        ],
        "shared-users": [
          {
            "username": "crypto_user2",
            "key-coverage": "full"
          }
        ],
        "key-quorum-values": {
          "manage-key-quorum-value": 2,
          "use-key-quorum-value": 2
        },
        "cluster-coverage": "full"
      },
      "attributes": {
        "key-type": "rsa",
        "label": "rsa-private-key-example",
        "id": "0x",
        "check-value": "0x218f50",
        "class": "private-key",
        "encrypt": false,
        "decrypt": false,
        "token": true,
        "always-sensitive": true,
        "derive": false,
        "destroyable": true,
        "extractable": true,
        "local": true,
        "modifiable": true,
        "never-extractable": false,
        "private": true,
        "sensitive": true,
        "sign": true,
        "trusted": false,
        "unwrap": false,
        "verify": false,
        "wrap": false,
        "wrap-with-trusted": false,
        "key-length-bytes": 1216,
        "public-exponent": "0x010001",
        "modulus": "0xbdf471a3d2a869492f51c767bece8780730ae6479a9a75efffe7cea3594fb28ca518630e7b1d988b45d2fedc830b7ab848448c24c476cacb73d1523278aed289551e07af0fbfabe4811cc4601678bd097b5c0a578249ed1eb0e4878a80ba1ed85ac46eb1fee60d2a8bdd322075196dec4b57fa2cd82af44ad068115ac219bc073ec65c19c97bd883cf26931408d7bc51e237626b8b9b8f2485425907a0eb42f2f4c40018c8dac7ceeb1b646305a2e537ab904346883e41d568264abee0137048e4657d2cf72801810f3212f662b7a7ae134848b922771f6a30aa76718008d9cc74ff8ddcd8d867b05c3d40020d1514999af96889911467191b9f390d8de07f83",
        "modulus-size-bits": 2048
      }
    }
  }
}
```

When generating a key with quorum controls, the key must be associated with a minimum number of users equal to the largest key quorum value. Associated users include the key owner and Crypto Users with whom the key is shared with. To determine the number of minimum users to share the key with, get the largest quorum value between the key usage quorum value and the key management quorum value and subtract 1 to account for the key owner, who is by default associated with the key. To share the key with more users, use the **[Share a key using CloudHSM CLI](cloudhsm_cli-key-share.md)** command.

Failure to share the key with enough users at key generation will result in failure, as shown below.

```
aws-cloudhsm > key generate-asymmetric-pair rsa \
--public-exponent 65537 \
--modulus-size-bits 2048 \
--public-label rsa-public-key-example \
--private-label rsa-private-key-example \
--public-attributes verify=true \
--private-attributes sign=true
--share-crypto-users crypto_user2 crypto_user3 \
--manage-private-key-quorum-value 3 \
--use-private-key-quorum-value 4
{
  "error_code": 1,
  "data": "Invalid quorum value provided."
}
```

# Key management and usage with quorum authentication enabled for AWS CloudHSM using CloudHSM CLI
<a name="key-quorum-auth-chsm-cli-crypto-user"></a>

After you configure quorum authentication for your AWS CloudHSM cluster, crypto users can't perform HSM key management or usage operations on their own if their key has associated quorum values. This topic explains how a crypto-user can get a temporary token to perform an HSM key management or key usage operation.

**Note**  
Each quorum token is valid for one operation. When that operation succeeds, the token is no longer valid and the crypto-user must obtain a new token. A quorum token is only valid during your current login session. If you log out of the CloudHSM CLI or if the network disconnects, the token is no longer valid and you need to get a new token. You can only use a CloudHSM token within the CloudHSM CLI. You can't use it to authenticate in a different application.

The following example shows the output when a crypto-user tries to create a signature with a quorum-associated key on the HSM after quorum authentication is configured. The command fails with a `Quorum Failed` error, which means quorum authentication failed:

```
aws-cloudhsm > crypto sign rsa-pkcs --key-filter attr.label=rsa-private-key-example --hash-function sha256 --data YWJjMTIz
{
  "error_code": 1,
  "data": "Quorum Failed"
}
```

A crypto-user must complete the following tasks to get a temporary token for performing a key management or key usage operation on the HSM:

**Topics**
+ [Step 1. Get a quorum token](#key-quorum-admin-gen-token-chsm-cli)
+ [Step 2. Get signatures from approving crypto-users](#key-quorum-crypto-user-get-approval-signatures-chsm-cli)
+ [Step 3. Approve the token on the CloudHSM; cluster and execute an operation](#key-quorum-crypto-user-approve-token-chsm-cli)

## Step 1. Get a quorum token
<a name="key-quorum-admin-gen-token-chsm-cli"></a>

1. Start CloudHSM CLI.

------
#### [ Linux ]

   ```
   $ /opt/cloudhsm/bin/cloudhsm-cli interactive
   ```

------
#### [ Windows ]

   ```
   PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\cloudhsm-cli.exe" interactive
   ```

------

1. Log in to the cluster as a crypto-user.

   ```
   aws-cloudhsm > login --username <crypto_user1> --role crypto-user --password password123
   ```

   This example signs `crypto_user1` into the CloudHSM CLI with the `crypto-user` role. Replace these values with your own.

   ```
   {
     "error_code": 0,
     "data": {
       "username": "crypto_user1",
       "role": "crypto-user"
     }
   }
   ```

1. Generate a quorum token using the **quorum token-sign generate** command.

   In the following command, `key-usage` identifies the *service name* where you will use token that you are generating. In this case, the token is for key-usage operations (`key-usage` service) This example uses the `--filter` flag to associate the token with a specific key.

   ```
   aws-cloudhsm > quorum token-sign generate --service key-usage --token </path/crypto_user1.token> --filter attr.label=rsa-private-key-example
   {
     "error_code": 0,
     "data": {
       "path": "/home/crypto_user1.token"
     }
   }
   ```

   This example gets a quorum token for the crypto-user with username `crypto_user1` and saves the token to a file named `crypto_user1.token`. To use the example command, replace these values with your own:

   The **quorum token-sign generate** command generates a key-usage service quorum token at the specified file path. You can inspect the token file:

   ```
   $ cat </path/crypto_user1.token>
   {
     "version": "2.0",
     "service": "key-usage",
     "key_reference": "0x0000000000680006",
     "approval_data": "AAIABQAAABkAAAAAAGgABi5CDa9x9VyyRIaFbkSrHgJjcnlwdG9fdXNlcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnPQBLAAAAAAAAAAAAAgAFAAAAGgAAAAAAaAAGQvd2qKY+GJj8gXo9lKuANGNyeXB0b191c2VyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGc9AEsAAAAAAAAAAA==",
     "token": "5GlgoWOlQU4fw4QIlbxkPGZVOVoDugFGuSKE/k67ncM=",
     "signatures": []
   }
   ```

   The token file consists of the following:
   + **service**: An identifier for the quorum service the token is associated with.
   + **key\$1reference**: An identifier for the key that this quorum token is associated with.
   + **approval\$1data**: A base64 encoded raw data token generated by the HSM.
   + **token**: A base64 encoded and SHA-256 hashed token of the approval\$1data
   + **signatures**: An array of base64 encoded signed tokens (signatures) of the unsigned token. Each approver signature is in the form of a JSON object literal: 

     ```
     {
           "username": "<APPROVER_USERNAME>",
           "role": "<APPROVER_ROLE>",
           "signature": "<APPROVER_RSA2048_BIT_SIGNATURE>"
     }
     ```

     Each signature is created from the result of an approver using their corresponding RSA 2048-bit private key whose public key was registered with the HSM.

1. Validate the new user service quorum token. The **quorum token-sign list** command confirms that the token exists on CloudHSM.

   ```
   aws-cloudhsm > quorum token-sign list
   {
     "error_code": 0,
     "data": {
       "tokens": [
         {
           "username": "crypto_user",
           "service": "key-usage",
           "key-reference": "0x0000000000680006",
           "minimum-token-count": 2
         }
       ]
     }
   }
   ```

   The `minimum-token-count` presents an aggregated cluster view of the minimum usable number of key tokens corresponding to the username, service, and key-reference that are retrieved from a single HSM in the cluster.

   For example, assuming a 2-HSM cluster, if we receive two (2) key-usage tokens generated by user `crypto_user1` for key with reference `0x0000000000680006` from the first HSM in the cluster and we receive one (1) key-usage tokens generated by user `crypto_user1` for key with reference `0x0000000000680006` from the other HSM in the cluster, we will display `"minimum-token-count": 1`.

## Step 2. Get signatures from approving crypto-users
<a name="key-quorum-crypto-user-get-approval-signatures-chsm-cli"></a>

An crypto user who has a quorum token must get the token approved by other crypto-users. To give their approval, the other crypto =-users use their signing key to cryptographically sign the token outside the HSM.

There are many different ways to sign the token. The following example shows how to sign the token using [OpenSSL](https://www.openssl.org/). To use a different signing tool, make sure that the tool uses the private key (signing key) of the crypto-user to sign a SHA-256 digest of the token.

In this example, the crypto-user that has the token (`crypto-user`) needs at least two (2) approvals. The following example commands show how two (2) crypto-users can use OpenSSL to cryptographically sign the token.

1. Decode the base64 encoded unsigned token and place it into a binary file:

   ```
   $echo -n '5GlgoWOlQU4fw4QIlbxkPGZVOVoDugFGuSKE/k67ncM=' | base64 -d > crypto_user1.bin
   ```

1. Use OpenSSL and the approver's private key to sign the binary quorum unsigned token for the user service and create a binary signature file:

   ```
   $openssl pkeyutl -sign \
   -inkey crypto_user1.key \
   -pkeyopt digest:sha256 \
   -keyform PEM \
   -in crypto_user1.bin \
   -out crypto_user1.sig.bin
   ```

1. Encode the binary signature into base64:

   ```
   $ base64 -w0 crypto_user1.sig.bin > crypto_user1.sig.b64
   ```

1. Copy and paste the base64 encoded signature into the token file, using the JSON object literal format specified earlier for approver signature:

   ```
   {
     "version": "2.0",
     "service": "key-usage",
     "key_reference": "0x0000000000680006",
     "approval_data": "AAIABQAAABkAAAAAAGgABi5CDa9x9VyyRIaFbkSrHgJjcnlwdG9fdXNlcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnPQBLAAAAAAAAAAAAAgAFAAAAGgAAAAAAaAAGQvd2qKY+GJj8gXo9lKuANGNyeXB0b191c2VyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGc9AEsAAAAAAAAAAA==",
     "token": "5GlgoWOlQU4fw4QIlbxkPGZVOVoDugFGuSKE/k67ncM=",
     "signatures": [
       {
         "username": "crypto_user1",
         "role": "crypto-user",
         "signature": "wa7aPzmGwBjcEoZ6jAzYASp841AfgOvcI27Y/tGlCj1E9DawnFw5Uf0IJT2Ca7T5XD2ThVkUi0B+dhAomdqYNl6aUUFrJyH9GBJ+E0PmA5jNVm25tzeRWBJzneTg4/zTeE2reNqrHFHicWnttQLe9jS09J1znuDGWDe0HaBKWUaz2gUInJRqmeXDsZYdSvZksrqUH5dci/RsaDE2+tGiS9g0RcIkFbsPW4HpGe2e5HVzGsqrV8O3PKlYQv6+fymfcNTTuoxKcHAkOjpl43QSuSIu2gVq7KI8mSmmWaPJL47NPjmcBVB5vdEQU+oiukaNfLJr+MoDKzAvCGDg4cDArg=="
       },
       {
         "username": "crypto_user2",
         "role": "crypto-user",
         "signature": "wa7aPzmGwBjcEoZ6jAzYASp841AfgOvcI27Y/tGlCj1E9DawnFw5Uf0IJT2Ca7T5XD2ThVkUi0B+dhAomdqYNl6aUUFrJyH9GBJ+E0PmA5jNVm25tzeRWBJzneTg4/zTeE2reNqrHFHicWnttQLe9jS09J1znuDGWDe0HaBKWUaz2gUInJRqmeXDsZYdSvZksrqUH5dci/RsaDE2+tGiS9g0RcIkFbsPW4HpGe2e5HVzGsqrV8O3PKlYQv6+fymfcNTTuoxKcHAkOjpl43QSuSIu2gVq7KI8mSmmWaPJL47NPjmcBVB5vdEQU+oiukaNfLJr+MoDKzAvCGDg4cDArg=="
       }
     ]
   }
   ```

## Step 3. Approve the token on the CloudHSM; cluster and execute an operation
<a name="key-quorum-crypto-user-approve-token-chsm-cli"></a>

After a crypto-user has the necessary approvals and signatures, they can supply that token to the CloudHSM cluster along with a key management or key usage operation. 

Make sure the key operation corresponds to the appropriate quorum service associated with the quorum token. For more information, see [Supported services and types](key-quorum-auth-chsm-cli-service-names.md) for more information.

During the transaction, the token will be approved within the AWS CloudHSM cluster and execute the requested key operation. The success of the key operation is contingent upon both a valid approved quorum token and a valid key operation.

**Example Generate a signature with the RSA-PKCS mechanism**  
In the following example, a logged in crypto-user creates a signature with a key on the HSM:  

```
aws-cloudhsm > crypto sign rsa-pkcs --key-filter attr.label=rsa-private-key-example --hash-function sha256 --data YWJjMTIz --approval /path/crypto_user1.token
      
{
  "error_code": 0,
  "data": {
    "key-reference": "0x0000000000640007",
    "signature": "h6hMqXacBrT3x3MXV13RXHdQno0+IQ6iy0kVrGzo23+eoWT0ZZgrSpBCu5KcuP6IYYHw9goQ5CfPf4jI1nO5m/IUJtF1A1lmcz0HjEy1CJ7ICXNReDRyeOU8m43dkJzt0OUdkbtkDJGAcxkbKHLZ02uWsGXaQ8bOKhoGwsRAHHF6nldTXquICfOHgSd4nimObKTqzUkghhJW5Ot5oUyLMYP+pZmUS38ythybney94Wj6fzYOER8v7VIY5ijQGa3LfxrjSG4aw6QijEEbno5LSf18ahEaVKmVEnDBL54tylCJBGvGsYSY9HNhuJoHPgiDL/TDd2wfvP4PaxbFRyyHaw=="
  }
}
```
If the crypto user tries to perform another HSM key usage operation with the same token, it fails:  

```
aws-cloudhsm > crypto sign rsa-pkcs --key-filter attr.label=rsa-private-key-example --hash-function sha256 --data YWJjMTIz --approval /home/crypto_user1.token
{
  "error_code": 1,
  "data": "Quorum approval is required for this operation"
}
```
To perform another HSM key operation, the crypto user must generate a new quorum token, get new signatures from approvers, and execute the desired key operation with the --approval argument to supply the quorum token.  
Use the **quorum token-sign list** to check for available token. This example shows that the crypto-user has no approved tokens.   

```
aws-cloudhsm > quorum token-sign list
{
  "error_code": 0,
  "data": {
    "tokens": []
  }
}
```