[openstack-dev] [infra][security] Encryption in Zuul v3

David Moreau Simard dms at redhat.com
Tue Mar 21 20:28:40 UTC 2017

I don't have a horse in this race or a strong opinion on the topic, in
fact I'm admittedly not very knowledgeable when it comes to low-level
encryption things.

However, I did have a question, even if just to generate discussion.
Did we ever consider simply leaving secrets out of Zuul and offloading
that "burden" to something else ?

For example, end-users could use something like git-crypt [1] to crypt
files in their git repos and Zuul could have a mean to decrypt them at
There is also ansible-vault [2] that could perhaps be leveraged.

Just trying to make sure we're not re-inventing any wheels,
implementing crypto is usually not straightfoward.

[1]: https://www.agwa.name/projects/git-crypt/
[2]: http://docs.ansible.com/ansible/playbooks_vault.html

David Moreau Simard
Senior Software Engineer | Openstack RDO

dmsimard = [irc, github, twitter]

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

More information about the OpenStack-dev mailing list