Signer API

The signer module provides a simple and unified cryptographic signing and signature verification API designed to work consistently regardless of the underlying signing technology. This is achieved with abstract interfaces backed by multiple implementations:

  • Signer.sign

  • Key.verify_signature

The interfaces can be implemented using arbitrary asymmetric signing technology. The Key class is also a container class for public key data. The Signer class, on the other hand, treats the private key as implementation detail. This means that one specific signer may indeed contain the private key, but another calls a remote cloud KMS, or a local hardware token for signing.

In addition to sign and verify interface methods, the signer API provides generic load methods:

  • Signer.from_priv_key_uri - Loads any specific signer from a URI. The specific signer implementation itself is responsible for the URI format and resolution. To become discoverable, signers and their URI schemes are registered in the SIGNER_FOR_URI_SCHEME lookup table.

  • Key.from_dict - Loads any specific key from a serialized format. The specific key implementation is responsible for the public key format and deserialization. To become discoverable, key type and signing scheme – required fields in any public key – are registered in the KEY_FOR_TYPE_AND_SCHEME lookup table.

An application can use these same methods to uniformly load any signer or public key, regardless of the specific implementation. Many signers and keys are already included in the signer API. And an application can also create and register its own.

Usage

The signer API is streamlined for the following series of user events, which may happen on different systems and at different points in time:

  1. Generate key pair (signature provider -specific)

    Typically, this is done outside of the signer API, e.g. by using a Cloud KMS web UI or an HSM console.

  2. Configure public key and signer access URI

    The public key for a signer must be available in the signing context, in order to express its eligibility.

    Some of the existing signer implementations have methods to import a public key from a signature provider and to build the related signer access URI.

    The public key can then be serialized with interface methods for use in the signing context and in the verification context.

  3. Sign, given a configured public key and signer access URI

  4. Verify, given a configured public key

Note

See ‘New Signer API’ blog post for background infos.

API documentation

SIGNER_FOR_URI_SCHEME: Dict[str, Type]

Signer dispatch table for Signer.from_priv_key()

See securesystemslib.signer.SIGNER_FOR_URI_SCHEME for default URI schemes, and how to register custom implementations.

KEY_FOR_TYPE_AND_SCHEME: Dict[Tuple[str, str], Type]

Key dispatch table for Key.from_dict()

See securesystemslib.signer.KEY_FOR_TYPE_AND_SCHEME for default key types and schemes, and how to register custom implementations.

class Signer

Signer interface that supports multiple signing implementations.

Usage example:

signer = Signer.from_priv_key_uri(uri, pub_key)
sig = signer.sign(b"data")

Note that signer implementations may raise errors (during both Signer.from_priv_key_uri() and Signer.sign()) that are not documented here: examples could include network errors or file read errors. Applications should use generic try-except here if unexpected raises are not an option.

See SIGNER_FOR_URI_SCHEME for supported private key URI schemes.

Interactive applications may also define a secrets handler that allows asking for user secrets if they are needed:

from getpass import getpass

def sec_handler(secret_name:str) -> str:
    return getpass(f"Enter {secret_name}: ")

signer = Signer.from_priv_key_uri(uri, pub_key, sec_handler)

Applications can provide their own Signer and Key implementations:

from securesystemslib.signer import Signer, SIGNER_FOR_URI_SCHEME
from mylib import MySigner

SIGNER_FOR_URI_SCHEME[MySigner.MY_SCHEME] = MySigner

This way the application code using signer API continues to work with default signers but now also uses the custom signer when the proper URI is used.

abstract classmethod from_priv_key_uri(priv_key_uri, public_key, secrets_handler=None)

Factory constructor for a given private key URI

Returns a specific Signer instance based on the private key URI and the supported uri schemes listed in SIGNER_FOR_URI_SCHEME.

Parameters:
  • priv_key_uri (str) – URI that identifies the private key

  • public_key (Key) – Key that is the public portion of this private key

  • secrets_handler (Callable[[str], str] | None) – Optional function that may be called if the signer needs additional secrets (like a PIN or passphrase). secrets_handler should return the requested secret string.

Raises:
  • ValueError – Incorrect arguments

  • Other Signer-specific errors – These could include OSErrors for reading files or network errors for connecting to a KMS.

Return type:

Signer

abstract property public_key: Key

Returns: Public key the signer is based off.

abstract sign(payload)

Signs a given payload by the key assigned to the Signer instance.

Parameters:

payload (bytes) – The bytes to be signed.

Returns:

Returns a “Signature” class instance.

Return type:

Signature

class Key(keyid, keytype, scheme, keyval, unrecognized_fields=None)

Abstract class representing the public portion of a key.

All parameters named below are not just constructor arguments but also instance attributes.

Parameters:
  • keyid (str) – Key identifier that is unique within the metadata it is used in. Keyid is not verified to be the hash of a specific representation of the key.

  • keytype (str) – Key type, e.g. “rsa”, “ed25519” or “ecdsa-sha2-nistp256”.

  • scheme (str) – Signature scheme. For example: “rsassa-pss-sha256”, “ed25519”, and “ecdsa-sha2-nistp256”.

  • keyval (Dict[str, Any]) – Opaque key content

  • unrecognized_fields (Dict[str, Any] | None) – Dictionary of all attributes that are not managed by Securesystemslib

Raises:

TypeError – Invalid type for an argument.

abstract classmethod from_dict(keyid, key_dict)

Creates Key object from a serialization dict

Key implementations must override this factory constructor that is used as a deserialization helper.

Users should call Key.from_dict(): it dispatches to the actual subclass implementation based on supported keys in KEY_FOR_TYPE_AND_SCHEME.

Raises:

KeyError, TypeError – Invalid arguments.

Parameters:
  • keyid (str)

  • key_dict (Dict[str, Any])

Return type:

Key

abstract to_dict()

Returns a serialization dict.

Key implementations must override this serialization helper.

Return type:

Dict[str, Any]

abstract verify_signature(signature, data)

Raises if verification of signature over data fails.

Parameters:
  • signature (Signature) – Signature object.

  • data (bytes) – Payload bytes.

Raises:
  • UnverifiedSignatureError – Failed to verify signature.

  • VerificationError – Signature verification process error. If you are only interested in the verify result, just handle UnverifiedSignatureError: it contains VerificationError as well

Return type:

None

class Signature(keyid, sig, unrecognized_fields=None)

A container class containing information about a signature.

Contains a signature and the keyid uniquely identifying the key used to generate the signature.

Provides utility methods to easily create an object from a dictionary and return the dictionary representation of the object.

Parameters:
  • keyid (str) – HEX string used as a unique identifier of the key.

  • sig (str) – HEX string representing the signature.

  • unrecognized_fields (Dict[str, Any] | None) – Dictionary of all attributes that are not managed by securesystemslib.

keyid

HEX string used as a unique identifier of the key.

signature

HEX string representing the signature.

unrecognized_fields

Dictionary of all attributes that are not managed by securesystemslib.

classmethod from_dict(signature_dict)

Creates a Signature object from its JSON/dict representation.

Parameters:

signature_dict (Dict) – A dict containing a valid keyid and a signature. Note that the fields in it should be named “keyid” and “sig” respectively.

Raises:

KeyError – If any of the “keyid” and “sig” fields are missing from the signature_dict.

Return type:

Signature

Side Effect:

Destroys the metadata dict passed by reference.

Returns:

A “Signature” instance.

Parameters:

signature_dict (Dict)

Return type:

Signature

to_dict()

Returns the JSON-serializable dictionary representation of self.

Return type:

Dict