<div dir="ltr"><div><div><div>Hello James,<br><br></div>Thanks for opening the discussion on this
 topic. I'd like to mention that a very common type of secrets that are 
used in Continuous Deployments scenarios are SSH keys. Correct me if I 
am wrong, but PKCS#1 wouldn't qualify if standard keys were to be 
stored.<br><br></div>Regards,<br><br></div>Matthieu<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 21, 2017 at 6:38 PM, Matthieu Huin <span dir="ltr"><<a href="mailto:mhuin@redhat.com" target="_blank">mhuin@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>Hello James,<br><br></div>Thanks for opening the discussion on this topic. I'd like to mention that a very common type of secrets that are used in Continuous Deployments scenarios are SSH keys. Correct me if I am wrong, but PKCS#1 wouldn't qualify if standard keys were to be stored.<br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 21, 2017 at 5:36 PM, James E. Blair <span dir="ltr"><<a href="mailto:corvus@inaugust.com" target="_blank">corvus@inaugust.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
In working on the implementation of the encrypted secrets feature of<br>
Zuul v3, I have found some things that warrant further discussion.  It's<br>
important to be deliberate about this and I welcome any feedback.<br>
<br>
For reference, here is the relevant portion of the Zuul v3 spec:<br>
<br>
<a href="http://specs.openstack.org/openstack-infra/infra-specs/specs/zuulv3.html#secrets" rel="noreferrer" target="_blank">http://specs.openstack.org/ope<wbr>nstack-infra/infra-specs/specs<wbr>/zuulv3.html#secrets</a><br>
<br>
And here is an implementation of that:<br>
<br>
<a href="https://review.openstack.org/#/q/status:open+topic:secrets+project:openstack-infra/zuul" rel="noreferrer" target="_blank">https://review.openstack.org/#<wbr>/q/status:open+topic:secrets+p<wbr>roject:openstack-infra/zuul</a><br>
<br>
The short version is that we want to allow users to store private keys<br>
in the public git repos which Zuul uses to run jobs.  To do this, we<br>
propose to use asymmetric cryptography (RSA) to encrypt the data.  The<br>
specification suggests implementing PKCS#1-OAEP, a standard for<br>
implementing RSA encryption.<br>
<br>
Note that RSA is not able to encrypt a message longer than the key, and<br>
PKCS#1 includes some overhead which eats into that.  If we use 4096 bit<br>
RSA keys in Zuul, we will be able to encrypt 3760 bits (or 470 bytes) of<br>
information.<br>
<br>
Further, note that value only holds if we use SHA-1.  It has been<br>
suggested that we may want to consider using SHA-256 with PKCS#1.  If we<br>
do, we will be able to encrypt slightly less data.  However, I'm not<br>
sure that the Python cryptography library allows this (yet?).  Also, see<br>
this answer for why it may not be necessary to use SHA-256 (and also,<br>
why we may want to anyway):<br>
<br>
<a href="https://security.stackexchange.com/questions/112029/should-sha-1-be-used-with-rsa-oaep" rel="noreferrer" target="_blank">https://security.stackexchange<wbr>.com/questions/112029/should-<wbr>sha-1-be-used-with-rsa-oaep</a><br>
<br>
One thing to note is that the OpenSSL CLI utility uses SHA-1.  Right<br>
now, I have a utility script which uses that to encrypt secrets so that<br>
it's easy for anyone to encrypt a secret without installing many<br>
dependencies.  Switching to another hash function would probably mean we<br>
wouldn't be able to use that anymore.  But that's also true for other<br>
systems (see below).<br>
<br>
In short, PKCS#1 pros: Simple, nicely packaged asymmetric encryption,<br>
hides plaintext message length (up to its limit).  Cons: limited to 470<br>
bytes (or less).<br>
<br>
Generally, when faced with the prospect of encrypting longer messages,<br>
the advice is to adopt a hybrid encryption scheme (as opposed to, say,<br>
chaining RSA messages together, or increasing the RSA key size) which<br>
uses symmetric encryption with a single-use key for the message and<br>
asymmetric encryption to hide the key.  If we want Zuul to support the<br>
encryption of longer secrets, we may want to adopt the hybrid approach.<br>
A frequent hybrid approach is to encrypt the message with AES, and then<br>
encrypt the AES key with RSA.<br>
<br>
The hiera-eyaml work which originally inspired some of this is based on<br>
PKCS#7 with AES as the cipher -- ultimately a hybrid approach.  An<br>
interesting aspect of that implementation is that the use of PKCS#7 as a<br>
message passing format allows for multiple possible underlying ciphers<br>
since the message is wrapped in ASN.1 and is self-descriptive.  We might<br>
have simply chosen to go with that except that there don't seem to be<br>
many good options for implementing this in Python, largely because of<br>
the nightmare that is ASN.1 parsing.<br>
<br>
The system we have devised for including encrypted content in our YAML<br>
files involves a YAML tag which specifies the encryption scheme.  So we<br>
can evolve our use to add or remove systems as needed in the future.<br>
<br>
So to break this down into a series of actionable questions:<br>
<br>
1) Do we want a system to support encrypting longer secrets?  Our PKCS#1<br>
system supports up to 470 bytes.  That should be sufficient for most<br>
passwords and API keys, but unlikely to be sufficient for some<br>
certificate related systems, etc.<br>
<br>
2) If so, what system should we use?<br>
<br>
   2.1a) GPG?  This has hybrid encryption and transport combined.<br>
   Implementation is likely to be a bit awkward, probably involving<br>
   popen to external processes.<br>
<br>
   2.1b) RSA+AES?  This recommendation from the pycryptodome<br>
   documentation illustrates a typical hybrid approach:<br>
   <a href="https://pycryptodome.readthedocs.io/en/latest/src/examples.html#encrypt-data-with-rsa" rel="noreferrer" target="_blank">https://pycryptodome.readthed<wbr>ocs.io/en/latest/src/examples.<wbr>html#encrypt-data-with-rsa</a><br>
   The transport protocol would likely just be the concatenation of<br>
   the RSA and AES encrypted data, as it is in that example.  We can<br>
   port that example to use the python-cryptography primatives, or we<br>
   can switch to pycryptodome and use it exactly.<br>
<br>
   2.1c) RSA+Fernet?  We can stay closer to the friendly recipes in<br>
   python-cryptography.  While there is no complete hybrid recipe,<br>
   there is a symmetric recipe for "Fernet" which is essentially a<br>
   recipe for AES encryption and transport.  We could encode the<br>
   Fernet key with RSA and concatenate the Fernet token.<br>
   <a href="https://github.com/fernet/spec/blob/master/Spec.md" rel="noreferrer" target="_blank">https://github.com/fernet/spe<wbr>c/blob/master/Spec.md</a><br>
<br>
   2.1d) NaCL?  A "sealed box" in libsodium (which underlies PyNaCL)<br>
   would do what we want with a completely different set of<br>
   algorithms.<br>
   <a href="https://github.com/pyca/pynacl/issues/189" rel="noreferrer" target="_blank">https://github.com/pyca/pynac<wbr>l/issues/189</a><br>
<br>
3) Do we think it is important to hide the length of the secret?  AES<br>
will expose the approximate length of the secret up to the block size<br>
(16 bytes).  This is probably not important for long secrets, but for<br>
short ones, it may at least indicate the order of magnitude of a<br>
password, for instance.  If we want, we can pad the secret further<br>
before encrypting it.<br>
<br>
4) If we adopt a system for longer secrets, do we still want to include<br>
PKCS#1 for shorter ones?  The PKCS#1 ciphertext will be shorter than the<br>
same secret would be in a hybrid system.  But either way, we're talking<br>
about a fairly big blob (about 9 lines of base64 for PKCS#1).<br>
<br>
5) If we keep PKCS#1, are we okay using SHA-1 or should we see about<br>
using SHA-256?<br>
<br>
6) Considering all of that, should we:<br>
<br>
  A) Stick with PKCS#1 for now (we can always add something else later)<br>
  B) Keep PKCS#1 and add something else now<br>
  C) Drop PKCS#1 and replace it with something else<br>
<br>
Thanks,<br>
<br>
Jim<br>
<br>
<br>
______________________________<wbr>______________________________<wbr>______________<br>
OpenStack Development Mailing List (not for usage questions)<br>
Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer" target="_blank">OpenStack-dev-request@lists.op<wbr>enstack.org?subject:unsubscrib<wbr>e</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi<wbr>-bin/mailman/listinfo/openstac<wbr>k-dev</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>