How should I load signers for immediate signing, e.g. in CLI?
lukpueh opened this issue · comments
The currently recommended signer API usage pattern requires two steps to load a signer.
1. Take user inputs to load a public key and configure the signer URI
2. Take public key and signer URI to load a signer and sign
This separation of signer authorisation (e.g. delegate a key via TUF or in-toto metadata) and its usage is especially useful when the two steps are not performed in direct succession or not even on the same host.
However, the signer API may also be useful in a context, where the delegation happens out-of-band or after-the-fact. That is, the invocation is authorisation enough:
1. Take user inputs to load a signer and sign
Here, the separation from above is not intuitive nor efficient. The latter, because all current signing technologies in securesystemslib
allow to infer the public key from the private key. Being forced to import the public key first, in order to then load the signer, adds unnecessary work (e.g. additional file read, network request, etc.)
Proposal
Add signer-specific API functions to load a signer including the public key material, e.g.:
class CryptoSigner(Signer):
@classmethod
def from_pem(private_bytes, keyid=None, scheme=None, password=None) -> CryptoSigner:
"""
private_bytes: PKCS8/PEM private bytes
keyid: use hex digest, if not passed
scheme: use default for inferred key, if not passed
password: treat as unencrytped, if not passed
"""
I see no problems with this.
from_priv_key_uri()
is generic but clumsy- likely all Signers could have more ergonomic signer-specific (or use-case-specific) constructors
I've never had a use-case where I wanted to avoid generic signer loading to have the latter but I can see others might.
Let's not add code "just because" but if an application use case gets easier by adding a constructor, let's do that.
likely all Signers could have more ergonomic signer-specific (or use-case-specific) constructors
Yes, a usable CryptoSigner.__init__
would already go a long way. Currently, CryptoSigner is abstract and all its subclasses are protected, which makes it unusable outside of from_priv_key_uri
. If I could create a CryptoSigner from a pyca/cryptography private key object, then it would be easy for an application to create their own from_pem
, e.g.:
from cryptography.hazmat.primitives.serialization import load_pem_private_key
private_key = load_pem_private_key(data, password)
signer = CryptoSigner(private_key) # generate default public Key, if not passed explicitly