import { TestBed, waitForAsync } from '@angular/core/testing';
import {HttpClient, HttpHeaders, HttpClientModule} from '@angular/common/http';
import { CookieService } from 'ngx-cookie';
import { base64 } from "rfc4648";
import { CookieModule } from 'ngx-cookie';


import { AESCipherSIVDeterministic, AESCipherSIVNonce96, AESCipherGCM, AESCipherCBC } from '../crypto/base/cipher/aes';
import { Ed25519KeyGenerator, Curve25519KeyGenerator } from '../crypto/base/key/ec';
import { Curve25519SharedSecretGenerator } from '../crypto/base/key/dh';
import { HKDFKeyGeneratorV1, HKDFKeyGeneratorV2, AbstractHKDFKeyGenerator } from '../crypto/base/key/kdf';
import { RandomKeyGenerator128, RandomKeyGenerator256, RandomKeyGenerator512 } from '../crypto/base/key/random';
import { Ed25519DS } from '../crypto/base/ds/ec';
import msgpack from "msgpack-lite";

import { AccountConfigLoadArgs, AccountConfigDumpArgs } from "../crypto/context/account/args";
import { AccountConfigV1 } from "../crypto/context/account/v1";
import { AccountRoomKeyConfigV1 } from "../crypto/context/account_key/room/v1";
import { SelfAccountKeyring } from "../crypto/keyring/account_self";
import { AbstractAccountKeyring, AbstractSelfAccountKeyring } from './keyring/account_base';
import { AbstractKeyring } from './keyring/base';
import { AbstractPrivateKeyring, PrivateKeyringV1, PrivateKeyringV2 } from './keyring/private';
import { AbstractRoomKeyring } from './keyring/room_base';
import { AbstractPeerAccountKeyring } from './keyring/account_base';
import { AccountMasterDeriveKeyV1, AccountPairDeriveKeyV1 } from './context/common';
import { RoomKeyring } from "./keyring/room";
import { AccountTrustConfigDumpArgs, AccountTrustConfigLoadArgs } from './context/account_trust/args';
import { AccountRoomKeyConfigDumpArgs, AccountRoomKeyConfigLoadArgs } from './context/account_key/room/args';
import { AccountRootKeyConfigDumpArgs, AccountRootKeyConfigLoadArgs } from './context/account_key/root/args';
import { AccountRootKeyConfigV1 } from './context/account_key/root/v1';
import { PeerAccountKeyring } from './keyring/account_peer';
import { AccountSignatureConfigDumpArgs, AccountSignatureConfigLoadArgs } from './context/account_signature/args';
import { AccountSignatureConfigV1 } from './context/account_signature/v1';
import { AccountTrustConfigV1 } from './context/account_trust/v1';
import { DialogueConfigDumpArgs, DialogueConfigLoadArgs } from './context/dialogue/args';
import { DialogueConfigV1 } from './context/dialogue/v1';
import { TimestampWindowCalculator } from './context/timestamp';
import { NanoConfigDumpArgs, NanoConfigLoadArgs } from './context/nano/args';
import { NanoConfigV1 } from './context/nano/v1';
import { NanoDataConfigDumpArgs, NanoDataConfigLoadArgs } from './context/nano_data/args';
import { NanoDataConfigV1 } from './context/nano_data/v1';
import { NanoOwnConfigDumpArgs, NanoOwnConfigLoadArgs } from './context/nano_own/args';
import { NanoOwnConfigV1 } from './context/nano_own/v1';
import { PrivateKeyConfigDumpArgs, PrivateKeyConfigLoadArgs } from './context/private_key/args';
import { PrivateKeyConfigV1 } from './context/private_key/v1';
import { RoomConfigDumpArgs, RoomConfigLoadArgs } from './context/room/args';
import { RoomConfigV1 } from './context/room/v1';
import { RoomKeyConfigDumpArgs, RoomKeyConfigLoadArgs } from './context/room_key/args';
import { RoomKeyConfigV1 } from './context/room_key/v1';

import { dump_raw_keyring } from './cryptography-context.spec';
import { ACCOUNT_SIGNATURE_CRYPTO_CONTEXT } from './context/account_signature/__init__';
import { ACCOUNT_TRUST_CRYPTO_CONTEXT } from './context/account_trust/__init__';


import { AuthValueError, auth_key_hash_function, generate_client_salt_input, server_salt } from "./auth/common";
import { 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 } from "./auth/register";
import { account_password_change, create_account_password_change_request } from "./auth/password";
import { create_account_login_keyring } from "./auth/login";
import { concatByteArray } from './utility';
import { create_account_register_prepare_request, create_account_register_keyring_request } from "./auth/register";
import { ACCOUNT_ROOT_KEY_CRYPTO_CONTEXT } from './context/account_key/root/__init__';
import { environment } from 'src/environments/environment';

/**
 *
 * 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 expectedList = ["account_peer", "account_self", "private_v1", "private_v2", "room"];

    let csrfToken = "";

    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;


                                    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));
                                                    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();
                                                                })

                                                            })
                                                        })
                                                    })

                                                })

                                            })
                                        })
                                    })

                                })

                            })
                        })


                    })
                })
            })
        })

    })

});
