-
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
Improve handling of native dependencies #200
Improve handling of native dependencies #200
Conversation
I need to figure out how to cleanly test Does it make sense to define a different test suite with a test for the public interfaces that verifies that all public functions either return successfully or return the expected Is there a cleaner/simpler way to do it? |
3b00c49
to
0ca75ef
Compare
Thanks, @joshuagl! This looks very reasonable to me. |
If colorama isn't present warn (via the logger) that terminal output won't be coloured and continue without. Signed-off-by: Joshua Lock <[email protected]>
eeabc4a
to
b3c9a42
Compare
So I just looked closer at your changes and they still seem very sensible. Thanks a lot, @joshuagl! I realized that the name of pyca_crypto_keys.py is quite misleading. It suggests that it is securesystemslib's interface to pyca/cryptography, although other modules (ecdsa_keys.py, hash.py) also interface that library. Maybe it would be clearer and more accurate to call it Another thing that I noticed is that pynacl import error handling is repeated on two levels of abstractions, i.e. in keys.py and in ed25519_keys.py. Do you think we could do it only once? Maybe we can draw the line that I described in #179 (comment) one level of abstraction further down. That is e.g.: # in ed25519_keys.py
NACL = True
try:
import nacl
except ImportError:
NACL = False
# ed25519_keys.sign() will raise an error if nacl does not exist
def sign():
if not NACL:
raise UnsupportedLibraryError()
else:
nacl.ed25519_sign()
# ed25519_keys.verify() has a pure-python fallback.
def verify():
if not NACL:
pure_python_ed25519_verify()
else:
nacl.ed25519_sign() This would make keys.py completely oblivious to the whole import story. And we could do the same thing for ecdsa_keys.py and rsa_keys.py (sic!), albeit without the pure-python fallback. In your approach, OTOH, I see the advantage of failing early, i.e. raising an I hope you don't mind my brainstorming here. I really appreciate your efforts and am curious about your thoughts. (cc @SantiagoTorres). |
Btw. since |
b3c9a42
to
9060e8b
Compare
Thanks for the constructive feedback @lukpueh
Would you like to see that rename here, or in a separate PR?
I was torn on this. Doing the import handling a level lower has the benefits of:
One downside to the approach is that the unit tests become more complex, as in many places we'll need to provide valid (enough) inputs to the higher-level functions so that the "unnecessary work" can be completed before the
I don't mind at all. I very much appreciate the constructive discussion around these changes. Assuming you agree, I'll revise this PR to:
I'll also take a look at adding similar logic to Does that seem like a reasonable approach? |
This better reflects the modules intent, it encapsulates RSA key algorithms not uses of pyca/cryptography. Signed-off-by: Joshua Lock <[email protected]>
Instead of having the caller of ed25519_keys.verify_signature() choose whether to use PyNaCl or not, default to always using nacl when it is available and otherwise fallback to the vendored copy of the pure Python ed25519 implementation. Signed-off-by: Joshua Lock <[email protected]>
Signed-off-by: Joshua Lock <[email protected]>
9060e8b
to
4b22f34
Compare
I didn't get around to addressing |
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.
Excellent work, @joshuagl. Thanks a lot for taking a stab at this task. I have left a few very minor comments. Let me know when you want me to take another look.
@@ -121,6 +125,10 @@ def generate_public_and_private(scheme='ecdsa-sha2-nistp256'): | |||
'securesystemslib.formats.PEMECDSA_SCHEMA', respectively. | |||
""" | |||
|
|||
if not CRYPTO: # pragma: no cover |
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.
It would be cool to configure coverage
to exclude these kinds of branches from py{27, 35, 36, 37, 38}
only, and do the inverse for purepy{27, 36}
. Do you want to look into it? We can also ticketize it.
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 technically easily handled thanks to the versatility of coverage[1], but I held off on doing it because I wasn't sure how valuable coverage results would be for the purepy environments - at least in the current setup with only check_public_interfaces.py
run in the purepy Tox environments we won't cover much of the code at all.
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 was thinking of a setup with mutual exclusive coverage exemption. Something like a # pragma: purepy
, to mark lines/branches that are excluded from py{27, 35, 36, 37, 38}
, but are also the only lines/branches considered for purepy{27, 38}
, so that all lines must be tested by either one or the other. But let's do this in a separate PR (I'll add a note on #179).
Raise UnsupportedLibraryError from each function in the low-level modules which encapsulate key algorithms (ecdsa_keys, ed25519_keys and rsa_keys) when the libraries needed by that function aren't available. Signed-off-by: Joshua Lock <[email protected]>
It should be possible to use securesystemslib in a pure Python mode, i.e. without any native dependencies installed, in which case any functions in the public interface should provide meaningful error messages when they aren't usable due to absent dependencies. Signed-off-by: Joshua Lock <[email protected]>
Ensure the pure Python fallback for ed25519 signature validation is tested by adding it to the check_public_interfaces test module which is run in an environment without any of the cryptographic library dependencies installed. Signed-off-by: Joshua Lock <[email protected]>
Now that the low-level modules handling interaction with the cryptographic libraries handle missing imports and throw UnsupportedLibraryException at the function level it's no longer required to wrap their import in a try/except block. Signed-off-by: Joshua Lock <[email protected]>
4b22f34
to
7162761
Compare
Thanks for the review @lukpueh. I think I've addressed all of your review comments except configuring coverage differently in the purepy case. I'd appreciate your thoughts on that one, I commented in-line. |
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.
Thanks for addressing all the comments! LGTM.
Please fill in the fields below to submit a pull request. The more information
that is provided, the better.
Fixes issue: #179 (partial fix,
securesystemslib.gpg
still needs to be addressed)Description of the changes being introduced by the pull request:
interface
andkeys
are importable even when the native dependencies are not availablePlease verify and check that the pull request fulfils the following
requirements: