Thoughts on opaque key material.
I apologize for how disorganized these thoughts are, the problems are more fully formed than 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. -- Currently RSA key material is represented as an object having a series of properties that correspond to the various mathematical components of an RSA key. The initial reasoning for this is that it would make the internal representation of a key backend independent and allow for moving key material from one backend to another (for example, loading the key from one backend and performing encryption with another backend). However, as an initial proponent of this argument I feel comfortable saying that I was completely wrong. It has variety of negative effects, 1) The mathematical components have terrible names that we MUST expose to users. In RSA n, p, q, e, and d. In ECDSA x and y. Even when these components have well known multisyllable names their value as descriptors is somewhat limited, "public exponent" is a much better name than "e" but still requires knowledge of the mathematical foundations of RSA to be of any value to anyone. (You can argue that the hazmat/primitives layers are the place for exposing this kind of detail to users and that if you don't understand the RSA mathematically you shouldn't be using them, however we've never felt any need to point out that AES S-boxes can be described by a system of 23 quadratic equations in 80 terms.) 2) Not all backend representations of keys expose the individual components. Even given a single backend such as openssl there is no guarantee that two internal structures will contain all the necessary data. This is most notable with keys stored in a HSMs or SmartCards where it is a feature that you can not extract the RSA private key from the system. However this is also evident in backends like CommonCrypto which don't have a public API for getting or setting the values of the various key components. To actually use an RSA key from OpenSSL on CommonCrypto you MUST convert it to some intermediate representation that both understand (likely PKCS#8). 3) Optional optimizations get exposed to users as required interface. Similarly, our exposure of the Chinese remainder theorem intermediate calculations on the RSAPrivateKey interface complicates the usage of RSA key material on multiple backends instead of simplifies it. Not all serialization formats or backends support storing/loading the CRT values potentially requiring us to perform duplicate calculations of these values for exposing them on the nonopaque interface. 4) Using the generic key components makes frequent operations (like obtaining a new signing/verify context) more expensive. These backend specific operations now require potentially costly (or even dangerous) conversions between the generic and backend specific representations. Given these issues I think we must seriously consider switching away from these backend independent representations as our primary interface to key materials. Preferring instead opaque backend specific implementations. For example, instead of a concrete RSAPrivateKey instance which can be instantiated with the underlying components, I imagine all key generation and loading being mediated by backends and resulting in objects that provide much more narrow interfaces organized around what you can do with a key (instead of what a key intrinsically is). For example, when generating an RSA key on the openssl backend you would get back an object which provides a basic interface indicating that it is an RSA key, that has some basic attributes for key size, and accessing the public key object, then methods for obtaining backend specific contexts for performing signing/verification and encryption/decryption operations. In addition to those basic operations the object may provide any number of backend specific serialization methods, potentially including "serializing" the key to something similar to the current interface (which we can think of as a bag of bignums). In this way we can facilitate converting between backend specific key representations through a process of serialization/deserialization (in many cases through a formal specification such as PKCS#8). -David
participants (4)
-
Alex Gaynor -
Alex Stapleton -
David Reid -
Glyph Lefkowitz