password-manager/frontend/delta/js/Clipperz/Crypto/SHA.js
2015-03-09 15:45:35 +01:00

297 lines
8.5 KiB
JavaScript

/*
Copyright 2008-2015 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
}
if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
if (typeof(Clipperz.Crypto.SHA) == 'undefined') { Clipperz.Crypto.SHA = {}; }
Clipperz.Crypto.SHA.VERSION = "0.3";
Clipperz.Crypto.SHA.NAME = "Clipperz.Crypto.SHA";
MochiKit.Base.update(Clipperz.Crypto.SHA, {
'__repr__': function () {
return "[" + this.NAME + " " + this.VERSION + "]";
},
'toString': function () {
return this.__repr__();
},
//-----------------------------------------------------------------------------
'rotateRight': function(aValue, aNumberOfBits) {
//Clipperz.Profile.start("Clipperz.Crypto.SHA.rotateRight");
var result;
result = (aValue >>> aNumberOfBits) | (aValue << (32 - aNumberOfBits));
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.rotateRight");
return result;
},
'shiftRight': function(aValue, aNumberOfBits) {
//Clipperz.Profile.start("Clipperz.Crypto.SHA.shiftRight");
var result;
result = aValue >>> aNumberOfBits;
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.shiftRight");
return result;
},
//-----------------------------------------------------------------------------
'safeAdd': function() {
//Clipperz.Profile.start("Clipperz.Crypto.SHA.safeAdd");
var result;
var i, c;
result = arguments[0];
c = arguments.length;
for (i=1; i<c; i++) {
var lowerBytesSum;
lowerBytesSum = (result & 0xffff) + (arguments[i] & 0xffff);
result = (((result >> 16) + (arguments[i] >> 16) + (lowerBytesSum >> 16)) << 16) | (lowerBytesSum & 0xffff);
}
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.safeAdd");
return result;
},
//-----------------------------------------------------------------------------
'sha256_array': function(aValue) {
//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha256_array");
var result;
var message;
var h0, h1, h2, h3, h4, h5, h6, h7;
var k;
var messageLength;
var messageLengthInBits;
var _i, _c;
var charBits;
var rotateRight;
var shiftRight;
var safeAdd;
var bytesPerBlock;
var currentMessageIndex;
bytesPerBlock = 512/8;
rotateRight = Clipperz.Crypto.SHA.rotateRight;
shiftRight = Clipperz.Crypto.SHA.shiftRight;
safeAdd = Clipperz.Crypto.SHA.safeAdd;
charBits = 8;
h0 = 0x6a09e667;
h1 = 0xbb67ae85;
h2 = 0x3c6ef372;
h3 = 0xa54ff53a;
h4 = 0x510e527f;
h5 = 0x9b05688c;
h6 = 0x1f83d9ab;
h7 = 0x5be0cd19;
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];
message = aValue;
messageLength = message.length;
//Pre-processing:
message.push(0x80); // append a single "1" bit to message
_c = (512 - (((messageLength + 1) * charBits) % 512) - 64) / charBits;
if (_c < 0) {
_c = _c + (512 / charBits);
}
for (_i=0; _i<_c; _i++) {
message.push(0x00); // append "0" bits until message length ≡ 448 ≡ -64 (mod 512)
}
messageLengthInBits = messageLength * charBits;
message.push(0x00); // the 4 most high byte are alway 0 as message length is represented with a 32bit value;
message.push(0x00);
message.push(0x00);
message.push(0x00);
message.push((messageLengthInBits >> 24) & 0xff);
message.push((messageLengthInBits >> 16) & 0xff);
message.push((messageLengthInBits >> 8) & 0xff);
message.push( messageLengthInBits & 0xff);
currentMessageIndex = 0;
while(currentMessageIndex < message.length) {
var w;
var a, b, c, d, e, f, g, h;
w = Array(64);
_c = 16;
for (_i=0; _i<_c; _i++) {
var _j;
_j = currentMessageIndex + _i*4;
w[_i] = (message[_j] << 24) | (message[_j + 1] << 16) | (message[_j + 2] << 8) | (message[_j + 3] << 0);
}
_c = 64;
for (_i=16; _i<_c; _i++) {
var s0, s1;
s0 = (rotateRight(w[_i-15], 7)) ^ (rotateRight(w[_i-15], 18)) ^ (shiftRight(w[_i-15], 3));
s1 = (rotateRight(w[_i-2], 17)) ^ (rotateRight(w[_i-2], 19)) ^ (shiftRight(w[_i-2], 10));
w[_i] = safeAdd(w[_i-16], s0, w[_i-7], s1);
}
a=h0; b=h1; c=h2; d=h3; e=h4; f=h5; g=h6; h=h7;
_c = 64;
for (_i=0; _i<_c; _i++) {
var s0, s1, ch, maj, t1, t2;
s0 = (rotateRight(a, 2)) ^ (rotateRight(a, 13)) ^ (rotateRight(a, 22));
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = safeAdd(s0, maj);
s1 = (rotateRight(e, 6)) ^ (rotateRight(e, 11)) ^ (rotateRight(e, 25));
ch = (e & f) ^ ((~e) & g);
t1 = safeAdd(h, s1, ch, k[_i], w[_i]);
h = g;
g = f;
f = e;
e = safeAdd(d, t1);
d = c;
c = b;
b = a;
a = safeAdd(t1, t2);
}
h0 = safeAdd(h0, a);
h1 = safeAdd(h1, b);
h2 = safeAdd(h2, c);
h3 = safeAdd(h3, d);
h4 = safeAdd(h4, e);
h5 = safeAdd(h5, f);
h6 = safeAdd(h6, g);
h7 = safeAdd(h7, h);
currentMessageIndex += bytesPerBlock;
}
result = new Array(256/8);
result[0] = (h0 >> 24) & 0xff;
result[1] = (h0 >> 16) & 0xff;
result[2] = (h0 >> 8) & 0xff;
result[3] = h0 & 0xff;
result[4] = (h1 >> 24) & 0xff;
result[5] = (h1 >> 16) & 0xff;
result[6] = (h1 >> 8) & 0xff;
result[7] = h1 & 0xff;
result[8] = (h2 >> 24) & 0xff;
result[9] = (h2 >> 16) & 0xff;
result[10] = (h2 >> 8) & 0xff;
result[11] = h2 & 0xff;
result[12] = (h3 >> 24) & 0xff;
result[13] = (h3 >> 16) & 0xff;
result[14] = (h3 >> 8) & 0xff;
result[15] = h3 & 0xff;
result[16] = (h4 >> 24) & 0xff;
result[17] = (h4 >> 16) & 0xff;
result[18] = (h4 >> 8) & 0xff;
result[19] = h4 & 0xff;
result[20] = (h5 >> 24) & 0xff;
result[21] = (h5 >> 16) & 0xff;
result[22] = (h5 >> 8) & 0xff;
result[23] = h5 & 0xff;
result[24] = (h6 >> 24) & 0xff;
result[25] = (h6 >> 16) & 0xff;
result[26] = (h6 >> 8) & 0xff;
result[27] = h6 & 0xff;
result[28] = (h7 >> 24) & 0xff;
result[29] = (h7 >> 16) & 0xff;
result[30] = (h7 >> 8) & 0xff;
result[31] = h7 & 0xff;
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256_array");
return result;
},
//-----------------------------------------------------------------------------
'sha256': function(aValue) {
//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha256");
var result;
var resultArray;
var valueArray;
valueArray = aValue.arrayValues();
resultArray = Clipperz.Crypto.SHA.sha256_array(valueArray);
result = new Clipperz.ByteArray(resultArray);
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256");
return result;
},
//-----------------------------------------------------------------------------
'sha_d256': function(aValue) {
//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha_d256");
var result;
var resultArray;
var valueArray;
valueArray = aValue.arrayValues();
resultArray = Clipperz.Crypto.SHA.sha256_array(valueArray);
resultArray = Clipperz.Crypto.SHA.sha256_array(resultArray);
result = new Clipperz.ByteArray(resultArray);
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256");
return result;
},
//-----------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});