-
Notifications
You must be signed in to change notification settings - Fork 4
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
Slice out KeyManager into 2 parts: KeyRing
, CertificateManager
#472
Comments
I've already got There's no work yet done on |
Experiments with Observable experiments will be for: #444 |
I suspect 1 point left for So 4 points in total. |
KeyRing
, CertificateManager
, KeyManager
KeyRing
, CertificateManager
Arbitrary subkey management is being factored out entirely to KeyManager. However currently we don't have a need to have this feature, so it's just entirely removed. I've renamed this issue to not bother with a |
Specification
The
KeyManager
is doing 3 duties:KeyRing
The first duty should be separated out into a
KeyRing
object. This object is a singleton that handles just the root key pair and symmetric DB key. It can be considered an Key Encapsulation Mechanism that enables PK to be a "hybrid cryptosystem". Many downstream domains that depend on theKeyManager
can instead depend on theKeyRing
, because they only require knowledge about the current node'sNodeId
. With the change to ed25519, the 32-byte/256-bit public key is now theNodeId
, there's no need to hash the public key to get theNodeId
. This has many advantages, such as the fact that ourNodeGraph
contains all the public keys we want to contact, and reduces the amount of chatter required to acquire the public keys of other nodes.Furthermore now that the
KeyRing
is a smaller interface, the main goal is that we can pass it around more freely like a POJO. However just passing aroundKeyRing
isn't going to change the behaviour of downstream objects that much. Therefore in the spirit of POLA/POLP, we are going to explore how to have the power ofKeyRing
object while being able to "extract" read-only dynamic/observable properties out of theKeyRing
that can be easily synthetically constructed during mock-testing.We find it difficult during prototyping time that one must asynchronously create the
KeyRing
before passing it in to downstream objects during mock-testing. This looks like:If we had a POJO instead, it would be easy to create synthetic key rings for any purpose.
But as we know with #386 and #444, the
keyPair
is a dynamic object. It could be considered aReadOnly
interface at this point, but the downstream domains should be "reacting" to changes to the keyring. So suppose we could do this:So the idea, is that we make use of
Observable
fromrxjs
and allow us the ability to "slice" out observable properties from the main singleton object ofKeyRing
, and pass just that observable property to downstream domains.The
rxdb
interface shows ways of doing this.At this point we would still have the
KeyRing
singleton object, and it will have the API methods of:And dynamic subproperties like the
keyPair
orpublicKey
orprivateKey
ornodeId
could preserve API methods on them, or we can expect downstream to use utilities on them, and expect the observable streams to only be passing data around instead of passing objects around.The
KeyRing
doesn't require the database, everything it stores is on the filesystem. This means it has to manage the on-disk encryption/decryption directly with encapsulation/decapsulation and wrap/unwrap methods. At minimum there will always be 1 asymmetric keypair and 1 symmetric key, we can think of these as the "root keys".CertificateManager
The
CertificateManager
is the remaining methods on theKeyManager
once the key ring functionality is sliced out. It has to manage all the root identity certificate chains just liek before. There was some initial exploration of the similarities between the sigchain and the x509 certificate chain. We still need this x509 certificate chain separate from sigchain because TLS still relies on x509.The certificates now rely on
CertificateId
which does need to be stored in the database, this meansCertificateManager
is a domain reliant on the DB unlikeKeyRing
.The methods that are relevant here are:
There's a couple problems to solve now that the
KeyRing
is separated out. TheKeyRing
can expose a general key rotation functionKeyRing.rotate
, doing this rotates the key pair, but it isn't aware of any of the certificates anymore. This means we have a couple of ways to do this:CertificateManager
depend onKeyRing
, and expose the above methods that end up callingKeyRing.rotate
.CertificateManager
depend on an observable ofKeyRing
key pair, and it would therefore react to change to the root key pair during rotation.KeyRing
andCertificateManager
together at a composition point, and expose the ability to rotate the key pair and regenerate certificates at a higher level.Solution 2. doesn't work because there's no way to control whether we want to renew the certificate with the new key pair, reset the certificate with the new keypair, or just reset the certificate with the existing key pair. Although renewing the certificate with the new key pair is the most common operation, and the latter 2 operations are not actually used in the normal operating flow of PK.
Solution 3. would allow a nice separation of duties, but it does mean a key functionality is now done at the RPC handler level. We talked about in the past whether our key functionality is in the handlers or done at the level of domain objects. Doing this would be different from our existing design which currently expects our domain objects to work independently of the RPC handlers. Essentially our RPC handlers are thin controllers that rely mostly on the domain objects. They just marshal RPC request and responses to domain methods and streams. This was intended to make it easier for us to test logic without introducing RPC request/response overhead all over our tests.
It appears solution 1. is the only practical way of doing this. The
CertificateManager
represents a higher abstraction level, that builds on top of root keys to present an "identity" for the PK node. The methods though can be renamed more appropriately.Note that symmetric key does not get rotated, doing so would require a new issue to address it as it requires encryption evolution in the DB.
KeyManager
After removing root key pair and removing the certificate duties. What's left for
KeyManager
.It is only to manage arbitrary sub "keys". These subkeys range from derived subkeys which could be asymmetric key pairs or symmetric keys, or they can be newly generated keypairs or keys. These keys can be used for any purpose by other domains.
This doesn't have a much usage right now. Only when we start to tackle secure computation will these become more useful. It is possible to then to generate keys for arbitrary signing, verification, encryption and decryption.
These keys unlike
KeyRing
is stored in the database. SoKeyManager
depends on the DB.Using this would mean that downstream domains that currently create a key like
vaultKey
orsessionKey
would instead depend on theKeyManager
to generate and manage these keys. This adds a bit of overhead to the domains relying on the creation of theKeyManager
instead of just having theDB
. But it can be useful once theKeyManager
has the ability to also manage rotations automatically or provide observables over these keys when they have TTLs.This new class would be low priority since we don't really need this kind of
KeyManager
until we start on secure computation.Additional context
NodeID
has changed. #386Tasks
The text was updated successfully, but these errors were encountered: