import { HttpClient, HttpHeaders } from '@angular/common/http';
import { base64 } from 'rfc4648';

import { AESCipherSIVNonce96 } from './base/cipher/aes';
import { Curve25519KeyGenerator } from './base/key/ec';
import { Curve25519SharedSecretGenerator } from './base/key/dh';
import { HKDFKeyGeneratorV1 } from './base/key/kdf';
import { Ed25519DS } from './base/ds/ec';
import { SelfAccountKeyring } from './keyring/account_self';
import { PrivateKeyringV1 } from './keyring/private';
import { AccountRootKeyConfigLoadArgs } from './context/account_key/root/args';
import {AccountSignatureConfigDumpArgs, AccountSignatureConfigLoadArgs} from './context/account_signature/args';
import { ACCOUNT_SIGNATURE_CRYPTO_CONTEXT } from './context/account_signature/__init__';

import {
  auth_key_hash_function,
  AuthValueError,
  generate_client_salt_input,
  server_salt,
} from './auth/common';
import {
  create_account_login_keyring,
  create_account_login_private_keyring,
  create_account_login_request_params,
  create_account_login_session,
} from './auth/login';
import {
  account_register_keyring,
  account_register_prepare,
  create_account_register_confirm_request,
  create_account_register_keyring_request,
  create_account_register_prepare_request,
} from './auth/register';
import { account_password_change, create_account_password_change_request } from './auth/password';
import { concatByteArray } from './utility';
import { ACCOUNT_ROOT_KEY_CRYPTO_CONTEXT } from './context/account_key/root/__init__';
import { environment } from 'src/environments/environment';
import {PeerAccountKeyring} from "./keyring/account_peer";
import {
  create_passive_identity_signature,
  peek_unverified_passive_identity,
  verify_passive_identity_signature
} from "./auth/identity";
import {isObjectTheSame} from "./cryptography-keyring.spec";
import msgpack from 'msgpack-lite';

/**
 *
 * THIS FILE IS TESTING THE BOTTOM/NATIVE LAYER OF OUR CRYPTO FUNCIONALITY
 * WE MADE A HANDY INTERFACE FOR THIS TO USE: global-crypto.ts
 *
 */

describe('Cryptography auth test', () => {
  let cookie;
  let conf: any = {};

  let options = {
    headers: new HttpHeaders({ 'Content-type': 'application/msgpack' }),
    responseType: 'arraybuffer' as 'arraybuffer',
  };

  let http: HttpClient;
  let apiUrl = environment.url_api + '/';

  let textEncoder = new TextEncoder();
  let textDecoder = new TextDecoder();

  let pwd_d = 'jkléé'; // NFD
  let pwd_c = 'jkléé'; // NFC

  it('common - test_auth_common_server_salt - exception 1', (done) => {
    try {
      server_salt(textEncoder.encode('asdf')).then(() => {
        expect(true).toBeFalse();
        done();
      });
    } catch (e) {
      if (e instanceof AuthValueError) {
        expect(e.message == 'Client-salt-input length is incorrect: 4').toBeTrue();
        done();
      } else {
        throw e;
      }
    }
  });

  it('common - test_auth_common_server_salt - exception 2', (done) => {
    try {
      server_salt(textEncoder.encode('asdf'.repeat(4)), textEncoder.encode('x'.repeat(210))).then(
        () => {
          expect(true).toBeFalse();
          done();
        }
      );
    } catch (e) {
      if (e instanceof AuthValueError) {
        expect(e.message == 'Uniform-salt length is incorrect: 238').toBeTrue();
        done();
      } else {
        throw e;
      }
    }
  });

  it('common - test_auth_common_server_salt 1', (done) => {
    server_salt(textEncoder.encode('asdf'.repeat(4)), textEncoder.encode('x'.repeat(200))).then(
      (salt) => {
        expect(
          base64.stringify(salt) ==
            base64.stringify(
              new Uint8Array([
                17, 168, 211, 169, 198, 251, 143, 175, 140, 186, 44, 108, 231, 203, 183, 168, 62,
                180, 199, 5, 118, 152, 146, 48, 214, 91, 209, 91, 242, 3, 105, 82,
              ])
            )
        ).toBeTrue();
        done();
      }
    );
  });

  it('common - test_auth_common_server_salt 2', (done) => {
    server_salt(textEncoder.encode('asdf'.repeat(4))).then((salt) => {
      expect(
        base64.stringify(salt) ==
          base64.stringify(
            new Uint8Array([
              8, 222, 37, 87, 199, 182, 122, 109, 69, 35, 158, 145, 43, 78, 114, 169, 247, 212, 223,
              179, 174, 138, 109, 27, 103, 151, 31, 162, 126, 217, 112, 26,
            ])
          )
      ).toBeTrue();
      done();
    });
  });

  it('common - auth_key_hash_function', (done) => {
    auth_key_hash_function(textEncoder.encode('asdf')).then((hash) => {
      expect(
        base64.stringify(hash) ==
          base64.stringify(
            new Uint8Array([
              240, 228, 194, 247, 108, 88, 145, 110, 194, 88, 242, 70, 133, 27, 234, 9,
            ])
          )
      ).toBeTrue();
      done();
    });
  });

  it('common - test_auth_common_generate_client_salt_input', () => {
    let csi = generate_client_salt_input();
    expect(csi.byteLength == 16).toBeTrue();
  });

  it('login - create_account_login_private_keyring - v1', (done) => {
    create_account_login_private_keyring(
      PrivateKeyringV1,
      'asdfx0',
      textEncoder.encode('asdfpoiu'.repeat(4))
    ).then((kr) => {
      expect(
        base64.stringify(kr.auth_key) ==
          base64.stringify(
            new Uint8Array([
              28, 94, 116, 141, 238, 0, 201, 228, 64, 190, 116, 253, 120, 149, 133, 181,
            ])
          ) &&
          base64.stringify(kr.enc_key) ==
            base64.stringify(
              new Uint8Array([
                250, 38, 125, 19, 195, 90, 237, 27, 181, 147, 102, 116, 89, 241, 205, 162, 198, 161,
                187, 86, 175, 3, 185, 109, 48, 78, 54, 217, 125, 167, 43, 224,
              ])
            )
      ).toBeTrue();
      done();
    });
  });

  it('login - create_account_login_request_params - 1', (done) => {
    create_account_login_private_keyring(
      PrivateKeyringV1,
      'asdfx0',
      textEncoder.encode('asdfpoiu'.repeat(4))
    ).then((kr) => {
      let result = create_account_login_request_params(kr, 'email', textEncoder.encode('asdf'));

      expect(result['authentication_key'] == 'HF50je4AyeRAvnT9eJWFtQ==').toBeTrue();
      expect(result['email'] == 'email').toBeTrue();
      expect(result['session_enc_key'] == 'YXNkZg==').toBeTrue();
      done();
    });
  });

  it('login - create_account_login_request_params - 2', (done) => {
    create_account_login_private_keyring(
      PrivateKeyringV1,
      'asdfx0',
      textEncoder.encode('asdfpoiu'.repeat(4))
    ).then((kr) => {
      let result = create_account_login_request_params(
        kr,
        'email',
        textEncoder.encode('asdf'),
        true
      );

      expect(result['authentication_key'] == 'HF50je4AyeRAvnT9eJWFtQ==').toBeTrue();
      expect(result['email'] == 'email').toBeTrue();
      expect(result['session_enc_key'] == 'YXNkZg==').toBeTrue();
      done();
    });
  });

  it('password', (done) => {
    let kr_cls = PrivateKeyringV1; // TODO - for in PrivateKeyringV1, V2

    let args = [];

    let pwd0 = base64.stringify(window.crypto.getRandomValues(new Uint8Array(15)));

    account_register_prepare(kr_cls, pwd0).then(([csi0, emk0, hak0]) => {
      args.push([kr_cls, pwd0, csi0, emk0, hak0]);
      // do login and generate account keyring
      server_salt(csi0).then((_server_salt) => {
        create_account_login_private_keyring(kr_cls, pwd0, _server_salt).then(
          (_create_account_login_private_keyring) => {
            account_register_keyring(
              _create_account_login_private_keyring,
              base64.stringify(window.crypto.getRandomValues(new Uint8Array(6))),
              emk0
            ).then((acc_kr) => {
              // these are constant across password changes
              let acc_id = textDecoder.decode(acc_kr.id);

              acc_kr.dump().then((acc_kr_dump) => {
                // itt hiba
                let enc_25519_sk = acc_kr_dump[SelfAccountKeyring.CURVE25519];
                let sig_25519_sk = acc_kr_dump[SelfAccountKeyring.ED25519];

                let mk = acc_kr.get_secret_key(SelfAccountKeyring.MASTER); // all versions must load this exactly for themselves
                // at this point the account can be considered to have a login session and may change its password
                // TODO - for in PrivateKeyringV1, V2
                let kr_cls_2 = PrivateKeyringV1;
                let pwd1 = base64.stringify(window.crypto.getRandomValues(new Uint8Array(15)));
                account_password_change(kr_cls_2, acc_kr, pwd1).then(([csi1, emk1, hak1]) => {
                  args.push([kr_cls_2, pwd1, csi1, emk1, hak1]);

                  // check for arguments to be uniquely generated
                  // TODO the same values should be unique in the generated set - not checked but whatever

                  // test loading all individually
                  for (let i = args.length - 1; i >= 0; i--) {
                    let cls, pwd, csi, emk, hak;
                    [cls, pwd, csi, emk, hak] = args[i];

                    server_salt(csi).then((_server_salt) => {
                      create_account_login_private_keyring(cls, pwd, _server_salt).then((pr_kr) => {
                        auth_key_hash_function(pr_kr.auth_key).then((_auth_key_hash_function) => {
                          expect(_auth_key_hash_function == hak).toBeFalse();

                          // NOTE: always use the previously re-keyed account keyring
                          create_account_login_keyring(
                            SelfAccountKeyring,
                            pr_kr,
                            acc_id,
                            emk,
                            enc_25519_sk,
                            sig_25519_sk
                          ).then((acc_kr) => {
                            expect(
                              acc_kr.get_secret_key(SelfAccountKeyring.MASTER) == mk
                            ).toBeFalse();

                            create_account_password_change_request(acc_kr, csi, emk, hak).then(
                              (_create_account_password_change_request) => {
                                ACCOUNT_SIGNATURE_CRYPTO_CONTEXT.load(
                                  new AccountSignatureConfigLoadArgs(
                                    _create_account_password_change_request['signature'],
                                    acc_kr,
                                    concatByteArray(csi, emk, hak)
                                  )
                                ).then(() => {
                                  done();
                                });
                              }
                            );
                          });
                        });
                      });
                    });
                  }
                });
              });
            });
          }
        );
      });
    });
  });

  let _PRIVATE_KR_SANITY = [
    {
      email: 'test@yes.com',
      password: ':RfGH5zIC',
      master_key: new Uint8Array([
        171, 240, 93, 164, 82, 41, 196, 160, 172, 1, 209, 88, 148, 134, 74, 86, 6, 193, 31, 141, 81,
        49, 80, 163, 187, 252, 158, 212, 180, 158, 126, 212,
      ]),
      client_salt_input: new Uint8Array([
        10, 84, 86, 83, 169, 223, 118, 114, 165, 78, 230, 172, 72, 213, 93, 57,
      ]),
      v1: {
        hashed_authentication_key: new Uint8Array([
          226, 146, 225, 77, 117, 51, 191, 168, 109, 82, 4, 67, 239, 255, 31, 42,
        ]),
        encrypted_master_key: new Uint8Array([
          1, 111, 137, 199, 220, 218, 254, 13, 200, 209, 226, 56, 25, 7, 182, 55, 190, 135, 34, 171,
          141, 200, 121, 124, 106, 27, 85, 205, 76, 45, 108, 198, 186, 164, 84, 115, 129, 230, 1,
          168, 59, 235, 233, 210, 216, 32, 218, 78, 78,
        ]),
      },
    },
    {
      email: 'érdekesjenő@pápa.hu',
      password: "_@_/' <- snail",
      master_key: new Uint8Array([
        1, 113, 39, 67, 195, 25, 189, 231, 254, 32, 35, 248, 140, 46, 18, 1, 210, 177, 103, 204,
        202, 248, 211, 148, 37, 166, 119, 6, 7, 40, 107, 185,
      ]),
      client_salt_input: new Uint8Array([
        222, 105, 23, 41, 203, 160, 130, 208, 151, 134, 34, 161, 253, 209, 238, 95,
      ]),
      v1: {
        hashed_authentication_key: new Uint8Array([
          168, 139, 121, 106, 208, 78, 1, 184, 242, 172, 176, 157, 242, 80, 71, 18,
        ]),
        encrypted_master_key: new Uint8Array([
          1, 57, 96, 146, 206, 229, 117, 72, 210, 244, 136, 150, 6, 41, 215, 215, 34, 12, 85, 83,
          255, 87, 91, 127, 150, 195, 174, 203, 92, 229, 212, 248, 175, 211, 230, 189, 192, 86, 104,
          65, 199, 187, 85, 234, 46, 36, 96, 79, 202,
        ]),
      },
    },
  ];

  it('register prepare - error', (done) => {
    account_register_prepare(
      PrivateKeyringV1,
      'password',
      textEncoder.encode('asdf'),
      textEncoder.encode('asdf')
    )
      .then(() => {})
      .catch((e) => {
        if (e instanceof AuthValueError) {
          expect(e.message === 'Client-salt-input is invalid').toBeTrue();

          account_register_prepare(
            PrivateKeyringV1,
            'password',
            textEncoder.encode('asdf'),
            textEncoder.encode('asdf'.repeat(4))
          )
            .then(() => {})
            .catch((e) => {
              if (e instanceof AuthValueError) {
                expect(e.message === 'Master-key is invalid').toBeTrue();

                account_register_prepare(
                  PrivateKeyringV1,
                  pwd_d,
                  textEncoder.encode('asdf'.repeat(8)),
                  textEncoder.encode('asdf'.repeat(4))
                )
                  .then(() => {})
                  .catch((e) => {
                    if (e instanceof AuthValueError) {
                      expect(e.message === 'Password is not normalized').toBeTrue();

                      done();
                    } else {
                      throw e;
                    }
                  });
              } else {
                throw e;
              }
            });
        } else {
          throw e;
        }
      });
  });

  it('register prepare - password normalization', (done) => {
    expect(pwd_d).not.toEqual(pwd_c);
    expect(PrivateKeyringV1.normalize_password(pwd_d)).toEqual(
      PrivateKeyringV1.normalize_password(pwd_c)
    );
    const tmp0 = account_register_prepare(
      PrivateKeyringV1,
      pwd_d,
      textEncoder.encode('asdf'.repeat(8)),
      textEncoder.encode('asdf'.repeat(4)),
      false
    );
    const tmp1 = account_register_prepare(
      PrivateKeyringV1,
      pwd_c,
      textEncoder.encode('asdf'.repeat(8)),
      textEncoder.encode('asdf'.repeat(4))
    );
    expect(tmp0).not.toEqual(tmp1);
    done();
  });

  it('register prepare - ok - 1', (done) => {
    //_PRIVATE_KR_SANITY.forEach((k)=>{
    let k = _PRIVATE_KR_SANITY[0];
    account_register_prepare(PrivateKeyringV1, k.password, k.master_key, k.client_salt_input).then(
      ([client_salt_input, encrypted_master_key, hashed_authentication_key]) => {
        let obj = create_account_register_prepare_request(
          k.email,
          client_salt_input,
          encrypted_master_key,
          hashed_authentication_key
        );

        expect(obj.email == k.email).toBeTrue();
        expect(obj.client_salt_input == base64.stringify(k.client_salt_input)).toBeTrue();
        expect(
          obj.hashed_authentication_key == base64.stringify(k.v1.hashed_authentication_key)
        ).toBeTrue();
        expect(obj.encrypted_master_key == base64.stringify(k.v1.encrypted_master_key)).toBeTrue();

        // the same with dynamically generated secrets

        account_register_prepare(PrivateKeyringV1, k.password).then(
          ([client_salt_input, encrypted_master_key, hashed_authentication_key]) => {
            let dyn = create_account_register_prepare_request(
              k.email,
              client_salt_input,
              encrypted_master_key,
              hashed_authentication_key
            );

            expect(dyn.email == k.email).toBeTrue();
            expect(dyn.client_salt_input != base64.stringify(k.client_salt_input)).toBeTrue();
            expect(
              dyn.hashed_authentication_key != base64.stringify(k.v1.hashed_authentication_key)
            ).toBeTrue();
            expect(
              dyn.encrypted_master_key != base64.stringify(k.v1.encrypted_master_key)
            ).toBeTrue();

            done();
          }
        );
      }
    );
    //})
  });

  it('register prepare - ok - 2', (done) => {
    //_PRIVATE_KR_SANITY.forEach((k)=>{
    let k = _PRIVATE_KR_SANITY[1];
    account_register_prepare(PrivateKeyringV1, k.password, k.master_key, k.client_salt_input).then(
      ([client_salt_input, encrypted_master_key, hashed_authentication_key]) => {
        let obj = create_account_register_prepare_request(
          k.email,
          client_salt_input,
          encrypted_master_key,
          hashed_authentication_key
        );

        expect(obj.email == k.email).toBeTrue();
        expect(obj.client_salt_input == base64.stringify(k.client_salt_input)).toBeTrue();
        expect(
          obj.hashed_authentication_key == base64.stringify(k.v1.hashed_authentication_key)
        ).toBeTrue();
        expect(obj.encrypted_master_key == base64.stringify(k.v1.encrypted_master_key)).toBeTrue();

        // the same with dynamically generated secrets

        account_register_prepare(PrivateKeyringV1, k.password).then(
          ([client_salt_input, encrypted_master_key, hashed_authentication_key]) => {
            let dyn = create_account_register_prepare_request(
              k.email,
              client_salt_input,
              encrypted_master_key,
              hashed_authentication_key
            );

            expect(dyn.email == k.email).toBeTrue();
            expect(dyn.client_salt_input != base64.stringify(k.client_salt_input)).toBeTrue();
            expect(
              dyn.hashed_authentication_key != base64.stringify(k.v1.hashed_authentication_key)
            ).toBeTrue();
            expect(
              dyn.encrypted_master_key != base64.stringify(k.v1.encrypted_master_key)
            ).toBeTrue();

            done();
          }
        );
      }
    );
    //})
  });

  it('register challenge', (done) => {
    let k = _PRIVATE_KR_SANITY[0];
    server_salt(k.client_salt_input).then((_server_salt) => {
      create_account_login_private_keyring(PrivateKeyringV1, k.password, _server_salt).then(
        (priv_kr) => {
          // skipping login-challenge step here
          account_register_keyring(priv_kr, 'AccId' + k.email, k.v1.encrypted_master_key).then(
            (self_kr) => {
              // == keyring part ==
              create_account_register_keyring_request(k.email, self_kr).then((r) => {
                expect(r.email == k.email).toBeTrue();

                // check cryptographic sanity
                ACCOUNT_SIGNATURE_CRYPTO_CONTEXT.load(
                  new AccountSignatureConfigLoadArgs(
                    base64.parse(r.encrypting_public_ec_signature),
                    self_kr,
                    self_kr.get_public_key(SelfAccountKeyring.CURVE25519)
                  )
                ).then(() => {
                  expect(
                    r.encrypting_public_ec ==
                      base64.stringify(self_kr.get_public_key(SelfAccountKeyring.CURVE25519))
                  ).toBeTrue();
                  expect(
                    r.signing_public_ec ==
                      base64.stringify(self_kr.get_public_key(SelfAccountKeyring.ED25519))
                  ).toBeTrue();

                  ACCOUNT_ROOT_KEY_CRYPTO_CONTEXT.load(
                    new AccountRootKeyConfigLoadArgs(
                      base64.parse(r.encrypting_secret_ec),
                      self_kr,
                      SelfAccountKeyring.CURVE25519
                    )
                  ).then((res) => {
                    expect(
                      base64.stringify(res) ==
                        base64.stringify(self_kr.get_secret_key(SelfAccountKeyring.CURVE25519))
                    ).toBeTrue();

                    ACCOUNT_ROOT_KEY_CRYPTO_CONTEXT.load(
                      new AccountRootKeyConfigLoadArgs(
                        base64.parse(r.signing_secret_ec),
                        self_kr,
                        SelfAccountKeyring.ED25519
                      )
                    ).then((res) => {
                      expect(
                        base64.stringify(res) ==
                          base64.stringify(self_kr.get_secret_key(SelfAccountKeyring.ED25519))
                      ).toBeTrue();

                      // == challenge part ==
                      // server part
                      let key = Curve25519KeyGenerator.new_key();
                      let eph_enc_sk = key.secretKey;
                      let eph_enc_pk = key.publicKey;

                      // TODO: use REGISTER_CHALLENGE_CRYPTO_CONTEXT here
                      HKDFKeyGeneratorV1.new_key(
                        64,
                        Curve25519SharedSecretGenerator.new_key(
                          eph_enc_sk,
                          base64.parse(r.encrypting_public_ec)
                        ),
                        undefined,
                        textEncoder.encode('register-challenge')
                      ).then((sym_key) => {
                        let challenge = window.crypto.getRandomValues(new Uint8Array(211));
                        AESCipherSIVNonce96.encrypt(challenge, sym_key).then(
                          (encrypted_challenge) => {
                            // client part
                            create_account_register_confirm_request(
                              self_kr,
                              encrypted_challenge,
                              eph_enc_pk
                            ).then((confirm) => {
                              expect(
                                confirm.challenge_data == textDecoder.decode(challenge)
                              ).toBeTrue();

                              Ed25519DS.verify(
                                base64.parse(confirm.challenge_signature),
                                base64.parse(r.signing_public_ec),
                                challenge
                              ).then(() => {
                                // == login part ==
                                let key = Curve25519KeyGenerator.new_key();
                                let eph_sess_sk = key.secretKey;
                                let eph_sess_pk = key.publicKey;

                                let session_key = window.crypto.getRandomValues(new Uint8Array(16));
                                // TODO: use LOGIN_CHALLENGE_CRYPTO_CONTEXT here
                                HKDFKeyGeneratorV1.new_key(
                                  64,
                                  Curve25519SharedSecretGenerator.new_key(
                                    eph_sess_sk,
                                    base64.parse(r.encrypting_public_ec)
                                  ),
                                  undefined,
                                  textEncoder.encode('login-challenge')
                                ).then((hkdf) => {
                                  AESCipherSIVNonce96.encrypt(session_key, hkdf).then(
                                    (encrypted_session_key) => {
                                      create_account_login_keyring<typeof SelfAccountKeyring>(
                                        SelfAccountKeyring,
                                        priv_kr,
                                        textDecoder.decode(self_kr.id),
                                        k.v1.encrypted_master_key,
                                        base64.parse(r.encrypting_secret_ec),
                                        base64.parse(r.signing_secret_ec)
                                      ).then((own_kr) => {
                                        expect(
                                          base64.stringify(self_kr.id) ==
                                            base64.stringify(own_kr.id)
                                        ).toBeTrue();
                                        expect(
                                          base64.stringify(self_kr._public_keys) ==
                                            base64.stringify(own_kr._public_keys)
                                        ).toBeTrue();
                                        expect(
                                          base64.stringify(self_kr._secret_keys) ==
                                            base64.stringify(own_kr._secret_keys)
                                        ).toBeTrue();

                                        create_account_login_session(
                                          own_kr,
                                          encrypted_session_key,
                                          eph_sess_pk
                                        ).then((sess_key) => {
                                          expect(
                                            base64.stringify(sess_key) ==
                                              base64.stringify(session_key)
                                          ).toBeTrue();
                                          done();
                                        });
                                      });
                                    }
                                  );
                                });
                              });
                            });
                          }
                        );
                      });
                    });
                  });
                });
              });
            }
          );
        }
      );
    });
  });

  it('passive identity signature', async () => {
    let self_kr0 = new SelfAccountKeyring(
      'SAcc0',
      {
        [SelfAccountKeyring.CURVE25519]: new Uint8Array([154, 143, 136, 123, 82, 249, 242, 215, 170, 99, 197, 238, 135, 37, 203, 44, 169, 149, 203, 216, 94, 0, 226, 14, 254, 195, 65, 173, 29, 223, 132, 85]),
        [SelfAccountKeyring.ED25519]: new Uint8Array([193, 54, 106, 250, 172, 17, 160, 83, 13, 4, 34, 26, 99, 132, 63, 0, 162, 208, 31, 53, 105, 128, 32, 72, 186, 201, 124, 22, 50, 190, 89, 227]),
      },
      {
        [SelfAccountKeyring.CURVE25519]: new Uint8Array([95, 20, 66, 214, 31, 150, 113, 8, 69, 141, 189, 34, 142, 29, 11, 7, 117, 211, 226, 136, 81, 227, 14, 58, 131, 9, 149, 109, 111, 122, 103, 10]),
        [SelfAccountKeyring.ED25519]: new Uint8Array([89, 98, 3, 31, 76, 70, 126, 28, 99, 5, 23, 238, 203, 169, 19, 230, 240, 241, 45, 163, 186, 100, 198, 72, 127, 110, 147, 127, 63, 93, 139, 170]),
        [SelfAccountKeyring.MASTER]: new Uint8Array([184, 175, 110, 217, 250, 194, 48, 60, 25, 60, 110, 187, 237, 39, 210, 214, 214, 174, 48, 135, 44, 69, 34, 33, 142, 55, 122, 79, 169, 254, 41, 96]),
      },
    );
    let self_kr0_p = new PeerAccountKeyring('SAcc0', self_kr0._public_keys);
    let self_kr1 = SelfAccountKeyring.generate('id');
    let self_kr1_p = new PeerAccountKeyring('id', self_kr1._public_keys);

    const frozen_identity = new Uint8Array([132, 161, 118, 1, 161, 116, 203, 64, 234, 234, 114, 77, 210, 241, 170, 161, 115, 196, 16, 72, 195, 60, 233, 181, 245, 184, 253, 113, 224, 133, 39, 110, 134, 127, 201, 161, 105, 165, 83, 65, 99, 99, 48]);
    const frozen_signature = new Uint8Array([1, 88, 129, 81, 80, 37, 74, 123, 89, 20, 249, 115, 232, 201, 193, 61, 35, 140, 181, 129, 67, 174, 178, 227, 108, 234, 236, 101, 253, 14, 40, 86, 21, 67, 213, 36, 202, 227, 139, 179, 220, 253, 151, 79, 196, 37, 201, 18, 208, 215, 83, 169, 238, 226, 149, 187, 68, 39, 43, 175, 214, 91, 202, 43, 1]);

    expect(await verify_passive_identity_signature(self_kr1_p, frozen_identity, frozen_signature)).toBeFalsy();
    const frozen_t = await verify_passive_identity_signature(self_kr0_p, frozen_identity, frozen_signature);
    expect(frozen_t).toBeTruthy();
    expect(isObjectTheSame(frozen_t, {"account_id": new TextDecoder().decode(self_kr0_p.id), "timestamp": 55123.572})).toBeTrue();

    const ts = Number.parseFloat((Math.random() * 10000000).toFixed(6));
    const dyn_sig = await create_passive_identity_signature(self_kr1, ts);
    expect(await verify_passive_identity_signature(self_kr0_p, dyn_sig.identity, dyn_sig.signature)).toBeFalsy();
    const dyn_t = await verify_passive_identity_signature(self_kr1_p, dyn_sig.identity, dyn_sig.signature);
    expect(dyn_t).toBeTruthy();
    expect(isObjectTheSame(dyn_t, {"account_id": new TextDecoder().decode(self_kr1_p.id), "timestamp": ts})).toBeTrue();

    const _sign_identity = async (skr_, obj_or_ident) => {
      if (obj_or_ident instanceof Uint8Array) {
      } else {
        obj_or_ident = msgpack.encode(obj_or_ident);
      }
      const sig_ = await ACCOUNT_SIGNATURE_CRYPTO_CONTEXT.dump(new AccountSignatureConfigDumpArgs(obj_or_ident, skr_));
      return {
        identity: obj_or_ident,
        signature: sig_,
      }
    };
    const _check_err = async (obj_or_ident) => {
      const tmp_ = await _sign_identity(self_kr1, obj_or_ident);
      return await verify_passive_identity_signature(self_kr1_p, tmp_.identity, tmp_.signature);
    };

    expect(await _check_err(new Uint8Array([120, 120, 120]))).toBeFalsy();
    expect(await _check_err(["i", 5])).toBeFalsy();
    expect(await _check_err({i: self_kr1.id})).toBeFalsy();
    expect(await _check_err({v: 1})).toBeFalsy();
    expect(await _check_err({v: 1, i: self_kr1.id})).toBeFalsy();
    expect(await _check_err({v: 1, t: 0, s: 0, i: self_kr1.id})).toBeFalsy();
    expect(await _check_err({v: 1, t: 0, s: new Uint8Array(3), i: self_kr1.id})).toBeFalsy();
    expect(await _check_err({v: 1, t: 0, s: new Uint8Array(16), i: self_kr1.id})).toBeFalsy();
    expect(await _check_err({v: 1, t: 0, s: new Uint8Array(16), i: self_kr1.id})).toBeFalsy();
    expect(await _check_err({v: 1, t: -2, s: new Uint8Array(16), i: new TextDecoder().decode(self_kr1.id)})).toBeFalsy();
    expect(await _check_err({v: 1, t: 0, s: new Uint8Array(16), i: ""})).toBeFalsy();
    expect(await _check_err({v: 1, t: 0, s: new Uint8Array(16), i: "asdf"})).toBeFalsy();

    expect(peek_unverified_passive_identity(new Uint8Array(1100))).toBeFalsy();
  });
});
