import { AESCipherSIVDeterministic } from '../../base/cipher/aes';
import { AbstractSelfAccountKeyring } from '../../keyring/account_base';
import { AccountMasterDeriveKeyV1 } from '../common';
import { AbstractAccountTrustConfig } from './common';
import { makeInfoByteArray } from '../../utility';

/**
 * The trust of the account builds on chained signatures of root trusts (by upgrades) and signatures of other keys.
    Account root key fingerprint: HKDF generated "fingerprint" by the peer's root as info encrypted with AES-SIV
    If the fingerprint is not salted with a secret of the account, then any attacker has the opportunity to try to do
    a known-plaintext-attack. This is prevented by the KDF, even though it would not give any practical advantage to
    an attacker as the AES-SIV RFC states in Section 7 (paraphrased): "even if the attacker knows the plaintext, they
    will be unable to construct a string of bits that will return anything other than FAIL". What this actually means
    is that the attacker could not discover the secret key.
 */
export class AccountTrustConfigV2 extends AbstractAccountTrustConfig {
  constructor(never_dump = false) {
    super(2, never_dump);
  }

  protected _decrypt(cipher: Uint8Array, key: Uint8Array): Promise<Uint8Array> {
    return AESCipherSIVDeterministic.decrypt(cipher.slice(this.version.byteLength), key);
  }

  protected _encrypt(plain: Uint8Array, key: Uint8Array): Promise<Uint8Array> {
    return AESCipherSIVDeterministic.encrypt(plain, key, undefined, this.version);
  }

  protected _get_fingerprint(
    peer_id: Uint8Array,
    peer_root_key: Uint8Array,
    self_kr: AbstractSelfAccountKeyring
  ): Promise<Uint8Array> {
    // NOTE: Could use HMAC for output, but even for that a HKDF would need to be called for a secret key...
    //       unless we agree to use the master key directly.
    return AccountMasterDeriveKeyV1.derive_key(
      self_kr,
      makeInfoByteArray(['explicit-peer-trust-', peer_id, '-', peer_root_key]),
      false, // these are not created or checked frequently
      19 // have more than 1 block worth of data to encrypt
    );
  }
}
