Signature Provider Plugin#

The Signature Provider is a crucial component of SPSDK that facilitates secure signing operations using custom hardware security module (HSM). It acts as an interface between the SPSDK and the HSM, allowing developers to leverage the cryptographic capabilities of the HSM for signing data securely.

1. Benefits of using the Signature Provider#

  • Enhanced Security:

    • The Signature Provider enables the use of HSMs, which are designed to provide a high level of security for cryptographic operations. By keeping private keys within the HSM, the risk of key exposure is significantly reduced.

  • Custom HSM Support:

    • One of the standout features of the Signature Provider is its ability to work with custom HSMs. This flexibility allows organizations to integrate their existing security infrastructure into the SPSDK, ensuring that they can utilize their preferred hardware solutions.

  • Interoperability:

    • The Signature Provider is designed to be compatible with various HSMs and cryptographic standards. This interoperability ensures that organizations can switch between different HSMs or use multiple HSMs without significant changes to their codebase.

  • Audit and Compliance:

    • Using an HSM for signing operations can help organizations meet regulatory compliance requirements. The Signature Provider can facilitate logging and auditing of cryptographic operations, providing a clear trail for compliance purposes.

This notebook describes how to setup a Signature Provider plugin

When signing the data with SPSDK, there are two options:

  • Using the local private key (not recommended)

  • Using the remote signing service(HSM)

Let’s look at the second option and setup Signature Provider

PLUGINS_DIR = "plugins/"
VERBOSITY = (
    "-v"  # verbosity of commands, might be -v or -vv for debug or blank for no additional info
)

2. Custom HSM setup#

First, we need to start the test HSM. In order to do that, open the HSM notebook and follow the instructions there. Once you are done, come back and continue here.

Now the test HSM should be up and running. In order to test the functionality of HSM from previous step, run a simple test:

import requests

# rsa2048 sign
response = requests.get("http://127.0.0.1:5000/signer/rsa2048/0", json={"data": b"\xab\xcd".hex()})
print(f"RSA2048: {response.json()}")

response = requests.get(
    "http://127.0.0.1:5000/signer/secp384r1/0", json={"data": b"\xab\xcd".hex()}
)
print(f"SECP384R1: {response.json()}")
RSA2048: {'signature': 'jQlUODoatHcpkieNYKoN903bmgF1dXy9pOUxhzTPgC60QeoTlANWw3i9a9qlZJHZ1kL90DcNGexZ5i1iMo9WCMjZrQ/OEahEsPZkbVFYz9Bb7ilBH6C2l3ptB9AR28Pq7G524Cp3XXT+9BdOy3jE1PW0PDasseBxrPcic59JAeAYqYz0F4P8KTIMlk6OqBKAm+vG8nvMzWwNEYRcP7GSGkeiOL1/WMUSf51vCnh2ynjwbOi/sZstj9RrxJ4y7kMLN/BMbNf2w/MIibyxcas/Dp62MlIElUcac9xk4g3NL1pp2ITer9y/rVCFShIzUQuUm3kYt1vLgd2Ij333Yo1Ylw=='}
SECP384R1: {'signature': 'p51j6h2riocSrl9Frm3cXMq3gKlrz5JwC3tmXMFFWoFZ083c0L5fAV/vkxG3/hw5vqtvbw2FXVo+eV4AMfRyOzZ0V0Nd1t6ehw57MerDMsQDwSBt9TicrF0e+umCvFg/'}

3. Signature Provider plugin#

Plugins extend the existing SPSDK functionality with additional features.

In order to get benefits of remote signing, a Signature Provider plugin must be implemented. The plugin is a self-contained Python package responsible for communication with HSM.

One such an example is located in folder plugins/spsdk_sasp/. It will be used later on in this example.

3.1 Plugin API#

Every Signature Provider plugin is derived from spsdk.crypto.SignatureProvider base class.

  • The derived class must implement:

    • identifier: str: class attribute that identifies the concrete implementation of SignatureProvider

    • sign(bytes) -> bytes: method which performs the actual signing

    • signature_length -> str: property which returns a length of a signature

  • The derived class can also optionally implement:

    • info() -> str: method which returns information about the signature provider (for debugging purposes). The default implementation returns a class name as a string

    • verify_public_key(bytes) -> bool: method which verifies if a given public key matches a private key.

Omitting the implementation of optional methods such as info() does not break the functionality of application.

3.2 Signature Formats#

The signature must meet following formats:

  • RSA: Standard format

  • ECC: Extracted public numbers r+s stored in big endian or DER-formatted signature

3.3 Installation#

In order to test the functionality of remote signing, you must install the Signature Provider plugin package into your Python venv.

Install using uv:

!uv pip install $PLUGINS_DIR/spsdk_sasp
Resolved 67 packages in 33.28s
Building spsdk-sasp @ plugins/spsdk_sasp
Built spsdk-sasp @ plugins/spsdk_sasp
Prepared 1 package in 2.15s
Installed 1 package in 24ms
+ spsdk-sasp==0.1.0 (from plugins/spsdk_sasp)

Install using pip:

%pip install $PLUGINS_DIR/spsdk_sasp


4 SPSDK Built-in Signature Providers#

SPSDK includes several built-in signature providers in the signature_provider.py module. These providers offer different ways to handle the signing process, from local files to remote services.

4.1 PlainFileSP#

A signature provider that uses plain local files for signing operations.

Identifier: file

Parameters:

  • file_path: Path to private key file

  • password: (Optional) Password for encrypted private key file. If provided as a string path with .txt extension, file content will be used as password

  • hash_alg: (Optional) Hash algorithm for the signature (instance of EnumHashAlgorithm)

  • search_paths: (Optional) List of paths where to search for the file

  • Additional parameters can be passed to the private key’s sign method via **kwargs

Password Handling:

  • Password can be provided directly as a string

  • Password can also be provided as a path to a text file containing the password or environment variable

  • Password can be provided as environment variable

  • If the key is encrypted and no password is provided, an error will be raised

Example:

"type=file;file_path=/path/to/key.pem;password=secret"
"type=file;file_path=/path/to/key.pem;password=/path/to/password.txt"

4.2 InteractivePlainFileSP#

A signature provider that uses plain local files but prompts for a password if the key is encrypted.

Identifier: interactive_file

Parameters:

  • file_path: Path to private key file

  • hash_alg: (Optional) Hash algorithm for the signature

  • search_paths: (Optional) List of paths where to search for the file

  • Additional parameters can be passed to the private key’s sign method via **kwargs

Password Handling:

  • If the key is encrypted, the user will be prompted to enter a password

  • A password can still be provided in the parameters, but if it fails, the user will be prompted

Example:

"type=interactive_file;file_path=/path/to/key.pem"

4.2 HttpProxySP#

A signature provider that delegates signing operations to a remote proxy server via HTTP.

Identifier: proxy

Parameters:

  • host: Hostname or IP address of the proxy server (default: “localhost”)

  • port: Port of the proxy server (default: “8000”)

  • url_prefix: REST API prefix (default: “api”)

  • timeout: REST API timeout in seconds (default: 60)

  • prehash: (Optional) Name of the hashing algorithm to pre-hash data before sending to the signing service

  • Additional parameters will be included in every API request as JSON payload

Password Handling:

  • Password handling is delegated to the remote proxy server

  • No passwords are processed directly by this provider

Example:

"type=proxy;host=192.168.1.100;port=8000"
"type=proxy;host=hsm.example.com;port=443;url_prefix=v1/signing"

REST API Endpoints: The HttpProxySP expects the following REST API endpoints on the server:

  • sign - To create a signature

  • signature_length - To get the length of the signature

  • verify_public_key - To verify if a public key matches the private key

Requests: The provider sends requests with HTTP headers:

  • spsdk-version: Version of SPSDK

  • spsdk-api-version: API version (currently “2.0”)