summaryrefslogtreecommitdiff
authorMichael Krelin <hacker@klever.net>2014-06-30 18:20:13 (UTC)
committer Michael Krelin <hacker@klever.net>2014-06-30 18:20:13 (UTC)
commitc392fe28606eefa0c814e5c25d641f5ffe623186 (patch) (side-by-side diff)
treeda03fe13ca09fadbebbad9b5d38750757270bae8
parentd341307d346dee62ee36b27f0f93b8f000748a96 (diff)
parent6dd16d9359e3a4dc306802588b09acd43947a606 (diff)
downloadclipperz-c392fe28606eefa0c814e5c25d641f5ffe623186.zip
clipperz-c392fe28606eefa0c814e5c25d641f5ffe623186.tar.gz
clipperz-c392fe28606eefa0c814e5c25d641f5ffe623186.tar.bz2
Merge remote-tracking branch 'github/master' into nmaster
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--README.md32
-rw-r--r--frontend/beta/js/Clipperz/Base.js28
-rw-r--r--frontend/beta/js/Clipperz/Crypto/PRNG.js130
-rw-r--r--frontend/beta/js/Clipperz/Crypto/SRP.js67
-rw-r--r--frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js2
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js4
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js22
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js2
-rw-r--r--frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js47
-rw-r--r--frontend/delta/js/Clipperz/Crypto/PRNG.js128
-rw-r--r--frontend/delta/js/Clipperz/Crypto/SRP.js53
-rw-r--r--frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js27
-rw-r--r--frontend/gamma/js/Clipperz/Crypto/PRNG.js128
-rw-r--r--frontend/gamma/js/Clipperz/Crypto/SRP.js53
-rw-r--r--frontend/gamma/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js35
15 files changed, 407 insertions, 351 deletions
diff --git a/README.md b/README.md
index e44df48..8e7cb6b 100644
--- a/README.md
+++ b/README.md
@@ -13,16 +13,21 @@ Read more on the [Clipperz website][home].
-[home]: http://www.clipperz.com
+[home]: https://clipperz.is
-## Why an open source version
+## Why an open source version of Clipperz?
-Because we want to enable as many people as possible to play with our code. So that you can start trusting it, the code not the developers.
+Because we want to enable as many people as possible to play with our code. So that they can start trusting it. The code, not its developers.
-In order to allow you to inspect the code and analyze the traffic it generates between client and server, we had to provide an easy way to locally deploy the whole service.
+In order to allow anyone not just to inspect the source code, but also to analyze the traffic it generates between client and server, we made available this open source version as an easy way to locally deploy the whole password manager web app on your machine. You can choose among the available backends (PHP/MySQL, Python/AppEngine, …) or [contribute][CA] your own.
-Feel free to host on your machine a web service identical to [Clipperz online password manager][home]. You can choose among **multiple backends** (PHP/MySQL, Python/AppEngine, …) or you can [contribute][CA] your own.
+Whatever is your motivation for playing with Clipperz code, we would love to hear from you: [get in contact][contact]!
-Whatever is your motivation, we would love to hear from you: [get in contact!][contact]
+## Security warning
-[CA]: http://www.clipperz.com/open_source/contributor_agreement
-[contact]: http://www.clipperz.com/about/contacts
+The open source version of Clipperz is suitable for **testing and educational purposes only**. Do not use it as an actual password management solution.
+
+As an example, the current PHP backend lacks several critical capabilities such as bot protection and concurrent sessions management, moreover it could be vulnerable to serious threats (SQL injections, remote code execution, ...).
+
+[CA]: https://clipperz.is/open_source/contributor_agreement
+[contact]: https://clipperz.is/about/contacts
+[clipperz]: https://clipperz.is
@@ -36,4 +41,4 @@ Our favorite payment method is clearly Bitcoin ([learn why here][why]), but you
-[why]: http://www.clipperz.com/pricing/why_bitcoin
-[donations]: http://www.clipperz.com/donations
+[why]: https://clipperz.is/pricing/why_bitcoin
+[donations]: https://clipperz.is/donations
@@ -41,3 +46,3 @@ Our favorite payment method is clearly Bitcoin ([learn why here][why]), but you
## License
-ALL the code included in this project, if not otherwise stated, is released with the [AGPL v3][agpl] license (see `LICENSE.txt`), and all rights are reserved to Clipperz Srl. For any use not allowed by the AGPL license, please [contact us][contact] to inquire about licensing options for commercial applications.
+ALL the code included in this project, if not otherwise stated, is released with the [AGPL v3][agpl] license (see `LICENSE.txt`), and all rights are reserved to Clipperz Srl. For any use not allowed by the AGPL license, please [contact us][contact] to inquire about licensing options for commercial applications.
@@ -46,5 +51,2 @@ ALL the code included in this project, if not otherwise stated, is released with
-## Warnings
-Please note that the open source version of Clipperz Password Manager may not be suitable for mass deployments, depending on how robust is the backend you select. As an example, the current PHP backend lacks several critical capabilities such as bot protection and concurrent sessions management.
-
## Contributions
@@ -117,2 +119,2 @@ This application has not been fully tested, so there may be still problems due t
-[pog]: http://www.phpobjectgenerator.com/ \ No newline at end of file
+[pog]: http://www.phpobjectgenerator.com/
diff --git a/frontend/beta/js/Clipperz/Base.js b/frontend/beta/js/Clipperz/Base.js
index cf40314..1c6faa1 100644
--- a/frontend/beta/js/Clipperz/Base.js
+++ b/frontend/beta/js/Clipperz/Base.js
@@ -248,2 +248,30 @@ MochiKit.Base.update(Clipperz.Base, {
+ 'javascriptInjectionPattern': new RegExp("javascript:\/\/\"", "g"),
+
+ 'sanitizeUrl': function(aValue) {
+ var result;
+
+ if ((aValue != null) && this.javascriptInjectionPattern.test(aValue)) {
+ result = aValue.replace(this.javascriptInjectionPattern, '');
+ console.log("sanitized url", aValue, result);
+ } else {
+ result = aValue;
+ }
+
+ return result;
+ },
+
+ 'sanitizeFavicon': function(aValue) {
+ var result;
+
+ if ((aValue != null) && this.javascriptInjectionPattern.test(aValue)) {
+ result = aValue.replace(this.javascriptInjectionPattern, '');
+ console.log("sanitized favicon", aValue, result);
+ } else {
+ result = aValue;
+ }
+
+ return result;
+ },
+
//-------------------------------------------------------------------------
diff --git a/frontend/beta/js/Clipperz/Crypto/PRNG.js b/frontend/beta/js/Clipperz/Crypto/PRNG.js
index b5c3f8a..6fdeca4 100644
--- a/frontend/beta/js/Clipperz/Crypto/PRNG.js
+++ b/frontend/beta/js/Clipperz/Crypto/PRNG.js
@@ -199,8 +199,2 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -247,4 +241,4 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
- collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
- this.setRandomBitsCollector(collectetBits);
+ collectedBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
+ this.setRandomBitsCollector(collectedBits);
numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
@@ -252,3 +246,3 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
if (numberOfRandomBitsCollected == 8) {
- this.updateGeneratorWithValue(collectetBits);
+ this.updateGeneratorWithValue(collectedBits);
numberOfRandomBitsCollected = 0;
@@ -291,8 +285,2 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -302,11 +290,11 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
-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;
@@ -314,30 +302,10 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) {
-Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
-
- //-------------------------------------------------------------------------
-
- 'randomBitsCollector': function() {
- return this._randomBitsCollector;
- },
+Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
- '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;
},
@@ -346,28 +314,18 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(n
- '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());
},
@@ -375,8 +333,2 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(n
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -609,9 +561,6 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
-//MochiKit.Logging.logDebug(">>> PRNG.deferredEntropyCollection");
if (this.isReadyToGenerateRandomValues()) {
-//MochiKit.Logging.logDebug("--- PRNG.deferredEntropyCollection - 1");
result = aValue;
} else {
-//MochiKit.Logging.logDebug("--- PRNG.deferredEntropyCollection - 2");
var deferredResult;
@@ -621,5 +570,3 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
deferredResult = new MochiKit.Async.Deferred();
-// deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.1 - PRNG.deferredEntropyCollection - 1: " + res); return res;});
deferredResult.addCallback(MochiKit.Base.partial(MochiKit.Async.succeed, aValue));
-// deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.2 - PRNG.deferredEntropyCollection - 2: " + res); return res;});
MochiKit.Signal.connect(this,
@@ -631,3 +578,2 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
}
-//MochiKit.Logging.logDebug("<<< PRNG.deferredEntropyCollection - result: " + result);
@@ -645,3 +591,3 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
//-------------------------------------------------------------------------
-
+/*
'dump': function(appendToDoc) {
@@ -751,3 +697,3 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
},
-
+*/
//-----------------------------------------------------------------------------
@@ -826,3 +772,3 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
//
- // KeyboardRandomnessSource
+ // CryptoRandomRandomnessSource
//
@@ -831,7 +777,17 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
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);
+ }
}
-
}
diff --git a/frontend/beta/js/Clipperz/Crypto/SRP.js b/frontend/beta/js/Clipperz/Crypto/SRP.js
index 8cc80ba..8c522ad 100644
--- a/frontend/beta/js/Clipperz/Crypto/SRP.js
+++ b/frontend/beta/js/Clipperz/Crypto/SRP.js
@@ -46,2 +46,4 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
'_g': null,
+ '_k': null,
+
//-------------------------------------------------------------------------
@@ -66,2 +68,11 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
+ '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;
+ },
+
//-----------------------------------------------------------------------------
@@ -131,3 +142,2 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
// this._a = new Clipperz.Crypto.BigInt("37532428169486597638072888476611365392249575518156687476805936694442691012367", 10);
-//MochiKit.Logging.logDebug("SRP a: " + this._a);
}
@@ -141,10 +151,8 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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)) {
-MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
+ if (this._A.equals(0) || negative(this._A)) {
+ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
throw Clipperz.Crypto.SRP.exception.InvalidValue;
}
-//MochiKit.Logging.logDebug("SRP A: " + this._A);
}
@@ -158,3 +166,2 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to
return this._s;
-//MochiKit.Logging.logDebug("SRP s: " + this._S);
},
@@ -172,8 +179,6 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to
'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;
-//MochiKit.Logging.logDebug("SRP B: " + this._B);
- } else {
-MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
+ // Warning: this value should be strictly greater than zero
+ this._B = aValue;
+ if (this._B.equals(0) || negative(this._B)) {
+ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
throw Clipperz.Crypto.SRP.exception.InvalidValue;
@@ -187,3 +192,2 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
this._x = new Clipperz.Crypto.BigInt(this.stringHash(this.s().asString(16, 64) + this.P()), 16);
-//MochiKit.Logging.logDebug("SRP x: " + this._x);
}
@@ -197,4 +201,3 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
if (this._u == null) {
- this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.B().asString()), 16);
-//MochiKit.Logging.logDebug("SRP u: " + this._u);
+ this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.A().asString() + this.B().asString()), 16);
}
@@ -215,7 +218,12 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
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()
)
-//MochiKit.Logging.logDebug("SRP S: " + this._S);
}
@@ -230,3 +238,2 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
this._K = this.stringHash(this.S().asString());
-//MochiKit.Logging.logDebug("SRP K: " + this._K);
}
@@ -240,4 +247,16 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
if (this._M1 == null) {
- this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
-//MochiKit.Logging.logDebug("SRP M1: " + this._M1);
+// 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);
}
@@ -252,3 +271,3 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
-//MochiKit.Logging.logDebug("SRP M2: " + this._M2);
+//console.log("M2", this._M2);
}
diff --git a/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js b/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js
index 2295d3f..369b9ce 100644
--- a/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js
+++ b/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js
@@ -140,3 +140,3 @@ Clipperz.PM.BookmarkletProcessor.prototype = MochiKit.Base.update(null, {
- actionUrl = this.configuration()['form']['attributes']['action'];
+ actionUrl = Clipperz.Base.sanitizeUrl(this.configuration()['form']['attributes']['action']);
//MochiKit.Logging.logDebug("+++ actionUrl: " + actionUrl);
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js
index 0e4640e..a5a4697 100644
--- a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js
@@ -102,3 +102,3 @@ YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent, C
// TODO: remove the value: field and replace it with element.dom.value = <some value>
- option = {tag:'option', value:recordFieldKey, html:recordFields[recordFieldKey].label()}
+ option = {tag:'option', value:recordFieldKey, html:Clipperz.Base.sanitizeString(recordFields[recordFieldKey].label())}
if (recordFieldKey == this.directLoginBinding().fieldKey()) {
@@ -152,3 +152,3 @@ YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent, C
- this.getElement('viewValue').update(this.directLoginBinding().field().label());
+ this.getElement('viewValue').update(Clipperz.Base.sanitizeString(this.directLoginBinding().field().label()));
//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.updateViewMode");
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js b/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js
index c0cfa3c..56d9d59 100644
--- a/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js
+++ b/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js
@@ -40,3 +40,3 @@ Clipperz.PM.DataModel.DirectLogin = function(args) {
this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
- this._favicon = args.favicon || null;
+ this._favicon = Clipperz.Base.sanitizeFavicon(args.favicon) || null;
this._bookmarkletVersion = args.bookmarkletVersion || "0.1";
@@ -104,5 +104,5 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
- actionUrl = this.formData()['attributes']['action'];
+ actionUrl = this.action();
hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1');
- this._favicon = "http://" + hostname + "/favicon.ico";
+ this._favicon = Clipperz.Base.sanitizeFavicon("http://" + hostname + "/favicon.ico");
}
@@ -139,2 +139,10 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
+ 'action': function () {
+ var result;
+
+ result = Clipperz.Base.sanitizeUrl(this.formData()['attributes']['action']);
+
+ return result;
+ },
+
//-------------------------------------------------------------------------
@@ -444,3 +452,3 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
formElement = MochiKit.DOM.FORM(MochiKit.Base.update({id:'directLoginForm'}, { 'method':this.formData()['attributes']['method'],
- 'action':this.formData()['attributes']['action']}));
+ 'action': this.action()}));
//MochiKit.Logging.logDebug("### runDirectLogin - 5");
@@ -489,5 +497,5 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
// if (/^javascript/.test(this.formData()['attributes']['action'])) {
- if ((/^(https?|webdav|ftp)\:/.test(this.formData()['attributes']['action']) == false) &&
- (this.formData()['attributes']['type'] != 'http_auth'))
- {
+ if ((/^(https?|webdav|ftp)\:/.test(this.action()) == false) &&
+ (this.formData()['attributes']['type'] != 'http_auth')
+ ) {
var messageBoxConfiguration;
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js
index 236d7c9..ba302da 100644
--- a/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js
+++ b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js
@@ -49,3 +49,3 @@ Clipperz.PM.DataModel.DirectLoginReference = function(args) {
this._label = args.label;
- this._favicon = args.favicon || null;
+ this._favicon = Clipperz.Base.sanitizeFavicon(args.favicon) || null;
diff --git a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
index 1a5caff..b0b9b63 100644
--- a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
+++ b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
@@ -39,2 +39,3 @@ Clipperz.PM.Proxy.Offline.DataStore = function(args) {
+ this._C = null;
this._b = null;
@@ -146,2 +147,12 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
+ 'C': function() {
+ return this._C;
+ },
+
+ 'set_C': function(aValue) {
+ this._C = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
'b': function() {
@@ -238,4 +249,4 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
//=========================================================================
-
- 'processMessage': function(aFunctionName, someParameters) {
+
+ 'processMessage': function (aFunctionName, someParameters) {
var result;
@@ -305,3 +316,3 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
} else {
- throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
+ throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
}
@@ -312,3 +323,3 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
'result': 'done'
- },
+ },
toll: this.getTollForRequestType('CONNECT')
@@ -342,5 +353,6 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
+ this.set_C(someParameters.parameters.C);
this.set_b(new Clipperz.Crypto.BigInt(randomBytes, 16));
v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16);
- this.set_B(v.add(Clipperz.Crypto.SRP.g().powerModule(this.b(), Clipperz.Crypto.SRP.n())));
+ this.set_B((Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(this.b(), Clipperz.Crypto.SRP.n())));
@@ -353,3 +365,6 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
} else if (someParameters.message == "credentialCheck") {
- var v, u, S, A, K, M1;
+ var v, u, s, S, A, K, M1;
+ var stringHash = function (aValue) {
+ return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
+ };
@@ -357,9 +372,17 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16);
- u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(this.B().asString(10))).toHexString(), 16);
A = new Clipperz.Crypto.BigInt(this.A(), 16);
+ u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + this.B().asString(10))).toHexString(), 16);
+ s = new Clipperz.Crypto.BigInt(this.userData()['s'], 16);
S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(this.b(), Clipperz.Crypto.SRP.n());
- K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
+ K = stringHash(S.asString(10));
- M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + this.B().asString(10) + K)).toHexString().slice(2);
+ M1 = stringHash(
+ "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
+ stringHash(this.C()) +
+ s.asString(10) +
+ A.asString(10) +
+ this.B().asString(10) +
+ K
+ );
if (someParameters.parameters.M1 == M1) {
@@ -367,3 +390,7 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
- M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
+ M2 = stringHash(
+ A.asString(10) +
+ someParameters.parameters.M1 +
+ K
+ );
result['M2'] = M2;
diff --git a/frontend/delta/js/Clipperz/Crypto/PRNG.js b/frontend/delta/js/Clipperz/Crypto/PRNG.js
index c539f06..80d972f 100644
--- a/frontend/delta/js/Clipperz/Crypto/PRNG.js
+++ b/frontend/delta/js/Clipperz/Crypto/PRNG.js
@@ -23,2 +23,4 @@ refer to http://www.clipperz.com.
+"use strict";
+
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
@@ -199,8 +201,2 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -247,4 +243,4 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
- collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
- this.setRandomBitsCollector(collectetBits);
+ collectedBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
+ this.setRandomBitsCollector(collectedBits);
numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
@@ -252,3 +248,3 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
if (numberOfRandomBitsCollected == 8) {
- this.updateGeneratorWithValue(collectetBits);
+ this.updateGeneratorWithValue(collectedBits);
numberOfRandomBitsCollected = 0;
@@ -291,8 +287,2 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -302,11 +292,11 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
-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;
@@ -314,30 +304,10 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) {
-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;
},
@@ -346,28 +316,18 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(n
- '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());
},
@@ -375,8 +335,2 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(n
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -637,3 +591,3 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
//-------------------------------------------------------------------------
-
+/*
'dump': function(appendToDoc) {
@@ -743,3 +697,3 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
},
-
+*/
//-----------------------------------------------------------------------------
@@ -786,3 +740,3 @@ Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, {
-_clipperz_crypt_prng_defaultPRNG = null;
+var _clipperz_crypt_prng_defaultPRNG = null;
@@ -818,3 +772,3 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
//
- // KeyboardRandomnessSource
+ // CryptoRandomRandomnessSource
//
@@ -823,7 +777,17 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
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);
+ }
}
-
}
diff --git a/frontend/delta/js/Clipperz/Crypto/SRP.js b/frontend/delta/js/Clipperz/Crypto/SRP.js
index 597e72d..6898dfb 100644
--- a/frontend/delta/js/Clipperz/Crypto/SRP.js
+++ b/frontend/delta/js/Clipperz/Crypto/SRP.js
@@ -46,2 +46,4 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
'_g': null,
+ '_k': null,
+
//-------------------------------------------------------------------------
@@ -66,2 +68,11 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
+ '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;
+ },
+
//-----------------------------------------------------------------------------
@@ -140,6 +151,5 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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.");
@@ -169,6 +179,5 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
'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.");
@@ -192,3 +201,3 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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);
}
@@ -209,5 +218,11 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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()
)
@@ -232,3 +247,16 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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);
}
@@ -243,2 +271,3 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
+//console.log("M2", this._M2);
}
diff --git a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js
index 3f16f70..d03f873 100644
--- a/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js
+++ b/frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js
@@ -90,3 +90,3 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.P
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
- aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
+ aConnection['B'] = (Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
@@ -99,12 +99,23 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.P
} else if (someParameters.message == "credentialCheck") {
- var v, u, S, A, K, M1;
+ var v, u, s, S, A, K, M1;
+ var stringHash = function (aValue) {
+ return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
+ };
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
- u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
+ u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10))).toHexString(), 16);
+ s = new Clipperz.Crypto.BigInt(aConnection['userData']['s'], 16);
S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
- K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
+ K = stringHash(S.asString(10));
- M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
+ M1 = stringHash(
+ "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
+ stringHash(aConnection['C']) +
+ s.asString(10) +
+ A.asString(10) +
+ aConnection['B'].asString(10) +
+ K
+ );
if (someParameters.parameters.M1 == M1) {
@@ -112,3 +123,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.P
- M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
+ M2 = stringHash(
+ A.asString(10) +
+ someParameters.parameters.M1 +
+ K
+ );
result['M2'] = M2;
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
@@ -23,2 +23,4 @@ refer to http://www.clipperz.com.
+"use strict";
+
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
@@ -199,8 +201,2 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -247,4 +243,4 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
- collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
- this.setRandomBitsCollector(collectetBits);
+ collectedBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
+ this.setRandomBitsCollector(collectedBits);
numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
@@ -252,3 +248,3 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
if (numberOfRandomBitsCollected == 8) {
- this.updateGeneratorWithValue(collectetBits);
+ this.updateGeneratorWithValue(collectedBits);
numberOfRandomBitsCollected = 0;
@@ -291,8 +287,2 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -302,11 +292,11 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
-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;
@@ -314,30 +304,10 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) {
-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;
},
@@ -346,28 +316,18 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(n
- '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());
},
@@ -375,8 +335,2 @@ Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(n
//-------------------------------------------------------------------------
-
- 'pollingFrequency': function() {
- return 10;
- },
-
- //-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
@@ -637,3 +591,3 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
//-------------------------------------------------------------------------
-
+/*
'dump': function(appendToDoc) {
@@ -743,3 +697,3 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
},
-
+*/
//-----------------------------------------------------------------------------
@@ -786,3 +740,3 @@ Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, {
-_clipperz_crypt_prng_defaultPRNG = null;
+var _clipperz_crypt_prng_defaultPRNG = null;
@@ -818,3 +772,3 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
//
- // KeyboardRandomnessSource
+ // CryptoRandomRandomnessSource
//
@@ -823,7 +777,17 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
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);
+ }
}
-
}
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
@@ -46,2 +46,4 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
'_g': null,
+ '_k': null,
+
//-------------------------------------------------------------------------
@@ -66,2 +68,11 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
+ '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;
+ },
+
//-----------------------------------------------------------------------------
@@ -140,6 +151,5 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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.");
@@ -169,6 +179,5 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
'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.");
@@ -192,3 +201,3 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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);
}
@@ -209,5 +218,11 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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()
)
@@ -232,3 +247,16 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
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);
}
@@ -243,2 +271,3 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
+//console.log("M2", this._M2);
}
diff --git a/frontend/gamma/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js b/frontend/gamma/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
index b806cb7..e5f68a8 100644
--- a/frontend/gamma/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
+++ b/frontend/gamma/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
@@ -38,3 +38,3 @@ Clipperz.PM.Proxy.Offline.DataStore = function(args) {
this._currentStaticConnection = null;
-
+
return this;
@@ -293,3 +293,3 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
} else {
- throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
+ throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
}
@@ -300,3 +300,3 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
'result': 'done'
- },
+ },
toll: this.getTollForRequestType('CONNECT')
@@ -331,3 +331,3 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
- aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
+ aConnection['B'] = (Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
@@ -340,12 +340,23 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
} else if (someParameters.message == "credentialCheck") {
- var v, u, S, A, K, M1;
-
+ var v, u, s, S, A, K, M1;
+ var stringHash = function (aValue) {
+ return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
+ };
+
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
- u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
+ u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10))).toHexString(), 16);
+ s = new Clipperz.Crypto.BigInt(aConnection['userData']['s'], 16);
S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
- K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
+ K = stringHash(S.asString(10));
- M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
+ M1 = stringHash(
+ "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
+ stringHash(aConnection['C']) +
+ s.asString(10) +
+ A.asString(10) +
+ aConnection['B'].asString(10) +
+ K
+ );
if (someParameters.parameters.M1 == M1) {
@@ -353,3 +364,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
- M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
+ M2 = stringHash(
+ A.asString(10) +
+ someParameters.parameters.M1 +
+ K
+ );
result['M2'] = M2;