Created
November 19, 2022 05:52
-
-
Save quacksire/a07c7388c4e4d5ba809e56e1e154071b to your computer and use it in GitHub Desktop.
Apple iCloud Passwords for Edge/Chrome
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var pwlog = void 0, | |
pwerror = void 0; | |
function isStringEmpty(e) { | |
return !e || 0 === e.length | |
} | |
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" | |
} | |
return "Unrecognized" | |
} | |
function domainsForDisplayFromUsernamesAndDomains(e, t) { | |
const s = e.length; | |
let o = t.map((function(e) { | |
return e.replace(/^(www|m)\./, "") | |
})), | |
n = []; | |
for (var r = 0; r < s; r++) n.push([e[r], o[r]]); | |
for (r = 0; r < s; r++) { | |
let e = []; | |
for (var a = r + 1; a < s; a++) n[r].join("\n") === n[a].join("\n") && (e.length || e.push(r), e.push(a)); | |
for (identicalIndex of e) o[identicalIndex] = t[identicalIndex] | |
} | |
return o | |
} | |
class Localizer { | |
static configureDocumentElementForLanguage(e, t) { | |
switch (t) { | |
case "he": | |
case "ar": | |
case "fa": | |
e.setAttribute("dir", "rtl"), e.setAttribute("lang", t) | |
} | |
} | |
constructor(e) {} | |
getMessage(e, t, s) { | |
const o = this.messageNamesToTry(e); | |
for (let e of o) { | |
let o; | |
try { | |
o = chrome.i18n.getMessage(e, t, s) | |
} catch { | |
o = chrome.i18n.getMessage(e, t) | |
} | |
if (o) return o | |
} | |
return "" | |
} | |
messageNamesToTry(e) { | |
let t = []; | |
return t.push(e), t | |
} | |
} | |
class ExtensionSettings {# | |
e = !1;# | |
t = !0;# | |
s = !0; | |
eventTarget = new EventTarget; | |
constructor(e = !1) { | |
this.#e = e, this.#o(), this.#n() | |
} | |
get enableInPageAutoFill() { | |
return this.#t | |
} | |
set enableInPageAutoFill(e) { | |
this.#t = e, this.#r() | |
} | |
get allowExtensionToControlAutoFillSettings() { | |
return this.#s | |
} | |
set allowExtensionToControlAutoFillSettings(e) { | |
this.#s = e, this.#a().then(this.#r.bind(this)) | |
}# | |
a() { | |
return this.#s ? this.attemptToControlBrowserAutoFillSettings() : this.clearControlOfBrowserAutoFillSettings() | |
} | |
attemptToControlBrowserAutoFillSettings() { | |
return this.#e ? Promise.reject(new Error("This Settings instance does not allow writing browser settings")) : Promise.allSettled([this.#i(chrome.privacy.services.passwordSavingEnabled, !1), this.#i(chrome.privacy.services.autofillCreditCardEnabled, !1), this.#i(chrome.privacy.services.autofillAddressEnabled, !1)]).then((e => (this.#c(), e))) | |
} | |
clearControlOfBrowserAutoFillSettings() { | |
return this.#e ? Promise.reject(new Error("This Settings instance does not allow writing browser settings")) : Promise.allSettled([this.#l(chrome.privacy.services.passwordSavingEnabled), this.#l(chrome.privacy.services.autofillCreditCardEnabled), this.#l(chrome.privacy.services.autofillAddressEnabled)]).then((e => (this.#c(), e))) | |
}# | |
o() { | |
let e = new Promise((e => { | |
chrome.storage.sync.get({ | |
enableInPageAutoFill: !0, | |
allowExtensionToControlAutoFillSettings: !0 | |
}, (t => { | |
this.#t = t.enableInPageAutoFill, this.#s = t.allowExtensionToControlAutoFillSettings, e() | |
})) | |
})); | |
return this.#e || (e = e.then(this.#a.bind(this))), e.then(this.#c.bind(this)) | |
}# | |
r() { | |
return new Promise((e => { | |
chrome.storage.sync.set({ | |
enableInPageAutoFill: this.#t, | |
allowExtensionToControlAutoFillSettings: this.#s | |
}, (() => { | |
e() | |
})) | |
})).then(this.#c.bind(this)) | |
}# | |
n() { | |
this.#e || (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.#t | |
} | |
}); | |
this.eventTarget.dispatchEvent(e) | |
}# | |
i(e, t) { | |
return this.#d(e).then((s => s ? s.value === t ? { | |
details: s, | |
newValue: t | |
} : new Promise(((o, n) => { | |
e.set({ | |
value: t | |
}, (() => { | |
chrome.runtime.lastError && (chrome.runtime.lastError, chrome.runtime.lastError, n(chrome.runtime.lastError)), o({ | |
details: s, | |
newValue: t | |
}) | |
})) | |
})) : { | |
details: {}, | |
newValue: void 0 | |
})) | |
}# | |
d(e) { | |
return new Promise((t => { | |
e || t({}), e.get({}, (e => { | |
"not_controllable" === e.levelOfControl && reject(new Error("Cannot control this setting")), t(e) | |
})) | |
})) | |
}# | |
l(e) { | |
return new Promise((t => { | |
e || t(), e.clear({}, (() => { | |
t() | |
})) | |
})) | |
} | |
} | |
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 o = null; | |
try { | |
o = JSON.stringify({ | |
TID: this.bitsToString(this.I.toBits()), | |
SDATA: this.bitsToString(s, !1) | |
}) | |
} catch (e) { | |
return ErrCodes.InvalidMessage | |
} | |
return o | |
}, | |
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 o = sjcl.bn.fromBits(this.stringToBits(s.TID)); | |
if (!this.I.equals(o)) 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 a = SecretSessionVersion.SRPWithOldVerification; | |
"number" == typeof s.PROTO && (a = s.PROTO, Object.values(SecretSessionVersion).includes(a) || (a = SecretSessionVersion.SRPWithOldVerification)), this.protocolVersion = a, r = this.processMessage1(s) | |
} else n === MSGTypes.MSG3 && (r = this.processMessage3(s)); | |
return r | |
}, | |
createSessionKey: function(e, t) { | |
const s = sjcl.hash.sha256.hash, | |
o = this._calculateX(e, this.bitsToString(this.I.toBits()), this.P, s); | |
this.v = this._calculateVerifier(this.grp.g, o, this.grp.N); | |
const n = this.A.toString(), | |
r = t.toString(), | |
a = this._padToModulusLength(n).concat(this._padToModulusLength(r)), | |
i = sjcl.bn.fromBits(s(sjcl.codec.hex.toBits(a))), | |
c = this.a.add(i.mul(o)), | |
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, o) { | |
const n = o(t + ":" + s); | |
return sjcl.bn.fromBits(o(e.concat(n))) | |
}, | |
_calculateVerifier: function(e, t, s) { | |
return e.powermod(t, s) | |
}, | |
_calculateM: function(e, t, s) { | |
const o = sjcl.hash.sha256.hash; | |
let n = o(this.grp.N.toBits()), | |
r = o(sjcl.codec.hex.toBits(this._padToModulusLength(this.grp.g.toString()))); | |
const a = sjcl.bitArray.bitLength(n) / 32; | |
for (let e = 0; e < a; ++e) n[e] = n[e] ^ r[e]; | |
let i = o(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 o = new sjcl.bn(1); | |
if (0 == s.mulmod(o, 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()), | |
o = this.encrypt(e); | |
r.v = this.bitsToString(o, !1); | |
break; | |
default: | |
throw new SecretSessionError(ErrCodes.UnexpectedMessage, `Unknown protocol version ${this.protocolVersion}`) | |
} | |
let a = null; | |
try { | |
a = JSON.stringify(r) | |
} catch (e) { | |
throw new SecretSessionError(ErrCodes.InvalidMessage, `Error encoding Message 2 to string:${e}`) | |
} | |
return this.stringToBase64(a) | |
}, | |
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 o = this.stringToBits(e.HAMK); | |
sjcl.bitArray.equal(o, 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 o = null; | |
try { | |
o = sjcl.mode.gcm.encrypt(t, e, s) | |
} catch (e) { | |
throw new SecretSessionError(ErrCodes.CryptoError, e.message) | |
} | |
return sjcl.bitArray.concat(o, 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), | |
o = sjcl.bitArray.bitSlice(e, this.keyLen); | |
let n = null; | |
try { | |
n = sjcl.mode.gcm.decrypt(t, o, s) | |
} catch (e) { | |
throw new SecretSessionError(ErrCodes.CryptoError, `Exception while decrypting message. ${e}`) | |
} | |
return n | |
}, | |
_randomWords: function(e) { | |
return sjcl.random.randomWords(e, 10) | |
} | |
}; | |
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, | |
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, | |
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" | |
} | |
} | |
var actUnknown = -1, | |
actDelete = 0, | |
actUpdate = 1, | |
actSearch = 2, | |
actAddNew = 3, | |
actMaybeAdd = 4, | |
actGhostSearch = 5; | |
const DefaultCapabilities = { | |
shouldUseBase64: !1, | |
secretSessionVersion: SecretSessionVersion.SRPWithOldVerification, | |
canFillOneTimeCodes: !1, | |
supportsSubURLs: !1 | |
}, | |
AmountOfTimeToBlockRefreshForNativeAppDisconnection = 5e3; | |
var g_portToCompletionList, g_portToPopup, g_lastToolbarIconImageName, g_timeStartedFetchingCredentials, g_nativeAppPort = 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_appStoreURL = "https://support.apple.com/kb/DL1455", | |
g_localizer = new Localizer, | |
g_extensionSettings = new ExtensionSettings; | |
function imageDataForName(e) { | |
if (!e) return; | |
let t = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; | |
return { | |
16: "images/" + (g_lastToolbarIconImageName = e) + (t ? "-darkmode" : "") + "_icon16.png", | |
32: "images/" + g_lastToolbarIconImageName + (t ? "-darkmode" : "") + "_icon32.png" | |
} | |
} | |
function setUpEventListners() { | |
chrome.runtime.onInstalled && chrome.runtime.onInstalled.addListener((e => { | |
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() { | |
const e = new RegExp("\\(Windows\\s*\\w*\\s*(\\d*)\\.(\\d*)", "i").exec(window.navigator.userAgent); | |
return null !== e && 3 === e.length && (e[1] >= 10 ? (g_appStoreURL = "ms-windows-store://pdp/?productid=9PKTQ5699M62", !0) : !(e[1] < 6) && !(e[2] < 1)) | |
} | |
function setGlobalState(e, t) { | |
if (setToolbarIcon((g_theState = e) === ContextState.SessionKeySet ? "PasswordsToolbar" : "PasswordsToolbarUnpaired"), !t) try { | |
g_portToPopup.postMessage({ | |
subject: "nativeConnectionStateChanged", | |
state: g_theState, | |
appStoreURL: g_appStoreURL | |
}) | |
} catch (e) {} | |
} | |
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.browserAction && chrome.browserAction.setIcon({ | |
path: imageDataForName(e) | |
}) | |
} | |
function sendMessageToPopupAndCompletionList(e) { | |
try { | |
chrome.runtime.sendMessage(e) | |
} catch (e) {} | |
try { | |
g_portToCompletionList && g_portToCompletionList.postMessage(e) | |
} catch (e) {} | |
} | |
function connectToBackgroundNativeAppAndSetUpListeners() { | |
setToolbarIcon("PasswordsToolbarUnpaired"), g_nativeAppCapabilities || (g_nativeAppCapabilities = DefaultCapabilities), g_localizer = new Localizer(g_nativeAppCapabilities), g_secretSession = new SecretSession(g_nativeAppCapabilities); | |
try { | |
(g_nativeAppPort = chrome.runtime.connectNative("com.apple.passwordmanager")).onDisconnect.addListener((function(e) { | |
const t = chrome.runtime.lastError; | |
t.message, setTimeout((function() { | |
if ("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) | |
})), chrome.runtime.onMessage.addListener(((e, t, s) => { | |
const o = new URL(t.url); | |
if (o.hostname, t.tab.id, t.frameId, e.from, "content" === e.from) switch (e.subject, e.subject) { | |
case "CmdDidFocusIntoPage": | |
runPageMetadataHeuristicsOnActiveTab(); | |
break; | |
case "CmdCheckEstablishSession": | |
CheckEstablishSession(); | |
break; | |
case "SaveStage1LoginName": | |
o.hostname, t.tab.id, e.theLogin, g_tabIdToURL.set(t.tab.id, o.hostname), g_Stage1Logins.set(o.hostname, e.theLogin); | |
break; | |
case "CmdGetPassword4LoginName": | |
let s = JSON.stringify({ | |
ACT: actSearch, | |
URL: o.hostname, | |
USR: e.theLogin | |
}); | |
var n = g_secretSession.createSMSG(s), | |
r = { | |
cmd: 5, | |
tabId: t.tab.id, | |
frameId: t.frameId, | |
url: e.theURL, | |
payload: JSON.stringify({ | |
QID: e.subject, | |
SMSG: n | |
}) | |
}; | |
e.subject, e.subject, g_nativeAppPort.postMessage(r); | |
break; | |
case "CmdSetPassword4LoginName_URL": | |
case "CmdNewAccount4URL": | |
if (g_theState === ContextState.SessionKeySet) { | |
e.theNLogin, o.hostname; | |
let s = consultStage1Logins(e.theNLogin, o.hostname); | |
if (!isStringEmpty(s)) { | |
let o = JSON.stringify({ | |
ACT: actMaybeAdd, | |
URL: e.theURL, | |
USR: e.theLogin, | |
PWD: e.thePassword, | |
NURL: e.theNURL, | |
NUSR: s, | |
NPWD: e.theNPassword | |
}); | |
n = g_secretSession.createSMSG(o), 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 = !1; | |
switch (e.hostPageType) { | |
case WBSAutoFillFormTypeUndetermined: | |
case WBSAutoFillFormTypeAutoFillableStandard: | |
case WBSAutoFillFormTypeNonAutoFillable: | |
s = !1; | |
break; | |
case WBSAutoFillFormTypeAutoFillableLogin: | |
case WBSAutoFillFormTypeNewAccount: | |
case WBSAutoFillFormTypeChangePassword: | |
s = !0 | |
} | |
switch (g_TabsToStateMap.has(t.tab.id) && g_TabsToStateMap.get(t.tab.id) || g_TabsToStateMap.set(t.tab.id, s), o.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: | |
r = { | |
cmd: 3, | |
tabId: t.tab.id, | |
frameId: t.frameId, | |
payload: JSON.stringify({ | |
TID: "CmdSetIconNTitle", | |
URL: o.hostname | |
}) | |
}; | |
JSON.stringify(r), g_nativeAppPort.postMessage(r) | |
} | |
} | |
break; | |
case "CmdClearCache": | |
g_tabIdToURL.has(t.tab.id) && (strURL = g_tabIdToURL.get(t.tab.id), o.hostname !== strURL && g_Stage1Logins.delete(strURL), g_tabIdToURL.delete(t.tab.id)); | |
break; | |
case "ThemeChanged": | |
chrome.pageAction && chrome.pageAction.setIcon({ | |
path: imageDataForName(g_lastToolbarIconImageName), | |
tabId: t.tab.id | |
}); | |
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": | |
g_portToCompletionList.postMessage(e) | |
} | |
return Promise.resolve("Dummy response to keep the console quiet") | |
})), g_nativeAppPort.onMessage.addListener((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 { | |
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 = [], | |
o = [], | |
n = [], | |
r = e.payload, | |
a = e.tabId, | |
i = e.frameId, | |
c = g_secretSession.parseSMSG(r.SMSG), | |
l = JSON.parse(c); | |
switch (JSON.stringify(l), l.STATUS) { | |
case QueryStatus.Success: | |
performance.now(); | |
var d = entriesFromLoginNames4URLData(l); | |
d.sort(((e, t) => e.USR.localeCompare(t.USR, void 0, { | |
numeric: !0, | |
sensitivity: "base" | |
}))), d.forEach((e => { | |
if ("Passwords not saved" === e.USR) t = RememberIC.DoNotRemember; | |
else if (s.push(e.USR), o.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: o, | |
arrHLDs: n, | |
tabId: a, | |
frameId: i, | |
theRememberICSelection: t | |
}); | |
break; | |
case QueryStatus.NoResults: | |
sendMessageToPopupAndCompletionList({ | |
from: "background", | |
subject: "users", | |
arrDates: [], | |
tabId: a, | |
frameId: i, | |
arrLoginNames: [], | |
arrHLDs: [], | |
theRememberICSelection: RememberIC.UnknownPage | |
}); | |
break; | |
default: | |
STATUSErrorReturned(l.STATUS) | |
} | |
break; | |
case 5: | |
r = e.payload, c = g_secretSession.parseSMSG(r.SMSG); | |
switch ((l = JSON.parse(c)).STATUS) { | |
case 0: | |
chrome.tabs.query({ | |
active: !0, | |
currentWindow: !0 | |
}, (function(t) { | |
try { | |
entriesFromLoginNames4URLData(l).forEach((s => { | |
for (site of s.sites) | |
if (site === e.url) return void chrome.tabs.sendMessage(t[0].id, { | |
from: "background", | |
subject: "password", | |
tabId: e.tabId, | |
frameId: e.frameId, | |
theLoginName: s.USR, | |
thePassword: s.PWD, | |
theURL: site | |
}, { | |
frameId: e.frameId | |
}) | |
})) | |
} catch (t) { | |
e.tabId, e.frameId, t.message | |
} | |
})); | |
break; | |
case 3: | |
break; | |
default: | |
STATUSErrorReturned(l.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), sendMessageToPopupAndCompletionList({ | |
subject: "hello", | |
capabilities: g_nativeAppCapabilities | |
}), resetTheSession(ContextState.NotInSession); | |
break; | |
case 15: | |
handleOneTimeCodeAvailableCommand(e); | |
break; | |
case 17: | |
handleDidFillOneTimeCodeCommand(e); | |
break; | |
default: | |
cmd2string(e.cmd) | |
} | |
return Promise.resolve("Dummy response to keep the console quiet") | |
})) | |
} catch (e) { | |
resetTheSession(ContextState.NativeSupportNotInstalled) | |
} | |
try { | |
g_nativeAppPort.postMessage({ | |
cmd: 14 | |
}) | |
} catch (e) { | |
resetTheSession(ContextState.NativeSupportNotInstalled) | |
} | |
} | |
function handleOneTimeCodeAvailableCommand(e) { | |
getCurrentActiveTabAndFrame().then((e => getOneTimeCodes(e[0], e[1], null))) | |
} | |
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 o = t.Entries; | |
o && sendMessageToPopupAndCompletionList({ | |
from: "background", | |
subject: "oneTimeCodes", | |
oneTimeCodes: o | |
}) | |
} | |
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 o = t.Entries; | |
o && o.length && chrome.tabs.sendMessage(e.tabId, { | |
subject: "fillCurrentTOTPCodeIntoForm", | |
oneTimeCodes: o | |
}, { | |
frameId: e.frameId | |
}) | |
} | |
function CheckEstablishSession() { | |
if (g_theState === ContextState.NotInSession) ChallengePIN() | |
} | |
function RunHeuristics(e, t, s) { | |
g_theState !== ContextState.MSG1Set && g_theState !== ContextState.ChallengeSent || PINSet(""); | |
try { | |
chrome.tabs.sendMessage(t, { | |
from: "background", | |
subject: "runFormMetadataHeuristics", | |
url: e, | |
tabId: t, | |
frameId: s | |
}, { | |
frameId: s | |
}) | |
} catch (e) { | |
e.message | |
} | |
} | |
function startiCloudControlPanel() { | |
var e = { | |
cmd: 11 | |
}; | |
JSON.stringify(e), g_nativeAppPort.postMessage(e) | |
} | |
function startPasswordsApp() { | |
var e = { | |
cmd: 13 | |
}; | |
JSON.stringify(e), g_nativeAppPort.postMessage(e) | |
} | |
function GetLoginNames4URL(e, t, s) { | |
let o = JSON.stringify({ | |
ACT: actGhostSearch, | |
URL: e | |
}), | |
n = g_secretSession.createSMSG(o), | |
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((o => { | |
let n = { | |
ACT: actGhostSearch, | |
TYPE: "oneTimeCodes", | |
frameURLs: o | |
}; | |
s && (n.username = s); | |
let r = g_secretSession.createSMSG(n), | |
a = { | |
cmd: 16, | |
tabId: e.id, | |
frameId: t.frameId, | |
payload: JSON.stringify({ | |
QID: "CmdGetOneTimeCodes", | |
SMSG: r | |
}) | |
}; | |
g_nativeAppPort.postMessage(a) | |
})) | |
} | |
function didFillOneTimeCode(e, t, s) { | |
if ("totp" === e.source) getAllParentFrameURLsOfFrame(t, s).then((o => { | |
let n = { | |
ACT: actSearch, | |
TYPE: "oneTimeCodes", | |
frameURLs: o | |
}, | |
r = e.username; | |
r && (n.username = r); | |
let a = g_secretSession.createSMSG(n), | |
i = { | |
cmd: 17, | |
tabId: t.id, | |
frameId: s.frameId, | |
payload: JSON.stringify({ | |
QID: "CmdDidFillOneTimeCode", | |
SMSG: a | |
}) | |
}; | |
g_nativeAppPort.postMessage(i) | |
})) | |
} | |
function getAllParentFrameURLsOfFrame(e, t) { | |
let s = e.id; | |
return new Promise((o => { | |
-1 !== t.parentFrameId ? chrome.webNavigation.getFrame({ | |
tabId: s, | |
frameId: t.parentFrameId | |
}, (s => { | |
getAllParentFrameURLsOfFrame(e, s).then((e => { | |
o([t.url].concat(e)) | |
})) | |
})) : o([t.url]) | |
})) | |
} | |
function ChallengePIN() { | |
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) { | |
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 runPageMetadataHeuristicsOnActiveTab() { | |
chrome.tabs.query({ | |
active: !0, | |
currentWindow: !0 | |
}, (function(e) { | |
g_TabsToStateMap.delete(e[0].id), chrome.webNavigation.getAllFrames({ | |
tabId: e[0].id | |
}, (t => { | |
e[0].id, t.forEach(((t, s, o) => { | |
const n = new URL(t.url), | |
r = n.protocol; | |
"http:" === r || "https:" === r ? (e[0].id, t.frameId, RunHeuristics(n.hostname, e[0].id, t.frameId)) : t.url | |
})) | |
})) | |
})) | |
} | |
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 | |
} | |
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((e => { | |
g_nativeAppPort && e !== chrome.windows.WINDOW_ID_NONE && chrome.tabs.query({ | |
active: !0, | |
currentWindow: !0 | |
}, (function(e) { | |
let t = { | |
cmd: 8, | |
tabId: e[0].id, | |
event: 1 | |
}; | |
JSON.stringify(t), g_nativeAppPort.postMessage(t) | |
})) | |
})); | |
var g_IsDirty = !1; | |
function setUpPortToCompetionList(e) { | |
g_portToCompletionList = e, e.onMessage.addListener((function(t) { | |
switch (t.subject) { | |
case "getContextAndMetadataFromContent": | |
getCurrentActiveTabAndItsFrames().then((function(t) { | |
const s = t[0].id; | |
for (const o of t[1]) { | |
const t = o.frameId; | |
chrome.tabs.sendMessage(s, { | |
from: "background", | |
subject: "getTextFieldAndFormMetadataOfActiveTextFieldAndPresetUserNameAndHostname" | |
}, { | |
frameId: t | |
}, (function(o) { | |
o && e.postMessage({ | |
subject: "replyForGetContextAndMetadataFromContent", | |
state: g_theState, | |
tabId: s, | |
frameId: t, | |
textFieldMetadata: o.textFieldMetadata, | |
formMetadata: o.formMetadata, | |
presetUserName: o.presetUserName, | |
hostname: o.hostname, | |
canFillOneTimeCodes: canFillOneTimeCodes() | |
}) | |
})) | |
} | |
})); | |
break; | |
case "GetLoginNames4URL": | |
GetLoginNames4URL(t.hostname, t.tabId, t.frameId); | |
break; | |
case "getOneTimeCodes": | |
const s = t.tabId, | |
o = t.frameId; | |
chrome.webNavigation.getFrame({ | |
tabId: s, | |
frameId: o | |
}, (e => { | |
e.frameId = o, getOneTimeCodes({ | |
id: t.tabId | |
}, e, t.username) | |
})); | |
break; | |
case "openPasswordManagerAndDismissCompletionList": | |
startPasswordsApp(), chrome.tabs.sendMessage(t.tabId, { | |
subject: "dismissCompletionList" | |
}, { | |
frameId: t.frameId | |
}); | |
break; | |
case "resizeCompletionList": | |
case "fillLoginIntoForm": | |
case "fillOneTimeCodeIntoForm": | |
case "dismissCompletionList": | |
chrome.tabs.sendMessage(t.tabId, t, { | |
frameId: t.frameId | |
}) | |
} | |
})), e.postMessage({ | |
subject: "hello", | |
capabilities: g_nativeAppCapabilities | |
}) | |
} | |
function setUpPortToPopup(e) { | |
g_portToPopup = e, e.onMessage.addListener((function(t, s, o) { | |
switch (t.subject) { | |
case "getNativeConnectionState": | |
e.postMessage({ | |
subject: "nativeConnectionStateChanged", | |
state: g_theState, | |
appStoreURL: g_appStoreURL | |
}); | |
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() | |
} | |
})), e.onDisconnect.addListener((function() { | |
g_theState === ContextState.MSG1Set && PINSet("") | |
})), e.postMessage({ | |
subject: "hello", | |
capabilities: g_nativeAppCapabilities | |
}) | |
} | |
chrome.tabs.onUpdated.addListener(((e, t, s) => { | |
switch (s.status) { | |
case "unloaded": | |
break; | |
case "loading": | |
g_IsDirty = !0; | |
break; | |
case "complete": | |
g_IsDirty && (JSON.stringify(t), JSON.stringify(s), g_IsDirty = !1, runPageMetadataHeuristicsOnActiveTab()) | |
} | |
})), 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.webNavigation.onHistoryStateUpdated.addListener((function(e) { | |
JSON.stringify(e), e.transitionQualifiers.includes("forward_back"); | |
try { | |
const t = new URL(e.url); | |
let s = e.tabId; | |
chrome.webNavigation.getAllFrames({ | |
tabId: s | |
}, (e => { | |
e.forEach(((e, o, n) => { | |
JSON.stringify(e), chrome.tabs.sendMessage(s, { | |
from: "background", | |
subject: "historyStateDidUpdateInTab", | |
url: t.hostname, | |
tabId: s, | |
frameId: e.frameId | |
}, { | |
frameId: e.frameId | |
}) | |
})) | |
})) | |
} catch (t) { | |
e.tabId, e.frameId, t.message | |
} | |
setTimeout((function() { | |
runPageMetadataHeuristicsOnActiveTab() | |
}), 500) | |
})), chrome.runtime.onConnect.addListener((function(e) { | |
"completionList" === e.name ? setUpPortToCompetionList(e) : "popup" === e.name && setUpPortToPopup(e) | |
})), chrome.app && (chrome.manifest = chrome.app.getDetails()); | |
var injectScriptIntoTab = function(e) { | |
if (chrome.manifest) { | |
var t = chrome.manifest.content_scripts[0].js; | |
for (let s of t) chrome.tabs.executeScript(e.id, { | |
file: s | |
}) | |
} | |
}; | |
chrome.windows.getAll({ | |
populate: !0 | |
}, (function(e) { | |
for (let o of e) | |
for (var t = 0, s = o.tabs.length; t < s; t++) { | |
const e = o.tabs[t]; | |
let s; | |
try { | |
s = new URL(e.url).protocol | |
} catch (e) { | |
s = "" | |
} | |
"http:" !== s && "https:" !== s || injectScriptIntoTab(e) | |
} | |
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var pwlog = void 0, | |
pwerror = void 0; | |
function isStringEmpty(e) { | |
return !e || 0 === e.length | |
} | |
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" | |
} | |
return "Unrecognized" | |
} | |
function domainsForDisplayFromUsernamesAndDomains(e, t) { | |
const n = e.length; | |
let o = t.map((function(e) { | |
return e.replace(/^(www|m)\./, "") | |
})), | |
s = []; | |
for (var i = 0; i < n; i++) s.push([e[i], o[i]]); | |
for (i = 0; i < n; i++) { | |
let e = []; | |
for (var a = i + 1; a < n; a++) s[i].join("\n") === s[a].join("\n") && (e.length || e.push(i), e.push(a)); | |
for (identicalIndex of e) o[identicalIndex] = t[identicalIndex] | |
} | |
return o | |
} | |
class Localizer { | |
static configureDocumentElementForLanguage(e, t) { | |
switch (t) { | |
case "he": | |
case "ar": | |
case "fa": | |
e.setAttribute("dir", "rtl"), e.setAttribute("lang", t) | |
} | |
} | |
constructor(e) {} | |
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 = []; | |
return t.push(e), t | |
} | |
} | |
class ExtensionSettings {# | |
e = !1;# | |
t = !0;# | |
n = !0; | |
eventTarget = new EventTarget; | |
constructor(e = !1) { | |
this.#e = e, this.#o(), this.#s() | |
} | |
get enableInPageAutoFill() { | |
return this.#t | |
} | |
set enableInPageAutoFill(e) { | |
this.#t = e, this.#i() | |
} | |
get allowExtensionToControlAutoFillSettings() { | |
return this.#n | |
} | |
set allowExtensionToControlAutoFillSettings(e) { | |
this.#n = e, this.#a().then(this.#i.bind(this)) | |
}# | |
a() { | |
return this.#n ? this.attemptToControlBrowserAutoFillSettings() : this.clearControlOfBrowserAutoFillSettings() | |
} | |
attemptToControlBrowserAutoFillSettings() { | |
return this.#e ? Promise.reject(new Error("This Settings instance does not allow writing browser settings")) : Promise.allSettled([this.#r(chrome.privacy.services.passwordSavingEnabled, !1), this.#r(chrome.privacy.services.autofillCreditCardEnabled, !1), this.#r(chrome.privacy.services.autofillAddressEnabled, !1)]).then((e => (this.#l(), e))) | |
} | |
clearControlOfBrowserAutoFillSettings() { | |
return this.#e ? Promise.reject(new Error("This Settings instance does not allow writing browser settings")) : Promise.allSettled([this.#d(chrome.privacy.services.passwordSavingEnabled), this.#d(chrome.privacy.services.autofillCreditCardEnabled), this.#d(chrome.privacy.services.autofillAddressEnabled)]).then((e => (this.#l(), e))) | |
}# | |
o() { | |
let e = new Promise((e => { | |
chrome.storage.sync.get({ | |
enableInPageAutoFill: !0, | |
allowExtensionToControlAutoFillSettings: !0 | |
}, (t => { | |
this.#t = t.enableInPageAutoFill, this.#n = t.allowExtensionToControlAutoFillSettings, e() | |
})) | |
})); | |
return this.#e || (e = e.then(this.#a.bind(this))), e.then(this.#l.bind(this)) | |
}# | |
i() { | |
return new Promise((e => { | |
chrome.storage.sync.set({ | |
enableInPageAutoFill: this.#t, | |
allowExtensionToControlAutoFillSettings: this.#n | |
}, (() => { | |
e() | |
})) | |
})).then(this.#l.bind(this)) | |
}# | |
s() { | |
this.#e || (chrome.privacy.services.passwordSavingEnabled && chrome.privacy.services.passwordSavingEnabled.onChange.addListener((e => { | |
this.#l() | |
})), chrome.privacy.services.autofillCreditCardEnabled && chrome.privacy.services.autofillCreditCardEnabled.onChange.addListener((e => { | |
this.#l() | |
})), chrome.privacy.services.autofillAddressEnabled && chrome.privacy.services.autofillAddressEnabled.onChange.addListener((e => { | |
this.#l() | |
}))) | |
}# | |
l() { | |
const e = new CustomEvent("settingsChanged", { | |
detail: { | |
enableInPageAutoFill: this.#t | |
} | |
}); | |
this.eventTarget.dispatchEvent(e) | |
}# | |
r(e, t) { | |
return this.#g(e).then((n => n ? n.value === t ? { | |
details: n, | |
newValue: t | |
} : new Promise(((o, s) => { | |
e.set({ | |
value: t | |
}, (() => { | |
chrome.runtime.lastError && (chrome.runtime.lastError, chrome.runtime.lastError, s(chrome.runtime.lastError)), o({ | |
details: n, | |
newValue: t | |
}) | |
})) | |
})) : { | |
details: {}, | |
newValue: void 0 | |
})) | |
}# | |
g(e) { | |
return new Promise((t => { | |
e || t({}), e.get({}, (e => { | |
"not_controllable" === e.levelOfControl && reject(new Error("Cannot control this setting")), t(e) | |
})) | |
})) | |
}# | |
d(e) { | |
return new Promise((t => { | |
e || t(), e.clear({}, (() => { | |
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; | |
let g_presetUserName, g_theRememberICSelection, g_tabId, g_frameId, g_username, g_LoginNames = [], | |
g_HLDs = [], | |
g_arrDates = [], | |
g_canFillOneTimeCodes = !1, | |
g_oneTimeCodes = [], | |
g_extensionSettings = new ExtensionSettings(!0); | |
const RequestDataState = { | |
DoNotRequest: 0, | |
WillOrAreRequesting: 1, | |
RequestReturnedData: 2 | |
}; | |
let g_requestOneTimeCodesState = RequestDataState.DoNotRequest, | |
g_requestLoginsState = RequestDataState.DoNotRequest, | |
g_localizer = new Localizer; | |
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 listItemIsInView(e) { | |
let t = e.getBoundingClientRect(); | |
return t.top >= 0 && t.bottom <= window.innerHeight | |
} | |
function keyHandler(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 && e.preventDefault(), t.classList.remove("active"), o && (o.classList.add("active"), listItemIsInView(o) || o.scrollIntoView(!0)), !1; | |
case "ArrowDown": | |
if (e.preventDefault && e.preventDefault(), !t) { | |
let e = document.querySelector("li"); | |
return e && (e.classList.add("active"), listItemIsInView(e) || e.scrollIntoView(!0)), !1 | |
} | |
return s && (t.classList.remove("active"), s.classList.add("active"), listItemIsInView(s) || s.scrollIntoView(!1)), !1; | |
case "Enter": | |
if (t) return e.preventDefault && e.preventDefault(), t.click(), !1 | |
} | |
} | |
function showChoices(e, t, n, o, s, i, a, r, l) { | |
let d = document.getElementById("credentialList"), | |
g = document.querySelector("li.active"); | |
clearCredentialListContents(), addOneTimeCodeItemsToCompletionList(l, d, g); | |
const c = function() { | |
const e = /(.*)@/.exec(r); | |
return e ? e[1] : null | |
}(), | |
u = domainsForDisplayFromUsernamesAndDomains(s, i), | |
m = s.length; | |
let h = [], | |
p = []; | |
for (var S = 0; S < m; S++) { | |
let a = i[S], | |
l = s[S], | |
d = u[S]; | |
const g = l.toLowerCase().startsWith(r.toLowerCase()), | |
m = g || l.toLowerCase().startsWith(c ? c.toLowerCase() : null); | |
if (!g && !m) continue; | |
let C = newCredentialListItem(); | |
e && e === l && C.classList.add("haspresetusername"); | |
let f = ""; | |
isStringEmpty(l) ? f += `<div style="float: left"><p class="name no-user-name">${g_localizer.getMessage("NoUserName")}</p>` : f += `<div style="float: left"><p class="name">${l}</p>`, f += `<br><p class="website">${d}</p></div>`, C.innerHTML += f, C.addEventListener("click", (function() { | |
g_portToBackgroundPage.postMessage({ | |
from: "completionList", | |
subject: "fillLoginIntoForm", | |
theRememberICSelection: t, | |
tabId: n, | |
frameId: o, | |
theLogin: l, | |
theURL: a | |
}) | |
})), g ? h.push(C) : m && p.push(C) | |
} | |
for (const e of h) d.appendChild(e); | |
for (const e of p) d.appendChild(e); | |
if (d.children.length || !r.length) { | |
const e = !d.children.length; | |
d.appendChild(newPasswordsButtonListItem(e)) | |
} | |
g && d.children.length && d.children[0].classList.add("active"), 1 === d.children.length ? document.body.style.overflowY = "hidden" : document.body.style.overflowY = "initial", platformScrollbarWidth() > 0 && document.body.classList.add("visibleScroller"), resizeCompletionList(calculateFittingSizeOfCompletionList(d)) | |
} | |
function addOneTimeCodeItemsToCompletionList(e, t, n) { | |
for (let n of e) { | |
let e = newCredentialListItem(); | |
if ("totp" === n.source) { | |
let t = n.domain ? g_localizer.getMessage("totpVerificationCodeNameWithDomain", [n.domain]) : g_localizer.getMessage("totpVerificationCodeName"); | |
e.innerHTML += `<p class="name">${t}</p>`; | |
let o = n.username, | |
s = o || n.code; | |
e.innerHTML += `<br><p class="website">${s}</p>` | |
} | |
e.addEventListener("click", (() => { | |
g_portToBackgroundPage.postMessage({ | |
tabId: g_tabId, | |
frameId: g_frameId, | |
subject: "fillOneTimeCodeIntoForm", | |
oneTimeCode: n | |
}) | |
})), t.appendChild(e) | |
} | |
} | |
function populateCompletionListWithCachedContentIfReady() { | |
g_requestOneTimeCodesState !== RequestDataState.WillOrAreRequesting && g_requestLoginsState !== RequestDataState.WillOrAreRequesting && showChoices(g_presetUserName, g_theRememberICSelection, g_tabId, g_frameId, g_LoginNames, g_HLDs, g_arrDates, g_username, g_oneTimeCodes) | |
} | |
function gotOneTimeCodeChoices(e) { | |
g_oneTimeCodes = e, g_requestOneTimeCodesState = RequestDataState.RequestReturnedData, populateCompletionListWithCachedContentIfReady() | |
} | |
function scrollbarWidth() { | |
return platformScrollbarWidth() > 0 ? 18 : 0 | |
} | |
function platformScrollbarWidth() { | |
const e = document.createElement("div"); | |
e.style.visibility = "hidden", e.style.overflow = "scroll", document.body.appendChild(e); | |
const t = document.createElement("div"); | |
e.appendChild(t); | |
const n = e.offsetWidth - t.offsetWidth; | |
return e.parentNode.removeChild(e), n | |
} | |
function calculateFittingSizeOfCompletionList(e) { | |
if (!g_extensionSettings.enableInPageAutoFill) return { | |
width: 0, | |
height: 0 | |
}; | |
e.classList.add("inline"); | |
let t = 0; | |
for (let n of e.children) { | |
getComputedStyle(n); | |
let e = Math.ceil(parseFloat(n.getBoundingClientRect().width)); | |
e > t && (t = e) | |
} | |
e.classList.remove("inline"); | |
let n = e.offsetHeight, | |
o = 0; | |
if (e.children.length > 5) { | |
n = 4.5 * parseFloat(e.children[0].getBoundingClientRect().height), o = scrollbarWidth() | |
} | |
return { | |
width: Math.max(t + o, 200), | |
height: n | |
} | |
} | |
function resizeCompletionList(e) { | |
g_portToBackgroundPage.postMessage({ | |
subject: "resizeCompletionList", | |
tabId: g_tabId, | |
frameId: g_frameId, | |
height: e.height, | |
width: e.width | |
}) | |
} | |
function UpdateUserContents(e, t, n, o, s, i) { | |
switch (clearCredentialListContents(), e) { | |
case RememberIC.UnknownPage: | |
case RememberIC.RememberLoginAndPassword: | |
{ | |
g_theRememberICSelection = e, | |
g_tabId = t, | |
g_frameId = n, | |
g_LoginNames = o, | |
g_HLDs = s, | |
g_arrDates = i; | |
const a = new URLSearchParams(document.location.search).get("username");g_username = a, | |
g_requestLoginsState = RequestDataState.RequestReturnedData, | |
populateCompletionListWithCachedContentIfReady(), | |
divICs.style.display = "block" | |
} | |
} | |
} | |
function newCredentialListItem() { | |
let e = document.createElement("li"); | |
return e.classList.add("selectable"), e.classList.add("credential"), e.onmouseover = listItemMouseOverHandler, e.onmouseout = listItemMouseOutHandler, e.innerHTML = '<img src="images/key.svg"/>', e | |
} | |
function newPasswordsButtonListItem(e) { | |
let t = document.createElement("li"); | |
return t.classList.add("selectable"), t.classList.add("open-password-manager"), t.onmouseover = listItemMouseOverHandler, t.onmouseout = listItemMouseOutHandler, t.innerHTML = e ? `<span><p class="title">${g_localizer.getMessage("divOpenPasswords")}</p><p class="subtitle">${g_localizer.getMessage("divOpenPasswordsSubtitle")}</p></span>` : `<span>${g_localizer.getMessage("divOpenPasswords")}</span>`, t.addEventListener("click", (function() { | |
g_portToBackgroundPage.postMessage({ | |
tabId: g_tabId, | |
frameId: g_frameId, | |
subject: "openPasswordManagerAndDismissCompletionList" | |
}) | |
})), t | |
} | |
function clearCredentialListContents() { | |
document.getElementById("needToPairMessageBox").style.display = "none"; | |
let e = document.getElementById("credentialList"); | |
for (; e.firstChild;) e.removeChild(e.lastChild) | |
} | |
function updateCompletionList(e, t, n) { | |
if (e === ContextState.NotInSession) { | |
document.getElementById("needToPairTitle").innerHTML = g_localizer.getMessage("enableAutoFillPasswordsTitle"), document.getElementById("needToPairMessage").innerHTML = g_localizer.getMessage("enableAutoFillPasswordsMessage"); | |
let e = document.getElementById("needToPairMessageBox"); | |
e.style.display = "flex"; | |
const t = e.getBoundingClientRect(); | |
return void resizeCompletionList({ | |
width: t.width, | |
height: t.height | |
}) | |
} | |
g_requestOneTimeCodesState = RequestDataState.DoNotRequest, g_requestLoginsState = RequestDataState.DoNotRequest; | |
let o = n ? n.AutoFillFormType : WBSAutoFillFormTypeUndetermined; | |
switch (g_canFillOneTimeCodes && t && t.ControlLooksLikeOneTimeCodeField && (g_requestOneTimeCodesState = RequestDataState.WillOrAreRequesting), o) { | |
case WBSAutoFillFormTypeAutoFillableLogin: | |
g_requestLoginsState = RequestDataState.WillOrAreRequesting; | |
break; | |
case WBSAutoFillFormTypeChangePassword: | |
case WBSAutoFillFormTypeNewAccount: | |
if (t.ControlUniqueID === n.UsernameElementUniqueID || t.ControlUniqueID === n.OldPasswordElementUniqueID) { | |
g_requestLoginsState = RequestDataState.WillOrAreRequesting; | |
break | |
} | |
if (t.ControlUniqueID === n.PasswordElementUniqueID || t.ControlUniqueID === n.ConfirmPasswordElementUniqueID) return void showChoices(g_presetUserName, g_theRememberICSelection, g_tabId, g_frameId, [], [], [], "", []); | |
default: | |
(t.ControlIsSecureTextField || t.ControlClaimsToBeUsernameViaAutocompleteAttribute || t.ControlIsLabeledUsernameField) && (g_hostname, g_requestLoginsState = RequestDataState.WillOrAreRequesting) | |
} | |
g_requestOneTimeCodesState === RequestDataState.WillOrAreRequesting && g_portToBackgroundPage.postMessage({ | |
subject: "getOneTimeCodes", | |
tabId: g_tabId, | |
frameId: g_frameId, | |
username: g_presetUserName | |
}), g_requestLoginsState === RequestDataState.WillOrAreRequesting && g_portToBackgroundPage.postMessage({ | |
subject: "GetLoginNames4URL", | |
hostname: g_hostname, | |
tabId: g_tabId, | |
frameId: g_frameId | |
}) | |
} | |
document.documentElement.addEventListener("keydown", keyHandler), window.onload = function() { | |
Localizer.configureDocumentElementForLanguage(document.documentElement, chrome.i18n.getUILanguage()), g_portToBackgroundPage = chrome.runtime.connect({ | |
name: "completionList" | |
}), g_portToBackgroundPage.onMessage.addListener((function(e) { | |
switch (e.subject) { | |
case "hello": | |
g_localizer = new Localizer(e.capabilities); | |
break; | |
case "replyForGetContextAndMetadataFromContent": | |
g_tabId = e.tabId, g_frameId = e.frameId, g_hostname = e.hostname, g_presetUserName = e.presetUserName, g_canFillOneTimeCodes = e.canFillOneTimeCodes; | |
updateCompletionList(e.state, e.textFieldMetadata, e.formMetadata); | |
break; | |
case "users": | |
UpdateUserContents(e.theRememberICSelection, e.tabId, e.frameId, e.arrLoginNames, e.arrHLDs, e.arrDates); | |
break; | |
case "oneTimeCodes": | |
gotOneTimeCodeChoices(e.oneTimeCodes); | |
break; | |
case "keydown": | |
keyHandler(e.event); | |
break; | |
case "typedUserNameChanged": | |
if ("flex" === document.getElementById("needToPairMessageBox").style.display) { | |
g_portToBackgroundPage.postMessage({ | |
tabId: g_tabId, | |
frameId: g_frameId, | |
subject: "dismissCompletionList" | |
}); | |
break | |
} | |
if (!g_LoginNames.length) { | |
g_portToBackgroundPage.postMessage({ | |
tabId: g_tabId, | |
frameId: g_frameId, | |
subject: "dismissCompletionList" | |
}); | |
break | |
} | |
showChoices(g_presetUserName, g_theRememberICSelection, g_tabId, g_frameId, g_LoginNames, g_HLDs, g_arrDates, e.username, g_oneTimeCodes) | |
} | |
})), g_portToBackgroundPage.postMessage({ | |
subject: "getContextAndMetadataFromContent" | |
}) | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"background": { | |
"persistent": false, | |
"scripts": [ "sjcl.js", "background.js" ] | |
}, | |
"browser_action": { | |
"default_icon": { | |
"16": "images/PasswordsToolbar_icon16.png", | |
"32": "images/PasswordsToolbar_icon32.png" | |
}, | |
"default_popup": "page_popup.html" | |
}, | |
"content_scripts": [ { | |
"all_frames": true, | |
"js": [ "content_script.js" ], | |
"matches": [ "*://*/*" ], | |
"run_at": "document_idle" | |
} ], | |
"default_locale": "en", | |
"description": "__MSG_extDescription__", | |
"icons": { | |
"128": "images/PasswordsExtensionIcon_128.png", | |
"16": "images/PasswordsExtensionIcon_16.png", | |
"32": "images/PasswordsExtensionIcon_32.png" | |
}, | |
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+TQP8e6VgCOUmwbwfJF+tIh99O9CkdErBGzk1KUxRetfXX6MuJVo10DEDE3e94WHwzzBiy9izP9q9zfNOGoT+9FkB3ebOQ8oZWaKMP8Y4070OC0u4csPb7ScL0LF3VbcotaKuLRYgZxtzj4QTtntsfdi2nhjx/liTk3hQDQyCMFcCZjT9ZfGnVtPcgYrbRrkfdX756p14wzSFvS6VgrsoiJCpbBOLOT66S7hj0fveP1w0swSU31mHdnX9VRkQSBKkEf7ScahE0P6sx8wdza+hp/z5KUsiM/ejJ8MAyPWcCMsyxqf+SmmmB0FpT0q6RA6cTtzQ/bfQJhO40raxSWiewIDAQAB", | |
"manifest_version": 2, | |
"name": "__MSG_extName__", | |
"options_ui": { | |
"open_in_tab": false, | |
"page": "settings.html" | |
}, | |
"permissions": [ "\u003Call_urls>", "privacy", "declarativeContent", "nativeMessaging", "webNavigation", "storage" ], | |
"update_url": "https://edge.microsoft.com/extensionwebstorebase/v1/crx", | |
"version": "1.3.77", | |
"web_accessible_resources": [ "completion_list.html" ] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var pwlog = void 0, | |
pwerror = void 0; | |
function isStringEmpty(e) { | |
return !e || 0 === e.length | |
} | |
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" | |
} | |
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 (identicalIndex of e) o[identicalIndex] = t[identicalIndex] | |
} | |
return o | |
} | |
class Localizer { | |
static configureDocumentElementForLanguage(e, t) { | |
switch (t) { | |
case "he": | |
case "ar": | |
case "fa": | |
e.setAttribute("dir", "rtl"), e.setAttribute("lang", t) | |
} | |
} | |
constructor(e) {} | |
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 = []; | |
return t.push(e), t | |
} | |
} | |
class ExtensionSettings {# | |
e = !1;# | |
t = !0;# | |
n = !0; | |
eventTarget = new EventTarget; | |
constructor(e = !1) { | |
this.#e = e, this.#o(), this.#s() | |
} | |
get enableInPageAutoFill() { | |
return this.#t | |
} | |
set enableInPageAutoFill(e) { | |
this.#t = e, this.#a() | |
} | |
get allowExtensionToControlAutoFillSettings() { | |
return this.#n | |
} | |
set allowExtensionToControlAutoFillSettings(e) { | |
this.#n = e, this.#i().then(this.#a.bind(this)) | |
}# | |
i() { | |
return this.#n ? this.attemptToControlBrowserAutoFillSettings() : this.clearControlOfBrowserAutoFillSettings() | |
} | |
attemptToControlBrowserAutoFillSettings() { | |
return this.#e ? Promise.reject(new Error("This Settings instance does not allow writing browser settings")) : Promise.allSettled([this.#r(chrome.privacy.services.passwordSavingEnabled, !1), this.#r(chrome.privacy.services.autofillCreditCardEnabled, !1), this.#r(chrome.privacy.services.autofillAddressEnabled, !1)]).then((e => (this.#l(), e))) | |
} | |
clearControlOfBrowserAutoFillSettings() { | |
return this.#e ? Promise.reject(new Error("This Settings instance does not allow writing browser settings")) : Promise.allSettled([this.#d(chrome.privacy.services.passwordSavingEnabled), this.#d(chrome.privacy.services.autofillCreditCardEnabled), this.#d(chrome.privacy.services.autofillAddressEnabled)]).then((e => (this.#l(), e))) | |
}# | |
o() { | |
let e = new Promise((e => { | |
chrome.storage.sync.get({ | |
enableInPageAutoFill: !0, | |
allowExtensionToControlAutoFillSettings: !0 | |
}, (t => { | |
this.#t = t.enableInPageAutoFill, this.#n = t.allowExtensionToControlAutoFillSettings, e() | |
})) | |
})); | |
return this.#e || (e = e.then(this.#i.bind(this))), e.then(this.#l.bind(this)) | |
}# | |
a() { | |
return new Promise((e => { | |
chrome.storage.sync.set({ | |
enableInPageAutoFill: this.#t, | |
allowExtensionToControlAutoFillSettings: this.#n | |
}, (() => { | |
e() | |
})) | |
})).then(this.#l.bind(this)) | |
}# | |
s() { | |
this.#e || (chrome.privacy.services.passwordSavingEnabled && chrome.privacy.services.passwordSavingEnabled.onChange.addListener((e => { | |
this.#l() | |
})), chrome.privacy.services.autofillCreditCardEnabled && chrome.privacy.services.autofillCreditCardEnabled.onChange.addListener((e => { | |
this.#l() | |
})), chrome.privacy.services.autofillAddressEnabled && chrome.privacy.services.autofillAddressEnabled.onChange.addListener((e => { | |
this.#l() | |
}))) | |
}# | |
l() { | |
const e = new CustomEvent("settingsChanged", { | |
detail: { | |
enableInPageAutoFill: this.#t | |
} | |
}); | |
this.eventTarget.dispatchEvent(e) | |
}# | |
r(e, t) { | |
return this.#c(e).then((n => n ? n.value === t ? { | |
details: n, | |
newValue: t | |
} : new Promise(((o, s) => { | |
e.set({ | |
value: t | |
}, (() => { | |
chrome.runtime.lastError && (chrome.runtime.lastError, chrome.runtime.lastError, s(chrome.runtime.lastError)), o({ | |
details: n, | |
newValue: t | |
}) | |
})) | |
})) : { | |
details: {}, | |
newValue: void 0 | |
})) | |
}# | |
c(e) { | |
return new Promise((t => { | |
e || t({}), e.get({}, (e => { | |
"not_controllable" === e.levelOfControl && reject(new Error("Cannot control this setting")), t(e) | |
})) | |
})) | |
}# | |
d(e) { | |
return new Promise((t => { | |
e || t(), e.clear({}, (() => { | |
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; | |
var g_lastUpdatedPopupContentsState, g_portToBackgroundPage = null, | |
g_appStoreURL = null, | |
g_localizer = new Localizer; | |
function setControlText(e, t) { | |
var n = document.getElementById(e); | |
n && (n.innerHTML = g_localizer.getMessage(t), n.textContent) | |
} | |
function setMessageTitle(e) { | |
var t = document.getElementById("divMessageBoardTitle"); | |
t && (t.innerHTML = g_localizer.getMessage(e), t.textContent) | |
} | |
function setMessageSubtitle(e) { | |
var t = document.getElementById("divMessageBoardMessage"); | |
t && (t.innerHTML = 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) { | |
showMessage(e, t); | |
let n = document.querySelector("#openPasswordManagerList"); | |
n.children.length || n.appendChild(listItemForOpenPasswordManager()) | |
} | |
function SetOpeniC4WTitleText(e) { | |
var t = document.getElementById("idOpeniC4WTitle"); | |
t && (t.innerHTML = g_localizer.getMessage(e), t.textContent) | |
} | |
function SetOpeniC4WButtonText(e) { | |
var t = document.getElementById("idOpeniC4WButton"); | |
t && (t.innerHTML = g_localizer.getMessage(e), t.textContent) | |
} | |
function clearCredentialListContents() { | |
let e = document.getElementById("credentialList"); | |
for (; e.firstChild;) e.removeChild(e.lastChild) | |
} | |
function tryToEstablishNativeConnectionInResponseToUserActivatingPopupAfterDelay() { | |
setTimeout((function() { | |
g_portToBackgroundPage.postMessage({ | |
subject: "tryToEstablishNativeConnectionInResponseToUserActivatingPopup" | |
}) | |
}), 50) | |
} | |
function UpdatePopupContents(e) { | |
if (!g_lastUpdatedPopupContentsState || g_lastUpdatedPopupContentsState !== ContextState.NativeSupportNotInstalled || e !== ContextState.NativeSupportNotInstalled) { | |
g_lastUpdatedPopupContentsState = e; | |
var 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"), g_portToBackgroundPage.postMessage({ | |
subject: "challengePIN" | |
}); | |
break; | |
case ContextState.CheckEngine: | |
SetOpeniC4WTitleText("CheckEngineMessage"), SetOpeniC4WButtonText("openiCloudForWindowsButtonText"), a.style.display = "block"; | |
break; | |
case ContextState.ChallengeSent: | |
break; | |
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(), chrome.webNavigation.getAllFrames({ | |
tabId: n[0].id | |
}, (e => { | |
n[0].id, e.forEach(((e, t, o) => { | |
JSON.stringify(e); | |
const s = new URL(e.url), | |
a = s.protocol; | |
if ("http:" !== a && "https:" !== a) return e.url, void showMessageWithOpenPasswordManagerButton("GenericPopupTitle", "divNoPasswordsMessage"); | |
try { | |
chrome.tabs.sendMessage(n[0].id, { | |
from: "popup", | |
subject: "getPageType", | |
URL: s.hostname, | |
tabId: n[0].id, | |
frameId: e.frameId | |
}, { | |
frameId: e.frameId | |
}, (function(t) { | |
switch (t || (s.hostname, n[0].id, e.frameId, t = WBSAutoFillFormTypeUndetermined), s.hostname, n[0].id, e.frameId, humanReadableFormType(t), humanReadableFormType(t), t) { | |
case WBSAutoFillFormTypeUndetermined: | |
case WBSAutoFillFormTypeAutoFillableStandard: | |
case WBSAutoFillFormTypeNonAutoFillable: | |
showMessageWithOpenPasswordManagerButton("GenericPopupTitle", "divNoPasswordsMessage"); | |
break; | |
case WBSAutoFillFormTypeAutoFillableLogin: | |
case WBSAutoFillFormTypeChangePassword: | |
case WBSAutoFillFormTypeNewAccount: | |
showMessage("extName", "GettingPasswords"), g_portToBackgroundPage.postMessage({ | |
subject: "GetLoginNames4URL", | |
hostname: s.hostname, | |
tabId: n[0].id, | |
frameId: e.frameId | |
}) | |
} | |
})) | |
} catch (t) { | |
n[0].id, e.frameId, t.message | |
} | |
})) | |
})); | |
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 updatePopupContents(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"); | |
break; | |
case RememberIC.DoNotRemember: | |
showMessageWithOpenPasswordManagerButton("divDoNotRememberTitle", "divDoNotRememberMessage"); | |
break; | |
case RememberIC.RememberLoginAndPassword: | |
{ | |
try { | |
chrome.tabs.sendMessage(t, { | |
from: "popup", | |
subject: "getPresetUserName", | |
tabId: t, | |
frameId: n | |
}, { | |
frameId: n | |
}, (function(a) { | |
JSON.stringify(a), document.querySelector("#iCloudIconId").style.display = "none", clearCredentialListContents(); | |
const i = domainsForDisplayFromUsernamesAndDomains(o, s), | |
r = o.length; | |
for (var l = 0; l < r; l++) { | |
let r = document.createElement("li"), | |
d = s[l], | |
c = o[l], | |
g = i[l]; | |
a.isPresetUserNamePresent && a.thePresetUserName === c && r.classList.add("haspresetusername"), r.classList.add("selectable"), r.classList.add("credential"), r.onmouseover = listItemMouseOverHandler, r.onmouseout = listItemMouseOutHandler, r.innerHTML = '<img src="images/key.svg"/>', isStringEmpty(c) ? r.innerHTML += `<p class="name no-user-name">${g_localizer.getMessage("NoUserName")}</p>` : r.innerHTML += `<p class="name">${c}</p>`, r.innerHTML += `<p class="website">${g}</p>`, r.addEventListener("click", (function() { | |
chrome.tabs.query({ | |
active: !0, | |
currentWindow: !0 | |
}, (function(o) { | |
chrome.tabs.sendMessage(o[0].id, { | |
from: "popup", | |
subject: "fillLoginIntoForm", | |
theRememberICSelection: e, | |
tabId: t, | |
frameId: n, | |
theLogin: c, | |
theURL: d | |
}, { | |
frameId: n | |
}), window.close() | |
})) | |
})), u.appendChild(r) | |
} | |
u.appendChild(listItemForOpenPasswordManager()) | |
})) | |
} catch (e) { | |
e.message | |
} | |
let a = document.querySelector("#divMessageBoard .credential-list");a && a.remove(), | |
l.style.display = "block" | |
} | |
} | |
} | |
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.innerHTML = g_localizer.getMessage("divOpenPasswords"), e.addEventListener("click", openPasswordsButtonHandler), 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(""); | |
g_portToBackgroundPage.postMessage({ | |
subject: "userEnteredPIN", | |
pin: a | |
}) | |
} | |
} | |
function openPasswordsButtonHandler(e) { | |
g_portToBackgroundPage.postMessage({ | |
subject: "openPasswordManager" | |
}), 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.onload = function() { | |
let e = chrome.i18n.getUILanguage(); | |
Localizer.configureDocumentElementForLanguage(document.documentElement, e), (g_portToBackgroundPage = chrome.runtime.connect({ | |
name: "popup" | |
})).onMessage.addListener((function(e, t, n) { | |
switch (e.subject) { | |
case "hello": | |
g_localizer = new Localizer(e.capabilities); | |
break; | |
case "nativeConnectionStateChanged": | |
g_appStoreURL = e.appStoreURL, UpdatePopupContents(e.state) | |
} | |
})), g_portToBackgroundPage.postMessage({ | |
subject: "getNativeConnectionState" | |
}) | |
}, document.getElementById("downloadButton").onclick = function(e) { | |
chrome.tabs.create({ | |
url: g_appStoreURL | |
}) | |
}, document.getElementById("idOpeniC4WButton").onclick = function() { | |
g_portToBackgroundPage.postMessage({ | |
subject: "startiCloudControlPanel" | |
}), window.close() | |
}, document.getElementById("dismiss").onclick = function() { | |
window.close() | |
}, chrome.runtime.onMessage.addListener(((e, t, n) => { | |
if ("users" === e.subject) chrome.tabs.query({ | |
active: !0, | |
currentWindow: !0 | |
}, (function(t) { | |
t[0].id === e.tabId && updatePopupContents(e.theRememberICSelection, e.tabId, e.frameId, e.arrLoginNames, e.arrHLDs, e.arrDates) | |
})); | |
return Promise.resolve("Dummy response to keep the console quiet") | |
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var pwlog = void 0, | |
pwerror = void 0; | |
function isStringEmpty(e) { | |
return !e || 0 === e.length | |
} | |
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" | |
} | |
return "Unrecognized" | |
} | |
function domainsForDisplayFromUsernamesAndDomains(e, t) { | |
const n = e.length; | |
let o = t.map((function(e) { | |
return e.replace(/^(www|m)\./, "") | |
})), | |
i = []; | |
for (var s = 0; s < n; s++) i.push([e[s], o[s]]); | |
for (s = 0; s < n; s++) { | |
let e = []; | |
for (var r = s + 1; r < n; r++) i[s].join("\n") === i[r].join("\n") && (e.length || e.push(s), e.push(r)); | |
for (identicalIndex of e) o[identicalIndex] = t[identicalIndex] | |
} | |
return o | |
} | |
class Localizer { | |
static configureDocumentElementForLanguage(e, t) { | |
switch (t) { | |
case "he": | |
case "ar": | |
case "fa": | |
e.setAttribute("dir", "rtl"), e.setAttribute("lang", t) | |
} | |
} | |
constructor(e) {} | |
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 = []; | |
return t.push(e), t | |
} | |
} | |
class ExtensionSettings {# | |
e = !1;# | |
t = !0;# | |
n = !0; | |
eventTarget = new EventTarget; | |
constructor(e = !1) { | |
this.#e = e, this.#o(), this.#i() | |
} | |
get enableInPageAutoFill() { | |
return this.#t | |
} | |
set enableInPageAutoFill(e) { | |
this.#t = e, this.#s() | |
} | |
get allowExtensionToControlAutoFillSettings() { | |
return this.#n | |
} | |
set allowExtensionToControlAutoFillSettings(e) { | |
this.#n = e, this.#r().then(this.#s.bind(this)) | |
}# | |
r() { | |
return this.#n ? this.attemptToControlBrowserAutoFillSettings() : this.clearControlOfBrowserAutoFillSettings() | |
} | |
attemptToControlBrowserAutoFillSettings() { | |
return this.#e ? Promise.reject(new Error("This Settings instance does not allow writing browser settings")) : Promise.allSettled([this.#l(chrome.privacy.services.passwordSavingEnabled, !1), this.#l(chrome.privacy.services.autofillCreditCardEnabled, !1), this.#l(chrome.privacy.services.autofillAddressEnabled, !1)]).then((e => (this.#a(), e))) | |
} | |
clearControlOfBrowserAutoFillSettings() { | |
return this.#e ? Promise.reject(new Error("This Settings instance does not allow writing browser settings")) : Promise.allSettled([this.#g(chrome.privacy.services.passwordSavingEnabled), this.#g(chrome.privacy.services.autofillCreditCardEnabled), this.#g(chrome.privacy.services.autofillAddressEnabled)]).then((e => (this.#a(), e))) | |
}# | |
o() { | |
let e = new Promise((e => { | |
chrome.storage.sync.get({ | |
enableInPageAutoFill: !0, | |
allowExtensionToControlAutoFillSettings: !0 | |
}, (t => { | |
this.#t = t.enableInPageAutoFill, this.#n = t.allowExtensionToControlAutoFillSettings, e() | |
})) | |
})); | |
return this.#e || (e = e.then(this.#r.bind(this))), e.then(this.#a.bind(this)) | |
}# | |
s() { | |
return new Promise((e => { | |
chrome.storage.sync.set({ | |
enableInPageAutoFill: this.#t, | |
allowExtensionToControlAutoFillSettings: this.#n | |
}, (() => { | |
e() | |
})) | |
})).then(this.#a.bind(this)) | |
}# | |
i() { | |
this.#e || (chrome.privacy.services.passwordSavingEnabled && chrome.privacy.services.passwordSavingEnabled.onChange.addListener((e => { | |
this.#a() | |
})), chrome.privacy.services.autofillCreditCardEnabled && chrome.privacy.services.autofillCreditCardEnabled.onChange.addListener((e => { | |
this.#a() | |
})), chrome.privacy.services.autofillAddressEnabled && chrome.privacy.services.autofillAddressEnabled.onChange.addListener((e => { | |
this.#a() | |
}))) | |
}# | |
a() { | |
const e = new CustomEvent("settingsChanged", { | |
detail: { | |
enableInPageAutoFill: this.#t | |
} | |
}); | |
this.eventTarget.dispatchEvent(e) | |
}# | |
l(e, t) { | |
return this.#c(e).then((n => n ? n.value === t ? { | |
details: n, | |
newValue: t | |
} : new Promise(((o, i) => { | |
e.set({ | |
value: t | |
}, (() => { | |
chrome.runtime.lastError && (chrome.runtime.lastError, chrome.runtime.lastError, i(chrome.runtime.lastError)), o({ | |
details: n, | |
newValue: t | |
}) | |
})) | |
})) : { | |
details: {}, | |
newValue: void 0 | |
})) | |
}# | |
c(e) { | |
return new Promise((t => { | |
e || t({}), e.get({}, (e => { | |
"not_controllable" === e.levelOfControl && reject(new Error("Cannot control this setting")), t(e) | |
})) | |
})) | |
}# | |
g(e) { | |
return new Promise((t => { | |
e || t(), e.clear({}, (() => { | |
t() | |
})) | |
})) | |
} | |
} | |
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.innerHTML = 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) | |
})) | |
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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 && (console.log("There was an error collecting entropy from the browser:"), console.log(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 | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment