Skip to content
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

Refactor KeyManager #204

Merged
merged 2 commits into from
May 16, 2024
Merged

Refactor KeyManager #204

merged 2 commits into from
May 16, 2024

Conversation

diehuxx
Copy link
Contributor

@diehuxx diehuxx commented May 13, 2024

Partially addresses #158

Context

The KeyManager and KeyStore traits are fuzzy abstractions -- the conceptual boundary between a "store" and a "manager" is not clear to me. KeyManager currently seems to be a wrapper around KeyStore with little-to-no added functionality. Also, the traits themselves have methods export_private_keys() and import_private_keys() which ought not to be coupled to the notion of "management" which entails storing private keys, signing, and getting public keys. See #158 for more.

Design

  1. Remove the KeyStore trait entirely. Move logic from struct InMemoryKeyStore into LocalKeyManager.
  2. Pare down KeyManager to just three methods: generate_private_key(), sign(), and get_public_key().
  3. Add trait KeyImporter with one required method import_with_alias() and one provided method import() which generates its own alias.

This PR does NOT add the KeyExporter trait described in #158 because I do not see an immediate use case in web5-rs. Exporting private keys is risky stuff. Until we have a clear need for a standard interface for exporting, we ought to omit it.

Open questions

  1. What is the purpose of the .alias() method in the Key trait? Is it a unique digest? Whatever it is, we should probably rename the method.
  2. What is the expected behavior of KeyImporter when a key alias is overwritten with a new private key? Should that be an error? Is it up to each individual impl of KeyImporter? I lean towards the former.

@@ -31,41 +38,81 @@ impl KeyManager for LocalKeyManager {
curve: Curve,
key_alias: Option<String>,
) -> Result<String, KeyManagerError> {
let key_alias = self.key_store.generate_new(curve, key_alias)?;
let private_key = Arc::new(match curve {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI #205 (not necessary for this PR, just raising awareness)

#[error(transparent)]
KeyStoreError(#[from] KeyStoreError),
#[error("{0}")]
InternalKeyStoreError(String),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thoughts?

Suggested change
InternalKeyStoreError(String),
KeyStoreError(String),

Comment on lines +58 to +61
fn import(&self, private_key: Arc<dyn PrivateKey>) -> Result<String, KeyManagerError> {
let key_alias = private_key.alias()?;
self.import_with_alias(private_key, &key_alias)?;
Ok(key_alias)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is clever 👏

@KendallWeihe
Copy link
Contributor

Alright a handful of things...

  • This is amazing work. I've ✅'d but I propose we let it sit for a couple days at least to give people time to chime in if they choose.
  • I respect taking the discretion to remove the KeyStore and I approve. We have a guiding principal here in rust core to "prefer modularity over convenience" but in this case, we don't have a concrete use case (that we can even think of) where decoupling the abstractions is necessary, so yeah I think it's wise to remove.
  • I appreciate the named functions import_with_alias and import rather than using a single function with Option param. I think this is the ideal pattern here in our rust initiative -- it's slightly more verbose than what we're accustomed to with other languages, but it'll pay dividends IMO as we start bindings things.
  • 💯 on not implementing the KeyExporter trait. I think what I'll probably do is eventually close Move import & export functions to new trait called UnsafeKeyManager #158 and create a new ticket for the export functionality, which hopefully just sits there forever. I'll handle that.

What is the purpose of the .alias() method in the Key trait? Is it a unique digest? Whatever it is, we should probably rename the method.

It's a good point... the way I think about it is, the key alias is akin to a primary key in a db, so it's self referential with respect to a key. It's slightly confusing though because we enable callers of key manager methods to override the key alias, so it's a matter which is conceptualized at the key manager level, but at the same time we implement the alias for the Jwk which is the thumbprint. 🤔 created #206

What is the expected behavior of KeyImporter when a key alias is overwritten with a new private key? Should that be an error? Is it up to each individual impl of KeyImporter? I lean towards the former.

Yeah that should be an error. So the requirement is: key's cannot be imported which have a key alias which pre-exist in the key manager. Created #207 @diehuxx feel free to go ahead and do that here or not and we can follow up, your call.

@mistermoe
Copy link

How is a portable did created without a key exporter?

@KendallWeihe
Copy link
Contributor

KendallWeihe commented May 15, 2024

How is a portable did created without a key exporter?

It can't. But, TBD. This is a hot topic, so perhaps I'll open a ticket to discuss the full merits. I know this has been discussed at length a while back, but it's appropriate to take a bit of time to reopen the matter with the rust initiative.

@KendallWeihe
Copy link
Contributor

Added #211, we can close #158 upon merging this PR

@KendallWeihe KendallWeihe merged commit 807067e into main May 16, 2024
6 checks passed
@KendallWeihe KendallWeihe deleted the key-importer branch May 16, 2024 00:41
diehuxx pushed a commit that referenced this pull request May 21, 2024
* main:
  implement vc verification (#182)
  Remove unused credentials/tests, rename vc.rs to verifiable_credential.rs (#214)
  Refactor KeyManager (#204)
  Rename 'method' module to 'methods' (plural) (#210)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants