-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
signer: Add abstract Key class, implement private key uri scheme for Signer #456
Conversation
The scheme allows instantiating signers and signing with them without knowing the signer or privtae key type beforehand., Signers can now be used like this: # demo setup pubkey = generate_ecdsa_key() privkey = pubkey["keyval"].pop("private") os.environ["myprivatekey"] = privkey # sign: Correct Signer subclass is chosen based on the URI signer = Signer.from_priv_key_uri("envvar://myprivatekey", pubkey) sig = signer.sign(b"data") Just three schemes are supported by default but more can be added here and exernally, in applications. Default schemes: envvar: read private key content from environment variable file: read private key content from file encfile: read encrypted private key content from file, decrypt with passphrase from application
This is copied from python-tuf with following changes * verify_signature() is left in python-tuf as Metadata-related * is_verified() is added instead * type of keyval is changed from Dict[str, str] to Dict[str, Any] * Some docstrings made more reasonable for SSLib Signer.from_priv_key_uri() now takes a Key as argument. SSlibSigner constructor still takes a classic keydict as constructor argument and not a Key (in order to not break API) but that is now documented as an implementation detail.
python-tuf has an extensive test suite for Metadata in general: * I don't think python-tuf should stop testing Key just because it's now in securesystemslib * Maybe it's not necessary to copy e.g. all serialization tests here? Still, added a few basic tests for Key. Key is also used in the Signer tests.
Results from chat with Lukas:
This is quite a bit more than just moving the Key class... but it fits in well with Signer change as they are both dispatcher-style abstractions (for Key and Signer respectively) |
The idea is to allow more Key implementations, but SSlibKey provides the current implementations.
GPGSigner and GPGKey are not in the default dispatch list as the serialization formats they produce are not compatible with TUF or in-toto specifications Tests are very smoke testy so far
verify_signature now has two exceptions: class UnverifiedSignatureError(Error): class VerificationError(UnverifiedSignatureError): First one for those who just want to know if verify succeeded. Second one for those who want to also know if process failed somehow.
This ballooned "a bit"... I've updated the description, hoping it makes sense to others. |
Oh and I forgot to mention: Most of the GPGKey implementation in here comes from https://github.com/in-toto/securesystemslib/ so is likely @PradyumnaKrishna's work: if this PR looks like a path forward, should make sure he gets credited (I can try editing the commit history so authorship is visible in git) |
A couple of high-level comments:
Some thoughts about fixing gpg issues
|
I think we can do both:
but I certainly wouldn't oppose to in-toto keeping the GPGKey and GPGSigner in their code base -- and with this architecture it would be quite easy As mentionedin the other reply, GPGKey does support |
I think the special keyid matching is not too much to ask from the |
👍 Let's do that in a follow-up PR.
I suggest to remove it from securesystemslib, for these reasons (as discussed above):
|
Yes, this should be easy if it's only needed in in-toto. The reason why we defined the |
Signer and Key are now abstract and can have multiple implementations that get dispatched by the base classes. The current GPG implementation is just non-compliant enough that it is not included in the dispatch. Plan is: * move GPGSigner to intoto, add GPGKey in intoto: this allows intoto to keep using this implementation without too much pain * Possibly implement a more compliant GPG signer and key in securesystemslib
Current state:
Potential review questions/improvements:
|
No it does not. |
I think it's more than just |
No, Key is still part of the python-tuf Metadata API -- it's just that it comes from securesystemslib. This is not as clear as it should be since we are not explicit about API: I think it would make sense to use So currently python-tuf users can do Now that I think about it the |
Related comment on Signer:
the former is #463. The latter idea (just using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this, nice work! I left a couple of minor comments, notably a request to document the dynamic dispatch method and how folks add their own implementations of the abstract base classes and wire them in.
* Fix the incorrect metaclass syntax * Also refactor constructor so it is shorter
fixed a few latest comments (thanks!): No real functional changes here. |
There is (at least currently) no promise that Signer implementations do not raise unexpected errors.
Ok, I think I'm now done. All future tickets are filed, PR should be ready. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so neat! Many thanks, Jussi. I'm approving, although we should probably check for None instead of Falseyness when creating the default self.unrecognized_fields
value. But this is no blocker.
Also, there is an annotation inconsistency in Key and Signature unrecognized_fields constructor argument and instance variables (Dict vs. Mapping, and type hint at declaration in one but not the other). You probably just copied those over. 🤷
* do not check falsyness of argument containers: the results are unexpected if the argument container is empty * Do not use Mapping annotation for unrecognized_fields. The original idea was that Metadata API is not changing them: this is true but we don't want to prevent users from modifying the fields...
Fixes: #447
Summary
The private key URI scheme allows application code to handle private keys in a generic way: the keytype, used signer implementation or private key storage system are not something the application needs to worry about. Example
Changelist
The user facing API additions are:
Signer.from_priv_key_uri()
addedSIGNER_FOR_URI_SCHEME
andKEY_FOR_TYPE_AND_SCHEME
define supported signers and keysOther changes that do not really affect users
Other notes:
Signer.from_priv_key_uri()
Key.from_dict()
TODO later: I will file issues