author | Michael Krelin <hacker@klever.net> | 2014-06-30 18:20:13 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2014-06-30 18:20:13 (UTC) |
commit | c392fe28606eefa0c814e5c25d641f5ffe623186 (patch) (side-by-side diff) | |
tree | da03fe13ca09fadbebbad9b5d38750757270bae8 /frontend | |
parent | d341307d346dee62ee36b27f0f93b8f000748a96 (diff) | |
parent | 6dd16d9359e3a4dc306802588b09acd43947a606 (diff) | |
download | clipperz-c392fe28606eefa0c814e5c25d641f5ffe623186.zip clipperz-c392fe28606eefa0c814e5c25d641f5ffe623186.tar.gz clipperz-c392fe28606eefa0c814e5c25d641f5ffe623186.tar.bz2 |
Merge remote-tracking branch 'github/master' into nmaster
-rw-r--r-- | frontend/beta/js/Clipperz/Base.js | 28 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/Crypto/PRNG.js | 126 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/Crypto/SRP.js | 57 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js | 2 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js | 4 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js | 22 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js | 2 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js | 39 | ||||
-rw-r--r-- | frontend/delta/js/Clipperz/Crypto/PRNG.js | 124 | ||||
-rw-r--r-- | frontend/delta/js/Clipperz/Crypto/SRP.js | 47 | ||||
-rw-r--r-- | frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.LocalStorageDataStore.js | 27 | ||||
-rw-r--r-- | frontend/gamma/js/Clipperz/Crypto/PRNG.js | 124 | ||||
-rw-r--r-- | frontend/gamma/js/Clipperz/Crypto/SRP.js | 47 | ||||
-rw-r--r-- | frontend/gamma/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js | 27 |
14 files changed, 365 insertions, 311 deletions
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 @@ -245,8 +245,36 @@ MochiKit.Base.update(Clipperz.Base, { return result; }, + '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; + }, + //------------------------------------------------------------------------- 'exception': { 'AbstractMethod': new MochiKit.Base.NamedError("Clipperz.Base.exception.AbstractMethod"), 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 @@ -196,14 +196,8 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C return 5; }, //------------------------------------------------------------------------- - - 'pollingFrequency': function() { - return 10; - }, - - //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); //***************************************************************************** @@ -244,14 +238,14 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new 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); } @@ -288,95 +282,53 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new 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, { - - //------------------------------------------------------------------------- - - 'randomBitsCollector': function() { - return this._randomBitsCollector; - }, - - 'setRandomBitsCollector': function(aValue) { - this._randomBitsCollector = aValue; - }, - - '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) - }, - - //------------------------------------------------------------------------- +Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, { - 'numberOfRandomBitsCollected': function() { - return this._numberOfRandomBitsCollected; + 'intervalTime': function() { + return this._intervalTime; }, - 'setNumberOfRandomBitsCollected': function(aValue) { - this._numberOfRandomBitsCollected = aValue; + 'browserCrypto': function () { + return this._browserCrypto; }, //------------------------------------------------------------------------- - 'collectEntropy': function(anEvent) { -/* - var mouseLocation; - var randomBit; - - mouseLocation = anEvent.mouse().client; - - randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1); - this.appendRandomBitToRandomBitsCollector(randomBit); -*/ - }, - - //------------------------------------------------------------------------- + 'collectEntropy': function() { + var bytesToCollect; - 'numberOfRandomBits': function() { - return 1; - }, + if (this.boostMode() == true) { + bytesToCollect = 64; + } else { + bytesToCollect = 8; + } - //------------------------------------------------------------------------- + var randomValuesArray = new Uint8Array(bytesToCollect); + this.browserCrypto().getRandomValues(randomValuesArray); + for (var i = 0; i < randomValuesArray.length; i++) { + this.updateGeneratorWithValue(randomValuesArray[i]); + } - 'pollingFrequency': function() { - return 10; + setTimeout(this.collectEntropy, this.intervalTime()); }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" @@ -606,31 +558,25 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!"); 'deferredEntropyCollection': function(aValue) { var result; -//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; Clipperz.NotificationCenter.notify(this, 'updatedProgressState', 'collectingEntropy', true); 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, 'readyToGenerateRandomBytes', deferredResult, 'callback'); result = deferredResult; } -//MochiKit.Logging.logDebug("<<< PRNG.deferredEntropyCollection - result: " + result); return result; }, @@ -642,9 +588,9 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!"); } }, //------------------------------------------------------------------------- - +/* 'dump': function(appendToDoc) { var tbl; var i,c; @@ -748,9 +694,9 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!"); } return tbl; }, - +*/ //----------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); @@ -823,18 +769,28 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() { } //............................................................. // - // 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; }; 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 @@ -43,8 +43,10 @@ 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) { @@ -63,8 +65,17 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, { 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") @@ -128,9 +139,8 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { '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); -//MochiKit.Logging.logDebug("SRP a: " + this._a); } return this._a; }, @@ -138,16 +148,14 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- '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)) { 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); } return this._A; }, @@ -155,9 +163,8 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to //------------------------------------------------------------------------- 's': function () { return this._s; -//MochiKit.Logging.logDebug("SRP s: " + this._S); }, 'set_s': function(aValue) { this._s = aValue; @@ -169,13 +176,11 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 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)) { + // Warning: this value should be strictly greater than zero this._B = aValue; -//MochiKit.Logging.logDebug("SRP B: " + this._B); - } else { + 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; } }, @@ -184,9 +189,8 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 'x': function () { if (this._x == null) { this._x = new Clipperz.Crypto.BigInt(this.stringHash(this.s().asString(16, 64) + this.P()), 16); -//MochiKit.Logging.logDebug("SRP x: " + this._x); } return this._x; }, @@ -194,10 +198,9 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to //------------------------------------------------------------------------- 'u': function () { 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); } return this._u; }, @@ -212,13 +215,18 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 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.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); } return this._S; }, @@ -227,9 +235,8 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 'K': function () { if (this._K == null) { this._K = this.stringHash(this.S().asString()); -//MochiKit.Logging.logDebug("SRP K: " + this._K); } return this._K; }, @@ -237,10 +244,22 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to //------------------------------------------------------------------------- 'M1': function () { 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); } return this._M1; }, @@ -249,9 +268,9 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 'M2': function () { if (this._M2 == null) { this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K()); -//MochiKit.Logging.logDebug("SRP M2: " + this._M2); +//console.log("M2", this._M2); } return 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 @@ -137,9 +137,9 @@ Clipperz.PM.BookmarkletProcessor.prototype = MochiKit.Base.update(null, { 'hostname': function() { if (this._hostname == null) { var actionUrl; - actionUrl = this.configuration()['form']['attributes']['action']; + actionUrl = Clipperz.Base.sanitizeUrl(this.configuration()['form']['attributes']['action']); //MochiKit.Logging.logDebug("+++ actionUrl: " + actionUrl); this._hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1'); } 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 @@ -99,9 +99,9 @@ YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent, C option = {tag:'option', value:null, html:'---'}; result.push(option); for (recordFieldKey in recordFields) { // 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()) { option['selected'] = true; } result.push(option); @@ -149,9 +149,9 @@ YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent, C //MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.updateViewMode"); this.getElement('editModeBox').hide(); this.getElement('viewModeBox').show(); - 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 @@ -37,9 +37,9 @@ Clipperz.PM.DataModel.DirectLogin = function(args) { //MochiKit.Logging.logDebug("--- new Clipperz.PM.DataModel.DirectLogin - args: " + Clipperz.Base.serializeJSON(MochiKit.Base.keys(args))); this._record = args.record || null; this._label = args.label || "unnamed record" 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"; this._directLoginInputs = null; @@ -101,11 +101,11 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, { if (this._favicon == null) { var actionUrl; var hostname; - 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"); } return this._favicon; }, @@ -136,8 +136,16 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, { 'setFixedFavicon': function(aValue) { this._fixedFavicon = aValue; }, + 'action': function () { + var result; + + result = Clipperz.Base.sanitizeUrl(this.formData()['attributes']['action']); + + return result; + }, + //------------------------------------------------------------------------- 'bookmarkletVersion': function() { return this._bookmarkletVersion; @@ -441,9 +449,9 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, { MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body, MochiKit.DOM.H3(null, "Loading " + this.label() + " ...")); //MochiKit.Logging.logDebug("### runDirectLogin - 4"); //console.log(this.formData()['attributes']); 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"); formSubmitFunction = MochiKit.Base.method(formElement, 'submit'); //MochiKit.Logging.logDebug("### runDirectLogin - 6"); @@ -486,11 +494,11 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, { var newWindow; //console.log("formData.attributes", this.formData()['attributes']); // 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; if (typeof(aNewWindow) != 'undefined') { aNewWindow.close(); 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 @@ -46,9 +46,9 @@ Clipperz.PM.DataModel.DirectLoginReference = function(args) { } else { this._reference = args.reference; this._recordReference = args.record; this._label = args.label; - this._favicon = args.favicon || null; + this._favicon = Clipperz.Base.sanitizeFavicon(args.favicon) || null; this._directLogin = null; this._record = 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 @@ -36,8 +36,9 @@ Clipperz.PM.Proxy.Offline.DataStore = function(args) { this._tolls = {}; this._connections = {}; + this._C = null; this._b = null; this._B = null; this._A = null; this._userData = null; @@ -143,8 +144,18 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, { }, //========================================================================= + 'C': function() { + return this._C; + }, + + 'set_C': function(aValue) { + this._C = aValue; + }, + + //------------------------------------------------------------------------- + 'b': function() { return this._b; }, @@ -339,34 +350,50 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, { this.setUserData(this.data()['users']['catchAllUser']); } 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()))); this.set_A(someParameters.parameters.A); result['s'] = this.userData()['s']; result['B'] = this.B().asString(16); nextTollRequestType = 'CONNECT'; } 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); + }; //console.log(">>> Proxy.Offline.DataStore._handshake.credentialCheck", someParameters); 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) { var M2; - 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; } else { throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); } 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 @@ -20,8 +20,10 @@ refer to http://www.clipperz.com. 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!"; } @@ -196,14 +198,8 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C return 5; }, //------------------------------------------------------------------------- - - 'pollingFrequency': function() { - return 10; - }, - - //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); //***************************************************************************** @@ -244,14 +240,14 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new 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); } @@ -288,95 +284,53 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new 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, { - - //------------------------------------------------------------------------- - - 'randomBitsCollector': function() { - return this._randomBitsCollector; - }, - - 'setRandomBitsCollector': function(aValue) { - this._randomBitsCollector = aValue; - }, - - '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) - }, +Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, { - //------------------------------------------------------------------------- - - 'numberOfRandomBitsCollected': function() { - return this._numberOfRandomBitsCollected; + 'intervalTime': function() { + return this._intervalTime; }, - 'setNumberOfRandomBitsCollected': function(aValue) { - this._numberOfRandomBitsCollected = aValue; + 'browserCrypto': function () { + return this._browserCrypto; }, //------------------------------------------------------------------------- - 'collectEntropy': function(anEvent) { -/* - var mouseLocation; - var randomBit; - - mouseLocation = anEvent.mouse().client; - - randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1); - this.appendRandomBitToRandomBitsCollector(randomBit); -*/ - }, - - //------------------------------------------------------------------------- + 'collectEntropy': function() { + var bytesToCollect; - 'numberOfRandomBits': function() { - return 1; - }, + if (this.boostMode() == true) { + bytesToCollect = 64; + } else { + bytesToCollect = 8; + } - //------------------------------------------------------------------------- + var randomValuesArray = new Uint8Array(bytesToCollect); + this.browserCrypto().getRandomValues(randomValuesArray); + for (var i = 0; i < randomValuesArray.length; i++) { + this.updateGeneratorWithValue(randomValuesArray[i]); + } - 'pollingFrequency': function() { - return 10; + setTimeout(this.collectEntropy, this.intervalTime()); }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" @@ -634,9 +588,9 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!"); } }, //------------------------------------------------------------------------- - +/* 'dump': function(appendToDoc) { var tbl; var i,c; @@ -740,9 +694,9 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!"); } return tbl; }, - +*/ //----------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); @@ -783,9 +737,9 @@ Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, { }); //############################################################################# -_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(); @@ -815,18 +769,28 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() { } //............................................................. // - // 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; }; 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 @@ -43,8 +43,10 @@ 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) { @@ -63,8 +65,17 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, { 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") @@ -137,12 +148,11 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- '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; } } @@ -166,12 +176,11 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { 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)) { + // Warning: this value should be strictly greater than zero this._B = aValue; - } else { + 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; } }, @@ -189,9 +198,9 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- '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; }, @@ -206,9 +215,15 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { 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.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() ) } @@ -229,9 +244,22 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- '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; }, @@ -240,8 +268,9 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { '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; }, 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 @@ -87,31 +87,46 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.P randomBytes = Clipperz.Crypto.Base.generateRandomSeed(); aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16); 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())); aConnection['A'] = someParameters.parameters.A; result['s'] = aConnection['userData']['s']; result['B'] = aConnection['B'].asString(16); nextTollRequestType = 'CONNECT'; } 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) { var M2; - 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; } else { throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); } 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 @@ -20,8 +20,10 @@ refer to http://www.clipperz.com. 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!"; } @@ -196,14 +198,8 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C return 5; }, //------------------------------------------------------------------------- - - 'pollingFrequency': function() { - return 10; - }, - - //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); //***************************************************************************** @@ -244,14 +240,14 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new 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); } @@ -288,95 +284,53 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new 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, { - - //------------------------------------------------------------------------- - - 'randomBitsCollector': function() { - return this._randomBitsCollector; - }, - - 'setRandomBitsCollector': function(aValue) { - this._randomBitsCollector = aValue; - }, - - '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) - }, +Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, { - //------------------------------------------------------------------------- - - 'numberOfRandomBitsCollected': function() { - return this._numberOfRandomBitsCollected; + 'intervalTime': function() { + return this._intervalTime; }, - 'setNumberOfRandomBitsCollected': function(aValue) { - this._numberOfRandomBitsCollected = aValue; + 'browserCrypto': function () { + return this._browserCrypto; }, //------------------------------------------------------------------------- - 'collectEntropy': function(anEvent) { -/* - var mouseLocation; - var randomBit; - - mouseLocation = anEvent.mouse().client; - - randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1); - this.appendRandomBitToRandomBitsCollector(randomBit); -*/ - }, - - //------------------------------------------------------------------------- + 'collectEntropy': function() { + var bytesToCollect; - 'numberOfRandomBits': function() { - return 1; - }, + if (this.boostMode() == true) { + bytesToCollect = 64; + } else { + bytesToCollect = 8; + } - //------------------------------------------------------------------------- + var randomValuesArray = new Uint8Array(bytesToCollect); + this.browserCrypto().getRandomValues(randomValuesArray); + for (var i = 0; i < randomValuesArray.length; i++) { + this.updateGeneratorWithValue(randomValuesArray[i]); + } - 'pollingFrequency': function() { - return 10; + setTimeout(this.collectEntropy, this.intervalTime()); }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" @@ -634,9 +588,9 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!"); } }, //------------------------------------------------------------------------- - +/* 'dump': function(appendToDoc) { var tbl; var i,c; @@ -740,9 +694,9 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!"); } return tbl; }, - +*/ //----------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); @@ -783,9 +737,9 @@ Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, { }); //############################################################################# -_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(); @@ -815,18 +769,28 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() { } //............................................................. // - // 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; }; 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 @@ -43,8 +43,10 @@ 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) { @@ -63,8 +65,17 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, { 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") @@ -137,12 +148,11 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- '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; } } @@ -166,12 +176,11 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { 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)) { + // Warning: this value should be strictly greater than zero this._B = aValue; - } else { + 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; } }, @@ -189,9 +198,9 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- '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; }, @@ -206,9 +215,15 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { 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.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() ) } @@ -229,9 +244,22 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- '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; }, @@ -240,8 +268,9 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { '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; }, 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 @@ -328,31 +328,46 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, { randomBytes = Clipperz.Crypto.Base.generateRandomSeed(); aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16); 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())); aConnection['A'] = someParameters.parameters.A; result['s'] = aConnection['userData']['s']; result['B'] = aConnection['B'].asString(16); nextTollRequestType = 'CONNECT'; } 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) { var M2; - 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; } else { throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); } |