summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/Clipperz/Crypto
Side-by-side diff
Diffstat (limited to 'frontend/gamma/js/Clipperz/Crypto') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/gamma/js/Clipperz/Crypto/PRNG.js128
-rw-r--r--frontend/gamma/js/Clipperz/Crypto/SRP.js53
2 files changed, 87 insertions, 94 deletions
diff --git a/frontend/gamma/js/Clipperz/Crypto/PRNG.js b/frontend/gamma/js/Clipperz/Crypto/PRNG.js
index c539f06..80d972f 100644
--- a/frontend/gamma/js/Clipperz/Crypto/PRNG.js
+++ b/frontend/gamma/js/Clipperz/Crypto/PRNG.js
@@ -1,47 +1,49 @@
/*
Copyright 2008-2013 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/.
*/
+"use strict";
+
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
}
try { if (typeof(Clipperz.Crypto.SHA) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.Crypto.PRNG depends on Clipperz.Crypto.SHA!";
}
try { if (typeof(Clipperz.Crypto.AES) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.Crypto.PRNG depends on Clipperz.Crypto.AES!";
}
if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { Clipperz.Crypto.PRNG = {}; }
//#############################################################################
Clipperz.Crypto.PRNG.EntropyAccumulator = function(args) {
args = args || {};
// MochiKit.Base.bindMethods(this);
this._stack = new Clipperz.ByteArray();
this._maxStackLengthBeforeHashing = args.maxStackLengthBeforeHashing || 256;
return this;
}
@@ -176,230 +178,182 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C
'collectEntropy': function() {
var now;
var entropyByte;
var intervalTime;
now = new Date();
entropyByte = (now.getTime() & 0xff);
intervalTime = this.intervalTime();
if (this.boostMode() == true) {
intervalTime = intervalTime / 9;
}
this.updateGeneratorWithValue(entropyByte);
setTimeout(this.collectEntropy, intervalTime);
},
//-------------------------------------------------------------------------
'numberOfRandomBits': function() {
return 5;
},
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
//*****************************************************************************
Clipperz.Crypto.PRNG.MouseRandomnessSource = function(args) {
args = args || {};
Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
this._numberOfBitsToCollectAtEachEvent = 4;
this._randomBitsCollector = 0;
this._numberOfRandomBitsCollected = 0;
MochiKit.Signal.connect(document, 'onmousemove', this, 'collectEntropy');
return this;
}
Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
//-------------------------------------------------------------------------
'numberOfBitsToCollectAtEachEvent': function() {
return this._numberOfBitsToCollectAtEachEvent;
},
//-------------------------------------------------------------------------
'randomBitsCollector': function() {
return this._randomBitsCollector;
},
'setRandomBitsCollector': function(aValue) {
this._randomBitsCollector = aValue;
},
'appendRandomBitsToRandomBitsCollector': function(aValue) {
var collectedBits;
var numberOfRandomBitsCollected;
numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
- collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
- this.setRandomBitsCollector(collectetBits);
+ collectedBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
+ this.setRandomBitsCollector(collectedBits);
numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
if (numberOfRandomBitsCollected == 8) {
- this.updateGeneratorWithValue(collectetBits);
+ this.updateGeneratorWithValue(collectedBits);
numberOfRandomBitsCollected = 0;
this.setRandomBitsCollector(0);
}
this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
},
//-------------------------------------------------------------------------
'numberOfRandomBitsCollected': function() {
return this._numberOfRandomBitsCollected;
},
'setNumberOfRandomBitsCollected': function(aValue) {
this._numberOfRandomBitsCollected = aValue;
},
//-------------------------------------------------------------------------
'collectEntropy': function(anEvent) {
var mouseLocation;
var randomBit;
var mask;
mask = 0xffffffff >>> (32 - this.numberOfBitsToCollectAtEachEvent());
mouseLocation = anEvent.mouse().client;
randomBit = ((mouseLocation.x ^ mouseLocation.y) & mask);
this.appendRandomBitsToRandomBitsCollector(randomBit)
},
//-------------------------------------------------------------------------
'numberOfRandomBits': function() {
return 1;
},
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
//*****************************************************************************
-Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) {
+Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource = function(args) {
args = args || {};
- Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
- this._randomBitsCollector = 0;
- this._numberOfRandomBitsCollected = 0;
+ this._intervalTime = args.intervalTime || 1000;
+ this._browserCrypto = args.browserCrypto;
- MochiKit.Signal.connect(document, 'onkeypress', this, 'collectEntropy');
+ Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
+ this.collectEntropy();
return this;
}
-Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
+Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
- //-------------------------------------------------------------------------
-
- 'randomBitsCollector': function() {
- return this._randomBitsCollector;
- },
-
- 'setRandomBitsCollector': function(aValue) {
- this._randomBitsCollector = aValue;
+ 'intervalTime': function() {
+ return this._intervalTime;
},
-
- 'appendRandomBitToRandomBitsCollector': function(aValue) {
- var collectedBits;
- var numberOfRandomBitsCollected;
-
- numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
- collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
- this.setRandomBitsCollector(collectetBits);
- numberOfRandomBitsCollected ++;
-
- if (numberOfRandomBitsCollected == 8) {
- this.updateGeneratorWithValue(collectetBits);
- numberOfRandomBitsCollected = 0;
- this.setRandomBitsCollector(0);
- }
-
- this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
+
+ 'browserCrypto': function () {
+ return this._browserCrypto;
},
//-------------------------------------------------------------------------
- 'numberOfRandomBitsCollected': function() {
- return this._numberOfRandomBitsCollected;
- },
-
- 'setNumberOfRandomBitsCollected': function(aValue) {
- this._numberOfRandomBitsCollected = aValue;
- },
+ 'collectEntropy': function() {
+ var bytesToCollect;
- //-------------------------------------------------------------------------
+ if (this.boostMode() == true) {
+ bytesToCollect = 64;
+ } else {
+ bytesToCollect = 8;
+ }
- 'collectEntropy': function(anEvent) {
-/*
- var mouseLocation;
- var randomBit;
-
- mouseLocation = anEvent.mouse().client;
-
- randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1);
- this.appendRandomBitToRandomBitsCollector(randomBit);
-*/
- },
-
- //-------------------------------------------------------------------------
+ var randomValuesArray = new Uint8Array(bytesToCollect);
+ this.browserCrypto().getRandomValues(randomValuesArray);
+ for (var i = 0; i < randomValuesArray.length; i++) {
+ this.updateGeneratorWithValue(randomValuesArray[i]);
+ }
- 'numberOfRandomBits': function() {
- return 1;
+ setTimeout(this.collectEntropy, this.intervalTime());
},
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
//#############################################################################
Clipperz.Crypto.PRNG.Fortuna = function(args) {
var i,c;
args = args || {};
this._key = args.seed || null;
if (this._key == null) {
this._counter = 0;
this._key = new Clipperz.ByteArray();
} else {
this._counter = 1;
}
this._aesKey = null;
this._firstPoolReseedLevel = args.firstPoolReseedLevel || 32 || 64;
this._numberOfEntropyAccumulators = args.numberOfEntropyAccumulators || 32;
this._accumulators = [];
@@ -614,49 +568,49 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
var deferredResult;
deferredResult = new Clipperz.Async.Deferred("PRNG.deferredEntropyCollection");
deferredResult.addCallback(MochiKit.Base.partial(MochiKit.Async.succeed, aValue));
MochiKit.Signal.connect(this,
'readyToGenerateRandomBytes',
deferredResult,
'callback');
result = deferredResult;
}
return result;
},
//-------------------------------------------------------------------------
'fastEntropyAccumulationForTestingPurpose': function() {
while (! this.isReadyToGenerateRandomValues()) {
this.addRandomByte(Math.floor(Math.random() * 32), Math.floor(Math.random() * 32), Math.floor(Math.random() * 256));
}
},
//-------------------------------------------------------------------------
-
+/*
'dump': function(appendToDoc) {
var tbl;
var i,c;
tbl = document.createElement("table");
tbl.border = 0;
with (tbl.style) {
border = "1px solid lightgrey";
fontFamily = 'Helvetica, Arial, sans-serif';
fontSize = '8pt';
//borderCollapse = "collapse";
}
var hdr = tbl.createTHead();
var hdrtr = hdr.insertRow(0);
// document.createElement("tr");
{
var ntd;
ntd = hdrtr.insertCell(0);
ntd.style.borderBottom = "1px solid lightgrey";
ntd.style.borderRight = "1px solid lightgrey";
ntd.appendChild(document.createTextNode("#"));
ntd = hdrtr.insertCell(1);
@@ -720,122 +674,132 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
}
if (appendToDoc) {
var ne = document.createElement("div");
ne.id = "entropyGeneratorStatus";
with (ne.style) {
fontFamily = "Courier New, monospace";
fontSize = "12px";
lineHeight = "16px";
borderTop = "1px solid black";
padding = "10px";
}
if (document.getElementById(ne.id)) {
MochiKit.DOM.swapDOM(ne.id, ne);
} else {
document.body.appendChild(ne);
}
ne.appendChild(tbl);
}
return tbl;
},
-
+*/
//-----------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
//#############################################################################
Clipperz.Crypto.PRNG.Random = function(args) {
args = args || {};
// MochiKit.Base.bindMethods(this);
return this;
}
Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, {
'toString': function() {
return "Clipperz.Crypto.PRNG.Random";
},
//-------------------------------------------------------------------------
'getRandomBytes': function(aSize) {
//Clipperz.Profile.start("Clipperz.Crypto.PRNG.Random.getRandomBytes");
var result;
var i,c;
result = new Clipperz.ByteArray()
c = aSize || 1;
for (i=0; i<c; i++) {
result.appendByte((Math.random()*255) & 0xff);
}
//Clipperz.Profile.stop("Clipperz.Crypto.PRNG.Random.getRandomBytes");
return result;
},
//-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
//#############################################################################
-_clipperz_crypt_prng_defaultPRNG = null;
+var _clipperz_crypt_prng_defaultPRNG = null;
Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
if (_clipperz_crypt_prng_defaultPRNG == null) {
_clipperz_crypt_prng_defaultPRNG = new Clipperz.Crypto.PRNG.Fortuna();
//.............................................................
//
// TimeRandomnessSource
//
//.............................................................
{
var newRandomnessSource;
newRandomnessSource = new Clipperz.Crypto.PRNG.TimeRandomnessSource({intervalTime:111});
_clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
}
//.............................................................
//
// MouseRandomnessSource
//
//.............................................................
{
var newRandomnessSource;
newRandomnessSource = new Clipperz.Crypto.PRNG.MouseRandomnessSource();
_clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
}
//.............................................................
//
- // KeyboardRandomnessSource
+ // CryptoRandomRandomnessSource
//
//.............................................................
{
var newRandomnessSource;
+ var browserCrypto;
- newRandomnessSource = new Clipperz.Crypto.PRNG.KeyboardRandomnessSource();
- _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
+ if (window.crypto && window.crypto.getRandomValues) {
+ browserCrypto = window.crypto;
+ } else if (window.msCrypto && window.msCrypto.getRandomValues) {
+ browserCrypto = window.msCrypto;
+ } else {
+ browserCrypto = null;
+ }
+
+ if (browserCrypto != null) {
+ newRandomnessSource = new Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource({'browserCrypto':browserCrypto});
+ _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
+ }
}
-
}
return _clipperz_crypt_prng_defaultPRNG;
};
//#############################################################################
Clipperz.Crypto.PRNG.exception = {
NotEnoughEntropy: new MochiKit.Base.NamedError("Clipperz.Crypto.PRNG.exception.NotEnoughEntropy")
};
MochiKit.DOM.addLoadEvent(Clipperz.Crypto.PRNG.defaultRandomGenerator);
diff --git a/frontend/gamma/js/Clipperz/Crypto/SRP.js b/frontend/gamma/js/Clipperz/Crypto/SRP.js
index 597e72d..6898dfb 100644
--- a/frontend/gamma/js/Clipperz/Crypto/SRP.js
+++ b/frontend/gamma/js/Clipperz/Crypto/SRP.js
@@ -23,68 +23,79 @@ refer to http://www.clipperz.com.
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
}
try { if (typeof(Clipperz.Crypto.BigInt) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.BigInt!";
}
try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.PRNG!";
}
if (typeof(Clipperz.Crypto.SRP) == 'undefined') { Clipperz.Crypto.SRP = {}; }
Clipperz.Crypto.SRP.VERSION = "0.1";
Clipperz.Crypto.SRP.NAME = "Clipperz.Crypto.SRP";
//#############################################################################
MochiKit.Base.update(Clipperz.Crypto.SRP, {
'_n': null,
'_g': null,
+ '_k': null,
+
//-------------------------------------------------------------------------
'n': function() {
if (Clipperz.Crypto.SRP._n == null) {
Clipperz.Crypto.SRP._n = new Clipperz.Crypto.BigInt("115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3", 16);
}
return Clipperz.Crypto.SRP._n;
},
//-------------------------------------------------------------------------
'g': function() {
if (Clipperz.Crypto.SRP._g == null) {
Clipperz.Crypto.SRP._g = new Clipperz.Crypto.BigInt(2); // eventually 5 (as suggested on the Diffi-Helmann documentation)
}
return Clipperz.Crypto.SRP._g;
},
+ 'k': function() {
+ if (Clipperz.Crypto.SRP._k == null) {
+// Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt(this.stringHash(this.n().asString() + this.g().asString()), 16);
+ Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt("64398bff522814e306a97cb9bfc4364b7eed16a8c17c5208a40a2bad2933c8e", 16);
+ }
+
+ return Clipperz.Crypto.SRP._k;
+ },
+
//-----------------------------------------------------------------------------
'exception': {
'InvalidValue': new MochiKit.Base.NamedError("Clipperz.Crypto.SRP.exception.InvalidValue")
},
//-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
//#############################################################################
//
// S R P C o n n e c t i o n version 1.0
//
//=============================================================================
Clipperz.Crypto.SRP.Connection = function (args) {
args = args || {};
this._C = args.C;
this._P = args.P;
this.hash = args.hash;
this._a = null;
@@ -117,151 +128,169 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
return this._C;
},
//-------------------------------------------------------------------------
'P': function () {
return this._P;
},
//-------------------------------------------------------------------------
'a': function () {
if (this._a == null) {
this._a = new Clipperz.Crypto.BigInt(Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2), 16);
// this._a = new Clipperz.Crypto.BigInt("37532428169486597638072888476611365392249575518156687476805936694442691012367", 10);
}
return this._a;
},
//-------------------------------------------------------------------------
'A': function () {
if (this._A == null) {
- // Warning: this value should be strictly greater than zero: how should we perform this check?
+ // Warning: this value should be strictly greater than zero
this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n());
-
- if (this._A.equals(0)) {
+ if (this._A.equals(0) || negative(this._A)) {
Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
throw Clipperz.Crypto.SRP.exception.InvalidValue;
}
}
return this._A;
},
//-------------------------------------------------------------------------
's': function () {
return this._s;
},
'set_s': function(aValue) {
this._s = aValue;
},
//-------------------------------------------------------------------------
'B': function () {
return this._B;
},
'set_B': function(aValue) {
- // Warning: this value should be strictly greater than zero: how should we perform this check?
- if (! aValue.equals(0)) {
- this._B = aValue;
- } else {
+ // Warning: this value should be strictly greater than zero
+ this._B = aValue;
+ if (this._B.equals(0) || negative(this._B)) {
Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
throw Clipperz.Crypto.SRP.exception.InvalidValue;
}
},
//-------------------------------------------------------------------------
'x': function () {
if (this._x == null) {
this._x = new Clipperz.Crypto.BigInt(this.stringHash(this.s().asString(16, 64) + this.P()), 16);
}
return this._x;
},
//-------------------------------------------------------------------------
'u': function () {
if (this._u == null) {
- this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.B().asString()), 16);
+ this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.A().asString() + this.B().asString()), 16);
}
return this._u;
},
//-------------------------------------------------------------------------
'S': function () {
if (this._S == null) {
var bigint;
var srp;
bigint = Clipperz.Crypto.BigInt;
srp = Clipperz.Crypto.SRP;
this._S = bigint.powerModule(
- bigint.subtract(this.B(), bigint.powerModule(srp.g(), this.x(), srp.n())),
- bigint.add(this.a(), bigint.multiply(this.u(), this.x())),
- srp.n()
+ bigint.subtract(
+ this.B(),
+ bigint.multiply(
+ Clipperz.Crypto.SRP.k(),
+ bigint.powerModule(srp.g(), this.x(), srp.n())
+ )
+ ),
+ bigint.add(this.a(), bigint.multiply(this.u(), this.x())),
+ srp.n()
)
}
return this._S;
},
//-------------------------------------------------------------------------
'K': function () {
if (this._K == null) {
this._K = this.stringHash(this.S().asString());
}
return this._K;
},
//-------------------------------------------------------------------------
'M1': function () {
if (this._M1 == null) {
- this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
+// this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
+
+ // http://srp.stanford.edu/design.html
+ // User -> Host: M = H(H(N) xor H(g), H(I), s, A, B, K)
+
+ this._M1 = this.stringHash(
+ "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
+ this.stringHash(this.C()) +
+ this.s().asString() +
+ this.A().asString() +
+ this.B().asString() +
+ this.K()
+ );
+//console.log("M1", this._M1);
}
return this._M1;
},
//-------------------------------------------------------------------------
'M2': function () {
if (this._M2 == null) {
this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
+//console.log("M2", this._M2);
}
return this._M2;
},
//=========================================================================
'serverSideCredentialsWithSalt': function(aSalt) {
var result;
var s, x, v;
s = aSalt;
x = this.stringHash(s + this.P());
v = Clipperz.Crypto.SRP.g().powerModule(new Clipperz.Crypto.BigInt(x, 16), Clipperz.Crypto.SRP.n());
result = {};
result['C'] = this.C();
result['s'] = s;
result['v'] = v.asString(16);
return result;
},
'serverSideCredentials': function() {