mirror of
https://github.com/zadam/trilium.git
synced 2025-03-03 18:49:27 +08:00
initial support for encryption of individual notes. Shouldn't be used for now.
This commit is contained in:
parent
f20717e29f
commit
49db61e5e0
8 changed files with 2594 additions and 98 deletions
|
@ -44,7 +44,12 @@ def updateNote(note_id):
|
|||
|
||||
now = math.floor(time.time())
|
||||
|
||||
execute("update notes set note_text = ?, note_title = ?, date_modified = ? where note_id = ?", [note['detail']['note_text'], note['detail']['note_title'], now, note_id])
|
||||
execute("update notes set note_text = ?, note_title = ?, encryption = ?, date_modified = ? where note_id = ?", [
|
||||
note['detail']['note_text'],
|
||||
note['detail']['note_title'],
|
||||
note['detail']['encryption'],
|
||||
now,
|
||||
note_id])
|
||||
|
||||
delete("formatting", note_id)
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
const baseUrl = '';
|
||||
</script>
|
||||
|
||||
<script src="stat/lib/jquery.min.js"></script>
|
||||
<script src="stat/lib/jquery.min.js"></script>
|
||||
|
||||
<link href="stat/lib/jqueryui/jquery-ui.min.css" rel="stylesheet">
|
||||
<script src="stat/lib/jqueryui/jquery-ui.min.js"></script>
|
||||
|
@ -123,10 +123,13 @@
|
|||
|
||||
<!-- https://github.com/ricmoo/aes-js -->
|
||||
<script src="stat/lib/aes.js"></script>
|
||||
<!-- https://github.com/dcodeIO/bcrypt.js -->
|
||||
<script src="stat/lib/bcrypt.min.js"></script>
|
||||
<!-- https://github.com/emn178/js-sha256 -->
|
||||
<script src="stat/lib/sha256.min.js"></script>
|
||||
<!-- https://github.com/ricmoo/scrypt-js -->
|
||||
<script src="stat/lib/scrypt/scrypt.js"></script>
|
||||
<script src="stat/lib/scrypt/buffer.js"></script>
|
||||
<script src="stat/lib/scrypt/setImmediate.js"></script>
|
||||
<script src="stat/lib/scrypt/unorm.js"></script>
|
||||
|
||||
<link href="stat/style.css" rel="stylesheet">
|
||||
|
||||
|
|
|
@ -21,17 +21,7 @@ function noteChanged() {
|
|||
isNoteChanged = true;
|
||||
}
|
||||
|
||||
function saveNoteIfChanged(callback) {
|
||||
if (!isNoteChanged) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let note = globalNote;
|
||||
|
||||
function updateNoteFromInputs(note) {
|
||||
let contents = $('#noteDetail').summernote('code');
|
||||
|
||||
html2notecase(contents, note);
|
||||
|
@ -41,13 +31,15 @@ function saveNoteIfChanged(callback) {
|
|||
getNodeByKey(note.detail.note_id).setTitle(title);
|
||||
|
||||
note.detail.note_title = title;
|
||||
}
|
||||
|
||||
function saveNoteToServer(note, callback) {
|
||||
$.ajax({
|
||||
url: baseUrl + 'notes/' + note.detail.note_id,
|
||||
type: 'PUT',
|
||||
data: JSON.stringify(note),
|
||||
contentType: "application/json",
|
||||
success: function() {
|
||||
success: function () {
|
||||
isNoteChanged = false;
|
||||
|
||||
message("Saved!");
|
||||
|
@ -56,12 +48,28 @@ function saveNoteIfChanged(callback) {
|
|||
callback();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
error: function () {
|
||||
error("Error saving the note!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function saveNoteIfChanged(callback) {
|
||||
if (!isNoteChanged) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const note = globalNote;
|
||||
|
||||
updateNoteFromInputs(note);
|
||||
|
||||
saveNoteToServer(note, callback);
|
||||
}
|
||||
|
||||
setInterval(saveNoteIfChanged, 5000);
|
||||
|
||||
$(document).ready(function() {
|
||||
|
@ -143,22 +151,35 @@ function loadNote(noteId) {
|
|||
$("#noteTitle").focus().select();
|
||||
}
|
||||
|
||||
let noteText = notecase2html(note);
|
||||
let decryptPromise;
|
||||
|
||||
noteChangeDisabled = true;
|
||||
if (note.detail.encryption === 1) {
|
||||
decryptPromise = decryptNote(note.detail.note_text);
|
||||
}
|
||||
else {
|
||||
decryptPromise = Promise.resolve(note.detail.note_text);
|
||||
}
|
||||
|
||||
// Clear contents and remove all stored history. This is to prevent undo from going across notes
|
||||
$('#noteDetail').summernote('reset');
|
||||
decryptPromise.then(decrypted => {
|
||||
note.detail.note_text = decrypted;
|
||||
|
||||
$('#noteDetail').summernote('code', noteText);
|
||||
let noteText = notecase2html(note);
|
||||
|
||||
document.location.hash = noteId;
|
||||
noteChangeDisabled = true;
|
||||
|
||||
$(window).resize(); // to trigger resizing of editor
|
||||
// Clear contents and remove all stored history. This is to prevent undo from going across notes
|
||||
$('#noteDetail').summernote('reset');
|
||||
|
||||
addRecentNote(noteId, note.detail.note_id);
|
||||
$('#noteDetail').summernote('code', noteText);
|
||||
|
||||
noteChangeDisabled = false;
|
||||
document.location.hash = noteId;
|
||||
|
||||
$(window).resize(); // to trigger resizing of editor
|
||||
|
||||
addRecentNote(noteId, note.detail.note_id);
|
||||
|
||||
noteChangeDisabled = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -171,46 +192,111 @@ function addRecentNote(noteTreeId, noteContentId) {
|
|||
// if it's already there, remove the note
|
||||
c = recentNotes.filter(note => note !== noteTreeId);
|
||||
|
||||
//console.log("added after " + (new Date().getTime() - origDate.getTime()));
|
||||
|
||||
recentNotes.unshift(noteTreeId);
|
||||
}
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
function deriveEncryptionKey(password) {
|
||||
// why this is done is explained here: https://github.com/ricmoo/scrypt-js - "Encoding notes"
|
||||
const normalizedPassword = password.normalize('NFKC');
|
||||
// use password as a base for salt (which is itself salted with constant) so that we don't need to store it
|
||||
// this means everything is encrypted with the same salt.
|
||||
const salt = sha256("Jg&)hZ$" + normalizedPassword + "*P7j.");
|
||||
|
||||
const passwordBuffer = new buffer.SlowBuffer(normalizedPassword);
|
||||
const saltBuffer = new buffer.SlowBuffer(salt);
|
||||
|
||||
// this settings take ~500ms on my laptop
|
||||
const N = 16384, r = 16, p = 1;
|
||||
// 32 byte key - AES 256
|
||||
const dkLen = 32;
|
||||
|
||||
const startedDate = new Date();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
scrypt(passwordBuffer, saltBuffer, N, r, p, dkLen, function (error, progress, key) {
|
||||
if (error) {
|
||||
console.log("Error: " + error);
|
||||
|
||||
reject();
|
||||
}
|
||||
else if (key) {
|
||||
console.log("Computation took " + (new Date().getTime() - startedDate.getTime()) + "ms");
|
||||
|
||||
resolve(key);
|
||||
}
|
||||
else {
|
||||
// update UI with progress complete
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let globalEncryptionKeyPromise = null;
|
||||
|
||||
function getEncryptionKey() {
|
||||
if (globalEncryptionKeyPromise === null) {
|
||||
const password = prompt("Enter password for encryption");
|
||||
|
||||
globalEncryptionKeyPromise = deriveEncryptionKey(password);
|
||||
}
|
||||
|
||||
return globalEncryptionKeyPromise;
|
||||
}
|
||||
|
||||
function getAes() {
|
||||
return getEncryptionKey().then(encryptionKey => {
|
||||
return new aesjs.ModeOfOperation.ctr(encryptionKey, new aesjs.Counter(5));
|
||||
});
|
||||
}
|
||||
|
||||
function encryptNote() {
|
||||
let password = prompt("Enter password for encryption");
|
||||
getAes().then(aes => {
|
||||
const note = globalNote;
|
||||
|
||||
console.log(password);
|
||||
updateNoteFromInputs(note);
|
||||
|
||||
// 12 takes about 400 ms on my computer to compute
|
||||
let salt = dcodeIO.bcrypt.genSaltSync(12);
|
||||
const noteJson = note.detail.note_text;
|
||||
|
||||
let hashedPassword = dcodeIO.bcrypt.hashSync(password, salt);
|
||||
const noteBytes = aesjs.utils.utf8.toBytes(noteJson);
|
||||
|
||||
let hashedPasswordSha = sha256(hashedPassword).substr(0, 32);
|
||||
const encryptedBytes = aes.encrypt(noteBytes);
|
||||
|
||||
console.log(hashedPassword);
|
||||
// To print or store the binary data, you may convert it to hex
|
||||
const encryptedBase64 = uint8ToBase64(encryptedBytes);
|
||||
|
||||
let note = globalNote;
|
||||
note.detail.note_text = encryptedBase64;
|
||||
note.detail.encryption = 1;
|
||||
|
||||
let contents = $('#noteDetail').summernote('code');
|
||||
saveNoteToServer(note);
|
||||
});
|
||||
}
|
||||
|
||||
html2notecase(contents, note);
|
||||
function decryptNote(encryptedBase64) {
|
||||
return getAes().then(aes => {
|
||||
const encryptedBytes = base64ToUint8Array(encryptedBase64);
|
||||
|
||||
let noteJson = JSON.stringify(note);
|
||||
const decryptedBytes = aes.decrypt(encryptedBytes);
|
||||
|
||||
console.log('json: ' + noteJson);
|
||||
return aesjs.utils.utf8.fromBytes(decryptedBytes);
|
||||
});
|
||||
}
|
||||
|
||||
let hashedPasswordBytes = aesjs.utils.hex.toBytes(hashedPasswordSha);
|
||||
function uint8ToBase64(u8Arr) {
|
||||
const CHUNK_SIZE = 0x8000; //arbitrary number
|
||||
const length = u8Arr.length;
|
||||
let index = 0;
|
||||
let result = '';
|
||||
let slice;
|
||||
while (index < length) {
|
||||
slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length));
|
||||
result += String.fromCharCode.apply(null, slice);
|
||||
index += CHUNK_SIZE;
|
||||
}
|
||||
return btoa(result);
|
||||
}
|
||||
|
||||
let noteBytes = aesjs.utils.utf8.toBytes(noteJson);
|
||||
|
||||
let aesCtr = new aesjs.ModeOfOperation.ctr(hashedPasswordBytes, new aesjs.Counter(5));
|
||||
let encryptedBytes = aesCtr.encrypt(noteBytes);
|
||||
|
||||
// To print or store the binary data, you may convert it to hex
|
||||
let encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
|
||||
|
||||
console.log("encrypted: " + encryptedHex);
|
||||
function base64ToUint8Array(base64encoded) {
|
||||
return new Uint8Array(atob(base64encoded).split("").map(function(c) { return c.charCodeAt(0); }));
|
||||
}
|
48
static/lib/bcrypt.min.js
vendored
48
static/lib/bcrypt.min.js
vendored
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
bcrypt.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
|
||||
Released under the Apache License, Version 2.0
|
||||
see: https://github.com/dcodeIO/bcrypt.js for details
|
||||
*/
|
||||
(function(u,r){"function"===typeof define&&define.amd?define([],r):"function"===typeof require&&"object"===typeof module&&module&&module.exports?module.exports=r():(u.dcodeIO=u.dcodeIO||{}).bcrypt=r()})(this,function(){function u(e){if("undefined"!==typeof module&&module&&module.exports)try{return require("crypto").randomBytes(e)}catch(d){}try{var c;(self.crypto||self.msCrypto).getRandomValues(c=new Uint32Array(e));return Array.prototype.slice.call(c)}catch(b){}if(!w)throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative");
|
||||
return w(e)}function r(e,d){for(var c=0,b=0,a=0,f=e.length;a<f;++a)e.charCodeAt(a)===d.charCodeAt(a)?++c:++b;return 0>c?!1:0===b}function H(e){var d=[],c=0;I.encodeUTF16toUTF8(function(){return c>=e.length?null:e.charCodeAt(c++)},function(b){d.push(b)});return d}function x(e,d){var c=0,b=[],a,f;if(0>=d||d>e.length)throw Error("Illegal len: "+d);for(;c<d;){a=e[c++]&255;b.push(s[a>>2&63]);a=(a&3)<<4;if(c>=d){b.push(s[a&63]);break}f=e[c++]&255;a|=f>>4&15;b.push(s[a&63]);a=(f&15)<<2;if(c>=d){b.push(s[a&
|
||||
63]);break}f=e[c++]&255;a|=f>>6&3;b.push(s[a&63]);b.push(s[f&63])}return b.join("")}function B(e,d){var c=0,b=e.length,a=0,f=[],g,m,h;if(0>=d)throw Error("Illegal len: "+d);for(;c<b-1&&a<d;){h=e.charCodeAt(c++);g=h<q.length?q[h]:-1;h=e.charCodeAt(c++);m=h<q.length?q[h]:-1;if(-1==g||-1==m)break;h=g<<2>>>0;h|=(m&48)>>4;f.push(z(h));if(++a>=d||c>=b)break;h=e.charCodeAt(c++);g=h<q.length?q[h]:-1;if(-1==g)break;h=(m&15)<<4>>>0;h|=(g&60)>>2;f.push(z(h));if(++a>=d||c>=b)break;h=e.charCodeAt(c++);m=h<q.length?
|
||||
q[h]:-1;h=(g&3)<<6>>>0;h|=m;f.push(z(h));++a}b=[];for(c=0;c<a;c++)b.push(f[c].charCodeAt(0));return b}function v(e,d,c,b){var a,f=e[d],g=e[d+1],f=f^c[0];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[1];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[2];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[3];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[4];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|
|
||||
f>>8&255];a+=b[768|f&255];g=g^a^c[5];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[6];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[7];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[8];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[9];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[10];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^
|
||||
c[11];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[12];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[13];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[14];a=b[f>>>24];a+=b[256|f>>16&255];a^=b[512|f>>8&255];a+=b[768|f&255];g=g^a^c[15];a=b[g>>>24];a+=b[256|g>>16&255];a^=b[512|g>>8&255];a+=b[768|g&255];f=f^a^c[16];e[d]=g^c[17];e[d+1]=f;return e}function t(e,d){for(var c=0,b=0;4>c;++c)b=b<<8|e[d]&255,d=(d+1)%e.length;
|
||||
return{key:b,offp:d}}function C(e,d,c){for(var b=0,a=[0,0],f=d.length,g=c.length,m,h=0;h<f;h++)m=t(e,b),b=m.offp,d[h]^=m.key;for(h=0;h<f;h+=2)a=v(a,0,d,c),d[h]=a[0],d[h+1]=a[1];for(h=0;h<g;h+=2)a=v(a,0,d,c),c[h]=a[0],c[h+1]=a[1]}function J(e,d,c,b){for(var a=0,f=[0,0],g=c.length,m=b.length,h,l=0;l<g;l++)h=t(d,a),a=h.offp,c[l]^=h.key;for(l=a=0;l<g;l+=2)h=t(e,a),a=h.offp,f[0]^=h.key,h=t(e,a),a=h.offp,f[1]^=h.key,f=v(f,0,c,b),c[l]=f[0],c[l+1]=f[1];for(l=0;l<m;l+=2)h=t(e,a),a=h.offp,f[0]^=h.key,h=t(e,
|
||||
a),a=h.offp,f[1]^=h.key,f=v(f,0,c,b),b[l]=f[0],b[l+1]=f[1]}function D(e,d,c,b,a){function f(){a&&a(n/c);if(n<c)for(var h=Date.now();n<c&&!(n+=1,C(e,l,k),C(d,l,k),100<Date.now()-h););else{for(n=0;64>n;n++)for(y=0;y<m>>1;y++)v(g,y<<1,l,k);h=[];for(n=0;n<m;n++)h.push((g[n]>>24&255)>>>0),h.push((g[n]>>16&255)>>>0),h.push((g[n]>>8&255)>>>0),h.push((g[n]&255)>>>0);if(b){b(null,h);return}return h}b&&p(f)}var g=E.slice(),m=g.length,h;if(4>c||31<c){h=Error("Illegal number of rounds (4-31): "+c);if(b){p(b.bind(this,
|
||||
h));return}throw h;}if(16!==d.length){h=Error("Illegal salt length: "+d.length+" != 16");if(b){p(b.bind(this,h));return}throw h;}c=1<<c>>>0;var l,k,n=0,y;Int32Array?(l=new Int32Array(F),k=new Int32Array(G)):(l=F.slice(),k=G.slice());J(d,e,l,k);if("undefined"!==typeof b)f();else for(;;)if("undefined"!==typeof(h=f()))return h||[]}function A(e,d,c,b){function a(a){var b=[];b.push("$2");"a"<=f&&b.push(f);b.push("$");10>l&&b.push("0");b.push(l.toString());b.push("$");b.push(x(k,k.length));b.push(x(a,4*
|
||||
E.length-1));return b.join("")}if("string"!==typeof e||"string"!==typeof d){b=Error("Invalid string / salt: Not a string");if(c){p(c.bind(this,b));return}throw b;}var f,g;if("$"!==d.charAt(0)||"2"!==d.charAt(1)){b=Error("Invalid salt version: "+d.substring(0,2));if(c){p(c.bind(this,b));return}throw b;}if("$"===d.charAt(2))f=String.fromCharCode(0),g=3;else{f=d.charAt(2);if("a"!==f&&"b"!==f&&"y"!==f||"$"!==d.charAt(3)){b=Error("Invalid salt revision: "+d.substring(2,4));if(c){p(c.bind(this,b));return}throw b;
|
||||
}g=4}if("$"<d.charAt(g+2)){b=Error("Missing salt rounds");if(c){p(c.bind(this,b));return}throw b;}var m=10*parseInt(d.substring(g,g+1),10),h=parseInt(d.substring(g+1,g+2),10),l=m+h;d=d.substring(g+3,g+25);e=H(e+("a"<=f?"\x00":""));var k=B(d,16);if("undefined"==typeof c)return a(D(e,k,l));D(e,k,l,function(b,d){b?c(b,null):c(null,a(d))},b)}var k={},w=null;try{u(1)}catch(K){}w=null;k.setRandomFallback=function(e){w=e};k.genSaltSync=function(e,d){e=e||10;if("number"!==typeof e)throw Error("Illegal arguments: "+
|
||||
typeof e+", "+typeof d);4>e?e=4:31<e&&(e=31);var c=[];c.push("$2a$");10>e&&c.push("0");c.push(e.toString());c.push("$");c.push(x(u(16),16));return c.join("")};k.genSalt=function(e,d,c){function b(a){p(function(){try{a(null,k.genSaltSync(e))}catch(b){a(b)}})}"function"===typeof d&&(c=d,d=void 0);"function"===typeof e&&(c=e,e=void 0);if("undefined"===typeof e)e=10;else if("number"!==typeof e)throw Error("illegal arguments: "+typeof e);if(c){if("function"!==typeof c)throw Error("Illegal callback: "+
|
||||
typeof c);b(c)}else return new Promise(function(a,c){b(function(b,d){b?c(b):a(d)})})};k.hashSync=function(e,d){"undefined"===typeof d&&(d=10);"number"===typeof d&&(d=k.genSaltSync(d));if("string"!==typeof e||"string"!==typeof d)throw Error("Illegal arguments: "+typeof e+", "+typeof d);return A(e,d)};k.hash=function(e,d,c,b){function a(a){"string"===typeof e&&"number"===typeof d?k.genSalt(d,function(c,d){A(e,d,a,b)}):"string"===typeof e&&"string"===typeof d?A(e,d,a,b):p(a.bind(this,Error("Illegal arguments: "+
|
||||
typeof e+", "+typeof d)))}if(c){if("function"!==typeof c)throw Error("Illegal callback: "+typeof c);a(c)}else return new Promise(function(b,c){a(function(a,d){a?c(a):b(d)})})};k.compareSync=function(e,d){if("string"!==typeof e||"string"!==typeof d)throw Error("Illegal arguments: "+typeof e+", "+typeof d);return 60!==d.length?!1:r(k.hashSync(e,d.substr(0,d.length-31)),d)};k.compare=function(e,d,c,b){function a(a){"string"!==typeof e||"string"!==typeof d?p(a.bind(this,Error("Illegal arguments: "+typeof e+
|
||||
", "+typeof d))):60!==d.length?p(a.bind(this,null,!1)):k.hash(e,d.substr(0,29),function(b,c){b?a(b):a(null,r(c,d))},b)}if(c){if("function"!==typeof c)throw Error("Illegal callback: "+typeof c);a(c)}else return new Promise(function(b,c){a(function(a,d){a?c(a):b(d)})})};k.getRounds=function(e){if("string"!==typeof e)throw Error("Illegal arguments: "+typeof e);return parseInt(e.split("$")[2],10)};k.getSalt=function(e){if("string"!==typeof e)throw Error("Illegal arguments: "+typeof e);if(60!==e.length)throw Error("Illegal hash length: "+
|
||||
e.length+" != 60");return e.substring(0,29)};var p="undefined"!==typeof process&&process&&"function"===typeof process.nextTick?"function"===typeof setImmediate?setImmediate:process.nextTick:setTimeout,s="./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),q=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,54,55,56,57,58,59,60,61,62,63,-1,-1,-1,-1,-1,-1,-1,2,3,4,5,6,7,8,9,10,11,12,
|
||||
13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,-1,-1,-1,-1,-1,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,-1,-1,-1,-1,-1],z=String.fromCharCode,I=function(){var e={MAX_CODEPOINT:1114111,encodeUTF8:function(d,c){var b=null;"number"===typeof d&&(b=d,d=function(){return null});for(;null!==b||null!==(b=d());)128>b?c(b&127):(2048>b?c(b>>6&31|192):(65536>b?c(b>>12&15|224):(c(b>>18&7|240),c(b>>12&63|128)),c(b>>6&63|128)),c(b&63|128)),b=null},decodeUTF8:function(d,c){for(var b,
|
||||
a,f,e,k=function(a){a=a.slice(0,a.indexOf(null));var b=Error(a.toString());b.name="TruncatedError";b.bytes=a;throw b;};null!==(b=d());)if(0===(b&128))c(b);else if(192===(b&224))null===(a=d())&&k([b,a]),c((b&31)<<6|a&63);else if(224===(b&240))null!==(a=d())&&null!==(f=d())||k([b,a,f]),c((b&15)<<12|(a&63)<<6|f&63);else if(240===(b&248))null!==(a=d())&&null!==(f=d())&&null!==(e=d())||k([b,a,f,e]),c((b&7)<<18|(a&63)<<12|(f&63)<<6|e&63);else throw RangeError("Illegal starting byte: "+b);},UTF16toUTF8:function(d,
|
||||
c){for(var b,a=null;null!==(b=null!==a?a:d());)55296<=b&&57343>=b&&null!==(a=d())&&56320<=a&&57343>=a?(c(1024*(b-55296)+a-56320+65536),a=null):c(b);null!==a&&c(a)},UTF8toUTF16:function(d,c){var b=null;"number"===typeof d&&(b=d,d=function(){return null});for(;null!==b||null!==(b=d());)65535>=b?c(b):(b-=65536,c((b>>10)+55296),c(b%1024+56320)),b=null},encodeUTF16toUTF8:function(d,c){e.UTF16toUTF8(d,function(b){e.encodeUTF8(b,c)})},decodeUTF8toUTF16:function(d,c){e.decodeUTF8(d,function(b){e.UTF8toUTF16(b,
|
||||
c)})},calculateCodePoint:function(d){return 128>d?1:2048>d?2:65536>d?3:4},calculateUTF8:function(d){for(var c,b=0;null!==(c=d());)b+=e.calculateCodePoint(c);return b},calculateUTF16asUTF8:function(d){var c=0,b=0;e.UTF16toUTF8(d,function(a){++c;b+=e.calculateCodePoint(a)});return[c,b]}};return e}();Date.now=Date.now||function(){return+new Date};var F=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,
|
||||
3041331479,2450970073,2306472731],G=[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828,
|
||||
289532110,2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850,3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486,
|
||||
1724537150,2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683,2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557,
|
||||
442511882,3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616,3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592,
|
||||
3499020752,2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313,375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370,
|
||||
48609733,2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946,1266315497,3048417604,3681880366,3289982499,290971E4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509,
|
||||
1294809318,4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528,3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880,
|
||||
613907577,1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465,1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303,
|
||||
2151582166,1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079,3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385,
|
||||
1700445008,1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896,1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030,
|
||||
4236805024,3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597,1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055,3913112168,
|
||||
2491498743,4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625,3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499,
|
||||
499776247,1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970,69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905,
|
||||
3402727701,1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669,3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651,
|
||||
309677260,2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236,3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610,
|
||||
1181637006,548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074,2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037,
|
||||
2089974820,2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504,976866871,3556439503,2881648439,1522871579,1555064734,1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200,
|
||||
2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357,993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241,
|
||||
3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658,2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891,
|
||||
3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409E3,2509781533,112762804,3463356488,1866414978,891333506,18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588,
|
||||
3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953,1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493,
|
||||
1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296,2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462],E=[1332899944,1700884034,1701343084,1684370003,1668446532,
|
||||
1869963892];k.encodeBase64=x;k.decodeBase64=B;return k});
|
1381
static/lib/scrypt/buffer.js
Normal file
1381
static/lib/scrypt/buffer.js
Normal file
File diff suppressed because it is too large
Load diff
452
static/lib/scrypt/scrypt.js
Normal file
452
static/lib/scrypt/scrypt.js
Normal file
|
@ -0,0 +1,452 @@
|
|||
"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);
|
175
static/lib/scrypt/setImmediate.js
Normal file
175
static/lib/scrypt/setImmediate.js
Normal file
|
@ -0,0 +1,175 @@
|
|||
(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));
|
442
static/lib/scrypt/unorm.js
Normal file
442
static/lib/scrypt/unorm.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue