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

Fix recoveryCode, privateKey, privateKeyPath options usage in PolykeyAgentOptions #601

Merged
merged 4 commits into from
Oct 24, 2023

Conversation

addievo
Copy link
Contributor

@addievo addievo commented Oct 24, 2023

Description

This PR builds on #600 by implementing types that were added in the last PR, these include

    recoveryCode: string;
    privateKey: Buffer;
    privateKeyPath: string;

These types are a part of src/keys/KeyRing which is responsible for setting up the KeyRing, which is crucial in setting up the root key pair.

These types are implemented in keyRing as so:

 public async start(
    options: {
      password: string;
      fresh?: boolean;
    } & (
      | ObjectEmpty
      | { recoveryCode: RecoveryCode }
      | { privateKey: PrivateKey }
      | { privateKeyPath: string }
    ),
  ): Promise<void> {
    const { fresh = false, ...setupKeyPairOptions } = options;
    this.logger.info(`Starting ${this.constructor.name}`);
    if (fresh) {
      await this.fs.promises.rm(this.keysPath, {
        force: true,
        recursive: true,
      });
    }
    await this.fs.promises.mkdir(this.keysPath, { recursive: true });
    const [keyPair, recoveryCode] =
      await this.setupKeyPair(setupKeyPairOptions);
    const dbKey = await this.setupDbKey(keyPair);
    const [passwordHash, passwordSalt] = await this.setupPasswordHash(
      options.password,
    );
    bufferLock(keyPair.publicKey, this.strictMemoryLock);
    bufferLock(keyPair.privateKey, this.strictMemoryLock);
    bufferLock(keyPair.secretKey, this.strictMemoryLock);
    bufferLock(dbKey, this.strictMemoryLock);
    bufferLock(passwordHash, this.strictMemoryLock);
    bufferLock(passwordSalt, this.strictMemoryLock);
    this._keyPair = keyPair as KeyPairLocked;
    this._dbKey = dbKey;
    this.passwordHash = {
      hash: passwordHash,
      salt: passwordSalt,
    };
    if (recoveryCode != null) {
      const recoveryCodeData = Buffer.from(recoveryCode, 'utf-8');
      bufferLock(recoveryCodeData, this.strictMemoryLock);
      this._recoveryCodeData = recoveryCodeData as RecoveryCodeLocked;
    }
    this.logger.info(`Started ${this.constructor.name}`);
  }

In PolykeyAgent, the start function of KeyRing is called in the start function of PolykeyAgent.

Therefore, the further part of this PR is to pass the types in the start function of PolykeyAgent, which would be something like this:

 public async start({
    password,
    options = {},
    fresh = false,
  }: {
    password: string;
    options?: DeepPartial<{
      clientServiceHost: string;
      clientServicePort: number;
      agentServiceHost: string;
      agentServicePort: number;
      ipv6Only: boolean;
      workers: number;
      keys: {
        recoveryCode: string;
        privateKey: Buffer;
        privateKeyPath: string;
      }
    }>;
    workers?: number;
    fresh?: boolean;
  }) {
    const optionsDefaulted = utils.mergeObjects(options, {
      clientServiceHost: config.defaultsUser.clientServiceHost,
      clientServicePort: config.defaultsUser.clientServicePort,
      agentServiceHost: config.defaultsUser.agentServiceHost,
      agentServicePort: config.defaultsUser.agentServicePort,
      workers: config.defaultsUser.workers,
      ipv6Only: config.defaultsUser.ipv6Only,
    });
    ```
    
These are then called in when starting the keyRing, which would be something like this: 

```ts
      await this.keyRing.start({
        password,
        fresh,
        recoveryCode: optionsDefaulted.recoveryCode,
        privateKey: optionsDefaulted.privateKey,
        privateKeyPath: optionsDefaulted.privateKeyPath,
      });

Also, a thing to note here is that, recoverCode, privateKey and privateKeyPath can be independently supplied, which is ensured by:

    } & (
      | ObjectEmpty
      | { recoveryCode: RecoveryCode }
      | { privateKey: PrivateKey }
      | { privateKeyPath: string }
    ),

in KeyRing start.

Consequently, they are similarly implemented in PolykeyAgent types

type PolykeyAgentOptions = {
  nodePath: string;
  clientServiceHost: string;
  clientServicePort: number;
  agentServiceHost: string;
  agentServicePort: number;
  seedNodes: SeedNodes;
  workers: number;
  ipv6Only: boolean;
  keys: {
    passwordOpsLimit: PasswordOpsLimit;
    passwordMemLimit: PasswordMemLimit;
    strictMemoryLock: boolean;
    certDuration: number;
    certRenewLeadTime: number;
    recoveryCode: string;
    privateKey: Buffer;
    privateKeyPath: string;
  };
  client: {
    keepAliveTimeoutTime: number;
    keepAliveIntervalTime: number;
    rpcCallTimeoutTime: number;
    rpcParserBufferSize: number;
  };
  nodes: {
    connectionIdleTimeoutTime: number;
    connectionFindConcurrencyLimit: number;
    connectionConnectTimeoutTime: number;
    connectionKeepAliveTimeoutTime: number;
    connectionKeepAliveIntervalTime: number;
    connectionHolePunchIntervalTime: number;
    rpcCallTimeoutTime: number;
    rpcParserBufferSize: number;
  };
} & (
  | ObjectEmpty
  | { recoveryCode: RecoveryCode }
  | { privateKey: PrivateKey }
  | { privateKeyPath: string }
  );

Tasks

  • 1. Lintfix Adding privateKeyPath back to PolykeyAgent  #600
  • 2. Make privateKey type to Buffer from privateKey
  • 3. privateKey declared above privateKeyPath
  • 4. PolykeyAgent start requires the options privateKey and PrivateKeyPath to be specified.
  • 5. Also add recoveryCode to options and deep partial it into agent.start.

Final checklist

  • Domain specific tests
  • Full tests
  • Updated inline-comment documentation
  • Lint fixed
  • Squash and rebased
  • Sanity check the final build

@ghost
Copy link

ghost commented Oct 24, 2023

👇 Click on the image for a new way to code review

Review these changes using an interactive CodeSee Map

Legend

CodeSee Map legend

@CMCDragonkai CMCDragonkai changed the title Implementing privateKey in KeyRing Fix recoveryCode, privateKey, privateKeyPath options usage in PolykeyAgentOptions Oct 24, 2023
@addievo addievo self-assigned this Oct 24, 2023
@tegefaulkes
Copy link
Contributor

Re-based and applied final fixes.

@tegefaulkes tegefaulkes merged commit b15bdac into staging Oct 24, 2023
1 check passed
@CMCDragonkai
Copy link
Member

Should have squashed beforehand, @addievo committed an incorrect commit format.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants