-
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
PEM parsing is broken #54
Comments
++ on 2) |
Even if we did 2) (which seems to me, at first, the more attractive solution), it can still cause keys we use to break when the libraries are updated. And code will still break if we write code to parse all PEM formats and there are any changes to what PEM formats libraries support. In 1), 2), and the status quo, changes to the crypto libraries we use can result in causing parsing of either new or old keys to break (depending on the chosen scenario). The highest level solution to this problem is dependency pinning (which we use already) and good testing. If there were a test that generated new keys and then used them, then when the dependency pinnings were updated, the tests would have failed, and that update would never have been merged into In all cases, we need testing for the key formats we support, so we may as well start with that, I suppose. Beyond that, I prefer 2) if it's readily feasible, and if it's not readily feasible, then either 1) or, I suppose, neither (and make it explicit somewhere what PEM formats we support, and add support for the new one). |
@awwad, thanks for your take on this. I definitely agree with you on better testing and dependency pinning. Let me try to figure out how much effort approach |
Although I agree in principle, I don't think this would be a scenario we would run in real life. The key formats are standardized, and the underlying library developers have a (likely bigger) group of people providing support for these formats. At the end of the day, this issue boils down to us trying to reinvent the wheel at the moment of parsing PEM files and thus adding a new layer of code from which bugs can emerge. If SSLib is an easy-to-use crypto frontend to different (pluggable) cryptographic libraries it should remain like that. I think we need to have a clear focus on what is the goal of SSLib and not deviate from it. |
Btw. I found out what happened. The problem was not that pyca's cryptography had mysteriously changed its PEM format, nor was it the way we were calling pyca's crytpography. The problem was that, until recently, we never actually called pyca's cryptography to create encrypted RSA PEMs. This actually dates back to when securesystemslib was still part of theupdateframework. A quickfix would be to change the format parameter so that pyca's cryptography generates encrypted RSA PEM's the way pycrypto used to do it: diff --git securesystemslib/pyca_crypto_keys.py securesystemslib/pyca_crypto_keys.py
index ceef7c0..291c027 100755
--- securesystemslib/pyca_crypto_keys.py
+++ securesystemslib/pyca_crypto_keys.py
@@ -540,7 +540,7 @@ def create_rsa_encrypted_pem(private_key, passphrase):
encrypted_pem = \
private_key.private_bytes(encoding=serialization.Encoding.PEM,
- format=serialization.PrivateFormat.PKCS8,
+ format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.BestAvailableEncryption(passphrase.encode('utf-8')))
return encrypted_pem.decode() |
Makes me wonder if we should have two test suites with the different crypto providers in isolation |
Makes me wonder if we really benefit from supporting two libraries. |
This quickfix changes the PEM format from PKSC8 to PKSC5 (TraditionalOpenSSL) in pyca_crypto's variant of `create_rsa_encrypted_pem`. PKSC5 has the PEM headers expected by other PEM parsing functions, e.g. `is_pem_private` and `extract_pem`. See secure-systems-lab#54 for more details
While we're at it, we might want to reconsider the names of some of the affected functions: |
Re isolated test suites: for general_crypto_library in ['pycrypto', 'pyca-cryptography']:
KEYS._GENERAL_CRYPTO_LIBRARY = general_crypto_library
# Test routes
... Maybe we can remove those and run all the tests for each setting via the test aggregator script? Provided that we still want to support interchangeable crypto libraries. (see #56) |
Review of PEM format quickfix #54
Closing as outdated. |
High-level problem
We currently have an incomplete view on
PEM
formats. Several functions in the modulespycrypto_keys
,pyca_crypto_keys
,ecdsa_keys
andkeys
expectPEM
header and footer to be one of:However, there are many values for
VALUE
in-----BEGIN {VALUE} ... -----END {VALUE}-----
, as can be seen e.g. in openssl's pem.h.Breaking example
Securesystemlib's default crypto library
cryptography
has changed the PEM header for encrypted RSA private keys fromPKSC#5
toPKSC#8
(without our noticing):As a consequence a newly created encrypted RSA private key is not recognized as such anymore.
Note: The unit tests use a key that was generated before the update and therefor pass.
Solutions
Update our
PEM
parsing functions to account for all formatsPro: Quick/Easy fix
Con: IMHO bad documentation of PEM formats, seems like a shortcut that can easily break
Remove
PEM
parsing functions in securesystemslib and rely on crypto librariesPro: Seems like a more stable approach
Con: We support 2 crypto libraries (cryptography and pycrypto) and 3 key types (rsa, ecdsa, ed25519). And the affected functions are currently used to decide which crypto library functions should be called. Hence, this fix would require several larger changes.
Despite all, I would prefer solution (2).
Further readings
Below are random sources about PEM, PKCS5 and PKCS8. I didn't find the related RFC's very helpful, but I'll probably have to dig deeper:
pyca
pycrypto
PEM loadingcryptography
PEM loadingThe text was updated successfully, but these errors were encountered: