Signing for approval

πŸ“˜

In this article

By the end of this document you should have:

  • A basic understanding of how to sign & approve requests in Taurus-PROTECT.
  • How signatures are used to ensure authenticity of approvals.
  • The importance of private keys and keeping them secure.
  • How to programmatically sign a request.

Introduction

Many actions within Taurus-PROTECT are subject to governance rules that require digital signatures from designated operators in groups. Therefore, it is critical to ensure that every approval is genuine, traceable, and tamper-proof.

A digital signature allows an approver to sign a request in a way that:

  • Verifies the identity of the signer.
  • Guarantees the integrity of the signed data.
  • Prevents the signer from denying their approval (non-repudiation).

This document explains how Taurus-PROTECT utilizes digital signatures for approvals, how those signatures are used to confirm authenticity, and the management of these keys. Later, you'll also learn how to programmatically sign a request using standard tools and libraries.


πŸ”

User key management

Public and private keys can be assigned to users using the Taurus UI. For more information, please see the relevant section in the User Guide .

When is a signature required?

Several of Taurus Protect APIs include a signature parameter. The most important ones to consider are the following:

Approving a transaction request

Approving a whitelisted contract

Approving a whitelisted address

What do I need to have in order to sign a request?

🚧

Warning

A user in protect can only have one signing method enabled. This could be one of the following. Signing methods are mutually exclusive. Please ensure this is thoroughly understood prior to changing the public key field for any user in Taurus-PROTECT.

Signing MethodWebDesktopAPIAdditional Information
Key Containerβœ…βœ…βŒThis is the default method that protect ships with. It is quite long and required to be entered at login. To simplify use, Protect can save the encrypted Key Container and a passcode can be used to unlock the Key Container for signing.
Mobile Appβœ…βœ…βŒSeeSigning with Taurus Sign for more information.
YubikeyβŒβœ…βŒUsed in the desktop app only. Once set, user can no longer sign via web app.
Openssl EC Private KeyβŒβŒβœ…Used exclusively sign via API. A daemon or service account user should be created on behalf of your application. Once Open SSL keys are set, that user can only sign via API. Once keys are set, all other signing become unavailable. You will no longer be able to login to the web or desktop apps once this key type has been set.

Using the Taurus Protect UI, signatures are done through Key Containers, which carry an encrypted private key, accessed through a "passphrase". This is distinct from a "password", which is required for login. Alternative key storage mechanisms for interactive use include Yubikeys or the Taurus Mobile app.

The remainder of this document will discuss signing via API. Please ensure the user you are using to sign programatically does not require the ability to sign requests any other way.

To sign requests programmatically, you will need to make sure you have the following prepared:

  • Access to an unencrypted ECDSA private key which is set up for the API user as described in the User Guide
  • You must have the correct roles assigned to your API user. These roles are enforced for each API call, such as RequestApprover, WhitelistedAddressApprover, etc. You can read more about roles in the User Management section in our guides.
  • A user that is a member of the respective signature group based on the transaction rules configured in Protect. For more information on this, see Transaction Rulesin our guides.

πŸ”‘

Roles

The roles required are listed in the API documentation on each approval endpoint. If you do not have the right permissions, you will need to contact your admin.

Generate a new key

To generate a keypair that you can use to sign transactions programmatically, we recommend using the commonly available openssl tool.

First, you need to generate an ECDSA private key on the P256 NIST curve:

openssl ecparam -out ./[email protected] -name prime256v1 -genkey

Next, you must derive the corresponding public key from the private key:

openssl ec -in ./[email protected] -pubout -out ./[email protected]

Configure your user

A Protect Administrator will need to set or change thePublic Keyentry for the API user account and ensure the user is assigned to the correct approval group. Finally, another Administrator and a Superadmin must approve both, the account's group memberships and the public key.

πŸ”‘

Keep your private key secure

For production workloads, we recommend storing your private key in a secrets manager such as Vault, or KMS. Avoid storing unencrypted private keys in version control systems!

Signing Requests

Prepare the payload

Before applying the signature scheme, we must prepare the payload to be signed.

A single signature can cover multiple requests of the same kind, as each request kind will have its own numeric IDs that can overlap. To retrieve the necessary information for producing the signatures, you can use eg. the following endpoints:

These endpoints return with the same pattern in their responses. To produce a valid signature, we require 2 pieces of data from the response JSON structure: the id of the item and the metadata.hash property.

{
   "result": [
     {
       "id": "442",
       ...
       "metadata": {
         "hash": "fda859afd5dcc16f7abec8e7ab7fc528d90b094e43eeb111037581c45f8e16b5",
         ...
       }
       ...
     }
  ]
}

❗️

Always validate before you sign

While this document is focusing on producing a correct signature that's accepted by Taurus-PROTECT, for brevity we omit important steps to verify the data we sign.

For production workloads, ensure you validate and verify the contents of what is being signed and ensure it is correct.

Now that all necessary data is retrieved, 2 different structures must be prepared for a successful signature of requests:

  1. The numerically sorted list of IDs that are being signed off on
  2. The list of metadata.hash values for each request, numerically sorted by the corresponding IDs.

To make this practical, look at the following python code snippet:

sorted_results = sorted(response.result, key=lambda x: int(x['id']))
ids = [str(request.id) for request in sorted_results]
payload = json.dumps([request.metadata.hash for request in sorted_results])

# payload: ["fda859afd5dcc16f7abec8e7ab7fc528d90b094e43eeb111037581c45f8e16b5"]

The payload variable is required for the ECDSA-SHA256 signature below, while the ids variable is required to create the API call which also contains the final signature for approval.

Creating the ECDSA-SHA256 signature

Using the ECDSA-SHA256 signature scheme to produce a signature in the format Taurus-PROTECT expects requires the following steps:

  1. Signing the payload variable using the ECDSA private key and SHA256 hash function.
  2. Base64 encode the binary signature.

Putting these together into a code snippet, it will look something like below:

payload='["fda859afd5dcc16f7abec8e7ab7fc528d90b094e43eeb111037581c45f8e16b5"]'
echo -n "$payload" | openssl  dgst -sha256 -sign your-private.key | openssl asn1parse -inform DER

#    0:d=0  hl=2 l=  68 cons: SEQUENCE
#    2:d=1  hl=2 l=  32 prim: INTEGER           :234C56C972372F7DC331900ABEF2979E5583DC61975A1D00B8BE731C3D760C6A
#   36:d=1  hl=2 l=  32 prim: INTEGER           :76FE947687631B822419ACD181DBBB3F881F77F1480C2B5C5485B9B57CDC7C9F

echo -n "234C56C972372F7DC331900ABEF2979E5583DC61975A1D00B8BE731C3D760C6A76FE947687631B822419ACD181DBBB3F881F77F1480C2B5C5485B9B57CDC7C9F" | xxd -p -r | base64 | tr -d '\n'

# The outputed signature, base64 encoded.
#I0xWyXI3L33DMZAKvvKXnlWD3GGXWh0AuL5zHD12DGp2/pR2h2MbgiQZrNGB27s/iB938UgMK1xUhbm1fNx8nw==

πŸ“˜

Code Examples

Taurus customer support is able to provide more full fledged code examples upon request. The snippets above are intended for demonstration only. They are not complete and will not work on their own without additional library imports and supporting code.

Submitting the signature

After creating a request and listing pending items for approval, submitting the approval and the corresponding signature also has its own endpoint for each kind of request you can make:

Approvals all use the same JSON schema for the POST request:

{
  "comment": "mandatory comment to describe the action",
  "ids": ["1234", "2345"],
  "signature": 		 	          "I0xWyXI3L33DMZAKvvKXnlWD3GGXWh0AuL5zHD12DGp2/pR2h2MbgiQZrNGB27s/iB938UgMK1xUhbm1fNx8nw=="
}

At this point, all data should be available for creating the API call:

  • Comment is a free-form field, and typically you will want to use some internal reference or verifiable information that corresponds to the approval
  • We prepared the ids sorted list in the "Prepare the Payload" section above.
  • The signature field is the Base64 encoded signature created in the previous section.

Congratulations! You have successfully approved some requests in Taurus-PROTECT!

Complete examples

To see some complete workflow examples, please see the following pages:




  Β© 2025 Taurus SA. All rights reserved.