<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div style="font-family: sans-serif;">
<p>Individually I don't think these issues are much of a problem but their
combination does sound like it needs addressing. </p>
<p>1) This mostly seems like a documentation issue. If we expose these
values anywhere in our API we must document them, even if we hide them
inside some backend specific API. Perhaps we can give these values lower
priority in the docs and guide people towards the operations somehow?</p>
<p>2) There are 2 problems here. First are HSMs which provide only opaque
handles to work on keys. Yet they also often provide APIs for loading
existing keys into them. We still need to expose the individual key
parameters to write keys to them. If we only support generating keys inside
the HSM then we can avoid this to some extent, I suspect we will always
need access to *public* key material though. </p>
<p>The 2nd problem is APIs like CC which only provide DER encoded keys to
the user. This makes implementation annoying for sure. Fortunately we
currently have one mandatory backend that is fully capable of translating
those DER keys, OpenSSL. There is not yet any good reason not to use it for
this purpose. If we do make OpenSSL optional then working with raw DER for
key structures isn't impossible and we seem to have some more in depth
X.509 plans in progress anyway.</p>
<p>3) The problem is not that CRT is optional. The problem is that not
everyone uses PKCS#1. OpenPGP uses a different formulation of CRT, OpenSSH
regenerates CRT values on demand in places etc. Now certainly some backends
might not care about the CRT values we store. They are rare but maybe we
should still accommodate them? It seems like we should actually identify
them first. Currently all backends on our to do list have a strong
preference for the use of CRT.</p>
<p>4) Having investigated this issue in some depth we certainly have a
small timing side channel on conversion in the OpenSSL backend. I'm not
confident this is actually a serious danger though. IIRC the side channel
leaks a small amount of information about the sum of the number of 1 bits
in each part of the key, on Python 2.7.</p>
<p>The main slowness is in the constant reallocation of the internal key
structures. Abandoning our current API seems like a rather severe
optimisation to me. Until the opaque key idea came up our leading solution
to this problem was caching the backend internal representation on the key
objects. I don't think there's anything blocking us from implementing that?</p>
<p>So it seems like there's still a lot of different problems mixed up
here.</p>
<p>1) Our documentation has too much emphasis on key material. We can fix
this by writing better docs. </p>
<p>2) Implicit key conversion may be a security issue and is "slow". We can
fix this within the current API. </p>
<p>3) Insistence on PKCS#1 for RSA. We have taken some steps to make this
easier for users. I expect we will find application specific corner cases
regardless of representation here. IMO this is best solved at the protocol
library and documentation level.</p>
<p>4) Opaque backends. We can use OpenSSL to translate the key for them or
just get down to adding more in depth ASN1 support in general.</p>
<p>5) We don't have a good plan for HSMs. We should definitely address this
directly. I think they will inherently require their own interfaces though.
I would support splitting our current interfaces into *Material and
*Operations in anticipation of an HSM backend. We could do this easily
today without huge API impacts but multi backend should continue to require
a *Material key.</p>
<p>I do have concerns that multi backend will turn into a complexity tar
pit but so far it hasn't been too horrible.<br>
</p>
<div style="font-family: sans-serif;">
<p style="margin: 10pt 0; color: black;">On 22 April 2014 00:15:34 David
Reid <dreid@dreid.org> wrote:</p>
<blockquote type="cite" class="gmail_quote"
style="margin: 0 0 0 0.75ex; border-left: 1px solid #808080; padding-left: 0.75ex;"><div
dir="ltr"><div>I apologize for how disorganized these thoughts are, the
problems are more fully formed than</div><div>the solutions and I ended up
spending much more time than desired writing this email, so I just sort of
cut myself off at 4pm. Hopefully we can figure out some of these answers
on the mailing list.</div>
<div><br></div><div>--</div><div><br></div><div>Currently RSA key material
is represented as an object having a series of</div><div>properties that
correspond to the various mathematical components of an</div><div>RSA
key.</div>
<div><br></div><div>The initial reasoning for this is that it would make
the internal</div><div>representation of a key backend independent and
allow for moving key</div><div>material from one backend to another (for
example, loading the key from one</div>
<div>backend and performing encryption with another
backend).</div><div><br></div><div>However, as an initial proponent of this
argument I feel comfortable saying</div><div>that I was completely wrong.
It has variety of negative effects,</div>
<div><br></div><div>1) The mathematical components have terrible names that
we MUST expose to</div><div> users. In RSA n, p, q, e, and d. In ECDSA
x and y.</div><div><br></div><div> Even when these components have well
known multisyllable names their value</div>
<div> as descriptors is somewhat limited, "public exponent" is
a much better name</div><div> than "e" but still requires
knowledge of the mathematical foundations of</div><div> RSA to be of any
value to anyone. (You can argue that the</div>
<div> hazmat/primitives layers are the place for exposing this kind of
detail to</div><div> users and that if you don't understand the RSA
mathematically you shouldn't</div><div> be using them, however
we've never felt any need to point out that AES</div>
<div> S-boxes can be described by a system of 23 quadratic equations in
80 terms.)</div><div><br></div><div>2) Not all backend representations of
keys expose the individual components.</div><div><br></div><div> Even
given a single backend such as openssl there is no guarantee that</div>
<div> two internal structures will contain all the necessary data. This
is</div><div> most notable with keys stored in a HSMs or SmartCards where
it is a feature</div><div> that you can not extract the RSA private key
from the system.</div>
<div><br></div><div> However this is also evident in backends like
CommonCrypto which don't have</div><div> a public API for getting or
setting the values of the various key</div><div> components. To actually
use an RSA key from OpenSSL on CommonCrypto you</div>
<div> MUST convert it to some intermediate representation that both
understand</div><div> (likely PKCS#8).</div><div><br></div><div>3)
Optional optimizations get exposed to users as required
interface.</div><div><br></div>
<div> Similarly, our exposure of the Chinese remainder theorem
intermediate</div><div> calculations on the RSAPrivateKey interface
complicates the usage of RSA</div><div> key material on multiple backends
instead of simplifies it. Not all</div>
<div> serialization formats or backends support storing/loading the CRT
values</div><div> potentially requiring us to perform duplicate
calculations of these values</div><div> for exposing them on the
nonopaque interface.</div>
<div><br></div><div>4) Using the generic key components makes frequent
operations (like obtaining</div><div> a new signing/verify context) more
expensive.</div><div><br></div><div> These backend specific operations
now require potentially costly (or even</div>
<div> dangerous) conversions between the generic and backend</div><div>
specific representations.</div><div><br></div><div><br></div><div>Given
these issues I think we must seriously consider switching away from</div>
<div>these backend independent representations as our primary interface to
key</div><div>materials. Preferring instead opaque backend specific
implementations.</div><div><br></div><div>For example, instead of a
concrete RSAPrivateKey instance which can be</div>
<div>instantiated with the underlying components, I imagine all key
generation and</div><div>loading being mediated by backends and resulting
in objects that provide much</div><div>more narrow interfaces organized
around what you can do with a key (instead of</div>
<div>what a key intrinsically is). For example, when generating an RSA key
on the</div><div>openssl backend you would get back an object which
provides a basic interface</div><div>indicating that it is an RSA key, that
has some basic attributes for key</div>
<div>size, and accessing the public key object, then methods for obtaining
backend</div><div>specific contexts for performing signing/verification
and </div><div>encryption/decryption operations.</div><div><br></div><div>
In addition to those basic operations the object may provide any number
of</div><div>backend specific serialization methods, potentially including
"serializing" the</div><div>key to something similar to the
current interface (which we can think of as a </div>
<div>bag of bignums). </div><div><br></div><div>In this way we can
facilitate converting between backend specific
key </div><div>representations through a process of
serialization/deserialization (in many </div><div>cases through a formal
specification such as PKCS#8).</div>
<div><br></div><div>-David</div></div>
</blockquote>
</div>
</div>
</body>
</html>