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

Password decrypt the --root-key-file #433

Closed
CMCDragonkai opened this issue Jul 29, 2022 · 9 comments · Fixed by #446
Closed

Password decrypt the --root-key-file #433

CMCDragonkai opened this issue Jul 29, 2022 · 9 comments · Fixed by #446
Assignees
Labels
development Standard development r&d:polykey:core activity 2 Cross Platform Cryptography for JavaScript Platforms

Comments

@CMCDragonkai
Copy link
Member

CMCDragonkai commented Jul 29, 2022

Specification

The --root-key-file or PK_ROOT_KEY may be password encrypted. The agent start and bootstrap commands should check if the PEM is encrypted, and decrypt it with the --password. This means the same --password is used to decrypt (if encrypted) and to encrypt the root key.

This is important in case the root key is loaded from another PK node path. Or just generated in some other way.

Additional context

Tasks

  1. Check if PEM is encrypted
  2. Use password (which has to be have been supplied already), as it is mandatory option
  3. Remember if recovery code is supplied instead, then it should be ignored
  4. Document in this issue the precedence of root key file, recovery code, loading from disk, and generating a new root key from scratch
@CMCDragonkai CMCDragonkai added the development Standard development label Jul 29, 2022
@CMCDragonkai
Copy link
Member Author

@tegefaulkes this has been created now.

@CMCDragonkai
Copy link
Member Author

CMCDragonkai commented Aug 5, 2022

The privateKeyPemOverride parameter should be changed.

  static async createKeyManager({
    keysPath,
    password,
    rootKeyPairBits = 4096,
    rootCertDuration = 31536000,
    dbKeyBits = 256,
    changeCallback = () => {},
    fs = require('fs'),
    logger = new Logger(this.name),
    recoveryCode,
    privateKeyPemOverride,
    fresh = false,
  }

It should be similar to recoveryCode but I believe it probably invalidates parameters like rootKeyPairBits. And it should use the same name like rootPrivateKey. If supplied it needs to ignore recoveryCode and rootKeyPairBits. We could enforce this by creating multiple independent types.

During our crypto swap over, I'd want to make it so that domains don't rely on the existence of KeyManager, but instead facilitated with callbacks/hooks for anything, and that can be connected via the eventbus.

@CMCDragonkai
Copy link
Member Author

The root key file is assumed to be a PEM, but with the new crypto update, we are going to be using JWKs mostly. We may expect the root key to be in JWK format or in PCKS#8 format.

I think for now, we will only support JWK format.

@CMCDragonkai
Copy link
Member Author

Note that our webcrypto polyfill can load pkcs#8 format too, so we can support whatever format that webcrypto can import from. We could also use JOSE too.

@CMCDragonkai
Copy link
Member Author

Encrypted JWK would be using the PBES2... algorithm.

@CMCDragonkai
Copy link
Member Author

So by dropping node forge, we end up dropping support for PKCS#8 and SPKI mostly. We won't really be dealing with those formats anymore.

Even @peculiar/x509 and @peculiar/PKI doesn't really have all the support necessary. And we are only using @peculiar/x509.

@CMCDragonkai
Copy link
Member Author

The KeyRing now takes a recovery code or an existing private key.

All the utilities to deal with this are now in keys/utils. So it's expected to use the PrivateKey type.

This means any loading/decrypting of the private key must be done on the outside of KeyRing. It doesn't do anything fancy by itself.

There are a number of ways to acquire a hardcoded private key. In particular keysUtils.unwrapWithPassword, can now decrypt a password-encrypted JWE.

That will be the only one we would support for now.

@CMCDragonkai CMCDragonkai self-assigned this Oct 5, 2022
@CMCDragonkai
Copy link
Member Author

We can incorporate this into the KeyRing. However it current decides what to do based on whether the recovery code is set or the private key is set, and this is dependent on the input type.

Then if the private key is set, but it's a string, and not a Buffer or BufferSource, then it will need to load from disk.

Then if we load from disk, we have decide what format we expect it to be. The only format we would expect is an encrypted JWE or a JWK.

Furthermore a password is then expected to be used for decryption here. We can reuse the password for this.

To decrypt JWE however, we then have to use JOSE for this, and this means using the webcrypto interface, because there are so many different JWE and different ways of decrypting them. We may limit these algorithms specifically to our own version of JWE (ECDH-ES-NaCl or whatever symmetric one we are using with libsodium), so that way we don't need to have the full webcrypto support.

Ultimately the usecase here is primarily for debugging/testing, so that we can launch PK with a specific private key instead of using a recovery code. It could be useful if someone has the private key and password, but lost the recovery code.

Our tests are unlikely to be using this now. So let's just do the simplest thing.

Expect to use keysUtils.unwrapWithPassword. I'm not sure what we expect our custom alg to be. But it won't be PBES2-HS512+A256KW. It would use PBES-NaCl+XChaCha20-Poly1305. Probably make it so that case doesn't matter here.

@CMCDragonkai
Copy link
Member Author

This is now implemented in #446. However we are not taking a password pem encryption. We are using our own JWE algorithm.

@CMCDragonkai CMCDragonkai added the r&d:polykey:core activity 2 Cross Platform Cryptography for JavaScript Platforms label Jul 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
development Standard development r&d:polykey:core activity 2 Cross Platform Cryptography for JavaScript Platforms
Development

Successfully merging a pull request may close this issue.

1 participant