mirror of
https://github.com/zadam/trilium.git
synced 2024-09-20 23:55:59 +08:00
more cleanups
This commit is contained in:
parent
0a0421ec7e
commit
b28df3f093
|
@ -90,7 +90,7 @@ settings.addModule((function() {
|
|||
alert("Password has been changed. Trilium will be reloaded after you press OK.");
|
||||
|
||||
// encryption password changed so current encryption session is invalid and needs to be cleared
|
||||
encryption.resetEncryptionSession();
|
||||
encryption.resetProtectedSession();
|
||||
}
|
||||
else {
|
||||
showError(result.message);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
"use strict";
|
||||
|
||||
const encryption = (function() {
|
||||
const dialogEl = $("#encryption-password-dialog");
|
||||
const encryptionPasswordFormEl = $("#encryption-password-form");
|
||||
const encryptionPasswordEl = $("#encryption-password");
|
||||
const dialogEl = $("#protected-session-password-dialog");
|
||||
const passwordFormEl = $("#protected-session-password-form");
|
||||
const passwordEl = $("#protected-session-password");
|
||||
|
||||
let encryptionDeferred = null;
|
||||
let lastEncryptionOperationDate = null;
|
||||
let protectedSessionDeferred = null;
|
||||
let lastProtectedSessionOperationDate = null;
|
||||
let encryptionSessionTimeout = null;
|
||||
let protectedSessionId = null;
|
||||
|
||||
|
@ -22,14 +22,14 @@ const encryption = (function() {
|
|||
encryptionSessionTimeout = encSessTimeout;
|
||||
}
|
||||
|
||||
function ensureProtectedSession(requireEncryption, modal) {
|
||||
function ensureProtectedSession(requireProtectedSession, modal) {
|
||||
const dfd = $.Deferred();
|
||||
|
||||
if (requireEncryption && !isEncryptionAvailable()) {
|
||||
if (requireProtectedSession && !isProtectedSessionAvailable()) {
|
||||
// if this is entry point then we need to show the app even before the note is loaded
|
||||
showAppIfHidden();
|
||||
|
||||
encryptionDeferred = dfd;
|
||||
protectedSessionDeferred = dfd;
|
||||
|
||||
dialogEl.dialog({
|
||||
modal: modal,
|
||||
|
@ -50,8 +50,8 @@ const encryption = (function() {
|
|||
}
|
||||
|
||||
async function setupProtectedSession() {
|
||||
const password = encryptionPasswordEl.val();
|
||||
encryptionPasswordEl.val("");
|
||||
const password = passwordEl.val();
|
||||
passwordEl.val("");
|
||||
|
||||
const response = await enterProtectedSession(password);
|
||||
|
||||
|
@ -68,10 +68,10 @@ const encryption = (function() {
|
|||
noteEditor.reload();
|
||||
noteTree.reload();
|
||||
|
||||
if (encryptionDeferred !== null) {
|
||||
encryptionDeferred.resolve();
|
||||
if (protectedSessionDeferred !== null) {
|
||||
protectedSessionDeferred.resolve();
|
||||
|
||||
encryptionDeferred = null;
|
||||
protectedSessionDeferred = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ const encryption = (function() {
|
|||
return protectedSessionId;
|
||||
}
|
||||
|
||||
function resetEncryptionSession() {
|
||||
function resetProtectedSession() {
|
||||
protectedSessionId = null;
|
||||
|
||||
initAjax();
|
||||
|
@ -101,7 +101,7 @@ const encryption = (function() {
|
|||
window.location.reload(true);
|
||||
}
|
||||
|
||||
function isEncryptionAvailable() {
|
||||
function isProtectedSessionAvailable() {
|
||||
return protectedSessionId !== null;
|
||||
}
|
||||
|
||||
|
@ -133,23 +133,23 @@ const encryption = (function() {
|
|||
noteEditor.setNoteBackgroundIfProtected(note);
|
||||
}
|
||||
|
||||
encryptionPasswordFormEl.submit(() => {
|
||||
passwordFormEl.submit(() => {
|
||||
setupProtectedSession();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
if (lastEncryptionOperationDate !== null && new Date().getTime() - lastEncryptionOperationDate.getTime() > encryptionSessionTimeout * 1000) {
|
||||
resetEncryptionSession();
|
||||
if (lastProtectedSessionOperationDate !== null && new Date().getTime() - lastProtectedSessionOperationDate.getTime() > encryptionSessionTimeout * 1000) {
|
||||
resetProtectedSession();
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
return {
|
||||
setEncryptionSessionTimeout,
|
||||
ensureProtectedSession,
|
||||
resetEncryptionSession,
|
||||
isEncryptionAvailable,
|
||||
resetProtectedSession,
|
||||
isProtectedSessionAvailable,
|
||||
protectNoteAndSendToServer,
|
||||
unprotectNoteAndSendToServer,
|
||||
getProtectedSessionId
|
||||
|
|
|
@ -7,8 +7,8 @@ const noteEditor = (function() {
|
|||
const protectButton = $("#protect-button");
|
||||
const unprotectButton = $("#unprotect-button");
|
||||
const noteDetailWrapperEl = $("#note-detail-wrapper");
|
||||
const encryptionPasswordDialogEl = $("#encryption-password-dialog");
|
||||
const encryptionPasswordEl = $("#encryption-password");
|
||||
const encryptionPasswordDialogEl = $("#protected-session-password-dialog");
|
||||
const encryptionPasswordEl = $("#protected-session-password");
|
||||
|
||||
let currentNote = null;
|
||||
|
||||
|
@ -122,7 +122,7 @@ const noteEditor = (function() {
|
|||
async function createNote(node, parentKey, target, isProtected) {
|
||||
// if isProtected isn't available (user didn't enter password yet), then note is created as unencrypted
|
||||
// but this is quite weird since user doesn't see where the note is being created so it shouldn't occur often
|
||||
if (!isProtected || !encryption.isEncryptionAvailable()) {
|
||||
if (!isProtected || !encryption.isProtectedSessionAvailable()) {
|
||||
isProtected = false;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,452 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
(function(root) {
|
||||
var MAX_VALUE = 0x7fffffff;
|
||||
|
||||
// The SHA256 and PBKDF2 implementation are from scrypt-async-js:
|
||||
// See: https://github.com/dchest/scrypt-async-js
|
||||
function SHA256(m) {
|
||||
var K = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
|
||||
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
|
||||
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
|
||||
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
|
||||
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
|
||||
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
|
||||
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
|
||||
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
|
||||
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
];
|
||||
|
||||
var h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a;
|
||||
var h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19;
|
||||
var w = new Array(64);
|
||||
|
||||
function blocks(p) {
|
||||
var off = 0, len = p.length;
|
||||
while (len >= 64) {
|
||||
var a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7, u, i, j, t1, t2;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
j = off + i*4;
|
||||
w[i] = ((p[j] & 0xff)<<24) | ((p[j+1] & 0xff)<<16) |
|
||||
((p[j+2] & 0xff)<<8) | (p[j+3] & 0xff);
|
||||
}
|
||||
|
||||
for (i = 16; i < 64; i++) {
|
||||
u = w[i-2];
|
||||
t1 = ((u>>>17) | (u<<(32-17))) ^ ((u>>>19) | (u<<(32-19))) ^ (u>>>10);
|
||||
|
||||
u = w[i-15];
|
||||
t2 = ((u>>>7) | (u<<(32-7))) ^ ((u>>>18) | (u<<(32-18))) ^ (u>>>3);
|
||||
|
||||
w[i] = (((t1 + w[i-7]) | 0) + ((t2 + w[i-16]) | 0)) | 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
t1 = ((((((e>>>6) | (e<<(32-6))) ^ ((e>>>11) | (e<<(32-11))) ^
|
||||
((e>>>25) | (e<<(32-25)))) + ((e & f) ^ (~e & g))) | 0) +
|
||||
((h + ((K[i] + w[i]) | 0)) | 0)) | 0;
|
||||
|
||||
t2 = ((((a>>>2) | (a<<(32-2))) ^ ((a>>>13) | (a<<(32-13))) ^
|
||||
((a>>>22) | (a<<(32-22)))) + ((a & b) ^ (a & c) ^ (b & c))) | 0;
|
||||
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = (d + t1) | 0;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = (t1 + t2) | 0;
|
||||
}
|
||||
|
||||
h0 = (h0 + a) | 0;
|
||||
h1 = (h1 + b) | 0;
|
||||
h2 = (h2 + c) | 0;
|
||||
h3 = (h3 + d) | 0;
|
||||
h4 = (h4 + e) | 0;
|
||||
h5 = (h5 + f) | 0;
|
||||
h6 = (h6 + g) | 0;
|
||||
h7 = (h7 + h) | 0;
|
||||
|
||||
off += 64;
|
||||
len -= 64;
|
||||
}
|
||||
}
|
||||
|
||||
blocks(m);
|
||||
|
||||
var i, bytesLeft = m.length % 64,
|
||||
bitLenHi = (m.length / 0x20000000) | 0,
|
||||
bitLenLo = m.length << 3,
|
||||
numZeros = (bytesLeft < 56) ? 56 : 120,
|
||||
p = m.slice(m.length - bytesLeft, m.length);
|
||||
|
||||
p.push(0x80);
|
||||
for (i = bytesLeft + 1; i < numZeros; i++) { p.push(0); }
|
||||
p.push((bitLenHi>>>24) & 0xff);
|
||||
p.push((bitLenHi>>>16) & 0xff);
|
||||
p.push((bitLenHi>>>8) & 0xff);
|
||||
p.push((bitLenHi>>>0) & 0xff);
|
||||
p.push((bitLenLo>>>24) & 0xff);
|
||||
p.push((bitLenLo>>>16) & 0xff);
|
||||
p.push((bitLenLo>>>8) & 0xff);
|
||||
p.push((bitLenLo>>>0) & 0xff);
|
||||
|
||||
blocks(p);
|
||||
|
||||
return [
|
||||
(h0>>>24) & 0xff, (h0>>>16) & 0xff, (h0>>>8) & 0xff, (h0>>>0) & 0xff,
|
||||
(h1>>>24) & 0xff, (h1>>>16) & 0xff, (h1>>>8) & 0xff, (h1>>>0) & 0xff,
|
||||
(h2>>>24) & 0xff, (h2>>>16) & 0xff, (h2>>>8) & 0xff, (h2>>>0) & 0xff,
|
||||
(h3>>>24) & 0xff, (h3>>>16) & 0xff, (h3>>>8) & 0xff, (h3>>>0) & 0xff,
|
||||
(h4>>>24) & 0xff, (h4>>>16) & 0xff, (h4>>>8) & 0xff, (h4>>>0) & 0xff,
|
||||
(h5>>>24) & 0xff, (h5>>>16) & 0xff, (h5>>>8) & 0xff, (h5>>>0) & 0xff,
|
||||
(h6>>>24) & 0xff, (h6>>>16) & 0xff, (h6>>>8) & 0xff, (h6>>>0) & 0xff,
|
||||
(h7>>>24) & 0xff, (h7>>>16) & 0xff, (h7>>>8) & 0xff, (h7>>>0) & 0xff
|
||||
];
|
||||
}
|
||||
|
||||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) {
|
||||
// compress password if it's longer than hash block length
|
||||
password = password.length <= 64 ? password : SHA256(password);
|
||||
|
||||
var i;
|
||||
var innerLen = 64 + salt.length + 4;
|
||||
var inner = new Array(innerLen);
|
||||
var outerKey = new Array(64);
|
||||
var dk = [];
|
||||
|
||||
// inner = (password ^ ipad) || salt || counter
|
||||
for (i = 0; i < 64; i++) inner[i] = 0x36;
|
||||
for (i = 0; i < password.length; i++) inner[i] ^= password[i];
|
||||
for (i = 0; i < salt.length; i++) inner[64+i] = salt[i];
|
||||
for (i = innerLen - 4; i < innerLen; i++) inner[i] = 0;
|
||||
|
||||
// outerKey = password ^ opad
|
||||
for (i = 0; i < 64; i++) outerKey[i] = 0x5c;
|
||||
for (i = 0; i < password.length; i++) outerKey[i] ^= password[i];
|
||||
|
||||
// increments counter inside inner
|
||||
function incrementCounter() {
|
||||
for (var i = innerLen-1; i >= innerLen-4; i--) {
|
||||
inner[i]++;
|
||||
if (inner[i] <= 0xff) return;
|
||||
inner[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// output blocks = SHA256(outerKey || SHA256(inner)) ...
|
||||
while (dkLen >= 32) {
|
||||
incrementCounter();
|
||||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))));
|
||||
dkLen -= 32;
|
||||
}
|
||||
if (dkLen > 0) {
|
||||
incrementCounter();
|
||||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen));
|
||||
}
|
||||
|
||||
return dk;
|
||||
}
|
||||
|
||||
// The following is an adaptation of scryptsy
|
||||
// See: https://www.npmjs.com/package/scryptsy
|
||||
function blockmix_salsa8(BY, Yi, r, x, _X) {
|
||||
var i;
|
||||
|
||||
arraycopy(BY, (2 * r - 1) * 16, _X, 0, 16);
|
||||
for (i = 0; i < 2 * r; i++) {
|
||||
blockxor(BY, i * 16, _X, 16);
|
||||
salsa20_8(_X, x);
|
||||
arraycopy(_X, 0, BY, Yi + (i * 16), 16);
|
||||
}
|
||||
|
||||
for (i = 0; i < r; i++) {
|
||||
arraycopy(BY, Yi + (i * 2) * 16, BY, (i * 16), 16);
|
||||
}
|
||||
|
||||
for (i = 0; i < r; i++) {
|
||||
arraycopy(BY, Yi + (i * 2 + 1) * 16, BY, (i + r) * 16, 16);
|
||||
}
|
||||
}
|
||||
|
||||
function R(a, b) {
|
||||
return (a << b) | (a >>> (32 - b));
|
||||
}
|
||||
|
||||
function salsa20_8(B, x) {
|
||||
arraycopy(B, 0, x, 0, 16);
|
||||
|
||||
for (var i = 8; i > 0; i -= 2) {
|
||||
x[ 4] ^= R(x[ 0] + x[12], 7);
|
||||
x[ 8] ^= R(x[ 4] + x[ 0], 9);
|
||||
x[12] ^= R(x[ 8] + x[ 4], 13);
|
||||
x[ 0] ^= R(x[12] + x[ 8], 18);
|
||||
x[ 9] ^= R(x[ 5] + x[ 1], 7);
|
||||
x[13] ^= R(x[ 9] + x[ 5], 9);
|
||||
x[ 1] ^= R(x[13] + x[ 9], 13);
|
||||
x[ 5] ^= R(x[ 1] + x[13], 18);
|
||||
x[14] ^= R(x[10] + x[ 6], 7);
|
||||
x[ 2] ^= R(x[14] + x[10], 9);
|
||||
x[ 6] ^= R(x[ 2] + x[14], 13);
|
||||
x[10] ^= R(x[ 6] + x[ 2], 18);
|
||||
x[ 3] ^= R(x[15] + x[11], 7);
|
||||
x[ 7] ^= R(x[ 3] + x[15], 9);
|
||||
x[11] ^= R(x[ 7] + x[ 3], 13);
|
||||
x[15] ^= R(x[11] + x[ 7], 18);
|
||||
x[ 1] ^= R(x[ 0] + x[ 3], 7);
|
||||
x[ 2] ^= R(x[ 1] + x[ 0], 9);
|
||||
x[ 3] ^= R(x[ 2] + x[ 1], 13);
|
||||
x[ 0] ^= R(x[ 3] + x[ 2], 18);
|
||||
x[ 6] ^= R(x[ 5] + x[ 4], 7);
|
||||
x[ 7] ^= R(x[ 6] + x[ 5], 9);
|
||||
x[ 4] ^= R(x[ 7] + x[ 6], 13);
|
||||
x[ 5] ^= R(x[ 4] + x[ 7], 18);
|
||||
x[11] ^= R(x[10] + x[ 9], 7);
|
||||
x[ 8] ^= R(x[11] + x[10], 9);
|
||||
x[ 9] ^= R(x[ 8] + x[11], 13);
|
||||
x[10] ^= R(x[ 9] + x[ 8], 18);
|
||||
x[12] ^= R(x[15] + x[14], 7);
|
||||
x[13] ^= R(x[12] + x[15], 9);
|
||||
x[14] ^= R(x[13] + x[12], 13);
|
||||
x[15] ^= R(x[14] + x[13], 18);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
B[i] += x[i];
|
||||
}
|
||||
}
|
||||
|
||||
// naive approach... going back to loop unrolling may yield additional performance
|
||||
function blockxor(S, Si, D, len) {
|
||||
for (var i = 0; i < len; i++) {
|
||||
D[i] ^= S[Si + i]
|
||||
}
|
||||
}
|
||||
|
||||
function arraycopy(src, srcPos, dest, destPos, length) {
|
||||
while (length--) {
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
}
|
||||
|
||||
function checkBufferish(o) {
|
||||
if (!o || typeof(o.length) !== 'number') {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < o.length; i++) {
|
||||
if (typeof(o[i]) !== 'number') { return false; }
|
||||
|
||||
var v = parseInt(o[i]);
|
||||
if (v != o[i] || v < 0 || v >= 256) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function ensureInteger(value, name) {
|
||||
var intValue = parseInt(value);
|
||||
if (value != intValue) { throw new Error('invalid ' + name); }
|
||||
return intValue;
|
||||
}
|
||||
|
||||
// N = Cpu cost, r = Memory cost, p = parallelization cost
|
||||
// callback(error, progress, key)
|
||||
function scrypt(password, salt, N, r, p, dkLen, callback) {
|
||||
|
||||
if (!callback) { throw new Error('missing callback'); }
|
||||
|
||||
N = ensureInteger(N, 'N');
|
||||
r = ensureInteger(r, 'r');
|
||||
p = ensureInteger(p, 'p');
|
||||
|
||||
dkLen = ensureInteger(dkLen, 'dkLen');
|
||||
|
||||
if (N === 0 || (N & (N - 1)) !== 0) { throw new Error('N must be power of 2'); }
|
||||
|
||||
if (N > MAX_VALUE / 128 / r) { throw new Error('N too large'); }
|
||||
if (r > MAX_VALUE / 128 / p) { throw new Error('r too large'); }
|
||||
|
||||
if (!checkBufferish(password)) {
|
||||
throw new Error('password must be an array or buffer');
|
||||
}
|
||||
|
||||
if (!checkBufferish(salt)) {
|
||||
throw new Error('salt must be an array or buffer');
|
||||
}
|
||||
|
||||
var b = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r);
|
||||
var B = new Uint32Array(p * 32 * r)
|
||||
for (var i = 0; i < B.length; i++) {
|
||||
var j = i * 4;
|
||||
B[i] = ((b[j + 3] & 0xff) << 24) |
|
||||
((b[j + 2] & 0xff) << 16) |
|
||||
((b[j + 1] & 0xff) << 8) |
|
||||
((b[j + 0] & 0xff) << 0);
|
||||
}
|
||||
|
||||
var XY = new Uint32Array(64 * r);
|
||||
var V = new Uint32Array(32 * r * N);
|
||||
|
||||
var Yi = 32 * r;
|
||||
|
||||
// scratch space
|
||||
var x = new Uint32Array(16); // salsa20_8
|
||||
var _X = new Uint32Array(16); // blockmix_salsa8
|
||||
|
||||
var totalOps = p * N * 2;
|
||||
var currentOp = 0;
|
||||
var lastPercent10 = null;
|
||||
|
||||
// Set this to true to abandon the scrypt on the next step
|
||||
var stop = false;
|
||||
|
||||
// State information
|
||||
var state = 0;
|
||||
var i0 = 0, i1;
|
||||
var Bi;
|
||||
|
||||
// How many blockmix_salsa8 can we do per step?
|
||||
var limit = parseInt(1000 / r);
|
||||
|
||||
// Trick from scrypt-async; if there is a setImmediate shim in place, use it
|
||||
var nextTick = (typeof(setImmediate) !== 'undefined') ? setImmediate : setTimeout;
|
||||
|
||||
// This is really all I changed; making scryptsy a state machine so we occasionally
|
||||
// stop and give other evnts on the evnt loop a chance to run. ~RicMoo
|
||||
var incrementalSMix = function() {
|
||||
if (stop) {
|
||||
return callback(new Error('cancelled'), currentOp / totalOps);
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
// for (var i = 0; i < p; i++)...
|
||||
Bi = i0 * 32 * r;
|
||||
|
||||
arraycopy(B, Bi, XY, 0, Yi); // ROMix - 1
|
||||
|
||||
state = 1; // Move to ROMix 2
|
||||
i1 = 0;
|
||||
|
||||
// Fall through
|
||||
|
||||
case 1:
|
||||
|
||||
// Run up to 1000 steps of the first inner smix loop
|
||||
var steps = N - i1;
|
||||
if (steps > limit) { steps = limit; }
|
||||
for (var i = 0; i < steps; i++) { // ROMix - 2
|
||||
arraycopy(XY, 0, V, (i1 + i) * Yi, Yi) // ROMix - 3
|
||||
blockmix_salsa8(XY, Yi, r, x, _X); // ROMix - 4
|
||||
}
|
||||
|
||||
// for (var i = 0; i < N; i++)
|
||||
i1 += steps;
|
||||
currentOp += steps;
|
||||
|
||||
// Call the callback with the progress (optionally stopping us)
|
||||
var percent10 = parseInt(1000 * currentOp / totalOps);
|
||||
if (percent10 !== lastPercent10) {
|
||||
stop = callback(null, currentOp / totalOps);
|
||||
if (stop) { break; }
|
||||
lastPercent10 = percent10;
|
||||
}
|
||||
|
||||
if (i1 < N) {
|
||||
break;
|
||||
}
|
||||
|
||||
i1 = 0; // Move to ROMix 6
|
||||
state = 2;
|
||||
|
||||
// Fall through
|
||||
|
||||
case 2:
|
||||
|
||||
// Run up to 1000 steps of the second inner smix loop
|
||||
var steps = N - i1;
|
||||
if (steps > limit) { steps = limit; }
|
||||
for (var i = 0; i < steps; i++) { // ROMix - 6
|
||||
var offset = (2 * r - 1) * 16; // ROMix - 7
|
||||
var j = XY[offset] & (N - 1);
|
||||
blockxor(V, j * Yi, XY, Yi); // ROMix - 8 (inner)
|
||||
blockmix_salsa8(XY, Yi, r, x, _X); // ROMix - 9 (outer)
|
||||
}
|
||||
|
||||
// for (var i = 0; i < N; i++)...
|
||||
i1 += steps;
|
||||
currentOp += steps;
|
||||
|
||||
// Call the callback with the progress (optionally stopping us)
|
||||
var percent10 = parseInt(1000 * currentOp / totalOps);
|
||||
if (percent10 !== lastPercent10) {
|
||||
stop = callback(null, currentOp / totalOps);
|
||||
if (stop) { break; }
|
||||
lastPercent10 = percent10;
|
||||
}
|
||||
|
||||
if (i1 < N) {
|
||||
break;
|
||||
}
|
||||
|
||||
arraycopy(XY, 0, B, Bi, Yi); // ROMix - 10
|
||||
|
||||
// for (var i = 0; i < p; i++)...
|
||||
i0++;
|
||||
if (i0 < p) {
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
b = [];
|
||||
for (var i = 0; i < B.length; i++) {
|
||||
b.push((B[i] >> 0) & 0xff);
|
||||
b.push((B[i] >> 8) & 0xff);
|
||||
b.push((B[i] >> 16) & 0xff);
|
||||
b.push((B[i] >> 24) & 0xff);
|
||||
}
|
||||
|
||||
var derivedKey = PBKDF2_HMAC_SHA256_OneIter(password, b, dkLen);
|
||||
|
||||
// Done; don't break (which would reschedule)
|
||||
return callback(null, 1.0, derivedKey);
|
||||
}
|
||||
|
||||
// Schedule the next steps
|
||||
nextTick(incrementalSMix);
|
||||
}
|
||||
|
||||
// Bootstrap the incremental smix
|
||||
incrementalSMix();
|
||||
}
|
||||
|
||||
// node.js
|
||||
if (typeof(exports) !== 'undefined') {
|
||||
module.exports = scrypt;
|
||||
|
||||
// RequireJS/AMD
|
||||
// http://www.requirejs.org/docs/api.html
|
||||
// https://github.com/amdjs/amdjs-api/wiki/AMD
|
||||
} else if (typeof(define) === 'function' && define.amd) {
|
||||
define(scrypt);
|
||||
|
||||
// Web Browsers
|
||||
} else if (root) {
|
||||
|
||||
// If there was an existing library "scrypt", make sure it is still available
|
||||
if (root.scrypt) {
|
||||
root._scrypt = root.scrypt;
|
||||
}
|
||||
|
||||
root.scrypt = scrypt;
|
||||
}
|
||||
|
||||
})(this);
|
|
@ -1,175 +0,0 @@
|
|||
(function (global, undefined) {
|
||||
"use strict";
|
||||
|
||||
if (global.setImmediate) {
|
||||
return;
|
||||
}
|
||||
|
||||
var nextHandle = 1; // Spec says greater than zero
|
||||
var tasksByHandle = {};
|
||||
var currentlyRunningATask = false;
|
||||
var doc = global.document;
|
||||
var setImmediate;
|
||||
|
||||
function addFromSetImmediateArguments(args) {
|
||||
tasksByHandle[nextHandle] = partiallyApplied.apply(undefined, args);
|
||||
return nextHandle++;
|
||||
}
|
||||
|
||||
// This function accepts the same arguments as setImmediate, but
|
||||
// returns a function that requires no arguments.
|
||||
function partiallyApplied(handler) {
|
||||
var args = [].slice.call(arguments, 1);
|
||||
return function() {
|
||||
if (typeof handler === "function") {
|
||||
handler.apply(undefined, args);
|
||||
} else {
|
||||
(new Function("" + handler))();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function runIfPresent(handle) {
|
||||
// From the spec: "Wait until any invocations of this algorithm started before this one have completed."
|
||||
// So if we're currently running a task, we'll need to delay this invocation.
|
||||
if (currentlyRunningATask) {
|
||||
// Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
|
||||
// "too much recursion" error.
|
||||
setTimeout(partiallyApplied(runIfPresent, handle), 0);
|
||||
} else {
|
||||
var task = tasksByHandle[handle];
|
||||
if (task) {
|
||||
currentlyRunningATask = true;
|
||||
try {
|
||||
task();
|
||||
} finally {
|
||||
clearImmediate(handle);
|
||||
currentlyRunningATask = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearImmediate(handle) {
|
||||
delete tasksByHandle[handle];
|
||||
}
|
||||
|
||||
function installNextTickImplementation() {
|
||||
setImmediate = function() {
|
||||
var handle = addFromSetImmediateArguments(arguments);
|
||||
process.nextTick(partiallyApplied(runIfPresent, handle));
|
||||
return handle;
|
||||
};
|
||||
}
|
||||
|
||||
function canUsePostMessage() {
|
||||
// The test against `importScripts` prevents this implementation from being installed inside a web worker,
|
||||
// where `global.postMessage` means something completely different and can't be used for this purpose.
|
||||
if (global.postMessage && !global.importScripts) {
|
||||
var postMessageIsAsynchronous = true;
|
||||
var oldOnMessage = global.onmessage;
|
||||
global.onmessage = function() {
|
||||
postMessageIsAsynchronous = false;
|
||||
};
|
||||
global.postMessage("", "*");
|
||||
global.onmessage = oldOnMessage;
|
||||
return postMessageIsAsynchronous;
|
||||
}
|
||||
}
|
||||
|
||||
function installPostMessageImplementation() {
|
||||
// Installs an event handler on `global` for the `message` event: see
|
||||
// * https://developer.mozilla.org/en/DOM/window.postMessage
|
||||
// * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
|
||||
|
||||
var messagePrefix = "setImmediate$" + Math.random() + "$";
|
||||
var onGlobalMessage = function(event) {
|
||||
if (event.source === global &&
|
||||
typeof event.data === "string" &&
|
||||
event.data.indexOf(messagePrefix) === 0) {
|
||||
runIfPresent(+event.data.slice(messagePrefix.length));
|
||||
}
|
||||
};
|
||||
|
||||
if (global.addEventListener) {
|
||||
global.addEventListener("message", onGlobalMessage, false);
|
||||
} else {
|
||||
global.attachEvent("onmessage", onGlobalMessage);
|
||||
}
|
||||
|
||||
setImmediate = function() {
|
||||
var handle = addFromSetImmediateArguments(arguments);
|
||||
global.postMessage(messagePrefix + handle, "*");
|
||||
return handle;
|
||||
};
|
||||
}
|
||||
|
||||
function installMessageChannelImplementation() {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = function(event) {
|
||||
var handle = event.data;
|
||||
runIfPresent(handle);
|
||||
};
|
||||
|
||||
setImmediate = function() {
|
||||
var handle = addFromSetImmediateArguments(arguments);
|
||||
channel.port2.postMessage(handle);
|
||||
return handle;
|
||||
};
|
||||
}
|
||||
|
||||
function installReadyStateChangeImplementation() {
|
||||
var html = doc.documentElement;
|
||||
setImmediate = function() {
|
||||
var handle = addFromSetImmediateArguments(arguments);
|
||||
// Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
|
||||
// into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
|
||||
var script = doc.createElement("script");
|
||||
script.onreadystatechange = function () {
|
||||
runIfPresent(handle);
|
||||
script.onreadystatechange = null;
|
||||
html.removeChild(script);
|
||||
script = null;
|
||||
};
|
||||
html.appendChild(script);
|
||||
return handle;
|
||||
};
|
||||
}
|
||||
|
||||
function installSetTimeoutImplementation() {
|
||||
setImmediate = function() {
|
||||
var handle = addFromSetImmediateArguments(arguments);
|
||||
setTimeout(partiallyApplied(runIfPresent, handle), 0);
|
||||
return handle;
|
||||
};
|
||||
}
|
||||
|
||||
// If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
|
||||
var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
|
||||
attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
|
||||
|
||||
// Don't get fooled by e.g. browserify environments.
|
||||
if ({}.toString.call(global.process) === "[object process]") {
|
||||
// For Node.js before 0.9
|
||||
installNextTickImplementation();
|
||||
|
||||
} else if (canUsePostMessage()) {
|
||||
// For non-IE10 modern browsers
|
||||
installPostMessageImplementation();
|
||||
|
||||
} else if (global.MessageChannel) {
|
||||
// For web workers, where supported
|
||||
installMessageChannelImplementation();
|
||||
|
||||
} else if (doc && "onreadystatechange" in doc.createElement("script")) {
|
||||
// For IE 6–8
|
||||
installReadyStateChangeImplementation();
|
||||
|
||||
} else {
|
||||
// For older browsers
|
||||
installSetTimeoutImplementation();
|
||||
}
|
||||
|
||||
attachTo.setImmediate = setImmediate;
|
||||
attachTo.clearImmediate = clearImmediate;
|
||||
}(typeof self === "undefined" ? typeof global === "undefined" ? this : global : self));
|
File diff suppressed because one or more lines are too long
|
@ -137,11 +137,11 @@
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<div id="encryption-password-dialog" title="Encrypted note" style="display: none;">
|
||||
<form id="encryption-password-form">
|
||||
<div id="protected-session-password-dialog" title="Encrypted note" style="display: none;">
|
||||
<form id="protected-session-password-form">
|
||||
<div class="form-group">
|
||||
<label for="encryption-password">This note is encrypted. Enter password to show it:</label>
|
||||
<input id="encryption-password" style="width: 250px;" type="password">
|
||||
<label for="protected-session-password">This note is encrypted. Enter password to show it:</label>
|
||||
<input id="protected-session-password" style="width: 250px;" type="password">
|
||||
<button class="btn btn-sm">Show</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -267,11 +267,6 @@
|
|||
|
||||
<script src="libraries/jquery.ui-contextmenu.min.js"></script>
|
||||
|
||||
<script src="libraries/scrypt/scrypt.js"></script>
|
||||
<script src="libraries/scrypt/buffer.js"></script>
|
||||
<script src="libraries/scrypt/setImmediate.js"></script>
|
||||
<script src="libraries/scrypt/unorm.js"></script>
|
||||
|
||||
<link href="stylesheets/style.css" rel="stylesheet">
|
||||
|
||||
<script src="javascripts/init.js"></script>
|
||||
|
|
Loading…
Reference in a new issue