Skip to content

Instantly share code, notes, and snippets.

@AngeloD2022
Last active December 28, 2024 10:57

Revisions

  1. AngeloD2022 revised this gist Dec 16, 2023. 4 changed files with 18210 additions and 0 deletions.
    1,760 changes: 1,760 additions & 0 deletions background.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,1760 @@
    var pwlog = void 0,
    pwerror = void 0;

    function isStringEmpty(e) {
    return !e || 0 === e.length
    }

    function urlFromURLString(e) {
    try {
    return new URL(e)
    } catch {
    return null
    }
    }

    function humanReadableFormType(e) {
    switch (e) {
    case WBSAutoFillFormTypeUndetermined:
    return "Undetermined";
    case WBSAutoFillFormTypeAutoFillableStandard:
    return "AutoFillable:Standard";
    case WBSAutoFillFormTypeNonAutoFillable:
    return "NonAutoFillable";
    case WBSAutoFillFormTypeAutoFillableLogin:
    return "AutoFillable:Login";
    case WBSAutoFillFormTypeNewAccount:
    return "NewAccount";
    case WBSAutoFillFormTypeChangePassword:
    return "ChangePassword";
    case WBSAutoFillFormTypeFoundTOTPURI:
    return "FoundTOTPUri"
    }
    return "Unrecognized"
    }

    function domainsForDisplayFromUsernamesAndDomains(e, t) {
    const s = e.length;
    let a = t.map((function(e) {
    return e.replace(/^(www|m)\./, "")
    })),
    n = [];
    for (var r = 0; r < s; r++) n.push([e[r], a[r]]);
    for (r = 0; r < s; r++) {
    let e = [];
    for (var o = r + 1; o < s; o++) n[r].join("\n") === n[o].join("\n") && (e.length || e.push(r), e.push(o));
    for (let s of e) a[s] = t[s]
    }
    return a
    }

    function urlIsBrowserURL(e) {
    const t = e.protocol;
    return "chrome:" === t || "edge:" === t || "about:" == t
    }

    function isExtensionContextInvalidatedError(e) {
    return "Extension context invalidated." === e.message
    }

    function capabilitiesDeclaresMacOS(e) {
    try {
    return "macos" === e.operatingSystem.name
    } catch {
    return !1
    }
    }
    class Localizer {
    static configureDocumentElementForLanguage(e, t) {
    switch (t) {
    case "he":
    case "ar":
    case "fa":
    e.setAttribute("dir", "rtl"), e.setAttribute("lang", t)
    }
    }
    #e = {};
    constructor(e) {
    e && (this.#e = e.operatingSystem)
    }
    getMessage(e, t, s) {
    const a = this.messageNamesToTry(e);
    for (let e of a) {
    let a;
    try {
    a = chrome.i18n.getMessage(e, t, s)
    } catch {
    a = chrome.i18n.getMessage(e, t)
    }
    if (a) return a
    }
    return ""
    }
    messageNamesToTry(e) {
    let t = [];
    const s = this.#e,
    a = s ? s.name : void 0,
    n = s ? s.majorVersion : void 0,
    r = s ? s.minorVersion : void 0,
    o = void 0 !== n;
    return a && o && void 0 !== r && t.push(`${e}_${a}_${n}_${r}`), a && o && t.push(`${e}_${a}_${n}`), a ? t.push(`${e}_${a}`) : t.push(`${e}_${this.#t}`), t.push(e), t
    }
    get #t() {
    return navigator.platform.startsWith("Mac") ? "macos" : "windows"
    }
    }
    class ExtensionSettings {
    #s = !1;
    #a = !0;
    #n = !0;
    eventTarget = new EventTarget;
    constructor(e = !1) {
    this.#s = e, this.#r(), this.#o()
    }
    get enableInPageAutoFill() {
    return this.#a
    }
    set enableInPageAutoFill(e) {
    this.#a = e, this.#i()
    }
    get allowExtensionToControlAutoFillSettings() {
    return this.#n
    }
    set allowExtensionToControlAutoFillSettings(e) {
    this.#n = e, this.#c().then(this.#i.bind(this))
    }
    #c() {
    return this.#n ? this.attemptToControlBrowserAutoFillSettings() : this.clearControlOfBrowserAutoFillSettings()
    }
    async attemptToControlBrowserAutoFillSettings() {
    if (this.#s) throw new Error("This Settings instance does not allow writing browser settings");
    const e = await Promise.allSettled([this.#l(chrome.privacy.services.passwordSavingEnabled, !1), this.#l(chrome.privacy.services.autofillCreditCardEnabled, !1), this.#l(chrome.privacy.services.autofillAddressEnabled, !1)]);
    return this.#d(), e
    }
    async clearControlOfBrowserAutoFillSettings() {
    if (this.#s) throw new Error("This Settings instance does not allow writing browser settings");
    const e = await Promise.allSettled([this.#m(chrome.privacy.services.passwordSavingEnabled), this.#m(chrome.privacy.services.autofillCreditCardEnabled), this.#m(chrome.privacy.services.autofillAddressEnabled)]);
    return this.#d(), e
    }
    #r() {
    let e = new Promise((e => {
    chrome.storage.sync.get({
    enableInPageAutoFill: !0,
    allowExtensionToControlAutoFillSettings: !0
    }, (t => {
    this.#a = t.enableInPageAutoFill, this.#n = t.allowExtensionToControlAutoFillSettings, e()
    }))
    }));
    return this.#s || (e = e.then(this.#c.bind(this))), e.then(this.#d.bind(this))
    }
    #i() {
    return new Promise((e => {
    chrome.storage.sync.set({
    enableInPageAutoFill: this.#a,
    allowExtensionToControlAutoFillSettings: this.#n
    }, e)
    })).then(this.#d.bind(this))
    }
    #o() {
    this.#s || (chrome.privacy.services.passwordSavingEnabled && chrome.privacy.services.passwordSavingEnabled.onChange.addListener((e => {
    this.#d()
    })), chrome.privacy.services.autofillCreditCardEnabled && chrome.privacy.services.autofillCreditCardEnabled.onChange.addListener((e => {
    this.#d()
    })), chrome.privacy.services.autofillAddressEnabled && chrome.privacy.services.autofillAddressEnabled.onChange.addListener((e => {
    this.#d()
    })))
    }
    #d() {
    const e = new CustomEvent("settingsChanged", {
    detail: {
    enableInPageAutoFill: this.#a
    }
    });
    this.eventTarget.dispatchEvent(e)
    }
    async #l(e, t) {
    let s;
    try {
    s = await this.#u(e)
    } catch (e) {
    return
    }
    if (s) {
    if (s.value === t) return {
    details: s,
    newValue: t
    };
    try {
    s = await e.set({
    value: t
    })
    } catch (e) {
    return
    }
    return {
    details: s,
    newValue: t
    }
    }
    }
    async #u(e) {
    if (!e) throw new Error(`Unable to get ${e} setting.`);
    const t = await e.get({});
    if ("not_controllable" === t.levelOfControl) throw new Error(`Cannot control ${e} setting.`);
    return t
    }
    async #m(e) {
    if (!e) throw new Error(`Unable to clear browser setting: ${e}.`);
    await e.clear({})
    }
    }
    const ErrCodes = {
    ErrSuccess: "Success",
    InvalidMessage: "InvalidMessage",
    UnexpectedMessage: "UnexpectedMessage",
    InvalidSyntax: "InvalidSyntax",
    InvalidSessionKey: "InvalidSessionKey",
    CryptoError: "CryptoError",
    InvalidUserName: "InvalidUserName"
    };
    class SecretSessionError extends Error {
    constructor(e, t = null) {
    super(t), this.code = e
    }
    }
    const SecretSessionVersion = {
    SRPWithOldVerification: 0,
    SRPWithRFCVerification: 1
    },
    scriptVersion = "1.0",
    appVersion = "1.0",
    MSGTypes = {
    MSG0: 0,
    MSG1: 1,
    MSG2: 2,
    MSG3: 3
    };
    SecretSession = function(e) {
    this.shouldUseBase64 = !1, e.shouldUseBase64 && (this.shouldUseBase64 = e.shouldUseBase64), this.protocolVersion = SecretSessionVersion.SRPWithOldVerification, e.secretSessionVersion && (this.protocolVersion = e.secretSessionVersion), this.grp = sjcl.keyexchange.srp.knownGroup(3072), this.keyLen = 128, this.tagLen = 128, this.setUpSRP()
    }, SecretSession.prototype = {
    createSMSG: function(e) {
    if ("object" == typeof e) try {
    e = JSON.stringify(e)
    } catch (e) {
    return ErrCodes.InvalidMessage
    }
    const t = sjcl.codec.utf8String.toBits(e),
    s = this.encrypt(t);
    if ("string" == typeof s) return s;
    let a = null;
    try {
    a = JSON.stringify({
    TID: this.bitsToString(this.I.toBits()),
    SDATA: this.bitsToString(s, !1)
    })
    } catch (e) {
    return ErrCodes.InvalidMessage
    }
    return a
    },
    parseSMSG: function(e) {
    let t = e;
    if ("string" == typeof t) try {
    t = JSON.parse(e)
    } catch (t) {
    throw new SecretSessionError(ErrCodes.InvalidSyntax, `Unable to decode SMSG from string: ${t} ${e}`)
    }
    if ("string" != typeof t.SDATA) throw new SecretSessionError(ErrCodes.InvalidMessage, "Missing or invalid SDATA field in SMSG message.");
    if ("string" != typeof t.TID) throw new SecretSessionError(ErrCodes.InvalidUserName, "Missing or invalid 'TID' field in SMSG object.");
    const s = sjcl.bn.fromBits(this.stringToBits(t.TID));
    if (!this.I.equals(s)) throw new SecretSessionError(ErrCodes.InvalidUserName, "Received SMSG message meant for another session.");
    return sjcl.codec.utf8String.fromBits(this.decrypt(this.stringToBits(t.SDATA)))
    },
    setPin: function(e) {
    this.P = e
    },
    stringToBase64: function(e) {
    let t = sjcl.codec.utf8String.toBits(e);
    return sjcl.codec.base64.fromBits(t, !1, !1)
    },
    bitsToString: function(e, t = !0) {
    return this.shouldUseBase64 ? sjcl.codec.base64.fromBits(e) : (t ? "0x" : "") + sjcl.codec.hex.fromBits(e)
    },
    stringToBits: function(e) {
    return this.shouldUseBase64 ? sjcl.codec.base64.toBits(e) : sjcl.codec.hex.toBits(e)
    },
    setUpSRP: function() {
    this.I = sjcl.bn.fromBits(this._randomWords(4)), this.a = sjcl.bn.fromBits(this._randomWords(8)), this.A = this.grp.g.powermod(this.a, this.grp.N)
    },
    currProtocols: function() {
    return [SecretSessionVersion.SRPWithOldVerification, SecretSessionVersion.SRPWithRFCVerification]
    },
    initialMessage: function() {
    this.expectedMessage = MSGTypes.MSG1;
    let e = null;
    try {
    e = JSON.stringify({
    TID: this.bitsToString(this.I.toBits()),
    MSG: 0,
    A: this.bitsToString(this.A.toBits()),
    VER: "1.0",
    PROTO: this.currProtocols()
    })
    } catch (e) {
    return null
    }
    return this.stringToBase64(e)
    },
    _padToModulusLength: function(e) {
    e = e.replace(/^0x/, "");
    const t = 2 * (sjcl.bitArray.bitLength(this.grp.N.toBits()) + 7 >> 3) - e.length;
    if (0 === t) return e;
    return "0".repeat(t) + e
    },
    processMessage: function(e) {
    const t = sjcl.codec.utf8String.fromBits(sjcl.codec.base64.toBits(e));
    let s = null;
    try {
    s = JSON.parse(t)
    } catch (e) {
    throw new SecretSessionError(ErrCodes.InvalidMessage, `Unable to parse JSON message: ${e}`)
    }
    if ("string" != typeof s.TID) throw new SecretSessionError(ErrCodes.InvalidMessage, "Missing or invalid 'TID' field in PAKE message.");
    let a = sjcl.bn.fromBits(this.stringToBits(s.TID));
    if (!this.I.equals(a)) throw new SecretSessionError(ErrCodes.UnexpectedMessage, "Unexpected message");
    if (!s.MSG) throw new SecretSessionError(ErrCodes.InvalidMessage, "Missing 'MSG' field in PAKE message.");
    const n = parseInt(s.MSG, 10);
    if (this.expectedMessage !== n) throw new SecretSessionError(ErrCodes.UnexpectedMessage, `Received Message ${message.MSG}, but expected Message ${this.expectedMessage} `);
    let r = null;
    if (n === MSGTypes.MSG1) {
    var o = SecretSessionVersion.SRPWithOldVerification;
    "number" == typeof s.PROTO && (o = s.PROTO, Object.values(SecretSessionVersion).includes(o) || (o = SecretSessionVersion.SRPWithOldVerification)), this.protocolVersion = o, r = this.processMessage1(s)
    } else n === MSGTypes.MSG3 && (r = this.processMessage3(s));
    return r
    },
    createSessionKey: function(e, t) {
    const s = sjcl.hash.sha256.hash,
    a = this._calculateX(e, this.bitsToString(this.I.toBits()), this.P, s);
    this.v = this._calculateVerifier(this.grp.g, a, this.grp.N);
    const n = this.A.toString(),
    r = t.toString(),
    o = this._padToModulusLength(n).concat(this._padToModulusLength(r)),
    i = sjcl.bn.fromBits(s(sjcl.codec.hex.toBits(o))),
    c = this.a.add(i.mul(a)),
    l = this.grp.N.toString() + this._padToModulusLength(this.grp.g.toString()),
    d = sjcl.bn.fromBits(s(sjcl.codec.hex.toBits(l))).mulmod(this.v, this.grp.N);
    return s(t.sub(d).powermod(c, this.grp.N).toBits())
    },
    _calculateX: function(e, t, s, a) {
    const n = a(t + ":" + s);
    return sjcl.bn.fromBits(a(e.concat(n)))
    },
    _calculateVerifier: function(e, t, s) {
    return e.powermod(t, s)
    },
    _calculateM: function(e, t, s) {
    const a = sjcl.hash.sha256.hash;
    let n = a(this.grp.N.toBits()),
    r = a(sjcl.codec.hex.toBits(this._padToModulusLength(this.grp.g.toString())));
    const o = sjcl.bitArray.bitLength(n) / 32;
    for (let e = 0; e < o; ++e) n[e] = n[e] ^ r[e];
    let i = a(this.bitsToString(this.I.toBits())),
    c = new sjcl.hash.sha256;
    c.update(n), c.update(i), c.update(e), c.update(this.A.toBits()), c.update(t.toBits()), c.update(s);
    let l = c.finalize();
    return c = new sjcl.hash.sha256, c.update(this.A.toBits()), c.update(l), c.update(s), this.hamk = c.finalize(), l
    },
    processMessage1: function(e) {
    if ("string" != typeof e.s || "string" != typeof e.B) throw new SecretSessionError(ErrCodes.InvalidMessage, "Message 1 is missing some required keys.");
    e.VER && (this.appVer = e.VER);
    const t = this.stringToBits(e.s),
    s = sjcl.bn.fromBits(this.stringToBits(e.B));
    let a = new sjcl.bn(1);
    if (0 == s.mulmod(a, this.grp.N)) throw new SecretSessionError(ErrCodes.CryptoError, "B.mulmod error");
    const n = this.createSessionKey(t, s);
    this.encKey = sjcl.bitArray.bitSlice(n, 0, this.keyLen), this.expectedMessage = MSGTypes.MSG3;
    let r = {
    TID: this.bitsToString(this.I.toBits()),
    MSG: 2
    };
    switch (this.protocolVersion) {
    case SecretSessionVersion.SRPWithRFCVerification:
    r.M = this.bitsToString(this._calculateM(t, s, n), !1);
    break;
    case SecretSessionVersion.SRPWithOldVerification:
    const e = this.shouldUseBase64 ? this.v.toBits() : sjcl.codec.utf8String.toBits(this.v.toString()),
    a = this.encrypt(e);
    r.v = this.bitsToString(a, !1);
    break;
    default:
    throw new SecretSessionError(ErrCodes.UnexpectedMessage, `Unknown protocol version ${this.protocolVersion}`)
    }
    let o = null;
    try {
    o = JSON.stringify(r)
    } catch (e) {
    throw new SecretSessionError(ErrCodes.InvalidMessage, `Error encoding Message 2 to string:${e}`)
    }
    return this.stringToBase64(o)
    },
    processMessage3: function(e) {
    let t = ErrCodes.ErrSuccess,
    s = "";
    if (0 !== e.ErrCode) s = `Message 3 contained an error: ${e.ErrCode}`, t = ErrCodes.InvalidMessage;
    else switch (this.protocolVersion) {
    case SecretSessionVersion.SRPWithRFCVerification:
    if (e.HAMK) {
    const a = this.stringToBits(e.HAMK);
    sjcl.bitArray.equal(a, this.hamk) || (s = "Failed to verify server data.", this.msgExp = MSGTypes.MSG1, t = ErrCodes.InvalidSessionKey)
    } else s = `Message 3 does not contain necessary data:${e.ErrCode}`, t = ErrCodes.InvalidMessage;
    break;
    case SecretSessionVersion.SRPWithOldVerification:
    break;
    default:
    t = ErrCode.UnexpectedMessage, s = `Unknown SecretSessionVersion ${this.protocolVersion}.`
    }
    if (t != ErrCodes.ErrSuccess) throw this.sessionKey = null, this.expectedMessage = MSGTypes.MSG1, new SecretSessionError(t, s);
    return t === ErrCodes.ErrSuccess
    },
    encrypt: function(e) {
    if (!this.encKey) throw new SecretSessionError(ErrCodes.InvalidSessionKey, "Called encrypt() without a session key");
    const t = new sjcl.cipher.aes(this.encKey),
    s = this._randomWords(4);
    let a = null;
    try {
    a = sjcl.mode.gcm.encrypt(t, e, s)
    } catch (e) {
    throw new SecretSessionError(ErrCodes.CryptoError, e.message)
    }
    return sjcl.bitArray.concat(a, s)
    },
    decrypt: function(e) {
    if (!this.encKey) throw new SecretSessionError(ErrCodes.InvalidSessionKey, "Called decrypt() without a session key!");
    const t = new sjcl.cipher.aes(this.encKey),
    s = sjcl.bitArray.bitSlice(e, 0, this.keyLen),
    a = sjcl.bitArray.bitSlice(e, this.keyLen);
    let n = null;
    try {
    n = sjcl.mode.gcm.decrypt(t, a, s)
    } catch (e) {
    throw new SecretSessionError(ErrCodes.CryptoError, `Exception while decrypting message. ${e}`)
    }
    return n
    },
    _randomWords: function(e) {
    const t = new Int32Array(e);
    return self.crypto.getRandomValues(t), Array.from(t)
    }
    };
    const ContextState = {
    IncompatibleOS: "IncompatibleOS",
    NotInSession: "NotInSession",
    NativeSupportNotInstalled: "NativeSupportNotInstalled",
    CheckEngine: "CheckEngine",
    ChallengeSent: "ChallengeSent",
    MSG1Set: "MSG1Set",
    SessionKeySet: "SessionKeySet"
    },
    DataState = {
    Initial: "Initial",
    Frame0Processed: "Frame0Processed",
    DataProcessed: "DataProcessed"
    },
    RememberIC = {
    NoValueSet: "NoValueSet",
    UnknownPage: "UnknownPage",
    DoNotRemember: "DoNotRemember",
    RememberLoginAndPassword: "RememberLoginAndPassword"
    },
    WBSAutoFillFormTypeUndetermined = 0,
    WBSAutoFillFormTypeAutoFillableStandard = 1,
    WBSAutoFillFormTypeNonAutoFillable = 2,
    WBSAutoFillFormTypeAutoFillableLogin = 3,
    WBSAutoFillFormTypeNewAccount = 4,
    WBSAutoFillFormTypeChangePassword = 5,
    WBSAutoFillFormTypeFoundTOTPURI = 6;
    class FrameDoesNotExistError extends Error {
    frame;
    constructor(e) {
    super(`Frame ${e.id} does not exist in tab ${e.tab.id}`), this.frame = e
    }
    }
    class FrameIsBrowserFrameError extends Error {
    frame;
    constructor(e) {
    super(`Frame ${e.id} in tab ${e.tab.id} is a browser frame.`), this.frame = e
    }
    }
    class ContentScriptNotSetUpInFrame extends Error {
    frame;
    constructor(e) {
    super(`Frame ${e.id} in tab ${e.tab.id} does not have active content script.`), this.frame = e
    }
    }
    class PromiseFulfillment {
    resolve;
    reject;
    constructor(e, t) {
    this.resolve = e, this.reject = t
    }
    }
    class DelayedMessageSender {
    static defaultDelayMS = 50;
    delayMS;
    messageName;
    #g = null;
    #p = [];
    #h = null;
    constructor(e, t = DelayedMessageSender.defaultDelayMS) {
    this.messageName = e, this.delayMS = t
    }
    get dateOfLastSentMessage() {
    return this.#h
    }
    enqueueRequest(e, t) {
    return new Promise(((s, a) => {
    this.#p.push(new PromiseFulfillment(s, a)), this.#g && (clearTimeout(this.#g), this.#g = null), this.#g = setTimeout((async () => {
    const s = e.tab.id,
    a = e.id;
    let n;
    try {
    n = await this.#S(s, a, this.messageName, t)
    } catch (t) {
    let s = t;
    return t.message.includes("Receiving end does not exist.") && (s = new FrameDoesNotExistError(e)), this.#h = null, void this.#f(null, s)
    } finally {
    this.#g = null
    }
    this.#h = new Date, this.#f(n)
    }).bind(this), this.delayMS)
    }))
    }
    cancelPendingRequests() {
    this.#g && (clearTimeout(this.#g), this.#g = null), this.#f(null, new Error("Cancelled"))
    }
    reset() {
    this.cancelPendingRequests(), this.#h = null
    }
    #S(e, t, s, a) {
    let n = {
    subject: s
    };
    return a && (n = {
    ...n,
    ...a
    }), chrome.tabs.sendMessage(e, n, {
    frameId: t
    })
    }
    #f(e, t = null) {
    for (; this.#p.length;) {
    const s = this.#p.shift();
    t ? s.reject(t) : s.resolve(e)
    }
    }
    }
    class Frame {
    static delayForSettingUpContentScriptAfterFrameCreationMS = 50;
    static delayForRunningHeuristicsAfterFrameUpdateMS = 50;
    id;
    tab;
    url;
    state;
    #b = new DelayedMessageSender("setUp", Frame.delayForSettingUpContentScriptAfterFrameCreationMS);
    #C = new DelayedMessageSender("runFormMetadataHeuristics", Frame.delayForRunningHeuristicsAfterFrameUpdateMS);
    constructor(e, t) {
    this.id = e, this.tab = t
    }
    get isBrowserFrame() {
    const e = this.url;
    return !!e && urlIsBrowserURL(e)
    }
    get hasCompletedLoad() {
    return "complete" === this.state
    }
    get hasSetUpContentScript() {
    return !!this.#b.dateOfLastSentMessage
    }
    prepareForRemoval() {
    this.#b.cancelPendingRequests(), this.#C.cancelPendingRequests()
    }
    updateWithDetails(e, t) {
    this.state = e;
    const s = t.url;
    s && (this.url = urlFromURLString(s))
    }
    setUpContentScript(e) {
    return this.isBrowserFrame ? Promise.reject(new FrameIsBrowserFrameError(this)) : (e = !!e, this.#b.enqueueRequest(this, {
    shouldEnableQRCodeScanning: e
    }))
    }
    async enableQRCodeScanning(e) {
    return this.hasSetUpContentScript ? this.#S("enableQRCodeScanner", {
    isEnabled: e
    }) : Promise.reject(new ContentScriptNotSetUpInFrame(this))
    }
    runHeuristics() {
    return this.isBrowserFrame ? Promise.reject(new FrameIsBrowserFrameError(this)) : this.hasSetUpContentScript ? this.#C.enqueueRequest(this) : Promise.reject(new Error("Cannot run metadata heuristics before setting up content script"))
    }
    readyToReceiveMessages() {
    return this.#b.reset(), this.setUpContentScript(!0)
    }
    #S(e, t) {
    let s = {
    subject: e
    };
    return t && (s = {
    ...s,
    ...t
    }), chrome.tabs.sendMessage(this.tab.id, s, {
    frameId: this.id
    })
    }
    }
    class Tab {
    static delayForSettingUpFrameContentScript = 50;
    static delayForCleaningUpFrames = 2e3;
    static enableDeferredFrameCleanup = !0;
    id;
    state;
    framesById = new Map;
    url;
    #T = null;
    constructor(e) {
    this.id = e
    }
    get allFrames() {
    return chrome.webNavigation.getAllFrames({
    tabId: this.id
    })
    }
    async injectContentScripts(e = !0) {
    if (!this.url) return;
    const t = this.url.protocol;
    if ("http:" !== t && "https:" !== t) return;
    const s = chrome.runtime.getManifest().content_scripts[0],
    a = this.id;
    await chrome.scripting.executeScript({
    target: {
    tabId: a,
    allFrames: e
    },
    files: s.js
    });
    for (const e of this.framesById.values()) try {
    await e.setUpContentScript()
    } catch (e) {
    if (e instanceof FrameIsBrowserFrameError) return
    }
    }
    prepareForRemoval() {
    for (const e of this.framesById.values()) e.prepareForRemoval()
    }
    activated(e) {
    this.#I(), chrome.contextMenus && chrome.contextMenus.removeAll()
    }
    update(e, t) {
    this.#I(), this.state = t.status, e ? (this.state = e.status, "loading" === e.status && (this.url = urlFromURLString(e.url))) : (this.state = t.status, this.url = urlFromURLString(t.url))
    }
    addNewFrame(e, t, s = null) {
    this.#I();
    const a = t.frameId,
    n = new Frame(a, this);
    this.framesById.set(a, n), this.frameUpdated(e, a, s, t)
    }
    async frameUpdated(e, t, s, a) {
    this.#I();
    const n = this.ensureFrameExists(t);
    if (n.updateWithDetails(s, a), n.hasCompletedLoad) try {
    n.hasSetUpContentScript ? await n.runHeuristics() : await n.setUpContentScript(e.shouldEnableQRCodeScanning)
    } catch (e) {
    if (!(e instanceof FrameDoesNotExistError)) {
    if (e instanceof FrameIsBrowserFrameError) return;
    throw e
    } {
    const t = e.frameId;
    if (!this.framesById.get(t)) return;
    let s = await chrome.webNavigation.getFrame({
    tabId: this.id,
    frameId: t
    });
    s || (s.prepareForRemoval(), this.framesById.delete(t))
    }
    }
    }
    async frameCompleted(e, t, s) {
    try {
    await this.frameUpdated(e, t, "complete", s)
    } catch (e) {}
    }
    frameIsReadyToReceiveMessages(e) {
    return this.ensureFrameExists(e).readyToReceiveMessages()
    }
    ensureFrameExists(e) {
    let t = this.framesById.get(e);
    return t || (t = new Frame(e, this), this.framesById.set(e, t)), t
    }
    #I() {
    Tab.enableDeferredFrameCleanup && (this.#T && (clearTimeout(this.#T), this.#T = null), this.#T = setTimeout((async () => {
    let e = new Map;
    const t = await this.allFrames,
    s = new Set((t || []).map((e => e.frameId)));
    if (!s.size && !this.framesById.size) return;
    for (const [t, a] of this.framesById) s.has(t) && e.set(t, a);
    this.framesById.size, e.size;
    this.framesById = e, this.#T = null
    }).bind(this), Tab.delayForCleaningUpFrames))
    }
    }
    class TabMonitor {
    tabsById = new Map;
    #w;
    #y;
    constructor() {
    this.#A(), this.#v()
    }
    get extensionIsPaired() {
    return this.#w
    }
    set extensionIsPaired(e) {
    this.#w = e, this.#F()
    }
    get nativeAppSupportsQRCodeScanning() {
    return this.#y
    }
    set nativeAppSupportsQRCodeScanning(e) {
    this.#y = e, this.#F()
    }
    get shouldEnableQRCodeScanning() {
    return this.#w && this.#y
    }
    get #M() {
    return [...this.tabsById.values()].flatMap((e => [...e.framesById.values()]))
    }
    #F() {
    const e = this.shouldEnableQRCodeScanning;
    return Promise.allSettled(this.#M.map((t => t.enableQRCodeScanning(e).catch((e => {})))))
    }
    async #A() {
    const e = await chrome.tabs.query({});
    for (const t of e) {
    const e = t.id,
    s = new Tab(e);
    s.update(null, t), this.tabsById.set(e, s);
    const a = await chrome.webNavigation.getAllFrames({
    tabId: e
    });
    for (const e of a) {
    if (void 0 === e.frameId) break;
    s.addNewFrame(this, e, t.status)
    }
    }
    }
    #v() {
    chrome.tabs.onCreated.addListener((e => {
    const t = e.id;
    this.tabsById.set(t, new Tab(t))
    })), chrome.tabs.onUpdated.addListener(((e, t, s) => {
    this.ensureTabExists(e).update(t, s)
    })), chrome.tabs.onActivated.addListener((e => {
    this.ensureTabExists(e.tabId).activated(e)
    })), chrome.tabs.onRemoved.addListener(((e, t) => {
    this.tabsById.delete(e)
    })), chrome.webNavigation.onBeforeNavigate.addListener((e => {
    const t = e.tabId;
    this.ensureTabExists(t).addNewFrame(this, e)
    })), chrome.webNavigation.onCompleted.addListener((async e => {
    const t = e.tabId,
    s = e.frameId,
    a = this.ensureTabExists(t);
    try {
    await a.frameCompleted(this, s, e)
    } catch (e) {}
    })), chrome.webNavigation.onHistoryStateUpdated.addListener((async e => {
    const t = e.tabId,
    s = e.frameId,
    a = this.ensureTabExists(t);
    try {
    await a.frameUpdated(this, s, "updated", e)
    } catch (e) {}
    })), chrome.webNavigation.onTabReplaced.addListener((e => {
    const t = e.replacedTabId;
    this.tabsById.get(t).prepareForRemoval(), this.tabsById.delete(t);
    const s = e.tabId;
    this.tabsById.set(s, new Tab(s))
    }))
    }
    async performInitialSetup() {
    for (const e of this.tabsById.values()) await e.injectContentScripts()
    }
    ensureTabExists(e) {
    let t = this.tabsById.get(e);
    return t || (t = new Tab(e), this.tabsById.set(e, t)), t
    }
    frameIsReadyToReceiveMessages(e, t) {
    return this.ensureTabExists(e).frameIsReadyToReceiveMessages(t)
    }
    }
    "function" == typeof importScripts && importScripts("/sjcl.js");
    const CmdEndOp = 0,
    CmdUnused1 = 1,
    CmdChallengePIN = 2,
    CmdSetIconNTitle = 3,
    CmdGetLoginNames4URL = 4,
    CmdGetPassword4LoginName = 5,
    CmdSetPassword4LoginName_URL = 6,
    CmdNewAccount4URL = 7,
    CmdTabEvent = 8,
    CmdPasswordsDisabled = 9,
    CmdReloginNeeded = 10,
    CmdLaunchiCP = 11,
    CmdiCPStateChange = 12,
    CmdLaunchPasswordsApp = 13,
    CmdHello = 14,
    CmdOneTimeCodeAvailable = 15,
    CmdGetOneTimeCodes = 16,
    CmdDidFillOneTimeCode = 17,
    CmdSetUpTOTPGenerator = 18,
    CmdOpenURLInSafari = 1984,
    QueryStatus = {
    Success: 0,
    NoResults: 3
    };

    function cmd2string(e) {
    switch (e) {
    case 0:
    return "CmdEndOp";
    case 1:
    return "CmdUnused1";
    case 2:
    return "CmdChallengePIN";
    case 3:
    return "CmdSetIconNTitle";
    case 4:
    return "CmdGetLoginNames4URL";
    case 5:
    return "CmdGetPassword4LoginName";
    case 6:
    return "CmdSetPassword4LoginName_URL";
    case 7:
    return "CmdNewAccount4URL";
    case 8:
    return "CmdTabEvent";
    case 9:
    return "CmdPasswordsDisabled";
    case 10:
    return "CmdReloginNeeded";
    case 11:
    return "CmdLaunchiCP";
    case 12:
    return "CmdiCPStateChange";
    case 13:
    return "CmdLaunchPasswordsApp";
    case 14:
    return "CmdHello";
    case 15:
    return "CmdOneTimeCodeAvailable";
    case 16:
    return "CmdGetOneTimeCodes";
    case 17:
    return "CmdDidFillOneTimeCode";
    case 1984:
    return "CmdOpenURLInSafari";
    default:
    return "Unknown Command"
    }
    }
    var actUnknown = -1,
    actDelete = 0,
    actUpdate = 1,
    actSearch = 2,
    actAddNew = 3,
    actMaybeAdd = 4,
    actGhostSearch = 5;
    const DefaultCapabilities = {
    shouldUseBase64: !1,
    secretSessionVersion: SecretSessionVersion.SRPWithOldVerification,
    canFillOneTimeCodes: !1,
    operatingSystem: {},
    supportsSubURLs: !1,
    scanForOTPURI: !1
    },
    AmountOfTimeToBlockRefreshForNativeAppDisconnection = 5e3;
    let g_tabMonitor = new TabMonitor;
    var g_lastToolbarIconImageName, g_timeStartedFetchingCredentials, g_nativeAppPort = null,
    g_portToCompletionList = null,
    g_portToPopup = null,
    thePAKE = null,
    g_theState = ContextState.NotInSession,
    g_tabIdToURL = new Map,
    g_Stage1Logins = new Map,
    g_TabsToStateMap = new Map,
    g_ErrorReturned = !1,
    g_secretSession = null,
    g_nativeAppCapabilities = null,
    g_localizer = new Localizer,
    g_extensionSettings = new ExtensionSettings,
    g_urlToDownloadNativeSupport = "https://support.apple.com/kb/DL1455",
    g_isDark = !1;

    function setIsDark(e) {
    g_isDark !== e && (g_isDark = e, chrome.storage.local.set({
    isDark: e
    }))
    }

    function imageDataForName(e) {
    if (e) return {
    16: "images/" + (g_lastToolbarIconImageName = e) + (g_isDark ? "-darkmode" : "") + "_icon16.png",
    32: "images/" + g_lastToolbarIconImageName + (g_isDark ? "-darkmode" : "") + "_icon32.png"
    }
    }

    function setUpEventListners() {
    chrome.runtime.onInstalled && chrome.runtime.onInstalled.addListener((async e => {
    await g_tabMonitor.performInitialSetup(), chrome.declarativeContent && chrome.declarativeContent.onPageChanged.removeRules(void 0, (function() {
    chrome.declarativeContent.onPageChanged.addRules([{
    conditions: [new chrome.declarativeContent.PageStateMatcher({
    pageUrl: {
    schemes: ["https", "http"]
    }
    })],
    actions: [new chrome.declarativeContent.ShowPageAction]
    }])
    })), "install" === e.reason && g_extensionSettings.attemptToControlBrowserAutoFillSettings().then((e => {})).catch((e => {}))
    })), chrome.runtime.onSuspend && chrome.runtime.onSuspend.addListener((function() {
    g_tabIdToURL.clear(), g_Stage1Logins.clear(), g_TabsToStateMap.clear(), g_nativeAppPort.postMessage({
    cmd: 0
    })
    })), chrome.runtime.onSuspendCanceled && chrome.runtime.onSuspendCanceled.addListener((function() {})), chrome.runtime.onUpdateAvailable && chrome.runtime.onUpdateAvailable.addListener((function() {}))
    }

    function secdSTATUS2string(e) {
    switch (e) {
    case 0:
    return "secdSTATUSsuccess";
    case 1:
    return "genericError";
    case 2:
    return "invalidParam";
    case 3:
    return "itemNotFound";
    case 4:
    return "failedToDelete";
    case 5:
    return "failedToUpdate";
    case 6:
    return "invalidMessageFormat";
    case 7:
    return "duplicateItem";
    case 8:
    return "unknownAction";
    case 9:
    return "invalidSession"
    }
    }

    function checkForValidOS() {
    if ("MacIntel" === navigator.platform) return g_urlToDownloadNativeSupport = "https://www.apple.com/macos", !0;
    const e = new RegExp("\\(Windows\\s*\\w*\\s*(\\d*)\\.(\\d*)", "i").exec(navigator.userAgent);
    return null !== e && 3 === e.length && (e[1] >= 10 ? (g_urlToDownloadNativeSupport = "ms-windows-store://pdp/?productid=9PKTQ5699M62", !0) : !(e[1] < 6) && !(e[2] < 1))
    }

    function setGlobalState(e, t) {
    g_theState = e, g_tabMonitor.extensionIsPaired = g_theState === ContextState.SessionKeySet, setToolbarIcon(g_theState === ContextState.SessionKeySet ? "PasswordsToolbar" : "PasswordsToolbarUnpaired"), t || sendMessageToPopup({
    subject: "nativeConnectionStateChanged",
    state: g_theState,
    appStoreURL: g_urlToDownloadNativeSupport
    })
    }

    function resetTheSession(e) {
    setGlobalState(e), g_secretSession = new SecretSession(g_nativeAppCapabilities)
    }

    function STATUSErrorReturned(e) {
    switch (secdSTATUS2string(e), g_theState) {
    case ContextState.IncompatibleOS:
    case ContextState.NativeSupportNotInstalled:
    case ContextState.CheckEngine:
    case ContextState.MSG1Set:
    case ContextState.ChallengeSent:
    break;
    case ContextState.SessionKeySet:
    g_ErrorReturned = !0, resetTheSession(ContextState.NotInSession);
    case ContextState.NotInSession:
    chrome.tabs.query({
    active: !0,
    currentWindow: !0
    }, (function(e) {
    setToolbarIcon("PasswordsToolbarUnpaired")
    }))
    }
    }

    function logMapElements(e, t, s) {}

    function consultStage1Logins(e, t) {
    return isStringEmpty(e) ? g_Stage1Logins.has(t) ? (LoginName = g_Stage1Logins.get(t), LoginName, g_Stage1Logins.delete(t), LoginName) : "" : e
    }

    function entriesFromLoginNames4URLData(e) {
    let t = e.Entries;
    return t || (t = [], Object.entries(e).sort().map((([e, s]) => {
    e.includes("Entry_") && t.push(s)
    })), t)
    }

    function setToolbarIcon(e) {
    chrome.action && chrome.action.setIcon({
    path: imageDataForName(e)
    })
    }

    function sendMessageToPopupAndCompletionList(e) {
    sendMessageToPopup(e), sendMessageToCompletionList(e)
    }

    function sendMessageToPopup(e) {
    if (g_portToPopup) try {
    g_portToPopup.postMessage(e)
    } catch (e) {}
    }

    function sendMessageToCompletionList(e) {
    if (g_portToCompletionList) try {
    g_portToCompletionList.postMessage(e)
    } catch (e) {}
    }

    function onSetUpTOTPContextMenuClicked(e, t) {
    if (g_theState !== ContextState.SessionKeySet) window.alert(g_localizer.getMessage("enableAutoFillPasswordsMessage"));
    else {
    const t = new URL(e.pageUrl);
    t.hostname, e.menuItemId, setUpTOTP(t.hostname, e.menuItemId)
    }
    }

    function connectToBackgroundNativeAppAndSetUpListeners() {
    setToolbarIcon("PasswordsToolbarUnpaired"), g_nativeAppCapabilities || (g_nativeAppCapabilities = DefaultCapabilities), g_localizer = new Localizer(g_nativeAppCapabilities), g_secretSession = new SecretSession(g_nativeAppCapabilities), chrome.runtime.onMessage.addListener(((e, t, s) => {
    const a = t.tab.id,
    n = t.frameId,
    r = new URL(t.url);
    if (r.hostname, t.tab.id, t.frameId, e.from, "content" === e.from) switch (e.subject, e.subject) {
    case "CmdCheckEstablishSession":
    CheckEstablishSession();
    break;
    case "SaveStage1LoginName":
    g_tabIdToURL.has(a) && (strURL = g_tabIdToURL.get(a), g_Stage1Logins.delete(strURL), g_tabIdToURL.delete(a)), r.hostname, e.theLogin, g_tabIdToURL.set(a, r.hostname), g_Stage1Logins.set(r.hostname, e.theLogin);
    break;
    case "CmdGetPassword4LoginName":
    const o = JSON.stringify({
    ACT: actSearch,
    URL: r.hostname,
    USR: e.theLogin
    }),
    i = g_secretSession.createSMSG(o),
    c = {
    cmd: 5,
    tabId: t.tab.id,
    frameId: t.frameId,
    url: e.theURL,
    payload: JSON.stringify({
    QID: e.subject,
    SMSG: i
    })
    };
    e.subject, e.subject, g_nativeAppPort.postMessage(c);
    break;
    case "CmdSetPassword4LoginName_URL":
    case "CmdNewAccount4URL":
    if (g_theState === ContextState.SessionKeySet) {
    e.theNLogin, r.hostname;
    let s = consultStage1Logins(e.theNLogin, r.hostname);
    if (!isStringEmpty(s)) {
    let a = JSON.stringify({
    ACT: actMaybeAdd,
    URL: "",
    USR: "",
    PWD: "",
    NURL: e.theNURL,
    NUSR: s,
    NPWD: e.theNPassword
    }),
    n = g_secretSession.createSMSG(a),
    r = {
    cmd: 6,
    tabId: t.tab.id,
    frameId: t.frameId,
    payload: JSON.stringify({
    QID: e.subject,
    SMSG: n
    })
    };
    e.subject, g_nativeAppPort.postMessage(r)
    }
    }
    break;
    case "CmdSetIconNTitle": {
    let s = e.hostPageType;
    setIsDark(e.isDark);
    let a = !1;
    switch (s) {
    case WBSAutoFillFormTypeUndetermined:
    case WBSAutoFillFormTypeAutoFillableStandard:
    case WBSAutoFillFormTypeNonAutoFillable:
    a = !1;
    break;
    case WBSAutoFillFormTypeAutoFillableLogin:
    case WBSAutoFillFormTypeNewAccount:
    case WBSAutoFillFormTypeChangePassword:
    a = !0
    }
    switch (g_TabsToStateMap.has(t.tab.id) && g_TabsToStateMap.get(t.tab.id) || g_TabsToStateMap.set(t.tab.id, a), r.hostname, t.tab.id, t.frameId, humanReadableFormType(e.hostPageType), e.hostPageType, e.hostPageType) {
    case WBSAutoFillFormTypeUndetermined:
    case WBSAutoFillFormTypeAutoFillableStandard:
    case WBSAutoFillFormTypeNonAutoFillable:
    break;
    case WBSAutoFillFormTypeAutoFillableLogin:
    case WBSAutoFillFormTypeNewAccount:
    case WBSAutoFillFormTypeChangePassword:
    let e = {
    cmd: 3,
    tabId: t.tab.id,
    frameId: t.frameId,
    payload: JSON.stringify({
    TID: "CmdSetIconNTitle",
    URL: r.hostname
    })
    };
    JSON.stringify(e), g_nativeAppPort.postMessage(e)
    }
    }
    break;
    case "ThemeChanged":
    chrome.action && (setIsDark(e.isDark), chrome.action.setIcon({
    path: imageDataForName(g_lastToolbarIconImageName)
    }));
    break;
    case "fillOneTimeCodeIntoForm":
    chrome.webNavigation.getFrame({
    tabId: t.tab.id,
    frameId: t.frameId
    }, (s => {
    s.frameId = t.frameId, didFillOneTimeCode(e.oneTimeCode, {
    id: t.tab.id
    }, s)
    }));
    break;
    case "typedUserNameChanged":
    case "keydown":
    sendMessageToCompletionList(e);
    break;
    case "CmdAddSetUpTOTPContextMenu":
    const l = !1;
    if (!chrome.contextMenus) break;
    chrome.contextMenus.create({
    title: l ? `${g_localizer.getMessage("divTOTPMenu")} (${e.totpSetupURL})` : g_localizer.getMessage("divTOTPMenu"),
    id: e.totpSetupURL,
    contexts: ["all"]
    }), chrome.contextMenus.onClicked.addListener(onSetUpTOTPContextMenuClicked);
    break;
    case "CmdRemoveSetUpTOTPContextMenus":
    chrome.contextMenus && chrome.contextMenus.removeAll();
    break;
    case "getCapabilities":
    s(g_nativeAppCapabilities);
    break;
    case "readyToReceiveMessages":
    g_tabMonitor.frameIsReadyToReceiveMessages(a, n)
    }
    }));
    try {
    (g_nativeAppPort = chrome.runtime.connectNative("com.apple.passwordmanager")).onMessage.addListener((async function(e) {
    switch (JSON.stringify(e), chrome.storage.local.remove(["lastRetryTimestamp"]), cmd2string(e.cmd), e.cmd, e.cmd) {
    case 9:
    case 10:
    resetTheSession(ContextState.CheckEngine), chrome.tabs.query({
    active: !0,
    currentWindow: !0
    }, (function(e) {
    setToolbarIcon("PasswordsToolbarUnpaired")
    })), setGlobalState(ContextState.NotInSession, !0);
    break;
    case 2:
    switch (e.payload.QID, e.payload.QID) {
    case "m0":
    thePAKE = e.payload.PAKE, setGlobalState(ContextState.MSG1Set);
    break;
    case "m2":
    try {
    g_secretSession.processMessage(e.payload.PAKE);
    setGlobalState(ContextState.SessionKeySet), thePAKE = null
    } catch (e) {
    e.code, e.message, resetTheSession(ContextState.NotInSession)
    }
    }
    break;
    case 3:
    var t = RememberIC.UnknownPage;
    switch (e.payload, e.payload) {
    case "DoNotRemember":
    t = RememberIC.DoNotRemember;
    break;
    case "RememberLoginAndPassword":
    t = RememberIC.RememberLoginAndPassword;
    break;
    case "UnknownPage":
    t = RememberIC.UnknownPage;
    break;
    case "NoValueSet":
    t = RememberIC.NoValueSet, STATUSErrorReturned(e.STATUS)
    }
    try {
    await chrome.tabs.sendMessage(e.tabId, {
    from: "background",
    subject: "RememberICSelection",
    tabId: e.tabId,
    frameId: e.frameId,
    theRememberICSelection: t,
    capabilities: g_nativeAppCapabilities
    }, {
    frameId: e.frameId
    })
    } catch (t) {
    e.tabId, e.frameId, t.message
    }
    break;
    case 4:
    t = RememberIC.UnknownPage;
    var s = [],
    a = [],
    n = [],
    r = e.payload,
    o = e.tabId,
    i = e.frameId,
    c = g_secretSession.parseSMSG(r.SMSG);
    switch ((d = JSON.parse(c)).STATUS) {
    case QueryStatus.Success:
    performance.now();
    var l = entriesFromLoginNames4URLData(d);
    l.sort(((e, t) => e.USR.localeCompare(t.USR, void 0, {
    numeric: !0,
    sensitivity: "base"
    }))), l.forEach((e => {
    if ("Passwords not saved" === e.USR) t = RememberIC.DoNotRemember;
    else if (s.push(e.USR), a.push(e.CDate || e.ModDate), n.push(e.sites[0]), "Not Included" === e.PWD) t = RememberIC.RememberLoginAndPassword;
    else t = RememberIC.UnknownPage
    })), sendMessageToPopupAndCompletionList({
    from: "background",
    subject: "users",
    arrLoginNames: s,
    arrDates: a,
    arrHLDs: n,
    tabId: o,
    frameId: i,
    theRememberICSelection: t
    });
    break;
    case QueryStatus.NoResults:
    sendMessageToPopupAndCompletionList({
    from: "background",
    subject: "users",
    arrDates: [],
    tabId: o,
    frameId: i,
    arrLoginNames: [],
    arrHLDs: [],
    theRememberICSelection: RememberIC.UnknownPage
    });
    break;
    default:
    STATUSErrorReturned(d.STATUS)
    }
    break;
    case 5:
    var d;
    r = e.payload, c = g_secretSession.parseSMSG(r.SMSG);
    switch ((d = JSON.parse(c)).STATUS) {
    case QueryStatus.Success: {
    const t = e.url,
    s = entriesFromLoginNames4URLData(d).find((e => e.sites.includes(t)));
    s && sendUsernameAndPasswordToFrameForFilling(e.tabId, e.frameId, t, s.USR, s.PWD);
    break
    }
    case QueryStatus.NoResults:
    break;
    default:
    STATUSErrorReturned(d.STATUS)
    }
    break;
    case 16:
    handleGetOneTimeCodesCommand(e);
    break;
    case 8:
    case 7:
    case 6:
    break;
    case 14:
    g_nativeAppCapabilities = e.capabilities ? e.capabilities : DefaultCapabilities, g_localizer = new Localizer(g_nativeAppCapabilities), g_tabMonitor.nativeAppSupportsQRCodeScanning = g_nativeAppCapabilities.scanForOTPURI, sendMessageToPopupAndCompletionList({
    subject: "hello",
    capabilities: g_nativeAppCapabilities
    }), resetTheSession(ContextState.NotInSession);
    break;
    case 15:
    handleOneTimeCodeAvailableCommand(e);
    break;
    case 17:
    handleDidFillOneTimeCodeCommand(e);
    break;
    case 18: {
    let e = g_secretSession.parseSMSG(r.SMSG),
    t = JSON.parse(e);
    if (JSON.stringify(t), t.STATUS === QueryStatus.Success);
    else STATUSErrorReturned(t.STATUS);
    break
    }
    default:
    cmd2string(e.cmd)
    }
    })), g_nativeAppPort.onDisconnect.addListener((e => {
    const t = chrome.runtime.lastError;
    t.message, setTimeout((() => {
    if (t.message, "Native host has exited." === t.message) chrome.storage.local.get(["lastRetryTimestamp"], (e => {
    const t = e.lastRetryTimestamp;
    let s = !1;
    if (t) {
    s = Date.now() - t > 5e3
    } else s = !0;
    s ? (chrome.storage.local.set({
    lastRetryTimestamp: Date.now()
    }), connectToBackgroundNativeAppAndSetUpListeners()) : (chrome.storage.local.remove(["lastRetryTimestamp"]), resetTheSession(ContextState.NativeSupportNotInstalled))
    }));
    else t.message, resetTheSession(ContextState.NativeSupportNotInstalled)
    }), 1e3)
    })), g_nativeAppPort.postMessage({
    cmd: 14
    })
    } catch (e) {
    resetTheSession(ContextState.NativeSupportNotInstalled)
    }
    }
    async function sendUsernameAndPasswordToFrameForFilling(t, s, a, n, r) {
    try {
    await chrome.tabs.sendMessage(t, {
    from: "background",
    subject: "fillPassword",
    tabId: t,
    frameId: s,
    username: n,
    password: r,
    url: a
    }, {
    frameId: s
    })
    } catch (t) {
    e.message
    }
    }

    function handleOneTimeCodeAvailableCommand(e) {
    getCurrentActiveTabAndFrame().then((e => getOneTimeCodes(e[0], e[1], null))).catch((e => {}))
    }

    function handleGetOneTimeCodesCommand(e) {
    let t = null;
    try {
    t = JSON.parse(g_secretSession.parseSMSG(e.payload.SMSG))
    } catch (e) {
    return
    }
    let s = t.STATUS;
    if (s !== QueryStatus.Success) return s !== QueryStatus.NoResults && STATUSErrorReturned(s), void sendMessageToPopupAndCompletionList({
    from: "background",
    subject: "oneTimeCodes",
    oneTimeCodes: []
    });
    let a = t.Entries;
    a && sendMessageToPopupAndCompletionList({
    from: "background",
    subject: "oneTimeCodes",
    oneTimeCodes: a
    })
    }
    async function handleDidFillOneTimeCodeCommand(e) {
    let t = null;
    try {
    t = JSON.parse(g_secretSession.parseSMSG(e.payload.SMSG))
    } catch (e) {
    return
    }
    let s = t.STATUS;
    if (s !== QueryStatus.Success) return void(s !== QueryStatus.NoResults && STATUSErrorReturned(s));
    let a = t.Entries;
    if (a && a.length) try {
    await chrome.tabs.sendMessage(e.tabId, {
    subject: "fillCurrentTOTPCodeIntoForm",
    oneTimeCodes: a
    }, {
    frameId: e.frameId
    })
    } catch (e) {}
    }

    function CheckEstablishSession() {
    if (g_theState === ContextState.NotInSession) ChallengePIN()
    }

    function startiCloudControlPanel() {
    var e = {
    cmd: 11
    };
    JSON.stringify(e), g_nativeAppPort.postMessage(e)
    }

    function startPasswordsApp() {
    let e = {
    cmd: 13
    };
    JSON.stringify(e), g_nativeAppPort.postMessage(e)
    }

    function setUpTOTP(e, t) {
    if (!g_nativeAppCapabilities.scanForOTPURI) return;
    const s = {
    cmd: 13,
    setUpTOTPPageURL: e,
    setUpTOTPURI: t
    };
    JSON.stringify(s), g_nativeAppPort.postMessage(s)
    }
    async function getUsernamesForMainFrameOfActiveTab() {
    if (g_theState !== ContextState.SessionKeySet) return;
    const e = await chrome.tabs.query({
    active: !0,
    currentWindow: !0
    });
    if (!e.length) return;
    const t = e[0].id;
    GetLoginNames4URL(urlFromURLString((await chrome.webNavigation.getFrame({
    tabId: t,
    frameId: 0
    })).url).hostname, t, 0)
    }

    function GetLoginNames4URL(e, t, s) {
    let a = JSON.stringify({
    ACT: actGhostSearch,
    URL: e
    }),
    n = g_secretSession.createSMSG(a),
    r = {
    cmd: 4,
    url: e,
    tabId: t,
    frameId: s,
    payload: JSON.stringify({
    QID: "CmdGetLoginNames4URL",
    SMSG: n
    })
    };
    g_timeStartedFetchingCredentials = performance.now(), g_nativeAppPort.postMessage(r)
    }

    function getOneTimeCodes(e, t, s) {
    getAllParentFrameURLsOfFrame(e, t).then((a => {
    let n = {
    ACT: actGhostSearch,
    TYPE: "oneTimeCodes",
    frameURLs: a
    };
    s && (n.username = s);
    let r = g_secretSession.createSMSG(n),
    o = {
    cmd: 16,
    tabId: e.id,
    frameId: t.frameId,
    payload: JSON.stringify({
    QID: "CmdGetOneTimeCodes",
    SMSG: r
    })
    };
    g_nativeAppPort.postMessage(o)
    })).catch((e => {}))
    }

    function didFillOneTimeCode(e, t, s) {
    if ("totp" === e.source) getAllParentFrameURLsOfFrame(t, s).then((a => {
    let n = {
    ACT: actSearch,
    TYPE: "oneTimeCodes",
    frameURLs: a
    },
    r = e.username;
    r && (n.username = r);
    let o = g_secretSession.createSMSG(n),
    i = {
    cmd: 17,
    tabId: t.id,
    frameId: s.frameId,
    payload: JSON.stringify({
    QID: "CmdDidFillOneTimeCode",
    SMSG: o
    })
    };
    g_nativeAppPort.postMessage(i)
    })).catch((e => {}))
    }

    function openURLInSafari(e) {
    g_nativeAppPort.postMessage({
    cmd: 1984,
    url: e
    })
    }

    function getAllParentFrameURLsOfFrame(e, t) {
    let s = e.id;
    return new Promise((a => {
    -1 !== t.parentFrameId ? chrome.webNavigation.getFrame({
    tabId: s,
    frameId: t.parentFrameId
    }, (s => {
    getAllParentFrameURLsOfFrame(e, s).then((e => {
    a([t.url].concat(e))
    })).catch((e => {}))
    })) : a([t.url])
    }))
    }

    function ChallengePIN() {
    if (g_theState === ContextState.NotInSession) {
    var e = {
    QID: "m0",
    PAKE: g_secretSession.initialMessage(),
    HSTBRSR: g_localizer.getMessage("browserName")
    },
    t = {
    cmd: 2,
    msg: JSON.stringify(e)
    };
    setGlobalState(ContextState.ChallengeSent);
    try {
    g_nativeAppPort.postMessage(t)
    } catch (e) {
    e.message, resetTheSession(ContextState.NativeSupportNotInstalled)
    }
    }
    }

    function PINSet(e) {
    g_secretSession.setPin(e);
    try {
    let e = {
    QID: "m2",
    PAKE: g_secretSession.processMessage(thePAKE)
    },
    t = {
    cmd: 2,
    msg: JSON.stringify(e)
    };
    g_nativeAppPort.postMessage(t)
    } catch (e) {
    e.code, e.message, resetTheSession(ContextState.NotInSession)
    }
    }

    function getCurrentActiveTabAndFrame() {
    return new Promise((e => {
    chrome.tabs.query({
    active: !0,
    currentWindow: !0
    }, (function(t) {
    chrome.webNavigation.getAllFrames({
    tabId: t[0].id
    }, (function(s) {
    e([t[0], s[0]])
    }))
    }))
    }))
    }

    function getCurrentActiveTabAndItsFrames() {
    return new Promise((e => {
    chrome.tabs.query({
    active: !0,
    currentWindow: !0
    }, (function(t) {
    chrome.webNavigation.getAllFrames({
    tabId: t[0].id
    }, (function(s) {
    e([t[0], s])
    }))
    }))
    }))
    }

    function canFillOneTimeCodes() {
    return (g_nativeAppCapabilities || DefaultCapabilities).canFillOneTimeCodes
    }

    function setUpPortToCompetionList(e) {
    g_portToCompletionList = e, e.onMessage.addListener((async function(t) {
    switch (JSON.stringify(t), t.subject) {
    case "getContextAndMetadataFromContent":
    getCurrentActiveTabAndItsFrames().then((function(t) {
    const s = t[0].id;
    for (const a of t[1]) {
    const t = a.frameId;
    chrome.tabs.sendMessage(s, {
    from: "background",
    subject: "getContextAndMetadataForActiveTextField"
    }, {
    frameId: t
    }, (function(a) {
    a && e.postMessage({
    subject: "replyForGetContextAndMetadataFromContent",
    state: g_theState,
    tabId: s,
    frameId: t,
    url: a.url,
    textFieldMetadata: a.textFieldMetadata,
    formMetadata: a.formMetadata,
    presetUserName: a.presetUserName,
    hostname: a.hostname,
    canFillOneTimeCodes: canFillOneTimeCodes()
    })
    }))
    }
    })).catch((e => {}));
    break;
    case "GetLoginNames4URL":
    GetLoginNames4URL(t.hostname, t.tabId, t.frameId);
    break;
    case "getOneTimeCodes":
    const s = t.tabId,
    a = t.frameId;
    chrome.webNavigation.getFrame({
    tabId: s,
    frameId: a
    }, (e => {
    e.frameId = a, getOneTimeCodes({
    id: t.tabId
    }, e, t.username)
    }));
    break;
    case "openPasswordManagerAndDismissCompletionList":
    startPasswordsApp();
    try {
    await chrome.tabs.sendMessage(t.tabId, {
    subject: "dismissCompletionList"
    }, {
    frameId: t.frameId
    })
    } catch (e) {}
    break;
    case "openURLInSafari":
    openURLInSafari(t.url);
    break;
    case "resizeCompletionList":
    case "fillLoginIntoForm":
    case "fillOneTimeCodeIntoForm":
    case "dismissCompletionList":
    try {
    await chrome.tabs.sendMessage(t.tabId, t, {
    frameId: t.frameId
    })
    } catch (e) {}
    }
    })), e.onDisconnect.addListener((e => {
    e === g_portToCompletionList && (g_portToCompletionList = null)
    })), sendMessageToCompletionList({
    subject: "hello",
    capabilities: g_nativeAppCapabilities
    })
    }

    function setUpPortToPopup(e) {
    g_portToPopup = e, e.onMessage.addListener((function(t) {
    switch (JSON.stringify(t), t.subject) {
    case "getInitialPopupState":
    e.postMessage({
    subject: "nativeConnectionStateChanged",
    state: g_theState,
    appStoreURL: g_urlToDownloadNativeSupport
    });
    break;
    case "tryToEstablishNativeConnectionInResponseToUserActivatingPopup":
    chrome.storage.local.set({
    lastRetryTimestamp: Date.now()
    }), connectToBackgroundNativeAppAndSetUpListeners();
    break;
    case "challengePIN":
    ChallengePIN();
    break;
    case "userEnteredPIN":
    PINSet(t.pin);
    break;
    case "GetLoginNames4URL":
    GetLoginNames4URL(t.hostname, t.tabId, t.frameId);
    break;
    case "openPasswordManager":
    startPasswordsApp();
    break;
    case "startiCloudControlPanel":
    startiCloudControlPanel();
    break;
    case "SetUpTOTP":
    setUpTOTP(t.theURL, t.theTOTPURI);
    break;
    case "openURLInSafari":
    openURLInSafari(t.url)
    }
    })), e.onDisconnect.addListener((function() {
    g_theState === ContextState.MSG1Set && PINSet(""), g_portToPopup = null
    })), sendMessageToPopup({
    subject: "hello",
    capabilities: g_nativeAppCapabilities
    })
    }
    chrome.storage.local.get("isDark", (function(e) {
    void 0 !== e.isDark && (g_isDark = e.isDark), g_lastToolbarIconImageName && setToolbarIcon(g_lastToolbarIconImageName)
    })), setUpEventListners(), checkForValidOS() ? connectToBackgroundNativeAppAndSetUpListeners() : (chrome.storage.local.get("hideUnsupportedOSPrompt", (function(e) {
    e.hideUnsupportedOSPrompt || (chrome.storage.local.set({
    hideUnsupportedOSPrompt: 1
    }), window.alert(g_localizer.getMessage("unsupportedOS")))
    })), setGlobalState(ContextState.IncompatibleOS)), chrome.windows.onFocusChanged.addListener((async e => {
    if (!g_nativeAppPort || e === chrome.windows.WINDOW_ID_NONE) return;
    let t = await chrome.tabs.query({
    active: !0,
    currentWindow: !0
    });
    if (t.length < 1) return;
    const s = t[0].id;
    if (!s) return;
    const a = {
    cmd: 8,
    tabId: s,
    event: 1
    };
    JSON.stringify(a), g_nativeAppPort.postMessage(a)
    })), chrome.tabs.onActivated.addListener((e => {
    if (JSON.stringify(e), !g_nativeAppPort) return;
    let t = {
    cmd: 8,
    tabId: e.tabId,
    event: 1
    };
    JSON.stringify(t), g_nativeAppPort.postMessage(t)
    })), chrome.tabs.onRemoved.addListener(((e, t) => {
    if (JSON.stringify(t), !g_nativeAppPort) return;
    let s = {
    cmd: 8,
    tabId: e,
    event: 0
    };
    JSON.stringify(s), g_nativeAppPort.postMessage(s), g_TabsToStateMap.delete(e)
    })), chrome.runtime.onConnect.addListener((function(e) {
    e.name, "completionList" === e.name ? setUpPortToCompetionList(e) : "popup" === e.name ? setUpPortToPopup(e) : e.name
    }));
    15,527 changes: 15,527 additions & 0 deletions content_script.js
    15,527 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
    685 changes: 685 additions & 0 deletions page_popup.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,685 @@
    var pwlog = void 0,
    pwerror = void 0;

    function isStringEmpty(e) {
    return !e || 0 === e.length
    }

    function urlFromURLString(e) {
    try {
    return new URL(e)
    } catch {
    return null
    }
    }

    function humanReadableFormType(e) {
    switch (e) {
    case WBSAutoFillFormTypeUndetermined:
    return "Undetermined";
    case WBSAutoFillFormTypeAutoFillableStandard:
    return "AutoFillable:Standard";
    case WBSAutoFillFormTypeNonAutoFillable:
    return "NonAutoFillable";
    case WBSAutoFillFormTypeAutoFillableLogin:
    return "AutoFillable:Login";
    case WBSAutoFillFormTypeNewAccount:
    return "NewAccount";
    case WBSAutoFillFormTypeChangePassword:
    return "ChangePassword";
    case WBSAutoFillFormTypeFoundTOTPURI:
    return "FoundTOTPUri"
    }
    return "Unrecognized"
    }

    function domainsForDisplayFromUsernamesAndDomains(e, t) {
    const n = e.length;
    let o = t.map((function(e) {
    return e.replace(/^(www|m)\./, "")
    })),
    s = [];
    for (var a = 0; a < n; a++) s.push([e[a], o[a]]);
    for (a = 0; a < n; a++) {
    let e = [];
    for (var i = a + 1; i < n; i++) s[a].join("\n") === s[i].join("\n") && (e.length || e.push(a), e.push(i));
    for (let n of e) o[n] = t[n]
    }
    return o
    }

    function urlIsBrowserURL(e) {
    const t = e.protocol;
    return "chrome:" === t || "edge:" === t || "about:" == t
    }

    function isExtensionContextInvalidatedError(e) {
    return "Extension context invalidated." === e.message
    }

    function capabilitiesDeclaresMacOS(e) {
    try {
    return "macos" === e.operatingSystem.name
    } catch {
    return !1
    }
    }
    class Localizer {
    static configureDocumentElementForLanguage(e, t) {
    switch (t) {
    case "he":
    case "ar":
    case "fa":
    e.setAttribute("dir", "rtl"), e.setAttribute("lang", t)
    }
    }
    #e = {};
    constructor(e) {
    e && (this.#e = e.operatingSystem)
    }
    getMessage(e, t, n) {
    const o = this.messageNamesToTry(e);
    for (let e of o) {
    let o;
    try {
    o = chrome.i18n.getMessage(e, t, n)
    } catch {
    o = chrome.i18n.getMessage(e, t)
    }
    if (o) return o
    }
    return ""
    }
    messageNamesToTry(e) {
    let t = [];
    const n = this.#e,
    o = n ? n.name : void 0,
    s = n ? n.majorVersion : void 0,
    a = n ? n.minorVersion : void 0,
    i = void 0 !== s;
    return o && i && void 0 !== a && t.push(`${e}_${o}_${s}_${a}`), o && i && t.push(`${e}_${o}_${s}`), o ? t.push(`${e}_${o}`) : t.push(`${e}_${this.#t}`), t.push(e), t
    }
    get #t() {
    return navigator.platform.startsWith("Mac") ? "macos" : "windows"
    }
    }
    class ExtensionSettings {
    #n = !1;
    #o = !0;
    #s = !0;
    eventTarget = new EventTarget;
    constructor(e = !1) {
    this.#n = e, this.#a(), this.#i()
    }
    get enableInPageAutoFill() {
    return this.#o
    }
    set enableInPageAutoFill(e) {
    this.#o = e, this.#r()
    }
    get allowExtensionToControlAutoFillSettings() {
    return this.#s
    }
    set allowExtensionToControlAutoFillSettings(e) {
    this.#s = e, this.#l().then(this.#r.bind(this))
    }
    #l() {
    return this.#s ? this.attemptToControlBrowserAutoFillSettings() : this.clearControlOfBrowserAutoFillSettings()
    }
    async attemptToControlBrowserAutoFillSettings() {
    if (this.#n) throw new Error("This Settings instance does not allow writing browser settings");
    const e = await Promise.allSettled([this.#d(chrome.privacy.services.passwordSavingEnabled, !1), this.#d(chrome.privacy.services.autofillCreditCardEnabled, !1), this.#d(chrome.privacy.services.autofillAddressEnabled, !1)]);
    return this.#c(), e
    }
    async clearControlOfBrowserAutoFillSettings() {
    if (this.#n) throw new Error("This Settings instance does not allow writing browser settings");
    const e = await Promise.allSettled([this.#u(chrome.privacy.services.passwordSavingEnabled), this.#u(chrome.privacy.services.autofillCreditCardEnabled), this.#u(chrome.privacy.services.autofillAddressEnabled)]);
    return this.#c(), e
    }
    #a() {
    let e = new Promise((e => {
    chrome.storage.sync.get({
    enableInPageAutoFill: !0,
    allowExtensionToControlAutoFillSettings: !0
    }, (t => {
    this.#o = t.enableInPageAutoFill, this.#s = t.allowExtensionToControlAutoFillSettings, e()
    }))
    }));
    return this.#n || (e = e.then(this.#l.bind(this))), e.then(this.#c.bind(this))
    }
    #r() {
    return new Promise((e => {
    chrome.storage.sync.set({
    enableInPageAutoFill: this.#o,
    allowExtensionToControlAutoFillSettings: this.#s
    }, e)
    })).then(this.#c.bind(this))
    }
    #i() {
    this.#n || (chrome.privacy.services.passwordSavingEnabled && chrome.privacy.services.passwordSavingEnabled.onChange.addListener((e => {
    this.#c()
    })), chrome.privacy.services.autofillCreditCardEnabled && chrome.privacy.services.autofillCreditCardEnabled.onChange.addListener((e => {
    this.#c()
    })), chrome.privacy.services.autofillAddressEnabled && chrome.privacy.services.autofillAddressEnabled.onChange.addListener((e => {
    this.#c()
    })))
    }
    #c() {
    const e = new CustomEvent("settingsChanged", {
    detail: {
    enableInPageAutoFill: this.#o
    }
    });
    this.eventTarget.dispatchEvent(e)
    }
    async #d(e, t) {
    let n;
    try {
    n = await this.#g(e)
    } catch (e) {
    return
    }
    if (n) {
    if (n.value === t) return {
    details: n,
    newValue: t
    };
    try {
    n = await e.set({
    value: t
    })
    } catch (e) {
    return
    }
    return {
    details: n,
    newValue: t
    }
    }
    }
    async #g(e) {
    if (!e) throw new Error(`Unable to get ${e} setting.`);
    const t = await e.get({});
    if ("not_controllable" === t.levelOfControl) throw new Error(`Cannot control ${e} setting.`);
    return t
    }
    async #u(e) {
    if (!e) throw new Error(`Unable to clear browser setting: ${e}.`);
    await e.clear({})
    }
    }
    const ContextState = {
    IncompatibleOS: "IncompatibleOS",
    NotInSession: "NotInSession",
    NativeSupportNotInstalled: "NativeSupportNotInstalled",
    CheckEngine: "CheckEngine",
    ChallengeSent: "ChallengeSent",
    MSG1Set: "MSG1Set",
    SessionKeySet: "SessionKeySet"
    },
    DataState = {
    Initial: "Initial",
    Frame0Processed: "Frame0Processed",
    DataProcessed: "DataProcessed"
    },
    RememberIC = {
    NoValueSet: "NoValueSet",
    UnknownPage: "UnknownPage",
    DoNotRemember: "DoNotRemember",
    RememberLoginAndPassword: "RememberLoginAndPassword"
    },
    WBSAutoFillFormTypeUndetermined = 0,
    WBSAutoFillFormTypeAutoFillableStandard = 1,
    WBSAutoFillFormTypeNonAutoFillable = 2,
    WBSAutoFillFormTypeAutoFillableLogin = 3,
    WBSAutoFillFormTypeNewAccount = 4,
    WBSAutoFillFormTypeChangePassword = 5,
    WBSAutoFillFormTypeFoundTOTPURI = 6;
    var g_lastUpdatedPopupContentsState, g_portToBackgroundPage = null,
    g_appStoreURL = null,
    g_capabilities = null,
    g_localizer = new Localizer;

    function setControlText(e, t) {
    var n = document.getElementById(e);
    n && (n.textContent = g_localizer.getMessage(t), n.textContent)
    }

    function setMessageTitle(e) {
    var t = document.getElementById("divMessageBoardTitle");
    t && (t.textContent = g_localizer.getMessage(e), t.textContent)
    }

    function setMessageSubtitle(e) {
    var t = document.getElementById("divMessageBoardMessage");
    t && (t.textContent = g_localizer.getMessage(e), t.textContent)
    }

    function showMessage(e, t, n) {
    document.querySelector("#iCloudIconId").style.display = n ? "block" : "none", setMessageTitle(e), setMessageSubtitle(t);
    let o = document.getElementById("divMessageBoard");
    o.style.display = "block", n ? o.classList.add("logo-is-present") : o.classList.remove("logo-is-present")
    }

    function showMessageWithOpenPasswordManagerButton(e, t, n) {
    showMessage(e, t);
    let o = document.querySelector("#openPasswordManagerList");
    if (!o.children.length) {
    o.appendChild(listItemForOpenPasswordManager());
    capabilitiesDeclaresMacOS(g_capabilities) && n && o.appendChild(listItemForOpenPageInSafari())
    }
    }

    function SetOpeniC4WTitleText(e) {
    var t = document.getElementById("idOpeniC4WTitle");
    t && (t.textContent = g_localizer.getMessage(e), t.textContent)
    }

    function SetOpeniC4WButtonText(e) {
    var t = document.getElementById("idOpeniC4WButton");
    t && (t.textContent = g_localizer.getMessage(e), t.textContent)
    }

    function clearCredentialListContents() {
    let e = document.getElementById("credentialList");
    for (; e.firstChild;) e.removeChild(e.lastChild)
    }

    function tryToEstablishNativeConnectionInResponseToUserActivatingPopupAfterDelay() {
    setTimeout((function() {
    sendMessageToBackgroundPage({
    subject: "tryToEstablishNativeConnectionInResponseToUserActivatingPopup"
    })
    }), 50)
    }

    function updatePopupContents(e) {
    if (g_lastUpdatedPopupContentsState && g_lastUpdatedPopupContentsState === ContextState.NativeSupportNotInstalled && e === ContextState.NativeSupportNotInstalled) return;
    g_lastUpdatedPopupContentsState = e;
    let t = document.getElementById("divPIN"),
    n = document.getElementById("divMessageBoard"),
    o = document.getElementById("divICs"),
    s = document.getElementById("divDownloadPage"),
    a = document.getElementById("divOpeniC4WPage");
    for (let e of [t, n, o, s, a]) e.style.display = "none";
    chrome.tabs.query({
    active: !0,
    currentWindow: !0
    }, (function(n) {
    switch (e) {
    case ContextState.IncompatibleOS:
    document.querySelector("#openPasswordManagerList").remove(), showMessage("extName", "unsupportedOS", !0);
    break;
    case ContextState.NativeSupportNotInstalled:
    setControlText("downloadMessage", "downloadMessage"), g_appStoreURL ? setControlText("downloadButton", "downloadButton") : document.getElementById("downloadButton").display = "none", document.querySelector("#iCloudIconId").style.display = "block", s.classList.add("logo-is-present"), s.style.display = "block", tryToEstablishNativeConnectionInResponseToUserActivatingPopupAfterDelay();
    break;
    case ContextState.NotInSession:
    showMessage("extName", "GettingPasswords"), sendMessageToBackgroundPage({
    subject: "challengePIN"
    });
    break;
    case ContextState.CheckEngine:
    SetOpeniC4WTitleText("CheckEngineMessage"), SetOpeniC4WButtonText("openiCloudForWindowsButtonText"), a.style.display = "block";
    break;
    case ContextState.ChallengeSent:
    case ContextState.MSG1Set:
    setControlText("divPINTitle", "divPINTitle"), setControlText("divPINMessage", "divPINMessage"), mapOverPINFields((function(e) {
    e.value = "", e.onkeydown = pinKeyHandler
    })), t.style.display = "block", document.querySelector("#iCloudIconId").style.display = "block", document.getElementById("PIN0").focus();
    break;
    case ContextState.SessionKeySet: {
    setMessageTitle("extName", "GettingPasswords"), setControlText("divICsMessage", "divICsMessage"), clearCredentialListContents();
    const e = n[0].id;
    chrome.webNavigation.getAllFrames({
    tabId: e
    }, (t => {
    t.forEach((async (t, o) => {
    JSON.stringify(t);
    const s = t.frameId,
    a = new URL(t.url),
    i = a.protocol;
    if ("http:" !== i && "https:" !== i) return t.url, void showMessageWithOpenPasswordManagerButton("GenericPopupTitle", "divNoPasswordsMessage", !1);
    let r;
    try {
    r = await chrome.tabs.sendMessage(e, {
    from: "popup",
    subject: "getPageType",
    URL: a.hostname,
    tabId: e,
    frameId: s
    }, {
    frameId: s
    })
    } catch (e) {
    return void e.message
    }
    switch (r || (a.hostname, n[0].id, t.frameId, r = WBSAutoFillFormTypeUndetermined), a.hostname, n[0].id, t.frameId, humanReadableFormType(r), humanReadableFormType(r), r) {
    case WBSAutoFillFormTypeUndetermined:
    case WBSAutoFillFormTypeAutoFillableStandard:
    case WBSAutoFillFormTypeNonAutoFillable:
    showMessageWithOpenPasswordManagerButton("GenericPopupTitle", "divNoPasswordsMessage", !0);
    break;
    case WBSAutoFillFormTypeAutoFillableLogin:
    case WBSAutoFillFormTypeChangePassword:
    case WBSAutoFillFormTypeNewAccount:
    showMessage("extName", "GettingPasswords"), sendMessageToBackgroundPage({
    subject: "GetLoginNames4URL",
    hostname: a.hostname,
    tabId: n[0].id,
    frameId: t.frameId
    });
    break;
    case WBSAutoFillFormTypeFoundTOTPURI: {
    let e;
    try {
    e = await chrome.tabs.sendMessage(n[0].id, {
    from: "popup",
    subject: "getTOTPSetupInfo",
    URL: a.hostname,
    tabId: n[0].id,
    frameId: t.frameId
    }, {
    frameId: t.frameId
    })
    } catch (e) {
    break
    }
    updatePopupContentsWithTOTPSetupInfo(e, a.hostname, n[0].id, t.frameId);
    break
    }
    }
    }))
    }));
    break
    }
    default:
    t.style.display = "block"
    }
    }))
    }

    function listItemMouseOverHandler(e) {
    let t = e.target.closest("li");
    if (!t) return;
    let n = t.closest("ul");
    if (n) {
    for (let e of n.querySelectorAll("li")) e.classList.remove("active");
    t.classList.add("active")
    }
    }

    function listItemMouseOutHandler(e) {
    let t = e.target.closest("li");
    t && t.classList.remove("active")
    }

    function updatePopupContentsWithTOTPSetupInfo(e, t, n, o) {
    let s = document.getElementById("divPIN"),
    a = document.getElementById("divMessageBoard"),
    i = document.getElementById("divICs"),
    r = document.getElementById("divDownloadPage"),
    l = document.getElementById("divOpeniC4WPage");
    for (let e of [s, a, i, r, l]) e.style.display = "none";
    let d = document.getElementById("credentialList");
    try {
    document.querySelector("#iCloudIconId").style.display = "none", clearCredentialListContents();
    for (const [n, o] of Object.entries(e)) {
    let e = document.createElement("li");
    e.classList.add("selectable"), e.classList.add("credential"), e.onmouseover = listItemMouseOverHandler, e.onmouseout = listItemMouseOutHandler;
    let n = document.createElement("img");
    n.setAttribute("src", "images/key.svg"), e.appendChild(n);
    let s = document.createElement("p");
    s.classList.add("totpwebsite"), s.textContent = t, e.appendChild(s), e.addEventListener("click", (function() {
    chrome.tabs.query({
    active: !0,
    currentWindow: !0
    }, (function(e) {
    sendMessageToBackgroundPage({
    subject: "SetUpTOTP",
    theURL: t,
    theTOTPURI: o
    }), window.close()
    }))
    })), d.appendChild(e)
    }
    d.appendChild(listItemForOpenPasswordManager())
    } catch (e) {
    e.message
    }
    let c = document.querySelector("#divMessageBoard .credential-list");
    c && c.remove(), setControlText("divICsMessage", "divTOTPTitle"), i.style.display = "block"
    }
    async function updatePopupContents_ICs(e, t, n, o, s, a) {
    var i = document.getElementById("divPIN"),
    r = document.getElementById("divMessageBoard"),
    l = document.getElementById("divICs"),
    d = document.getElementById("divDownloadPage"),
    c = document.getElementById("divOpeniC4WPage");
    for (let e of [i, r, l, d, c]) e.style.display = "none";
    let u = document.getElementById("credentialList");
    switch (e) {
    case RememberIC.UnknownPage:
    showMessageWithOpenPasswordManagerButton("GenericPopupTitle", "divNoPasswordsMessage", !0);
    break;
    case RememberIC.DoNotRemember:
    showMessageWithOpenPasswordManagerButton("divDoNotRememberTitle", "divDoNotRememberMessage", !0);
    break;
    case RememberIC.RememberLoginAndPassword: {
    let a;
    try {
    a = await chrome.tabs.sendMessage(t, {
    from: "popup",
    subject: "getPresetUserNameAndURL",
    tabId: t,
    frameId: n
    }, {
    frameId: n
    })
    } catch (e) {
    return
    }
    JSON.stringify(a), document.querySelector("#iCloudIconId").style.display = "none", clearCredentialListContents();
    let i = "";
    a.isPresetUserNamePresent && (i = a.presetUserName);
    const r = function() {
    const e = /(.*)@/.exec(i);
    return e ? e[1] : null
    }(),
    d = domainsForDisplayFromUsernamesAndDomains(o, s),
    c = o.length;
    let m = [],
    p = [],
    h = [];
    for (var g = 0; g < c; g++) {
    let a = s[g],
    l = o[g],
    c = d[g];
    const u = l.toLowerCase().startsWith(i.toLowerCase()),
    S = u || l.toLowerCase().startsWith(r ? r.toLowerCase() : null);
    let w = document.createElement("li");
    w.classList.add("selectable"), w.classList.add("credential"), w.onmouseover = listItemMouseOverHandler, w.onmouseout = listItemMouseOutHandler;
    let y = document.createElement("img");
    y.setAttribute("src", "images/key.svg"), w.appendChild(y);
    let v = document.createElement("p");
    v.classList.add("name"), isStringEmpty(l) ? (v.classList.add("no-user-name"), v.textContent = g_localizer.getMessage("NoUserName")) : v.textContent = l, w.appendChild(v);
    let C = document.createElement("p");
    C.classList.add("website"), C.textContent = c, w.appendChild(C), w.addEventListener("click", (async function() {
    try {
    await chrome.tabs.sendMessage(t, {
    from: "popup",
    subject: "fillLoginIntoForm",
    theRememberICSelection: e,
    tabId: t,
    frameId: n,
    theLogin: l,
    theURL: a
    }, {
    frameId: n
    })
    } catch (e) {
    return
    }
    window.close()
    })), u ? m.push(w) : S ? p.push(w) : h.push(w)
    }
    for (const e of m) u.appendChild(e);
    for (const e of p) u.appendChild(e);
    for (const e of h) u.appendChild(e);
    u.appendChild(listItemForOpenPasswordManager());
    const S = capabilitiesDeclaresMacOS(g_capabilities),
    w = !urlIsBrowserURL(new URL(a.url));
    S && w && u.appendChild(listItemForOpenPageInSafari());
    let y = document.querySelector("#divMessageBoard .credential-list");
    y && y.remove(), l.style.display = "block";
    break
    }
    }
    }

    function listItemForOpenPasswordManager() {
    let e = document.createElement("li");
    return e.classList.add("selectable"), e.classList.add("open-password-manager"), e.onmouseover = listItemMouseOverHandler, e.onmouseout = listItemMouseOutHandler, e.textContent = g_localizer.getMessage("divOpenPasswords"), e.addEventListener("click", openPasswordsButtonHandler), e
    }

    function listItemForOpenPageInSafari() {
    let e = document.createElement("li");
    return e.classList.add("selectable"), e.classList.add("open-safari"), e.onmouseover = listItemMouseOverHandler, e.onmouseout = listItemMouseOutHandler, e.textContent = g_localizer.getMessage("openThisPageInSafari"), e.addEventListener("click", openThisPageInSafariButtonHandler), e
    }

    function sendMessageToBackgroundPage(e) {
    if (g_portToBackgroundPage) try {
    g_portToBackgroundPage.postMessage(e)
    } catch (e) {}
    }

    function mapOverPINFields(e) {
    return [document.getElementById("PIN0"), document.getElementById("PIN1"), document.getElementById("PIN2"), document.getElementById("PIN3"), document.getElementById("PIN4"), document.getElementById("PIN5")].map(e)
    }

    function pinKeyHandler(e) {
    let t = e.target,
    n = t ? t.previousElementSibling : null,
    o = t ? t.nextElementSibling : null,
    s = e.keyCode || e.charCode;
    switch (s) {
    case 46:
    t.value = "", e.preventDefault();
    break;
    case 8:
    return t.value = "", e.preventDefault(), n && (n.focus(), n.select()), !1;
    case 37:
    n && (e.preventDefault(), n.focus(), n.select());
    break;
    case 39:
    o && (e.preventDefault(), o.focus(), o.select());
    break;
    default:
    if (e.preventDefault(), !(s >= 48 && s <= 57 || s >= 96 && s <= 105)) {
    t.value = "";
    break
    }
    if (this.value = e.key, o) {
    o.focus();
    break
    }
    let a = mapOverPINFields((function(e) {
    return e.onkeydown = null, e.value.trim()
    })).join("");
    sendMessageToBackgroundPage({
    subject: "userEnteredPIN",
    pin: a
    })
    }
    }

    function openPasswordsButtonHandler(e) {
    sendMessageToBackgroundPage({
    subject: "openPasswordManager"
    }), window.close()
    }

    function openThisPageInSafariButtonHandler(e) {
    chrome.tabs.query({
    active: !0,
    currentWindow: !0
    }, (e => {
    sendMessageToBackgroundPage({
    subject: "openURLInSafari",
    url: e[0].url
    }), window.close()
    }))
    }
    document.documentElement.addEventListener("keydown", (function(e) {
    let t = document.querySelector("li.active"),
    n = e.key,
    o = t ? t.previousElementSibling : null,
    s = t ? t.nextElementSibling : null;
    switch (n) {
    case "ArrowUp":
    if (!t) break;
    return e.preventDefault(), t.classList.remove("active"), o && o.classList.add("active"), !1;
    case "ArrowDown":
    if (e.preventDefault(), !t) {
    let e = document.querySelector("li");
    return e && e.classList.add("active"), !1
    }
    return s && (t.classList.remove("active"), s.classList.add("active")), !1;
    case "Enter":
    if (t) return e.preventDefault(), t.click(), !1
    }
    })), window.addEventListener("load", (e => {
    let t = chrome.i18n.getUILanguage();
    Localizer.configureDocumentElementForLanguage(document.documentElement, t);
    try {
    (g_portToBackgroundPage = chrome.runtime.connect({
    name: "popup"
    })).onMessage.addListener((function(e, t, n) {
    switch (JSON.stringify(e), e.subject) {
    case "hello":
    g_capabilities = e.capabilities, g_localizer = new Localizer(e.capabilities);
    break;
    case "nativeConnectionStateChanged":
    g_appStoreURL = e.appStoreURL, updatePopupContents(e.state);
    break;
    case "users":
    chrome.tabs.query({
    active: !0,
    currentWindow: !0
    }, (async function(t) {
    t[0].id === e.tabId && await updatePopupContents_ICs(e.theRememberICSelection, e.tabId, e.frameId, e.arrLoginNames, e.arrHLDs, e.arrDates)
    }));
    break;
    case "oneTimeCodes":
    break;
    default:
    e.from, e.subject
    }
    })), g_portToBackgroundPage.onDisconnect.addListener((() => {
    g_portToBackgroundPage = null
    })), sendMessageToBackgroundPage({
    subject: "getInitialPopupState"
    });
    let e = document.createElement("span");
    e.textContent = g_localizer.getMessage("extName");
    let t = document.createElement("img");
    t.setAttribute("src", "images/PasswordsToolbar_icon32.png"), t.classList.add("fromiCloudPasswordsMenuIcon"), e.appendChild(t), document.querySelector("#fromiCloudPasswords").appendChild(e)
    } catch (e) {
    e.message
    }
    })), document.getElementById("downloadButton").onclick = function(e) {
    chrome.tabs.create({
    url: g_appStoreURL
    })
    }, document.getElementById("idOpeniC4WButton").onclick = function() {
    sendMessageToBackgroundPage({
    subject: "startiCloudControlPanel"
    }), window.close()
    }, document.getElementById("dismiss").onclick = function() {
    window.close()
    }, window.onfocus = () => {
    sendMessageToBackgroundPage({
    subject: "getInitialPopupState"
    })
    }, chrome.runtime.onMessage.addListener(((e, t, n) => {
    e.from, e.subject
    }));
    238 changes: 238 additions & 0 deletions settings.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,238 @@
    var pwlog = void 0,
    pwerror = void 0;

    function isStringEmpty(e) {
    return !e || 0 === e.length
    }

    function urlFromURLString(e) {
    try {
    return new URL(e)
    } catch {
    return null
    }
    }

    function humanReadableFormType(e) {
    switch (e) {
    case WBSAutoFillFormTypeUndetermined:
    return "Undetermined";
    case WBSAutoFillFormTypeAutoFillableStandard:
    return "AutoFillable:Standard";
    case WBSAutoFillFormTypeNonAutoFillable:
    return "NonAutoFillable";
    case WBSAutoFillFormTypeAutoFillableLogin:
    return "AutoFillable:Login";
    case WBSAutoFillFormTypeNewAccount:
    return "NewAccount";
    case WBSAutoFillFormTypeChangePassword:
    return "ChangePassword";
    case WBSAutoFillFormTypeFoundTOTPURI:
    return "FoundTOTPUri"
    }
    return "Unrecognized"
    }

    function domainsForDisplayFromUsernamesAndDomains(e, t) {
    const n = e.length;
    let o = t.map((function(e) {
    return e.replace(/^(www|m)\./, "")
    })),
    i = [];
    for (var r = 0; r < n; r++) i.push([e[r], o[r]]);
    for (r = 0; r < n; r++) {
    let e = [];
    for (var s = r + 1; s < n; s++) i[r].join("\n") === i[s].join("\n") && (e.length || e.push(r), e.push(s));
    for (let n of e) o[n] = t[n]
    }
    return o
    }

    function urlIsBrowserURL(e) {
    const t = e.protocol;
    return "chrome:" === t || "edge:" === t || "about:" == t
    }

    function isExtensionContextInvalidatedError(e) {
    return "Extension context invalidated." === e.message
    }

    function capabilitiesDeclaresMacOS(e) {
    try {
    return "macos" === e.operatingSystem.name
    } catch {
    return !1
    }
    }
    class Localizer {
    static configureDocumentElementForLanguage(e, t) {
    switch (t) {
    case "he":
    case "ar":
    case "fa":
    e.setAttribute("dir", "rtl"), e.setAttribute("lang", t)
    }
    }
    #e = {};
    constructor(e) {
    e && (this.#e = e.operatingSystem)
    }
    getMessage(e, t, n) {
    const o = this.messageNamesToTry(e);
    for (let e of o) {
    let o;
    try {
    o = chrome.i18n.getMessage(e, t, n)
    } catch {
    o = chrome.i18n.getMessage(e, t)
    }
    if (o) return o
    }
    return ""
    }
    messageNamesToTry(e) {
    let t = [];
    const n = this.#e,
    o = n ? n.name : void 0,
    i = n ? n.majorVersion : void 0,
    r = n ? n.minorVersion : void 0,
    s = void 0 !== i;
    return o && s && void 0 !== r && t.push(`${e}_${o}_${i}_${r}`), o && s && t.push(`${e}_${o}_${i}`), o ? t.push(`${e}_${o}`) : t.push(`${e}_${this.#t}`), t.push(e), t
    }
    get #t() {
    return navigator.platform.startsWith("Mac") ? "macos" : "windows"
    }
    }
    class ExtensionSettings {
    #n = !1;
    #o = !0;
    #i = !0;
    eventTarget = new EventTarget;
    constructor(e = !1) {
    this.#n = e, this.#r(), this.#s()
    }
    get enableInPageAutoFill() {
    return this.#o
    }
    set enableInPageAutoFill(e) {
    this.#o = e, this.#l()
    }
    get allowExtensionToControlAutoFillSettings() {
    return this.#i
    }
    set allowExtensionToControlAutoFillSettings(e) {
    this.#i = e, this.#a().then(this.#l.bind(this))
    }
    #a() {
    return this.#i ? this.attemptToControlBrowserAutoFillSettings() : this.clearControlOfBrowserAutoFillSettings()
    }
    async attemptToControlBrowserAutoFillSettings() {
    if (this.#n) throw new Error("This Settings instance does not allow writing browser settings");
    const e = await Promise.allSettled([this.#g(chrome.privacy.services.passwordSavingEnabled, !1), this.#g(chrome.privacy.services.autofillCreditCardEnabled, !1), this.#g(chrome.privacy.services.autofillAddressEnabled, !1)]);
    return this.#c(), e
    }
    async clearControlOfBrowserAutoFillSettings() {
    if (this.#n) throw new Error("This Settings instance does not allow writing browser settings");
    const e = await Promise.allSettled([this.#u(chrome.privacy.services.passwordSavingEnabled), this.#u(chrome.privacy.services.autofillCreditCardEnabled), this.#u(chrome.privacy.services.autofillAddressEnabled)]);
    return this.#c(), e
    }
    #r() {
    let e = new Promise((e => {
    chrome.storage.sync.get({
    enableInPageAutoFill: !0,
    allowExtensionToControlAutoFillSettings: !0
    }, (t => {
    this.#o = t.enableInPageAutoFill, this.#i = t.allowExtensionToControlAutoFillSettings, e()
    }))
    }));
    return this.#n || (e = e.then(this.#a.bind(this))), e.then(this.#c.bind(this))
    }
    #l() {
    return new Promise((e => {
    chrome.storage.sync.set({
    enableInPageAutoFill: this.#o,
    allowExtensionToControlAutoFillSettings: this.#i
    }, e)
    })).then(this.#c.bind(this))
    }
    #s() {
    this.#n || (chrome.privacy.services.passwordSavingEnabled && chrome.privacy.services.passwordSavingEnabled.onChange.addListener((e => {
    this.#c()
    })), chrome.privacy.services.autofillCreditCardEnabled && chrome.privacy.services.autofillCreditCardEnabled.onChange.addListener((e => {
    this.#c()
    })), chrome.privacy.services.autofillAddressEnabled && chrome.privacy.services.autofillAddressEnabled.onChange.addListener((e => {
    this.#c()
    })))
    }
    #c() {
    const e = new CustomEvent("settingsChanged", {
    detail: {
    enableInPageAutoFill: this.#o
    }
    });
    this.eventTarget.dispatchEvent(e)
    }
    async #g(e, t) {
    let n;
    try {
    n = await this.#h(e)
    } catch (e) {
    return
    }
    if (n) {
    if (n.value === t) return {
    details: n,
    newValue: t
    };
    try {
    n = await e.set({
    value: t
    })
    } catch (e) {
    return
    }
    return {
    details: n,
    newValue: t
    }
    }
    }
    async #h(e) {
    if (!e) throw new Error(`Unable to get ${e} setting.`);
    const t = await e.get({});
    if ("not_controllable" === t.levelOfControl) throw new Error(`Cannot control ${e} setting.`);
    return t
    }
    async #u(e) {
    if (!e) throw new Error(`Unable to clear browser setting: ${e}.`);
    await e.clear({})
    }
    }
    let extensionSettings = new ExtensionSettings;

    function localizeSettingsPage() {
    document.title = chrome.i18n.getMessage("optionsTitle"), document.querySelectorAll(".localizedElement").forEach((e => {
    const t = e.dataset.localizedMessage;
    if (!t) return;
    const n = chrome.i18n.getMessage(t);
    e.textContent = n
    }))
    }
    window.addEventListener("DOMContentLoaded", (e => {
    Localizer.configureDocumentElementForLanguage(document.documentElement, chrome.i18n.getUILanguage()), localizeSettingsPage();
    const setUpCheckbox = (e, t, n) => {
    const o = document.getElementById(e);
    o.checked = t, o.addEventListener("change", (e => {
    const t = e.target.checked;
    n(t)
    }))
    };
    setUpCheckbox("enable-inpage-autofill-checkbox", extensionSettings.enableInPageAutoFill, (e => {
    extensionSettings.enableInPageAutoFill = e
    })), setUpCheckbox("allow-extention-to-control-autofill-checkbox", extensionSettings.allowExtensionToControlAutoFillSettings, (e => {
    extensionSettings.allowExtensionToControlAutoFillSettings = e
    })), extensionSettings.eventTarget.addEventListener("settingsChanged", (e => {
    const t = e.detail;
    void 0 !== t.enableInPageAutoFill && (document.getElementById("enable-inpage-autofill-checkbox").checked = t.enableInPageAutoFill), void 0 !== t.allowExtensionToControlAutoFillSettings && (document.getElementById("allow-extention-to-control-autofill-checkbox").checked = t.allowExtensionToControlAutoFillSettings)
    }))
    }));
  2. AngeloD2022 created this gist Dec 16, 2023.
    1,195 changes: 1,195 additions & 0 deletions sjcl.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,1195 @@
    "use strict";
    var sjcl = {
    cipher: {},
    hash: {},
    keyexchange: {},
    mode: {},
    misc: {},
    codec: {},
    exception: {
    corrupt: function(a) {
    this.toString = function() {
    return "CORRUPT: " + this.message
    };
    this.message = a
    },
    invalid: function(a) {
    this.toString = function() {
    return "INVALID: " + this.message
    };
    this.message = a
    },
    bug: function(a) {
    this.toString = function() {
    return "BUG: " + this.message
    };
    this.message = a
    },
    notReady: function(a) {
    this.toString = function() {
    return "NOT READY: " + this.message
    };
    this.message = a
    }
    }
    };
    sjcl.cipher.aes = function(a) {
    this.w[0][0][0] || this.L();
    var b, c, d, e, f = this.w[0][4],
    g = this.w[1];
    b = a.length;
    var h = 1;
    if (4 !== b && 6 !== b && 8 !== b) throw new sjcl.exception.invalid("invalid aes key size");
    this.b = [d = a.slice(0), e = []];
    for (a = b; a < 4 * b + 28; a++) {
    c = d[a - 1];
    if (0 === a % b || 8 === b && 4 === a % b) c = f[c >>> 24] << 24 ^ f[c >> 16 & 255] << 16 ^ f[c >> 8 & 255] << 8 ^ f[c & 255], 0 === a % b && (c = c << 8 ^ c >>> 24 ^ h << 24, h = h << 1 ^ 283 * (h >> 7));
    d[a] = d[a - b] ^ c
    }
    for (b = 0; a; b++, a--) c = d[b & 3 ? a : a - 4], e[b] = 4 >= a || 4 > b ? c : g[0][f[c >>> 24]] ^ g[1][f[c >> 16 & 255]] ^ g[2][f[c >> 8 & 255]] ^ g[3][f[c &
    255]]
    };
    sjcl.cipher.aes.prototype = {
    encrypt: function(a) {
    return t(this, a, 0)
    },
    decrypt: function(a) {
    return t(this, a, 1)
    },
    w: [
    [
    [],
    [],
    [],
    [],
    []
    ],
    [
    [],
    [],
    [],
    [],
    []
    ]
    ],
    L: function() {
    var a = this.w[0],
    b = this.w[1],
    c = a[4],
    d = b[4],
    e, f, g, h = [],
    k = [],
    m, p, l, n;
    for (e = 0; 0x100 > e; e++) k[(h[e] = e << 1 ^ 283 * (e >> 7)) ^ e] = e;
    for (f = g = 0; !c[f]; f ^= m || 1, g = k[g] || 1)
    for (l = g ^ g << 1 ^ g << 2 ^ g << 3 ^ g << 4, l = l >> 8 ^ l & 255 ^ 99, c[f] = l, d[l] = f, p = h[e = h[m = h[f]]], n = 0x1010101 * p ^ 0x10001 * e ^ 0x101 * m ^ 0x1010100 * f, p = 0x101 * h[l] ^ 0x1010100 * l, e = 0; 4 > e; e++) a[e][f] = p = p << 24 ^ p >>> 8, b[e][l] = n = n << 24 ^ n >>> 8;
    for (e =
    0; 5 > e; e++) a[e] = a[e].slice(0), b[e] = b[e].slice(0)
    }
    };

    function t(a, b, c) {
    if (4 !== b.length) throw new sjcl.exception.invalid("invalid aes block size");
    var d = a.b[c],
    e = b[0] ^ d[0],
    f = b[c ? 3 : 1] ^ d[1],
    g = b[2] ^ d[2];
    b = b[c ? 1 : 3] ^ d[3];
    var h, k, m, p = d.length / 4 - 2,
    l, n = 4,
    r = [0, 0, 0, 0];
    h = a.w[c];
    a = h[0];
    var q = h[1],
    u = h[2],
    x = h[3],
    y = h[4];
    for (l = 0; l < p; l++) h = a[e >>> 24] ^ q[f >> 16 & 255] ^ u[g >> 8 & 255] ^ x[b & 255] ^ d[n], k = a[f >>> 24] ^ q[g >> 16 & 255] ^ u[b >> 8 & 255] ^ x[e & 255] ^ d[n + 1], m = a[g >>> 24] ^ q[b >> 16 & 255] ^ u[e >> 8 & 255] ^ x[f & 255] ^ d[n + 2], b = a[b >>> 24] ^ q[e >> 16 & 255] ^ u[f >> 8 & 255] ^ x[g & 255] ^ d[n + 3], n += 4, e = h, f = k, g = m;
    for (l =
    0; 4 > l; l++) r[c ? 3 & -l : l] = y[e >>> 24] << 24 ^ y[f >> 16 & 255] << 16 ^ y[g >> 8 & 255] << 8 ^ y[b & 255] ^ d[n++], h = e, e = f, f = g, g = b, b = h;
    return r
    }
    sjcl.bitArray = {
    bitSlice: function(a, b, c) {
    a = sjcl.bitArray.X(a.slice(b / 32), 32 - (b & 31)).slice(1);
    return void 0 === c ? a : sjcl.bitArray.clamp(a, c - b)
    },
    extract: function(a, b, c) {
    var d = Math.floor(-b - c & 31);
    return ((b + c - 1 ^ b) & -32 ? a[b / 32 | 0] << 32 - d ^ a[b / 32 + 1 | 0] >>> d : a[b / 32 | 0] >>> d) & (1 << c) - 1
    },
    concat: function(a, b) {
    if (0 === a.length || 0 === b.length) return a.concat(b);
    var c = a[a.length - 1],
    d = sjcl.bitArray.getPartial(c);
    return 32 === d ? a.concat(b) : sjcl.bitArray.X(b, d, c | 0, a.slice(0, a.length - 1))
    },
    bitLength: function(a) {
    var b = a.length;
    return 0 ===
    b ? 0 : 32 * (b - 1) + sjcl.bitArray.getPartial(a[b - 1])
    },
    clamp: function(a, b) {
    if (32 * a.length < b) return a;
    a = a.slice(0, Math.ceil(b / 32));
    var c = a.length;
    b = b & 31;
    0 < c && b && (a[c - 1] = sjcl.bitArray.partial(b, a[c - 1] & 2147483648 >> b - 1, 1));
    return a
    },
    partial: function(a, b, c) {
    return 32 === a ? b : (c ? b | 0 : b << 32 - a) + 0x10000000000 * a
    },
    getPartial: function(a) {
    return Math.round(a / 0x10000000000) || 32
    },
    equal: function(a, b) {
    if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) return !1;
    var c = 0,
    d;
    for (d = 0; d < a.length; d++) c |= a[d] ^ b[d];
    return 0 ===
    c
    },
    X: function(a, b, c, d) {
    var e;
    e = 0;
    for (void 0 === d && (d = []); 32 <= b; b -= 32) d.push(c), c = 0;
    if (0 === b) return d.concat(a);
    for (e = 0; e < a.length; e++) d.push(c | a[e] >>> b), c = a[e] << 32 - b;
    e = a.length ? a[a.length - 1] : 0;
    a = sjcl.bitArray.getPartial(e);
    d.push(sjcl.bitArray.partial(b + a & 31, 32 < b + a ? c : d.pop(), 1));
    return d
    },
    ka: function(a, b) {
    return [a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3]]
    },
    byteswapM: function(a) {
    var b, c;
    for (b = 0; b < a.length; ++b) c = a[b], a[b] = c >>> 24 | c >>> 8 & 0xff00 | (c & 0xff00) << 8 | c << 24;
    return a
    }
    };
    sjcl.codec.utf8String = {
    fromBits: function(a) {
    var b = "",
    c = sjcl.bitArray.bitLength(a),
    d, e;
    for (d = 0; d < c / 8; d++) 0 === (d & 3) && (e = a[d / 4]), b += String.fromCharCode(e >>> 8 >>> 8 >>> 8), e <<= 8;
    return decodeURIComponent(escape(b))
    },
    toBits: function(a) {
    a = unescape(encodeURIComponent(a));
    var b = [],
    c, d = 0;
    for (c = 0; c < a.length; c++) d = d << 8 | a.charCodeAt(c), 3 === (c & 3) && (b.push(d), d = 0);
    c & 3 && b.push(sjcl.bitArray.partial(8 * (c & 3), d));
    return b
    }
    };
    sjcl.codec.hex = {
    fromBits: function(a) {
    var b = "",
    c;
    for (c = 0; c < a.length; c++) b += ((a[c] | 0) + 0xf00000000000).toString(16).substr(4);
    return b.substr(0, sjcl.bitArray.bitLength(a) / 4)
    },
    toBits: function(a) {
    var b, c = [],
    d;
    a = a.replace(/\s|0x/g, "");
    d = a.length;
    a = a + "00000000";
    for (b = 0; b < a.length; b += 8) c.push(parseInt(a.substr(b, 8), 16) ^ 0);
    return sjcl.bitArray.clamp(c, 4 * d)
    }
    };
    sjcl.codec.base64 = {
    P: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    fromBits: function(a, b, c) {
    var d = "",
    e = 0,
    f = sjcl.codec.base64.P,
    g = 0,
    h = sjcl.bitArray.bitLength(a);
    c && (f = f.substr(0, 62) + "-_");
    for (c = 0; 6 * d.length < h;) d += f.charAt((g ^ a[c] >>> e) >>> 26), 6 > e ? (g = a[c] << 6 - e, e += 26, c++) : (g <<= 6, e -= 6);
    for (; d.length & 3 && !b;) d += "=";
    return d
    },
    toBits: function(a, b) {
    a = a.replace(/\s|=/g, "");
    var c = [],
    d, e = 0,
    f = sjcl.codec.base64.P,
    g = 0,
    h;
    b && (f = f.substr(0, 62) + "-_");
    for (d = 0; d < a.length; d++) {
    h = f.indexOf(a.charAt(d));
    if (0 > h) throw new sjcl.exception.invalid("this isn't base64!");
    26 < e ? (e -= 26, c.push(g ^ h >>> e), g = h << 32 - e) : (e += 6, g ^= h << 32 - e)
    }
    e & 56 && c.push(sjcl.bitArray.partial(e & 56, g, 1));
    return c
    }
    };
    sjcl.codec.base64url = {
    fromBits: function(a) {
    return sjcl.codec.base64.fromBits(a, 1, 1)
    },
    toBits: function(a) {
    return sjcl.codec.base64.toBits(a, 1)
    }
    };
    sjcl.codec.bytes = {
    fromBits: function(a) {
    var b = [],
    c = sjcl.bitArray.bitLength(a),
    d, e;
    for (d = 0; d < c / 8; d++) 0 === (d & 3) && (e = a[d / 4]), b.push(e >>> 24), e <<= 8;
    return b
    },
    toBits: function(a) {
    var b = [],
    c, d = 0;
    for (c = 0; c < a.length; c++) d = d << 8 | a[c], 3 === (c & 3) && (b.push(d), d = 0);
    c & 3 && b.push(sjcl.bitArray.partial(8 * (c & 3), d));
    return b
    }
    };
    sjcl.hash.sha256 = function(a) {
    this.b[0] || this.L();
    a ? (this.i = a.i.slice(0), this.f = a.f.slice(0), this.c = a.c) : this.reset()
    };
    sjcl.hash.sha256.hash = function(a) {
    return (new sjcl.hash.sha256).update(a).finalize()
    };
    sjcl.hash.sha256.prototype = {
    blockSize: 512,
    reset: function() {
    this.i = this.C.slice(0);
    this.f = [];
    this.c = 0;
    return this
    },
    update: function(a) {
    "string" === typeof a && (a = sjcl.codec.utf8String.toBits(a));
    var b, c = this.f = sjcl.bitArray.concat(this.f, a);
    b = this.c;
    a = this.c = b + sjcl.bitArray.bitLength(a);
    if (0x1fffffffffffff < a) throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");
    if ("undefined" !== typeof Uint32Array) {
    var d = new Uint32Array(c),
    e = 0;
    for (b = 512 + b - (512 + b & 0x1ff); b <= a; b += 512) this.m(d.subarray(16 * e,
    16 * (e + 1))), e += 1;
    c.splice(0, 16 * e)
    } else
    for (b = 512 + b - (512 + b & 0x1ff); b <= a; b += 512) this.m(c.splice(0, 16));
    return this
    },
    finalize: function() {
    var a, b = this.f,
    c = this.i,
    b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1, 1)]);
    for (a = b.length + 2; a & 15; a++) b.push(0);
    b.push(Math.floor(this.c / 0x100000000));
    for (b.push(this.c | 0); b.length;) this.m(b.splice(0, 16));
    this.reset();
    return c
    },
    C: [],
    b: [],
    L: function() {
    function a(a) {
    return 0x100000000 * (a - Math.floor(a)) | 0
    }
    for (var b = 0, c = 2, d, e; 64 > b; c++) {
    e = !0;
    for (d = 2; d * d <= c; d++)
    if (0 === c % d) {
    e = !1;
    break
    } e && (8 > b && (this.C[b] = a(Math.pow(c, .5))), this.b[b] = a(Math.pow(c, 1 / 3)), b++)
    }
    },
    m: function(a) {
    var b, c, d, e = this.i,
    f = this.b,
    g = e[0],
    h = e[1],
    k = e[2],
    m = e[3],
    p = e[4],
    l = e[5],
    n = e[6],
    r = e[7];
    for (b = 0; 64 > b; b++) 16 > b ? c = a[b] : (c = a[b + 1 & 15], d = a[b + 14 & 15], c = a[b & 15] = (c >>> 7 ^ c >>> 18 ^ c >>> 3 ^ c << 25 ^ c << 14) + (d >>> 17 ^ d >>> 19 ^ d >>> 10 ^ d << 15 ^ d << 13) + a[b & 15] + a[b + 9 & 15] | 0), c = c + r + (p >>> 6 ^ p >>> 11 ^ p >>> 25 ^ p << 26 ^ p << 21 ^ p << 7) + (n ^ p & (l ^ n)) + f[b], r = n, n = l, l = p, p = m + c | 0, m = k, k = h, h = g, g = c + (h & k ^ m & (h ^ k)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0;
    e[0] = e[0] + g |
    0;
    e[1] = e[1] + h | 0;
    e[2] = e[2] + k | 0;
    e[3] = e[3] + m | 0;
    e[4] = e[4] + p | 0;
    e[5] = e[5] + l | 0;
    e[6] = e[6] + n | 0;
    e[7] = e[7] + r | 0
    }
    };
    sjcl.hash.sha1 = function(a) {
    a ? (this.i = a.i.slice(0), this.f = a.f.slice(0), this.c = a.c) : this.reset()
    };
    sjcl.hash.sha1.hash = function(a) {
    return (new sjcl.hash.sha1).update(a).finalize()
    };
    sjcl.hash.sha1.prototype = {
    blockSize: 512,
    reset: function() {
    this.i = this.C.slice(0);
    this.f = [];
    this.c = 0;
    return this
    },
    update: function(a) {
    "string" === typeof a && (a = sjcl.codec.utf8String.toBits(a));
    var b, c = this.f = sjcl.bitArray.concat(this.f, a);
    b = this.c;
    a = this.c = b + sjcl.bitArray.bitLength(a);
    if (0x1fffffffffffff < a) throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");
    if ("undefined" !== typeof Uint32Array) {
    var d = new Uint32Array(c),
    e = 0;
    for (b = this.blockSize + b - (this.blockSize + b & this.blockSize - 1); b <=
    a; b += this.blockSize) this.m(d.subarray(16 * e, 16 * (e + 1))), e += 1;
    c.splice(0, 16 * e)
    } else
    for (b = this.blockSize + b - (this.blockSize + b & this.blockSize - 1); b <= a; b += this.blockSize) this.m(c.splice(0, 16));
    return this
    },
    finalize: function() {
    var a, b = this.f,
    c = this.i,
    b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1, 1)]);
    for (a = b.length + 2; a & 15; a++) b.push(0);
    b.push(Math.floor(this.c / 0x100000000));
    for (b.push(this.c | 0); b.length;) this.m(b.splice(0, 16));
    this.reset();
    return c
    },
    C: [1732584193, 4023233417, 2562383102, 271733878, 3285377520],
    b: [1518500249, 1859775393, 2400959708, 3395469782],
    m: function(a) {
    var b, c, d, e, f, g, h = this.i,
    k;
    if ("undefined" !== typeof Uint32Array)
    for (k = Array(80), c = 0; 16 > c; c++) k[c] = a[c];
    else k = a;
    c = h[0];
    d = h[1];
    e = h[2];
    f = h[3];
    g = h[4];
    for (a = 0; 79 >= a; a++) 16 <= a && (b = k[a - 3] ^ k[a - 8] ^ k[a - 14] ^ k[a - 16], k[a] = b << 1 | b >>> 31), b = 19 >= a ? d & e | ~d & f : 39 >= a ? d ^ e ^ f : 59 >= a ? d & e | d & f | e & f : 79 >= a ? d ^ e ^ f : void 0, b = (c << 5 | c >>> 27) + b + g + k[a] + this.b[Math.floor(a / 20)] | 0, g = f, f = e, e = d << 30 | d >>> 2, d = c, c = b;
    h[0] = h[0] + c | 0;
    h[1] = h[1] + d | 0;
    h[2] = h[2] + e | 0;
    h[3] = h[3] + f | 0;
    h[4] = h[4] + g | 0
    }
    };
    sjcl.mode.gcm = {
    name: "gcm",
    encrypt: function(a, b, c, d, e) {
    var f = b.slice(0);
    b = sjcl.bitArray;
    d = d || [];
    a = sjcl.mode.gcm.S(!0, a, f, d, c, e || 128);
    return b.concat(a.data, a.tag)
    },
    decrypt: function(a, b, c, d, e) {
    var f = b.slice(0),
    g = sjcl.bitArray,
    h = g.bitLength(f);
    e = e || 128;
    d = d || [];
    e <= h ? (b = g.bitSlice(f, h - e), f = g.bitSlice(f, 0, h - e)) : (b = f, f = []);
    a = sjcl.mode.gcm.S(!1, a, f, d, c, e);
    if (!g.equal(a.tag, b)) throw new sjcl.exception.corrupt("gcm: tag doesn't match");
    return a.data
    },
    ea: function(a, b) {
    var c, d, e, f, g, h = sjcl.bitArray.ka;
    e = [0, 0,
    0, 0
    ];
    f = b.slice(0);
    for (c = 0; 128 > c; c++) {
    (d = 0 !== (a[Math.floor(c / 32)] & 1 << 31 - c % 32)) && (e = h(e, f));
    g = 0 !== (f[3] & 1);
    for (d = 3; 0 < d; d--) f[d] = f[d] >>> 1 | (f[d - 1] & 1) << 31;
    f[0] >>>= 1;
    g && (f[0] ^= -0x1f000000)
    }
    return e
    },
    s: function(a, b, c) {
    var d, e = c.length;
    b = b.slice(0);
    for (d = 0; d < e; d += 4) b[0] ^= 0xffffffff & c[d], b[1] ^= 0xffffffff & c[d + 1], b[2] ^= 0xffffffff & c[d + 2], b[3] ^= 0xffffffff & c[d + 3], b = sjcl.mode.gcm.ea(b, a);
    return b
    },
    S: function(a, b, c, d, e, f) {
    var g, h, k, m, p, l, n, r, q = sjcl.bitArray;
    l = c.length;
    n = q.bitLength(c);
    r = q.bitLength(d);
    h = q.bitLength(e);
    g = b.encrypt([0, 0, 0, 0]);
    96 === h ? (e = e.slice(0), e = q.concat(e, [1])) : (e = sjcl.mode.gcm.s(g, [0, 0, 0, 0], e), e = sjcl.mode.gcm.s(g, e, [0, 0, Math.floor(h / 0x100000000), h & 0xffffffff]));
    h = sjcl.mode.gcm.s(g, [0, 0, 0, 0], d);
    p = e.slice(0);
    d = h.slice(0);
    a || (d = sjcl.mode.gcm.s(g, h, c));
    for (m = 0; m < l; m += 4) p[3]++, k = b.encrypt(p), c[m] ^= k[0], c[m + 1] ^= k[1], c[m + 2] ^= k[2], c[m + 3] ^= k[3];
    c = q.clamp(c, n);
    a && (d = sjcl.mode.gcm.s(g, h, c));
    a = [Math.floor(r / 0x100000000), r & 0xffffffff, Math.floor(n / 0x100000000), n & 0xffffffff];
    d = sjcl.mode.gcm.s(g, d, a);
    k = b.encrypt(e);
    d[0] ^= k[0];
    d[1] ^= k[1];
    d[2] ^= k[2];
    d[3] ^= k[3];
    return {
    tag: q.bitSlice(d, 0, f),
    data: c
    }
    }
    };
    sjcl.prng = function(a) {
    this.j = [new sjcl.hash.sha256];
    this.u = [0];
    this.M = 0;
    this.D = {};
    this.K = 0;
    this.R = {};
    this.W = this.l = this.v = this.da = 0;
    this.b = [0, 0, 0, 0, 0, 0, 0, 0];
    this.o = [0, 0, 0, 0];
    this.I = void 0;
    this.J = a;
    this.B = !1;
    this.H = {
    progress: {},
    seeded: {}
    };
    this.A = this.ca = 0;
    this.F = 1;
    this.G = 2;
    this.$ = 0x10000;
    this.O = [0, 48, 64, 96, 128, 192, 0x100, 384, 512, 768, 1024];
    this.aa = 3E4;
    this.Z = 80
    };
    sjcl.prng.prototype = {
    randomWords: function(a, b) {
    var c = [],
    d;
    d = this.isReady(b);
    var e;
    if (d === this.A) throw new sjcl.exception.notReady("generator isn't seeded");
    if (d & this.G) {
    d = !(d & this.F);
    e = [];
    var f = 0,
    g;
    this.W = e[0] = (new Date).valueOf() + this.aa;
    for (g = 0; 16 > g; g++) e.push(0x100000000 * Math.random() | 0);
    for (g = 0; g < this.j.length && (e = e.concat(this.j[g].finalize()), f += this.u[g], this.u[g] = 0, d || !(this.M & 1 << g)); g++);
    this.M >= 1 << this.j.length && (this.j.push(new sjcl.hash.sha256), this.u.push(0));
    this.l -= f;
    f > this.v && (this.v =
    f);
    this.M++;
    this.b = sjcl.hash.sha256.hash(this.b.concat(e));
    this.I = new sjcl.cipher.aes(this.b);
    for (d = 0; 4 > d && (this.o[d] = this.o[d] + 1 | 0, !this.o[d]); d++);
    }
    for (d = 0; d < a; d += 4) 0 === (d + 1) % this.$ && v(this), e = w(this), c.push(e[0], e[1], e[2], e[3]);
    v(this);
    return c.slice(0, a)
    },
    setDefaultParanoia: function(a, b) {
    if (0 === a && "Setting paranoia=0 will ruin your security; use it only for testing" !== b) throw new sjcl.exception.invalid("Setting paranoia=0 will ruin your security; use it only for testing");
    this.J = a
    },
    addEntropy: function(a,
    b, c) {
    c = c || "user";
    var d, e, f = (new Date).valueOf(),
    g = this.D[c],
    h = this.isReady(),
    k = 0;
    d = this.R[c];
    void 0 === d && (d = this.R[c] = this.da++);
    void 0 === g && (g = this.D[c] = 0);
    this.D[c] = (this.D[c] + 1) % this.j.length;
    switch (typeof a) {
    case "number":
    void 0 === b && (b = 1);
    this.j[g].update([d, this.K++, 1, b, f, 1, a | 0]);
    break;
    case "object":
    c = Object.prototype.toString.call(a);
    if ("[object Uint32Array]" === c) {
    e = [];
    for (c = 0; c < a.length; c++) e.push(a[c]);
    a = e
    } else
    for ("[object Array]" !== c && (k = 1), c = 0; c < a.length && !k; c++) "number" !== typeof a[c] &&
    (k = 1);
    if (!k) {
    if (void 0 === b)
    for (c = b = 0; c < a.length; c++)
    for (e = a[c]; 0 < e;) b++, e = e >>> 1;
    this.j[g].update([d, this.K++, 2, b, f, a.length].concat(a))
    }
    break;
    case "string":
    void 0 === b && (b = a.length);
    this.j[g].update([d, this.K++, 3, b, f, a.length]);
    this.j[g].update(a);
    break;
    default:
    k = 1
    }
    if (k) throw new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string");
    this.u[g] += b;
    this.l += b;
    h === this.A && (this.isReady() !== this.A && z("seeded", Math.max(this.v, this.l)), z("progress", this.getProgress()))
    },
    isReady: function(a) {
    a = this.O[void 0 !== a ? a : this.J];
    return this.v && this.v >= a ? this.u[0] > this.Z && (new Date).valueOf() > this.W ? this.G | this.F : this.F : this.l >= a ? this.G | this.A : this.A
    },
    getProgress: function(a) {
    a = this.O[a ? a : this.J];
    return this.v >= a ? 1 : this.l > a ? 1 : this.l / a
    },
    startCollectors: function() {
    if (!this.B) {
    this.a = {
    loadTimeCollector: A(this, this.ha),
    mouseCollector: A(this, this.ia),
    keyboardCollector: A(this, this.ga),
    accelerometerCollector: A(this, this.ba),
    touchCollector: A(this, this.ja)
    };
    if (window.addEventListener) window.addEventListener("load",
    this.a.loadTimeCollector, !1), window.addEventListener("mousemove", this.a.mouseCollector, !1), window.addEventListener("keypress", this.a.keyboardCollector, !1), window.addEventListener("devicemotion", this.a.accelerometerCollector, !1), window.addEventListener("touchmove", this.a.touchCollector, !1);
    else if (document.attachEvent) document.attachEvent("onload", this.a.loadTimeCollector), document.attachEvent("onmousemove", this.a.mouseCollector), document.attachEvent("keypress", this.a.keyboardCollector);
    else throw new sjcl.exception.bug("can't attach event");
    this.B = !0
    }
    },
    stopCollectors: function() {
    this.B && (window.removeEventListener ? (window.removeEventListener("load", this.a.loadTimeCollector, !1), window.removeEventListener("mousemove", this.a.mouseCollector, !1), window.removeEventListener("keypress", this.a.keyboardCollector, !1), window.removeEventListener("devicemotion", this.a.accelerometerCollector, !1), window.removeEventListener("touchmove", this.a.touchCollector, !1)) : document.detachEvent && (document.detachEvent("onload", this.a.loadTimeCollector), document.detachEvent("onmousemove",
    this.a.mouseCollector), document.detachEvent("keypress", this.a.keyboardCollector)), this.B = !1)
    },
    addEventListener: function(a, b) {
    this.H[a][this.ca++] = b
    },
    removeEventListener: function(a, b) {
    var c, d, e = this.H[a],
    f = [];
    for (d in e) e.hasOwnProperty(d) && e[d] === b && f.push(d);
    for (c = 0; c < f.length; c++) d = f[c], delete e[d]
    },
    ga: function() {
    B(this, 1)
    },
    ia: function(a) {
    var b, c;
    try {
    b = a.x || a.clientX || a.offsetX || 0, c = a.y || a.clientY || a.offsetY || 0
    } catch (d) {
    c = b = 0
    }
    0 != b && 0 != c && this.addEntropy([b, c], 2, "mouse");
    B(this, 0)
    },
    ja: function(a) {
    a =
    a.touches[0] || a.changedTouches[0];
    this.addEntropy([a.pageX || a.clientX, a.pageY || a.clientY], 1, "touch");
    B(this, 0)
    },
    ha: function() {
    B(this, 2)
    },
    ba: function(a) {
    a = a.accelerationIncludingGravity.x || a.accelerationIncludingGravity.y || a.accelerationIncludingGravity.z;
    if (window.orientation) {
    var b = window.orientation;
    "number" === typeof b && this.addEntropy(b, 1, "accelerometer")
    }
    a && this.addEntropy(a, 2, "accelerometer");
    B(this, 0)
    }
    };

    function z(a, b) {
    var c, d = sjcl.random.H[a],
    e = [];
    for (c in d) d.hasOwnProperty(c) && e.push(d[c]);
    for (c = 0; c < e.length; c++) e[c](b)
    }

    function B(a, b) {
    "undefined" !== typeof window && window.performance && "function" === typeof window.performance.now ? a.addEntropy(window.performance.now(), b, "loadtime") : a.addEntropy((new Date).valueOf(), b, "loadtime")
    }

    function v(a) {
    a.b = w(a).concat(w(a));
    a.I = new sjcl.cipher.aes(a.b)
    }

    function w(a) {
    for (var b = 0; 4 > b && (a.o[b] = a.o[b] + 1 | 0, !a.o[b]); b++);
    return a.I.encrypt(a.o)
    }

    function A(a, b) {
    return function() {
    b.apply(a, arguments)
    }
    }
    sjcl.random = new sjcl.prng(6);
    a: try {
    var C, D, E, F;
    if (F = "undefined" !== typeof module && module.exports) {
    var G;
    try {
    G = require("crypto")
    } catch (a) {
    G = null
    }
    F = D = G
    }
    if (F && D.randomBytes) C = D.randomBytes(128), C = new Uint32Array((new Uint8Array(C)).buffer), sjcl.random.addEntropy(C, 1024, "crypto['randomBytes']");
    else if ("undefined" !== typeof window && "undefined" !== typeof Uint32Array) {
    E = new Uint32Array(32);
    if (window.crypto && window.crypto.getRandomValues) window.crypto.getRandomValues(E);
    else if (window.msCrypto && window.msCrypto.getRandomValues) window.msCrypto.getRandomValues(E);
    else break a;
    sjcl.random.addEntropy(E, 1024, "crypto['getRandomValues']")
    }
    } catch (a) {
    "undefined" !== typeof window && window.console && (pwlog("There was an error collecting entropy from the browser:"), pwlog(a))
    }
    sjcl.bn = function(a) {
    this.initWith(a)
    };
    sjcl.bn.prototype = {
    radix: 24,
    maxMul: 8,
    h: sjcl.bn,
    copy: function() {
    return new this.h(this)
    },
    initWith: function(a) {
    var b = 0,
    c;
    switch (typeof a) {
    case "object":
    this.limbs = a.limbs.slice(0);
    break;
    case "number":
    this.limbs = [a];
    this.normalize();
    break;
    case "string":
    a = a.replace(/^0x/, "");
    this.limbs = [];
    c = this.radix / 4;
    for (b = 0; b < a.length; b += c) this.limbs.push(parseInt(a.substring(Math.max(a.length - b - c, 0), a.length - b), 16));
    break;
    default:
    this.limbs = [0]
    }
    return this
    },
    equals: function(a) {
    "number" === typeof a && (a = new this.h(a));
    var b = 0,
    c;
    this.fullReduce();
    a.fullReduce();
    for (c = 0; c < this.limbs.length || c < a.limbs.length; c++) b |= this.getLimb(c) ^ a.getLimb(c);
    return 0 === b
    },
    getLimb: function(a) {
    return a >= this.limbs.length ? 0 : this.limbs[a]
    },
    greaterEquals: function(a) {
    "number" === typeof a && (a = new this.h(a));
    var b = 0,
    c = 0,
    d, e, f;
    for (d = Math.max(this.limbs.length, a.limbs.length) - 1; 0 <= d; d--) e = this.getLimb(d), f = a.getLimb(d), c |= f - e & ~b, b |= e - f & ~c;
    return (c | ~b) >>> 31
    },
    toString: function() {
    this.fullReduce();
    var a = "",
    b, c, d = this.limbs;
    for (b = 0; b < this.limbs.length; b++) {
    for (c =
    d[b].toString(16); b < this.limbs.length - 1 && 6 > c.length;) c = "0" + c;
    a = c + a
    }
    return "0x" + a
    },
    addM: function(a) {
    "object" !== typeof a && (a = new this.h(a));
    var b = this.limbs,
    c = a.limbs;
    for (a = b.length; a < c.length; a++) b[a] = 0;
    for (a = 0; a < c.length; a++) b[a] += c[a];
    return this
    },
    doubleM: function() {
    var a, b = 0,
    c, d = this.radix,
    e = this.radixMask,
    f = this.limbs;
    for (a = 0; a < f.length; a++) c = f[a], c = c + c + b, f[a] = c & e, b = c >> d;
    b && f.push(b);
    return this
    },
    halveM: function() {
    var a, b = 0,
    c, d = this.radix,
    e = this.limbs;
    for (a = e.length - 1; 0 <= a; a--) c = e[a], e[a] = c + b >>
    1, b = (c & 1) << d;
    e[e.length - 1] || e.pop();
    return this
    },
    subM: function(a) {
    "object" !== typeof a && (a = new this.h(a));
    var b = this.limbs,
    c = a.limbs;
    for (a = b.length; a < c.length; a++) b[a] = 0;
    for (a = 0; a < c.length; a++) b[a] -= c[a];
    return this
    },
    mod: function(a) {
    var b = !this.greaterEquals(new sjcl.bn(0));
    a = (new sjcl.bn(a)).normalize();
    var c = (new sjcl.bn(this)).normalize(),
    d = 0;
    for (b && (c = (new sjcl.bn(0)).subM(c).normalize()); c.greaterEquals(a); d++) a.doubleM();
    for (b && (c = a.sub(c).normalize()); 0 < d; d--) a.halveM(), c.greaterEquals(a) &&
    c.subM(a).normalize();
    return c.trim()
    },
    inverseMod: function(a) {
    var b = new sjcl.bn(1),
    c = new sjcl.bn(0),
    d = new sjcl.bn(this),
    e = new sjcl.bn(a),
    f, g = 1;
    if (!(a.limbs[0] & 1)) throw new sjcl.exception.invalid("inverseMod: p must be odd");
    do
    for (d.limbs[0] & 1 && (d.greaterEquals(e) || (f = d, d = e, e = f, f = b, b = c, c = f), d.subM(e), d.normalize(), b.greaterEquals(c) || b.addM(a), b.subM(c)), d.halveM(), b.limbs[0] & 1 && b.addM(a), b.normalize(), b.halveM(), f = g = 0; f < d.limbs.length; f++) g |= d.limbs[f]; while (g);
    if (!e.equals(1)) throw new sjcl.exception.invalid("inverseMod: p and x must be relatively prime");
    return c
    },
    add: function(a) {
    return this.copy().addM(a)
    },
    sub: function(a) {
    return this.copy().subM(a)
    },
    mul: function(a) {
    "number" === typeof a ? a = new this.h(a) : a.normalize();
    this.normalize();
    var b, c = this.limbs,
    d = a.limbs,
    e = c.length,
    f = d.length,
    g = new this.h,
    h = g.limbs,
    k, m = this.maxMul;
    for (b = 0; b < this.limbs.length + a.limbs.length + 1; b++) h[b] = 0;
    for (b = 0; b < e; b++) {
    k = c[b];
    for (a = 0; a < f; a++) h[b + a] += k * d[a];
    --m || (m = this.maxMul, g.cnormalize())
    }
    return g.cnormalize().reduce()
    },
    square: function() {
    return this.mul(this)
    },
    power: function(a) {
    a =
    (new sjcl.bn(a)).normalize().trim().limbs;
    var b, c, d = new this.h(1),
    e = this;
    for (b = 0; b < a.length; b++)
    for (c = 0; c < this.radix; c++) {
    a[b] & 1 << c && (d = d.mul(e));
    if (b == a.length - 1 && 0 == a[b] >> c + 1) break;
    e = e.square()
    }
    return d
    },
    mulmod: function(a, b) {
    return this.mod(b).mul(a.mod(b)).mod(b)
    },
    powermod: function(a, b) {
    a = new sjcl.bn(a);
    b = new sjcl.bn(b);
    if (1 == (b.limbs[0] & 1)) {
    var c = this.montpowermod(a, b);
    if (0 != c) return c
    }
    for (var d, e = a.normalize().trim().limbs, f = new this.h(1), g = this, c = 0; c < e.length; c++)
    for (d = 0; d < this.radix; d++) {
    e[c] &
    1 << d && (f = f.mulmod(g, b));
    if (c == e.length - 1 && 0 == e[c] >> d + 1) break;
    g = g.mulmod(g, b)
    }
    return f
    },
    montpowermod: function(a, b) {
    function c(a, b) {
    var c = b % a.radix;
    return (a.limbs[Math.floor(b / a.radix)] & 1 << c) >> c
    }

    function d(a, c) {
    var d, e, f = (1 << m + 1) - 1;
    d = a.mul(c);
    e = d.mul(r);
    e.limbs = e.limbs.slice(0, k.limbs.length);
    e.limbs.length == k.limbs.length && (e.limbs[k.limbs.length - 1] &= f);
    e = e.mul(b);
    e = d.add(e).normalize().trim();
    e.limbs = e.limbs.slice(k.limbs.length - 1);
    for (d = 0; d < e.limbs.length; d++) 0 < d && (e.limbs[d - 1] |= (e.limbs[d] & f) <<
    g - m - 1), e.limbs[d] >>= m + 1;
    e.greaterEquals(b) && e.subM(b);
    return e
    }
    a = (new sjcl.bn(a)).normalize().trim();
    b = new sjcl.bn(b);
    var e, f, g = this.radix,
    h = new this.h(1);
    e = this.copy();
    var k, m, p;
    p = a.bitLength();
    k = new sjcl.bn({
    limbs: b.copy().normalize().trim().limbs.map(function() {
    return 0
    })
    });
    for (m = this.radix; 0 < m; m--)
    if (1 == (b.limbs[b.limbs.length - 1] >> m & 1)) {
    k.limbs[k.limbs.length - 1] = 1 << m;
    break
    } if (0 == p) return this;
    p = 18 > p ? 1 : 48 > p ? 3 : 144 > p ? 4 : 768 > p ? 5 : 6;
    var l = k.copy(),
    n = b.copy();
    f = new sjcl.bn(1);
    for (var r = new sjcl.bn(0),
    q = k.copy(); q.greaterEquals(1);) q.halveM(), 0 == (f.limbs[0] & 1) ? (f.halveM(), r.halveM()) : (f.addM(n), f.halveM(), r.halveM(), r.addM(l));
    f = f.normalize();
    r = r.normalize();
    l.doubleM();
    n = l.mulmod(l, b);
    if (!l.mul(f).sub(b.mul(r)).equals(1)) return !1;
    e = d(e, n);
    h = d(h, n);
    l = {};
    f = (1 << p - 1) - 1;
    l[1] = e.copy();
    l[2] = d(e, e);
    for (e = 1; e <= f; e++) l[2 * e + 1] = d(l[2 * e - 1], l[2]);
    for (e = a.bitLength() - 1; 0 <= e;)
    if (0 == c(a, e)) h = d(h, h), --e;
    else {
    for (n = e - p + 1; 0 == c(a, n);) n++;
    q = 0;
    for (f = n; f <= e; f++) q += c(a, f) << f - n, h = d(h, h);
    h = d(h, l[q]);
    e = n - 1
    } return d(h, 1)
    },
    trim: function() {
    var a = this.limbs,
    b;
    do b = a.pop(); while (a.length && 0 === b);
    a.push(b);
    return this
    },
    reduce: function() {
    return this
    },
    fullReduce: function() {
    return this.normalize()
    },
    normalize: function() {
    var a = 0,
    b, c = this.placeVal,
    d = this.ipv,
    e, f = this.limbs,
    g = f.length,
    h = this.radixMask;
    for (b = 0; b < g || 0 !== a && -1 !== a; b++) a = (f[b] || 0) + a, e = f[b] = a & h, a = (a - e) * d; - 1 === a && (f[b - 1] -= c);
    this.trim();
    return this
    },
    cnormalize: function() {
    var a = 0,
    b, c = this.ipv,
    d, e = this.limbs,
    f = e.length,
    g = this.radixMask;
    for (b = 0; b < f - 1; b++) a = e[b] + a, d = e[b] =
    a & g, a = (a - d) * c;
    e[b] += a;
    return this
    },
    toBits: function(a) {
    this.fullReduce();
    a = a || this.exponent || this.bitLength();
    var b = Math.floor((a - 1) / 24),
    c = sjcl.bitArray,
    d = [c.partial((a + 7 & -8) % this.radix || this.radix, this.getLimb(b))];
    for (b--; 0 <= b; b--) d = c.concat(d, [c.partial(Math.min(this.radix, a), this.getLimb(b))]), a -= this.radix;
    return d
    },
    bitLength: function() {
    this.fullReduce();
    for (var a = this.radix * (this.limbs.length - 1), b = this.limbs[this.limbs.length - 1]; b; b >>>= 1) a++;
    return a + 7 & -8
    }
    };
    sjcl.bn.fromBits = function(a) {
    var b = new this,
    c = [],
    d = sjcl.bitArray,
    e = this.prototype,
    f = Math.min(this.bitLength || 0x100000000, d.bitLength(a)),
    g = f % e.radix || e.radix;
    for (c[0] = d.extract(a, 0, g); g < f; g += e.radix) c.unshift(d.extract(a, g, e.radix));
    b.limbs = c;
    return b
    };
    sjcl.bn.prototype.ipv = 1 / (sjcl.bn.prototype.placeVal = Math.pow(2, sjcl.bn.prototype.radix));
    sjcl.bn.prototype.radixMask = (1 << sjcl.bn.prototype.radix) - 1;
    sjcl.bn.pseudoMersennePrime = function(a, b) {
    function c(a) {
    this.initWith(a)
    }
    var d = c.prototype = new sjcl.bn,
    e, f, g;
    g = d.modOffset = Math.ceil(f = a / d.radix);
    d.exponent = a;
    d.offset = [];
    d.factor = [];
    d.minOffset = g;
    d.fullMask = 0;
    d.fullOffset = [];
    d.fullFactor = [];
    d.modulus = c.modulus = new sjcl.bn(Math.pow(2, a));
    d.fullMask = 0 | -Math.pow(2, a % d.radix);
    for (e = 0; e < b.length; e++) d.offset[e] = Math.floor(b[e][0] / d.radix - f), d.fullOffset[e] = Math.floor(b[e][0] / d.radix) - g + 1, d.factor[e] = b[e][1] * Math.pow(.5, a - b[e][0] + d.offset[e] * d.radix),
    d.fullFactor[e] = b[e][1] * Math.pow(.5, a - b[e][0] + d.fullOffset[e] * d.radix), d.modulus.addM(new sjcl.bn(Math.pow(2, b[e][0]) * b[e][1])), d.minOffset = Math.min(d.minOffset, -d.offset[e]);
    d.h = c;
    d.modulus.cnormalize();
    d.reduce = function() {
    var a, b, c, d = this.modOffset,
    e = this.limbs,
    f = this.offset,
    g = this.offset.length,
    q = this.factor,
    u;
    for (a = this.minOffset; e.length > d;) {
    c = e.pop();
    u = e.length;
    for (b = 0; b < g; b++) e[u + f[b]] -= q[b] * c;
    a--;
    a || (e.push(0), this.cnormalize(), a = this.minOffset)
    }
    this.cnormalize();
    return this
    };
    d.Y = -1 === d.fullMask ?
    d.reduce : function() {
    var a = this.limbs,
    b = a.length - 1,
    c, d;
    this.reduce();
    if (b === this.modOffset - 1) {
    d = a[b] & this.fullMask;
    a[b] -= d;
    for (c = 0; c < this.fullOffset.length; c++) a[b + this.fullOffset[c]] -= this.fullFactor[c] * d;
    this.normalize()
    }
    };
    d.fullReduce = function() {
    var a, b;
    this.Y();
    this.addM(this.modulus);
    this.addM(this.modulus);
    this.normalize();
    this.Y();
    for (b = this.limbs.length; b < this.modOffset; b++) this.limbs[b] = 0;
    a = this.greaterEquals(this.modulus);
    for (b = 0; b < this.limbs.length; b++) this.limbs[b] -= this.modulus.limbs[b] *
    a;
    this.cnormalize();
    return this
    };
    d.inverse = function() {
    return this.power(this.modulus.sub(2))
    };
    c.fromBits = sjcl.bn.fromBits;
    return c
    };
    var H = sjcl.bn.pseudoMersennePrime;
    sjcl.bn.prime = {
    p127: H(127, [
    [0, -1]
    ]),
    p25519: H(255, [
    [0, -19]
    ]),
    p192k: H(192, [
    [32, -1],
    [12, -1],
    [8, -1],
    [7, -1],
    [6, -1],
    [3, -1],
    [0, -1]
    ]),
    p224k: H(224, [
    [32, -1],
    [12, -1],
    [11, -1],
    [9, -1],
    [7, -1],
    [4, -1],
    [1, -1],
    [0, -1]
    ]),
    p256k: H(0x100, [
    [32, -1],
    [9, -1],
    [8, -1],
    [7, -1],
    [6, -1],
    [4, -1],
    [0, -1]
    ]),
    p192: H(192, [
    [0, -1],
    [64, -1]
    ]),
    p224: H(224, [
    [0, 1],
    [96, -1]
    ]),
    p256: H(0x100, [
    [0, -1],
    [96, 1],
    [192, 1],
    [224, -1]
    ]),
    p384: H(384, [
    [0, -1],
    [32, 1],
    [96, -1],
    [128, -1]
    ]),
    p521: H(521, [
    [0, -1]
    ])
    };
    sjcl.bn.random = function(a, b) {
    "object" !== typeof a && (a = new sjcl.bn(a));
    for (var c, d, e = a.limbs.length, f = a.limbs[e - 1] + 1, g = new sjcl.bn;;) {
    do c = sjcl.random.randomWords(e, b), 0 > c[e - 1] && (c[e - 1] += 0x100000000); while (Math.floor(c[e - 1] / f) === Math.floor(0x100000000 / f));
    c[e - 1] %= f;
    for (d = 0; d < e - 1; d++) c[d] &= a.radixMask;
    g.limbs = c;
    if (!g.greaterEquals(a)) return g
    }
    };
    sjcl.keyexchange.srp = {
    makeVerifier: function(a, b, c, d) {
    a = sjcl.keyexchange.srp.makeX(a, b, c);
    a = sjcl.bn.fromBits(a);
    return d.g.powermod(a, d.N)
    },
    makeX: function(a, b, c) {
    a = sjcl.hash.sha1.hash(a + ":" + b);
    return sjcl.hash.sha1.hash(sjcl.bitArray.concat(c, a))
    },
    knownGroup: function(a) {
    "string" !== typeof a && (a = a.toString());
    sjcl.keyexchange.srp.T || sjcl.keyexchange.srp.fa();
    return sjcl.keyexchange.srp.V[a]
    },
    T: !1,
    fa: function() {
    var a, b;
    for (a = 0; a < sjcl.keyexchange.srp.U.length; a++) b = sjcl.keyexchange.srp.U[a].toString(),
    b = sjcl.keyexchange.srp.V[b], b.N = new sjcl.bn(b.N), b.g = new sjcl.bn(b.g);
    sjcl.keyexchange.srp.T = !0
    },
    U: [1024, 1536, 2048, 3072, 0x1000, 6144, 8192],
    V: {
    1024: {
    N: "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3",
    g: 2
    },
    1536: {
    N: "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB",
    g: 2
    },
    2048: {
    N: "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73",
    g: 2
    },
    3072: {
    N: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
    g: 5
    },
    0x1000: {
    N: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF",
    g: 5
    },
    6144: {
    N: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
    g: 5
    },
    8192: {
    N: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF",
    g: 19
    }
    }
    };
    "undefined" !== typeof module && module.exports && (module.exports = sjcl);
    "function" === typeof define && define([], function() {
    return sjcl
    });