import { AESCipherSIVDeterministic } from '../../base/cipher/aes';
import { HKDFKeyGeneratorV1 } from '../../base/key/kdf';
import { AbstractPrivateKeyring } from '../../keyring/private';
import { AbstractCryptoConfig } from '../base';
import { PrivateKeyConfigDumpArgs, PrivateKeyConfigLoadArgs } from './args';
import { concatByteArray, makeInfoByteArray } from '../../utility';

/**
 * Private key encryption: AES-SIV
        KEY: 32B from private keyring -> 64B HKDF by context
        NONCE: none

    This is used for encrypting the master key(s) of the account.
 */
export class PrivateKeyConfigV1 extends AbstractCryptoConfig<
  PrivateKeyConfigLoadArgs,
  PrivateKeyConfigDumpArgs
> {
  constructor(never_dump: boolean = false) {
    super(1, never_dump);
  }

  public load(args: PrivateKeyConfigLoadArgs): Promise<Uint8Array> {
    return this.derive_key(args.private_kr, args.key_version).then((derive_key) => {
      return AESCipherSIVDeterministic.decrypt(
        args.cipher.slice(this.version.byteLength),
        derive_key
      );
    });
  }

  public dump(args: PrivateKeyConfigDumpArgs): Promise<Uint8Array> {
    return this.derive_key(args.private_kr, args.key_version).then((derive_key) => {
      return AESCipherSIVDeterministic.encrypt(
        args.self_kr.get_secret_key(args.key_version),
        derive_key,
        undefined,
        this.version
      );
    });
  }

  // no cache, this instance is temporary
  public derive_key(private_kr: AbstractPrivateKeyring, key_version: string): Promise<Uint8Array> {
    return HKDFKeyGeneratorV1.new_key(
      64,
      private_kr.enc_key,
      concatByteArray(HKDFKeyGeneratorV1.SALTS[0], HKDFKeyGeneratorV1.SALTS[1]),
      makeInfoByteArray(['private-key-', this.version, '-', key_version])
    );
  }
}
