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) (unidiff)
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
@@ -11,20 +11,25 @@ Since passwords are the most common type of private information that you need to
11 11
12Read more on the [Clipperz website][home]. 12Read more on the [Clipperz website][home].
13 13
14[home]: http://www.clipperz.com 14[home]: https://clipperz.is
15 15
16## Why an open source version 16## Why an open source version of Clipperz?
17 17
18Because 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. 18Because 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.
19 19
20In 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. 20In 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.
21 21
22Feel 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. 22Whatever is your motivation for playing with Clipperz code, we would love to hear from you: [get in contact][contact]!
23 23
24Whatever is your motivation, we would love to hear from you: [get in contact!][contact] 24## Security warning
25 25
26[CA]: http://www.clipperz.com/open_source/contributor_agreement 26The open source version of Clipperz is suitable for **testing and educational purposes only**. Do not use it as an actual password management solution.
27[contact]: http://www.clipperz.com/about/contacts 27
28As 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, ...).
29
30[CA]: https://clipperz.is/open_source/contributor_agreement
31[contact]: https://clipperz.is/about/contacts
32[clipperz]: https://clipperz.is
28 33
29 34
30## Donations 35## Donations
@@ -34,19 +39,16 @@ Our favorite payment method is clearly Bitcoin ([learn why here][why]), but you
34 39
35**To make your donation visit [this page][donations]. Thanks!** 40**To make your donation visit [this page][donations]. Thanks!**
36 41
37[why]: http://www.clipperz.com/pricing/why_bitcoin 42[why]: https://clipperz.is/pricing/why_bitcoin
38[donations]: http://www.clipperz.com/donations 43[donations]: https://clipperz.is/donations
39 44
40 45
41## License 46## License
42ALL 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. 47ALL 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.
43 48
44[agpl]: http://www.gnu.org/licenses/agpl.html 49[agpl]: http://www.gnu.org/licenses/agpl.html
45 50
46 51
47## Warnings
48Please 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.
49
50## Contributions 52## Contributions
51Your contributions to Clipperz are very welcome! In order to avoid jeopardizing the ownership of the code base, we will require every developer to sign the Clipperz [Contributor Agreement][CA] 53Your contributions to Clipperz are very welcome! In order to avoid jeopardizing the ownership of the code base, we will require every developer to sign the Clipperz [Contributor Agreement][CA]
52 54
@@ -115,4 +117,4 @@ Once the index.html files have been built (one for each frontend) and a backend
115This application has not been fully tested, so there may be still problems due to the new build script or to the new repository structure. So, for the moment, **use it at your own risk!** 117This application has not been fully tested, so there may be still problems due to the new build script or to the new repository structure. So, for the moment, **use it at your own risk!**
116 118
117 119
118[pog]: http://www.phpobjectgenerator.com/ \ No newline at end of file 120[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
@@ -246,6 +246,34 @@ MochiKit.Base.update(Clipperz.Base, {
246 return result; 246 return result;
247 }, 247 },
248 248
249 'javascriptInjectionPattern': new RegExp("javascript:\/\/\"", "g"),
250
251 'sanitizeUrl': function(aValue) {
252 varresult;
253
254 if ((aValue != null) && this.javascriptInjectionPattern.test(aValue)) {
255 result = aValue.replace(this.javascriptInjectionPattern, '');
256 console.log("sanitized url", aValue, result);
257 } else {
258 result = aValue;
259 }
260
261 return result;
262 },
263
264 'sanitizeFavicon': function(aValue) {
265 varresult;
266
267 if ((aValue != null) && this.javascriptInjectionPattern.test(aValue)) {
268 result = aValue.replace(this.javascriptInjectionPattern, '');
269 console.log("sanitized favicon", aValue, result);
270 } else {
271 result = aValue;
272 }
273
274 return result;
275 },
276
249 //------------------------------------------------------------------------- 277 //-------------------------------------------------------------------------
250 278
251 'exception': { 279 'exception': {
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
@@ -197,12 +197,6 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C
197 }, 197 },
198 198
199 //------------------------------------------------------------------------- 199 //-------------------------------------------------------------------------
200
201 'pollingFrequency': function() {
202 return 10;
203 },
204
205 //-------------------------------------------------------------------------
206 __syntaxFix__: "syntax fix" 200 __syntaxFix__: "syntax fix"
207}); 201});
208 202
@@ -245,12 +239,12 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
245 var numberOfRandomBitsCollected; 239 var numberOfRandomBitsCollected;
246 240
247 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected(); 241 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
248 collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected); 242 collectedBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
249 this.setRandomBitsCollector(collectetBits); 243 this.setRandomBitsCollector(collectedBits);
250 numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent(); 244 numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
251 245
252 if (numberOfRandomBitsCollected == 8) { 246 if (numberOfRandomBitsCollected == 8) {
253 this.updateGeneratorWithValue(collectetBits); 247 this.updateGeneratorWithValue(collectedBits);
254 numberOfRandomBitsCollected = 0; 248 numberOfRandomBitsCollected = 0;
255 this.setRandomBitsCollector(0); 249 this.setRandomBitsCollector(0);
256 } 250 }
@@ -289,96 +283,54 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
289 }, 283 },
290 284
291 //------------------------------------------------------------------------- 285 //-------------------------------------------------------------------------
292
293 'pollingFrequency': function() {
294 return 10;
295 },
296
297 //-------------------------------------------------------------------------
298 __syntaxFix__: "syntax fix" 286 __syntaxFix__: "syntax fix"
299}); 287});
300 288
301//***************************************************************************** 289//*****************************************************************************
302 290
303Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) { 291Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource = function(args) {
304 args = args || {}; 292 args = args || {};
305 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
306 293
307 this._randomBitsCollector = 0; 294 this._intervalTime = args.intervalTime || 1000;
308 this._numberOfRandomBitsCollected = 0; 295 this._browserCrypto = args.browserCrypto;
309 296
310 MochiKit.Signal.connect(document, 'onkeypress', this, 'collectEntropy'); 297 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
311 298
299 this.collectEntropy();
312 return this; 300 return this;
313} 301}
314 302
315Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, { 303Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
316
317 //-------------------------------------------------------------------------
318
319 'randomBitsCollector': function() {
320 return this._randomBitsCollector;
321 },
322 304
323 'setRandomBitsCollector': function(aValue) { 305 'intervalTime': function() {
324 this._randomBitsCollector = aValue; 306 return this._intervalTime;
325 }, 307 },
326 308
327 'appendRandomBitToRandomBitsCollector': function(aValue) { 309 'browserCrypto': function () {
328 var collectedBits; 310 return this._browserCrypto;
329 var numberOfRandomBitsCollected;
330
331 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
332 collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
333 this.setRandomBitsCollector(collectetBits);
334 numberOfRandomBitsCollected ++;
335
336 if (numberOfRandomBitsCollected == 8) {
337 this.updateGeneratorWithValue(collectetBits);
338 numberOfRandomBitsCollected = 0;
339 this.setRandomBitsCollector(0);
340 }
341
342 this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
343 }, 311 },
344 312
345 //------------------------------------------------------------------------- 313 //-------------------------------------------------------------------------
346 314
347 'numberOfRandomBitsCollected': function() { 315 'collectEntropy': function() {
348 return this._numberOfRandomBitsCollected; 316 varbytesToCollect;
349 },
350
351 'setNumberOfRandomBitsCollected': function(aValue) {
352 this._numberOfRandomBitsCollected = aValue;
353 },
354 317
355 //------------------------------------------------------------------------- 318 if (this.boostMode() == true) {
319 bytesToCollect = 64;
320 } else {
321 bytesToCollect = 8;
322 }
356 323
357 'collectEntropy': function(anEvent) { 324 var randomValuesArray = new Uint8Array(bytesToCollect);
358/* 325 this.browserCrypto().getRandomValues(randomValuesArray);
359 var mouseLocation; 326 for (var i = 0; i < randomValuesArray.length; i++) {
360 var randomBit; 327 this.updateGeneratorWithValue(randomValuesArray[i]);
361 328 }
362 mouseLocation = anEvent.mouse().client;
363
364 randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1);
365 this.appendRandomBitToRandomBitsCollector(randomBit);
366*/
367 },
368
369 //-------------------------------------------------------------------------
370 329
371 'numberOfRandomBits': function() { 330 setTimeout(this.collectEntropy, this.intervalTime());
372 return 1;
373 }, 331 },
374 332
375 //------------------------------------------------------------------------- 333 //-------------------------------------------------------------------------
376
377 'pollingFrequency': function() {
378 return 10;
379 },
380
381 //-------------------------------------------------------------------------
382 __syntaxFix__: "syntax fix" 334 __syntaxFix__: "syntax fix"
383}); 335});
384 336
@@ -607,21 +559,16 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
607 'deferredEntropyCollection': function(aValue) { 559 'deferredEntropyCollection': function(aValue) {
608 var result; 560 var result;
609 561
610//MochiKit.Logging.logDebug(">>> PRNG.deferredEntropyCollection");
611 562
612 if (this.isReadyToGenerateRandomValues()) { 563 if (this.isReadyToGenerateRandomValues()) {
613//MochiKit.Logging.logDebug("--- PRNG.deferredEntropyCollection - 1");
614 result = aValue; 564 result = aValue;
615 } else { 565 } else {
616//MochiKit.Logging.logDebug("--- PRNG.deferredEntropyCollection - 2");
617 var deferredResult; 566 var deferredResult;
618 567
619 Clipperz.NotificationCenter.notify(this, 'updatedProgressState', 'collectingEntropy', true); 568 Clipperz.NotificationCenter.notify(this, 'updatedProgressState', 'collectingEntropy', true);
620 569
621 deferredResult = new MochiKit.Async.Deferred(); 570 deferredResult = new MochiKit.Async.Deferred();
622 // deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.1 - PRNG.deferredEntropyCollection - 1: " + res); return res;});
623 deferredResult.addCallback(MochiKit.Base.partial(MochiKit.Async.succeed, aValue)); 571 deferredResult.addCallback(MochiKit.Base.partial(MochiKit.Async.succeed, aValue));
624 // deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.2 - PRNG.deferredEntropyCollection - 2: " + res); return res;});
625 MochiKit.Signal.connect(this, 572 MochiKit.Signal.connect(this,
626 'readyToGenerateRandomBytes', 573 'readyToGenerateRandomBytes',
627 deferredResult, 574 deferredResult,
@@ -629,7 +576,6 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
629 576
630 result = deferredResult; 577 result = deferredResult;
631 } 578 }
632//MochiKit.Logging.logDebug("<<< PRNG.deferredEntropyCollection - result: " + result);
633 579
634 return result; 580 return result;
635 }, 581 },
@@ -643,7 +589,7 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
643 }, 589 },
644 590
645 //------------------------------------------------------------------------- 591 //-------------------------------------------------------------------------
646 592/*
647 'dump': function(appendToDoc) { 593 'dump': function(appendToDoc) {
648 var tbl; 594 var tbl;
649 var i,c; 595 var i,c;
@@ -749,7 +695,7 @@ MochiKit.Logging.logWarning("Fortuna generator has not enough entropy, yet!");
749 695
750 return tbl; 696 return tbl;
751 }, 697 },
752 698*/
753 //----------------------------------------------------------------------------- 699 //-----------------------------------------------------------------------------
754 __syntaxFix__: "syntax fix" 700 __syntaxFix__: "syntax fix"
755}); 701});
@@ -824,16 +770,26 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
824 770
825 //............................................................. 771 //.............................................................
826 // 772 //
827 // KeyboardRandomnessSource 773 // CryptoRandomRandomnessSource
828 // 774 //
829 //............................................................. 775 //.............................................................
830 { 776 {
831 varnewRandomnessSource; 777 varnewRandomnessSource;
778 varbrowserCrypto;
832 779
833 newRandomnessSource = new Clipperz.Crypto.PRNG.KeyboardRandomnessSource(); 780 if (window.crypto && window.crypto.getRandomValues) {
834 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource); 781 browserCrypto = window.crypto;
782 } else if (window.msCrypto && window.msCrypto.getRandomValues) {
783 browserCrypto = window.msCrypto;
784 } else {
785 browserCrypto = null;
786 }
787
788 if (browserCrypto != null) {
789 newRandomnessSource = new Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource({'browserCrypto':browserCrypto});
790 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
791 }
835 } 792 }
836
837 } 793 }
838 794
839 return _clipperz_crypt_prng_defaultPRNG; 795 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
@@ -44,6 +44,8 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
44 44
45 '_n': null, 45 '_n': null,
46 '_g': null, 46 '_g': null,
47 '_k': null,
48
47 //------------------------------------------------------------------------- 49 //-------------------------------------------------------------------------
48 50
49 'n': function() { 51 'n': function() {
@@ -64,6 +66,15 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
64 return Clipperz.Crypto.SRP._g; 66 return Clipperz.Crypto.SRP._g;
65 }, 67 },
66 68
69 'k': function() {
70 if (Clipperz.Crypto.SRP._k == null) {
71 // Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt(this.stringHash(this.n().asString() + this.g().asString()), 16);
72 Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt("64398bff522814e306a97cb9bfc4364b7eed16a8c17c5208a40a2bad2933c8e", 16);
73 }
74
75 return Clipperz.Crypto.SRP._k;
76 },
77
67 //----------------------------------------------------------------------------- 78 //-----------------------------------------------------------------------------
68 79
69 'exception': { 80 'exception': {
@@ -129,7 +140,6 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
129 if (this._a == null) { 140 if (this._a == null) {
130 this._a = new Clipperz.Crypto.BigInt(Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2), 16); 141 this._a = new Clipperz.Crypto.BigInt(Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2), 16);
131 // this._a = new Clipperz.Crypto.BigInt("37532428169486597638072888476611365392249575518156687476805936694442691012367", 10); 142 // this._a = new Clipperz.Crypto.BigInt("37532428169486597638072888476611365392249575518156687476805936694442691012367", 10);
132//MochiKit.Logging.logDebug("SRP a: " + this._a);
133 } 143 }
134 144
135 return this._a; 145 return this._a;
@@ -139,14 +149,12 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
139 149
140 'A': function () { 150 'A': function () {
141 if (this._A == null) { 151 if (this._A == null) {
142 //Warning: this value should be strictly greater than zero: how should we perform this check? 152 //Warning: this value should be strictly greater than zero
143 this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n()); 153 this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n());
144 154 if (this._A.equals(0) || negative(this._A)) {
145 if (this._A.equals(0)) { 155 MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
146MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
147 throw Clipperz.Crypto.SRP.exception.InvalidValue; 156 throw Clipperz.Crypto.SRP.exception.InvalidValue;
148 } 157 }
149//MochiKit.Logging.logDebug("SRP A: " + this._A);
150 } 158 }
151 159
152 return this._A; 160 return this._A;
@@ -156,7 +164,6 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to
156 164
157 's': function () { 165 's': function () {
158 return this._s; 166 return this._s;
159//MochiKit.Logging.logDebug("SRP s: " + this._S);
160 }, 167 },
161 168
162 'set_s': function(aValue) { 169 'set_s': function(aValue) {
@@ -170,12 +177,10 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to
170 }, 177 },
171 178
172 'set_B': function(aValue) { 179 'set_B': function(aValue) {
173 //Warning: this value should be strictly greater than zero: how should we perform this check? 180 //Warning: this value should be strictly greater than zero
174 if (! aValue.equals(0)) { 181 this._B = aValue;
175 this._B = aValue; 182 if (this._B.equals(0) || negative(this._B)) {
176//MochiKit.Logging.logDebug("SRP B: " + this._B); 183 MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
177 } else {
178MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
179 throw Clipperz.Crypto.SRP.exception.InvalidValue; 184 throw Clipperz.Crypto.SRP.exception.InvalidValue;
180 } 185 }
181 }, 186 },
@@ -185,7 +190,6 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
185 'x': function () { 190 'x': function () {
186 if (this._x == null) { 191 if (this._x == null) {
187 this._x = new Clipperz.Crypto.BigInt(this.stringHash(this.s().asString(16, 64) + this.P()), 16); 192 this._x = new Clipperz.Crypto.BigInt(this.stringHash(this.s().asString(16, 64) + this.P()), 16);
188//MochiKit.Logging.logDebug("SRP x: " + this._x);
189 } 193 }
190 194
191 return this._x; 195 return this._x;
@@ -195,8 +199,7 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
195 199
196 'u': function () { 200 'u': function () {
197 if (this._u == null) { 201 if (this._u == null) {
198 this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.B().asString()), 16); 202 this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.A().asString() + this.B().asString()), 16);
199//MochiKit.Logging.logDebug("SRP u: " + this._u);
200 } 203 }
201 204
202 return this._u; 205 return this._u;
@@ -213,11 +216,16 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
213 srp = Clipperz.Crypto.SRP; 216 srp = Clipperz.Crypto.SRP;
214 217
215 this._S =bigint.powerModule( 218 this._S =bigint.powerModule(
216 bigint.subtract(this.B(), bigint.powerModule(srp.g(), this.x(), srp.n())), 219 bigint.subtract(
217 bigint.add(this.a(), bigint.multiply(this.u(), this.x())), 220 this.B(),
218 srp.n() 221 bigint.multiply(
222 Clipperz.Crypto.SRP.k(),
223 bigint.powerModule(srp.g(), this.x(), srp.n())
224 )
225 ),
226 bigint.add(this.a(), bigint.multiply(this.u(), this.x())),
227 srp.n()
219 ) 228 )
220//MochiKit.Logging.logDebug("SRP S: " + this._S);
221 } 229 }
222 230
223 return this._S; 231 return this._S;
@@ -228,7 +236,6 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
228 'K': function () { 236 'K': function () {
229 if (this._K == null) { 237 if (this._K == null) {
230 this._K = this.stringHash(this.S().asString()); 238 this._K = this.stringHash(this.S().asString());
231//MochiKit.Logging.logDebug("SRP K: " + this._K);
232 } 239 }
233 240
234 return this._K; 241 return this._K;
@@ -238,8 +245,20 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
238 245
239 'M1': function () { 246 'M1': function () {
240 if (this._M1 == null) { 247 if (this._M1 == null) {
241 this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K()); 248 // this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
242//MochiKit.Logging.logDebug("SRP M1: " + this._M1); 249
250 //http://srp.stanford.edu/design.html
251 //User -> Host: M = H(H(N) xor H(g), H(I), s, A, B, K)
252
253 this._M1 = this.stringHash(
254 "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
255 this.stringHash(this.C()) +
256 this.s().asString() +
257 this.A().asString() +
258 this.B().asString() +
259 this.K()
260 );
261//console.log("M1", this._M1);
243 } 262 }
244 263
245 return this._M1; 264 return this._M1;
@@ -250,7 +269,7 @@ MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to
250 'M2': function () { 269 'M2': function () {
251 if (this._M2 == null) { 270 if (this._M2 == null) {
252 this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K()); 271 this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
253//MochiKit.Logging.logDebug("SRP M2: " + this._M2); 272//console.log("M2", this._M2);
254 } 273 }
255 274
256 return this._M2; 275 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
@@ -138,7 +138,7 @@ Clipperz.PM.BookmarkletProcessor.prototype = MochiKit.Base.update(null, {
138 if (this._hostname == null) { 138 if (this._hostname == null) {
139 var actionUrl; 139 var actionUrl;
140 140
141 actionUrl = this.configuration()['form']['attributes']['action']; 141 actionUrl = Clipperz.Base.sanitizeUrl(this.configuration()['form']['attributes']['action']);
142//MochiKit.Logging.logDebug("+++ actionUrl: " + actionUrl); 142//MochiKit.Logging.logDebug("+++ actionUrl: " + actionUrl);
143 this._hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1'); 143 this._hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1');
144 } 144 }
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
@@ -100,7 +100,7 @@ YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent, C
100 result.push(option); 100 result.push(option);
101 for (recordFieldKey in recordFields) { 101 for (recordFieldKey in recordFields) {
102 //TODO: remove the value: field and replace it with element.dom.value = <some value> 102 //TODO: remove the value: field and replace it with element.dom.value = <some value>
103 option = {tag:'option', value:recordFieldKey, html:recordFields[recordFieldKey].label()} 103 option = {tag:'option', value:recordFieldKey, html:Clipperz.Base.sanitizeString(recordFields[recordFieldKey].label())}
104 if (recordFieldKey == this.directLoginBinding().fieldKey()) { 104 if (recordFieldKey == this.directLoginBinding().fieldKey()) {
105 option['selected'] = true; 105 option['selected'] = true;
106 } 106 }
@@ -150,7 +150,7 @@ YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent, C
150 this.getElement('editModeBox').hide(); 150 this.getElement('editModeBox').hide();
151 this.getElement('viewModeBox').show(); 151 this.getElement('viewModeBox').show();
152 152
153 this.getElement('viewValue').update(this.directLoginBinding().field().label()); 153 this.getElement('viewValue').update(Clipperz.Base.sanitizeString(this.directLoginBinding().field().label()));
154//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.updateViewMode"); 154//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.updateViewMode");
155 }, 155 },
156 156
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
@@ -38,7 +38,7 @@ Clipperz.PM.DataModel.DirectLogin = function(args) {
38 this._record = args.record || null; 38 this._record = args.record || null;
39 this._label = args.label || "unnamed record" 39 this._label = args.label || "unnamed record"
40 this._reference = args.reference || Clipperz.PM.Crypto.randomKey(); 40 this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
41 this._favicon = args.favicon || null; 41 this._favicon = Clipperz.Base.sanitizeFavicon(args.favicon) || null;
42 this._bookmarkletVersion = args.bookmarkletVersion || "0.1"; 42 this._bookmarkletVersion = args.bookmarkletVersion || "0.1";
43 43
44 this._directLoginInputs = null; 44 this._directLoginInputs = null;
@@ -102,9 +102,9 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
102 varactionUrl; 102 varactionUrl;
103 var hostname; 103 var hostname;
104 104
105 actionUrl = this.formData()['attributes']['action']; 105 actionUrl = this.action();
106 hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1'); 106 hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1');
107 this._favicon = "http://" + hostname + "/favicon.ico"; 107 this._favicon = Clipperz.Base.sanitizeFavicon("http://" + hostname + "/favicon.ico");
108 } 108 }
109 109
110 return this._favicon; 110 return this._favicon;
@@ -137,6 +137,14 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
137 this._fixedFavicon = aValue; 137 this._fixedFavicon = aValue;
138 }, 138 },
139 139
140 'action': function () {
141 varresult;
142
143 result = Clipperz.Base.sanitizeUrl(this.formData()['attributes']['action']);
144
145 return result;
146 },
147
140 //------------------------------------------------------------------------- 148 //-------------------------------------------------------------------------
141 149
142 'bookmarkletVersion': function() { 150 'bookmarkletVersion': function() {
@@ -442,7 +450,7 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
442//MochiKit.Logging.logDebug("### runDirectLogin - 4"); 450//MochiKit.Logging.logDebug("### runDirectLogin - 4");
443//console.log(this.formData()['attributes']); 451//console.log(this.formData()['attributes']);
444 formElement = MochiKit.DOM.FORM(MochiKit.Base.update({id:'directLoginForm'}, {'method':this.formData()['attributes']['method'], 452 formElement = MochiKit.DOM.FORM(MochiKit.Base.update({id:'directLoginForm'}, {'method':this.formData()['attributes']['method'],
445 'action':this.formData()['attributes']['action']})); 453 'action': this.action()}));
446//MochiKit.Logging.logDebug("### runDirectLogin - 5"); 454//MochiKit.Logging.logDebug("### runDirectLogin - 5");
447 formSubmitFunction = MochiKit.Base.method(formElement, 'submit'); 455 formSubmitFunction = MochiKit.Base.method(formElement, 'submit');
448//MochiKit.Logging.logDebug("### runDirectLogin - 6"); 456//MochiKit.Logging.logDebug("### runDirectLogin - 6");
@@ -487,9 +495,9 @@ Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
487 495
488//console.log("formData.attributes", this.formData()['attributes']); 496//console.log("formData.attributes", this.formData()['attributes']);
489 // if (/^javascript/.test(this.formData()['attributes']['action'])) { 497 // if (/^javascript/.test(this.formData()['attributes']['action'])) {
490 if ((/^(https?|webdav|ftp)\:/.test(this.formData()['attributes']['action']) == false) && 498 if ((/^(https?|webdav|ftp)\:/.test(this.action()) == false) &&
491 (this.formData()['attributes']['type'] != 'http_auth')) 499 (this.formData()['attributes']['type'] != 'http_auth')
492 { 500 ) {
493 var messageBoxConfiguration; 501 var messageBoxConfiguration;
494 502
495 if (typeof(aNewWindow) != 'undefined') { 503 if (typeof(aNewWindow) != 'undefined') {
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
@@ -47,7 +47,7 @@ Clipperz.PM.DataModel.DirectLoginReference = function(args) {
47 this._reference = args.reference; 47 this._reference = args.reference;
48 this._recordReference = args.record; 48 this._recordReference = args.record;
49 this._label = args.label; 49 this._label = args.label;
50 this._favicon = args.favicon || null; 50 this._favicon = Clipperz.Base.sanitizeFavicon(args.favicon) || null;
51 51
52 this._directLogin = null; 52 this._directLogin = null;
53 this._record = null; 53 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
@@ -37,6 +37,7 @@ Clipperz.PM.Proxy.Offline.DataStore = function(args) {
37 this._tolls = {}; 37 this._tolls = {};
38 this._connections = {}; 38 this._connections = {};
39 39
40 this._C = null;
40 this._b = null; 41 this._b = null;
41 this._B = null; 42 this._B = null;
42 this._A = null; 43 this._A = null;
@@ -144,6 +145,16 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
144 145
145 //========================================================================= 146 //=========================================================================
146 147
148 'C': function() {
149 return this._C;
150 },
151
152 'set_C': function(aValue) {
153 this._C = aValue;
154 },
155
156 //-------------------------------------------------------------------------
157
147 'b': function() { 158 'b': function() {
148 return this._b; 159 return this._b;
149 }, 160 },
@@ -236,8 +247,8 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
236 }, 247 },
237 248
238 //========================================================================= 249 //=========================================================================
239 250
240 'processMessage': function(aFunctionName, someParameters) { 251 'processMessage': function (aFunctionName, someParameters) {
241 var result; 252 var result;
242 253
243 switch(aFunctionName) { 254 switch(aFunctionName) {
@@ -303,14 +314,14 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
303 throw "user already exists"; 314 throw "user already exists";
304 } 315 }
305 } else { 316 } else {
306 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly; 317 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
307 } 318 }
308 319
309 result = { 320 result = {
310 result: { 321 result: {
311 'lock': this.data()['users'][someParameters['credentials']['C']]['lock'], 322 'lock': this.data()['users'][someParameters['credentials']['C']]['lock'],
312 'result':'done' 323 'result':'done'
313 }, 324 },
314 toll: this.getTollForRequestType('CONNECT') 325 toll: this.getTollForRequestType('CONNECT')
315 } 326 }
316 327
@@ -340,9 +351,10 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
340 } 351 }
341 352
342 randomBytes = Clipperz.Crypto.Base.generateRandomSeed(); 353 randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
354 this.set_C(someParameters.parameters.C);
343 this.set_b(new Clipperz.Crypto.BigInt(randomBytes, 16)); 355 this.set_b(new Clipperz.Crypto.BigInt(randomBytes, 16));
344 v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16); 356 v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16);
345 this.set_B(v.add(Clipperz.Crypto.SRP.g().powerModule(this.b(), Clipperz.Crypto.SRP.n()))); 357 this.set_B((Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(this.b(), Clipperz.Crypto.SRP.n())));
346 358
347 this.set_A(someParameters.parameters.A); 359 this.set_A(someParameters.parameters.A);
348 360
@@ -351,21 +363,36 @@ Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
351 363
352 nextTollRequestType = 'CONNECT'; 364 nextTollRequestType = 'CONNECT';
353 } else if (someParameters.message == "credentialCheck") { 365 } else if (someParameters.message == "credentialCheck") {
354 var v, u, S, A, K, M1; 366 var v, u, s, S, A, K, M1;
367 var stringHash = function (aValue) {
368 return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
369 };
355 370
356//console.log(">>> Proxy.Offline.DataStore._handshake.credentialCheck", someParameters); 371//console.log(">>> Proxy.Offline.DataStore._handshake.credentialCheck", someParameters);
357 v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16); 372 v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16);
358 u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(this.B().asString(10))).toHexString(), 16);
359 A = new Clipperz.Crypto.BigInt(this.A(), 16); 373 A = new Clipperz.Crypto.BigInt(this.A(), 16);
374 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);
375 s = new Clipperz.Crypto.BigInt(this.userData()['s'], 16);
360 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(this.b(), Clipperz.Crypto.SRP.n()); 376 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(this.b(), Clipperz.Crypto.SRP.n());
361 377
362 K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2); 378 K = stringHash(S.asString(10));
363 379
364 M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + this.B().asString(10) + K)).toHexString().slice(2); 380 M1 = stringHash(
381 "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
382 stringHash(this.C()) +
383 s.asString(10) +
384 A.asString(10) +
385 this.B().asString(10) +
386 K
387 );
365 if (someParameters.parameters.M1 == M1) { 388 if (someParameters.parameters.M1 == M1) {
366 var M2; 389 var M2;
367 390
368 M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2); 391 M2 = stringHash(
392 A.asString(10) +
393 someParameters.parameters.M1 +
394 K
395 );
369 result['M2'] = M2; 396 result['M2'] = M2;
370 } else { 397 } else {
371 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); 398 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
@@ -21,6 +21,8 @@ refer to http://www.clipperz.com.
21 21
22*/ 22*/
23 23
24"use strict";
25
24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) { 26try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!"; 27 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
26} 28}
@@ -197,12 +199,6 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C
197 }, 199 },
198 200
199 //------------------------------------------------------------------------- 201 //-------------------------------------------------------------------------
200
201 'pollingFrequency': function() {
202 return 10;
203 },
204
205 //-------------------------------------------------------------------------
206 __syntaxFix__: "syntax fix" 202 __syntaxFix__: "syntax fix"
207}); 203});
208 204
@@ -245,12 +241,12 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
245 var numberOfRandomBitsCollected; 241 var numberOfRandomBitsCollected;
246 242
247 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected(); 243 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
248 collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected); 244 collectedBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
249 this.setRandomBitsCollector(collectetBits); 245 this.setRandomBitsCollector(collectedBits);
250 numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent(); 246 numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
251 247
252 if (numberOfRandomBitsCollected == 8) { 248 if (numberOfRandomBitsCollected == 8) {
253 this.updateGeneratorWithValue(collectetBits); 249 this.updateGeneratorWithValue(collectedBits);
254 numberOfRandomBitsCollected = 0; 250 numberOfRandomBitsCollected = 0;
255 this.setRandomBitsCollector(0); 251 this.setRandomBitsCollector(0);
256 } 252 }
@@ -289,96 +285,54 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
289 }, 285 },
290 286
291 //------------------------------------------------------------------------- 287 //-------------------------------------------------------------------------
292
293 'pollingFrequency': function() {
294 return 10;
295 },
296
297 //-------------------------------------------------------------------------
298 __syntaxFix__: "syntax fix" 288 __syntaxFix__: "syntax fix"
299}); 289});
300 290
301//***************************************************************************** 291//*****************************************************************************
302 292
303Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) { 293Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource = function(args) {
304 args = args || {}; 294 args = args || {};
305 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
306 295
307 this._randomBitsCollector = 0; 296 this._intervalTime = args.intervalTime || 1000;
308 this._numberOfRandomBitsCollected = 0; 297 this._browserCrypto = args.browserCrypto;
309 298
310 MochiKit.Signal.connect(document, 'onkeypress', this, 'collectEntropy'); 299 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
311 300
301 this.collectEntropy();
312 return this; 302 return this;
313} 303}
314 304
315Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, { 305Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
316 306
317 //------------------------------------------------------------------------- 307 'intervalTime': function() {
318 308 return this._intervalTime;
319 'randomBitsCollector': function() {
320 return this._randomBitsCollector;
321 },
322
323 'setRandomBitsCollector': function(aValue) {
324 this._randomBitsCollector = aValue;
325 }, 309 },
326 310
327 'appendRandomBitToRandomBitsCollector': function(aValue) { 311 'browserCrypto': function () {
328 var collectedBits; 312 return this._browserCrypto;
329 var numberOfRandomBitsCollected;
330
331 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
332 collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
333 this.setRandomBitsCollector(collectetBits);
334 numberOfRandomBitsCollected ++;
335
336 if (numberOfRandomBitsCollected == 8) {
337 this.updateGeneratorWithValue(collectetBits);
338 numberOfRandomBitsCollected = 0;
339 this.setRandomBitsCollector(0);
340 }
341
342 this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
343 }, 313 },
344 314
345 //------------------------------------------------------------------------- 315 //-------------------------------------------------------------------------
346 316
347 'numberOfRandomBitsCollected': function() { 317 'collectEntropy': function() {
348 return this._numberOfRandomBitsCollected; 318 varbytesToCollect;
349 },
350
351 'setNumberOfRandomBitsCollected': function(aValue) {
352 this._numberOfRandomBitsCollected = aValue;
353 },
354 319
355 //------------------------------------------------------------------------- 320 if (this.boostMode() == true) {
321 bytesToCollect = 64;
322 } else {
323 bytesToCollect = 8;
324 }
356 325
357 'collectEntropy': function(anEvent) { 326 var randomValuesArray = new Uint8Array(bytesToCollect);
358/* 327 this.browserCrypto().getRandomValues(randomValuesArray);
359 var mouseLocation; 328 for (var i = 0; i < randomValuesArray.length; i++) {
360 var randomBit; 329 this.updateGeneratorWithValue(randomValuesArray[i]);
361 330 }
362 mouseLocation = anEvent.mouse().client;
363
364 randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1);
365 this.appendRandomBitToRandomBitsCollector(randomBit);
366*/
367 },
368
369 //-------------------------------------------------------------------------
370 331
371 'numberOfRandomBits': function() { 332 setTimeout(this.collectEntropy, this.intervalTime());
372 return 1;
373 }, 333 },
374 334
375 //------------------------------------------------------------------------- 335 //-------------------------------------------------------------------------
376
377 'pollingFrequency': function() {
378 return 10;
379 },
380
381 //-------------------------------------------------------------------------
382 __syntaxFix__: "syntax fix" 336 __syntaxFix__: "syntax fix"
383}); 337});
384 338
@@ -635,7 +589,7 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
635 }, 589 },
636 590
637 //------------------------------------------------------------------------- 591 //-------------------------------------------------------------------------
638 592/*
639 'dump': function(appendToDoc) { 593 'dump': function(appendToDoc) {
640 var tbl; 594 var tbl;
641 var i,c; 595 var i,c;
@@ -741,7 +695,7 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
741 695
742 return tbl; 696 return tbl;
743 }, 697 },
744 698*/
745 //----------------------------------------------------------------------------- 699 //-----------------------------------------------------------------------------
746 __syntaxFix__: "syntax fix" 700 __syntaxFix__: "syntax fix"
747}); 701});
@@ -784,7 +738,7 @@ Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, {
784 738
785//############################################################################# 739//#############################################################################
786 740
787_clipperz_crypt_prng_defaultPRNG = null; 741var _clipperz_crypt_prng_defaultPRNG = null;
788 742
789Clipperz.Crypto.PRNG.defaultRandomGenerator = function() { 743Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
790 if (_clipperz_crypt_prng_defaultPRNG == null) { 744 if (_clipperz_crypt_prng_defaultPRNG == null) {
@@ -816,16 +770,26 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
816 770
817 //............................................................. 771 //.............................................................
818 // 772 //
819 // KeyboardRandomnessSource 773 // CryptoRandomRandomnessSource
820 // 774 //
821 //............................................................. 775 //.............................................................
822 { 776 {
823 varnewRandomnessSource; 777 varnewRandomnessSource;
778 varbrowserCrypto;
824 779
825 newRandomnessSource = new Clipperz.Crypto.PRNG.KeyboardRandomnessSource(); 780 if (window.crypto && window.crypto.getRandomValues) {
826 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource); 781 browserCrypto = window.crypto;
782 } else if (window.msCrypto && window.msCrypto.getRandomValues) {
783 browserCrypto = window.msCrypto;
784 } else {
785 browserCrypto = null;
786 }
787
788 if (browserCrypto != null) {
789 newRandomnessSource = new Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource({'browserCrypto':browserCrypto});
790 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
791 }
827 } 792 }
828
829 } 793 }
830 794
831 return _clipperz_crypt_prng_defaultPRNG; 795 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
@@ -44,6 +44,8 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
44 44
45 '_n': null, 45 '_n': null,
46 '_g': null, 46 '_g': null,
47 '_k': null,
48
47 //------------------------------------------------------------------------- 49 //-------------------------------------------------------------------------
48 50
49 'n': function() { 51 'n': function() {
@@ -64,6 +66,15 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
64 return Clipperz.Crypto.SRP._g; 66 return Clipperz.Crypto.SRP._g;
65 }, 67 },
66 68
69 'k': function() {
70 if (Clipperz.Crypto.SRP._k == null) {
71 // Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt(this.stringHash(this.n().asString() + this.g().asString()), 16);
72 Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt("64398bff522814e306a97cb9bfc4364b7eed16a8c17c5208a40a2bad2933c8e", 16);
73 }
74
75 return Clipperz.Crypto.SRP._k;
76 },
77
67 //----------------------------------------------------------------------------- 78 //-----------------------------------------------------------------------------
68 79
69 'exception': { 80 'exception': {
@@ -138,10 +149,9 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
138 149
139 'A': function () { 150 'A': function () {
140 if (this._A == null) { 151 if (this._A == null) {
141 //Warning: this value should be strictly greater than zero: how should we perform this check? 152 //Warning: this value should be strictly greater than zero
142 this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n()); 153 this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n());
143 154 if (this._A.equals(0) || negative(this._A)) {
144 if (this._A.equals(0)) {
145 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0."); 155 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
146 throw Clipperz.Crypto.SRP.exception.InvalidValue; 156 throw Clipperz.Crypto.SRP.exception.InvalidValue;
147 } 157 }
@@ -167,10 +177,9 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
167 }, 177 },
168 178
169 'set_B': function(aValue) { 179 'set_B': function(aValue) {
170 //Warning: this value should be strictly greater than zero: how should we perform this check? 180 //Warning: this value should be strictly greater than zero
171 if (! aValue.equals(0)) { 181 this._B = aValue;
172 this._B = aValue; 182 if (this._B.equals(0) || negative(this._B)) {
173 } else {
174 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0."); 183 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
175 throw Clipperz.Crypto.SRP.exception.InvalidValue; 184 throw Clipperz.Crypto.SRP.exception.InvalidValue;
176 } 185 }
@@ -190,7 +199,7 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
190 199
191 'u': function () { 200 'u': function () {
192 if (this._u == null) { 201 if (this._u == null) {
193 this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.B().asString()), 16); 202 this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.A().asString() + this.B().asString()), 16);
194 } 203 }
195 204
196 return this._u; 205 return this._u;
@@ -207,9 +216,15 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
207 srp = Clipperz.Crypto.SRP; 216 srp = Clipperz.Crypto.SRP;
208 217
209 this._S =bigint.powerModule( 218 this._S =bigint.powerModule(
210 bigint.subtract(this.B(), bigint.powerModule(srp.g(), this.x(), srp.n())), 219 bigint.subtract(
211 bigint.add(this.a(), bigint.multiply(this.u(), this.x())), 220 this.B(),
212 srp.n() 221 bigint.multiply(
222 Clipperz.Crypto.SRP.k(),
223 bigint.powerModule(srp.g(), this.x(), srp.n())
224 )
225 ),
226 bigint.add(this.a(), bigint.multiply(this.u(), this.x())),
227 srp.n()
213 ) 228 )
214 } 229 }
215 230
@@ -230,7 +245,20 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
230 245
231 'M1': function () { 246 'M1': function () {
232 if (this._M1 == null) { 247 if (this._M1 == null) {
233 this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K()); 248 // this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
249
250 //http://srp.stanford.edu/design.html
251 //User -> Host: M = H(H(N) xor H(g), H(I), s, A, B, K)
252
253 this._M1 = this.stringHash(
254 "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
255 this.stringHash(this.C()) +
256 this.s().asString() +
257 this.A().asString() +
258 this.B().asString() +
259 this.K()
260 );
261//console.log("M1", this._M1);
234 } 262 }
235 263
236 return this._M1; 264 return this._M1;
@@ -241,6 +269,7 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
241 'M2': function () { 269 'M2': function () {
242 if (this._M2 == null) { 270 if (this._M2 == null) {
243 this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K()); 271 this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
272//console.log("M2", this._M2);
244 } 273 }
245 274
246 return this._M2; 275 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
@@ -88,7 +88,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.P
88 randomBytes = Clipperz.Crypto.Base.generateRandomSeed(); 88 randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
89 aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16); 89 aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
90 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16); 90 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
91 aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n())); 91 aConnection['B'] = (Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
92 92
93 aConnection['A'] = someParameters.parameters.A; 93 aConnection['A'] = someParameters.parameters.A;
94 94
@@ -97,20 +97,35 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.P
97 97
98 nextTollRequestType = 'CONNECT'; 98 nextTollRequestType = 'CONNECT';
99 } else if (someParameters.message == "credentialCheck") { 99 } else if (someParameters.message == "credentialCheck") {
100 var v, u, S, A, K, M1; 100 var v, u, s, S, A, K, M1;
101 var stringHash = function (aValue) {
102 return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
103 };
101 104
102 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16); 105 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
103 u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
104 A = new Clipperz.Crypto.BigInt(aConnection['A'], 16); 106 A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
107 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);
108 s = new Clipperz.Crypto.BigInt(aConnection['userData']['s'], 16);
105 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()); 109 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
106 110
107 K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2); 111 K = stringHash(S.asString(10));
108 112
109 M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2); 113 M1 = stringHash(
114 "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
115 stringHash(aConnection['C']) +
116 s.asString(10) +
117 A.asString(10) +
118 aConnection['B'].asString(10) +
119 K
120 );
110 if (someParameters.parameters.M1 == M1) { 121 if (someParameters.parameters.M1 == M1) {
111 var M2; 122 var M2;
112 123
113 M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2); 124 M2 = stringHash(
125 A.asString(10) +
126 someParameters.parameters.M1 +
127 K
128 );
114 result['M2'] = M2; 129 result['M2'] = M2;
115 } else { 130 } else {
116 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); 131 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
@@ -21,6 +21,8 @@ refer to http://www.clipperz.com.
21 21
22*/ 22*/
23 23
24"use strict";
25
24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) { 26try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!"; 27 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
26} 28}
@@ -197,12 +199,6 @@ Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new C
197 }, 199 },
198 200
199 //------------------------------------------------------------------------- 201 //-------------------------------------------------------------------------
200
201 'pollingFrequency': function() {
202 return 10;
203 },
204
205 //-------------------------------------------------------------------------
206 __syntaxFix__: "syntax fix" 202 __syntaxFix__: "syntax fix"
207}); 203});
208 204
@@ -245,12 +241,12 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
245 var numberOfRandomBitsCollected; 241 var numberOfRandomBitsCollected;
246 242
247 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected(); 243 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
248 collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected); 244 collectedBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
249 this.setRandomBitsCollector(collectetBits); 245 this.setRandomBitsCollector(collectedBits);
250 numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent(); 246 numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
251 247
252 if (numberOfRandomBitsCollected == 8) { 248 if (numberOfRandomBitsCollected == 8) {
253 this.updateGeneratorWithValue(collectetBits); 249 this.updateGeneratorWithValue(collectedBits);
254 numberOfRandomBitsCollected = 0; 250 numberOfRandomBitsCollected = 0;
255 this.setRandomBitsCollector(0); 251 this.setRandomBitsCollector(0);
256 } 252 }
@@ -289,96 +285,54 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
289 }, 285 },
290 286
291 //------------------------------------------------------------------------- 287 //-------------------------------------------------------------------------
292
293 'pollingFrequency': function() {
294 return 10;
295 },
296
297 //-------------------------------------------------------------------------
298 __syntaxFix__: "syntax fix" 288 __syntaxFix__: "syntax fix"
299}); 289});
300 290
301//***************************************************************************** 291//*****************************************************************************
302 292
303Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) { 293Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource = function(args) {
304 args = args || {}; 294 args = args || {};
305 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
306 295
307 this._randomBitsCollector = 0; 296 this._intervalTime = args.intervalTime || 1000;
308 this._numberOfRandomBitsCollected = 0; 297 this._browserCrypto = args.browserCrypto;
309 298
310 MochiKit.Signal.connect(document, 'onkeypress', this, 'collectEntropy'); 299 Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
311 300
301 this.collectEntropy();
312 return this; 302 return this;
313} 303}
314 304
315Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, { 305Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
316 306
317 //------------------------------------------------------------------------- 307 'intervalTime': function() {
318 308 return this._intervalTime;
319 'randomBitsCollector': function() {
320 return this._randomBitsCollector;
321 },
322
323 'setRandomBitsCollector': function(aValue) {
324 this._randomBitsCollector = aValue;
325 }, 309 },
326 310
327 'appendRandomBitToRandomBitsCollector': function(aValue) { 311 'browserCrypto': function () {
328 var collectedBits; 312 return this._browserCrypto;
329 var numberOfRandomBitsCollected;
330
331 numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
332 collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
333 this.setRandomBitsCollector(collectetBits);
334 numberOfRandomBitsCollected ++;
335
336 if (numberOfRandomBitsCollected == 8) {
337 this.updateGeneratorWithValue(collectetBits);
338 numberOfRandomBitsCollected = 0;
339 this.setRandomBitsCollector(0);
340 }
341
342 this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
343 }, 313 },
344 314
345 //------------------------------------------------------------------------- 315 //-------------------------------------------------------------------------
346 316
347 'numberOfRandomBitsCollected': function() { 317 'collectEntropy': function() {
348 return this._numberOfRandomBitsCollected; 318 varbytesToCollect;
349 },
350
351 'setNumberOfRandomBitsCollected': function(aValue) {
352 this._numberOfRandomBitsCollected = aValue;
353 },
354 319
355 //------------------------------------------------------------------------- 320 if (this.boostMode() == true) {
321 bytesToCollect = 64;
322 } else {
323 bytesToCollect = 8;
324 }
356 325
357 'collectEntropy': function(anEvent) { 326 var randomValuesArray = new Uint8Array(bytesToCollect);
358/* 327 this.browserCrypto().getRandomValues(randomValuesArray);
359 var mouseLocation; 328 for (var i = 0; i < randomValuesArray.length; i++) {
360 var randomBit; 329 this.updateGeneratorWithValue(randomValuesArray[i]);
361 330 }
362 mouseLocation = anEvent.mouse().client;
363
364 randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1);
365 this.appendRandomBitToRandomBitsCollector(randomBit);
366*/
367 },
368
369 //-------------------------------------------------------------------------
370 331
371 'numberOfRandomBits': function() { 332 setTimeout(this.collectEntropy, this.intervalTime());
372 return 1;
373 }, 333 },
374 334
375 //------------------------------------------------------------------------- 335 //-------------------------------------------------------------------------
376
377 'pollingFrequency': function() {
378 return 10;
379 },
380
381 //-------------------------------------------------------------------------
382 __syntaxFix__: "syntax fix" 336 __syntaxFix__: "syntax fix"
383}); 337});
384 338
@@ -635,7 +589,7 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
635 }, 589 },
636 590
637 //------------------------------------------------------------------------- 591 //-------------------------------------------------------------------------
638 592/*
639 'dump': function(appendToDoc) { 593 'dump': function(appendToDoc) {
640 var tbl; 594 var tbl;
641 var i,c; 595 var i,c;
@@ -741,7 +695,7 @@ Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
741 695
742 return tbl; 696 return tbl;
743 }, 697 },
744 698*/
745 //----------------------------------------------------------------------------- 699 //-----------------------------------------------------------------------------
746 __syntaxFix__: "syntax fix" 700 __syntaxFix__: "syntax fix"
747}); 701});
@@ -784,7 +738,7 @@ Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, {
784 738
785//############################################################################# 739//#############################################################################
786 740
787_clipperz_crypt_prng_defaultPRNG = null; 741var _clipperz_crypt_prng_defaultPRNG = null;
788 742
789Clipperz.Crypto.PRNG.defaultRandomGenerator = function() { 743Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
790 if (_clipperz_crypt_prng_defaultPRNG == null) { 744 if (_clipperz_crypt_prng_defaultPRNG == null) {
@@ -816,16 +770,26 @@ Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
816 770
817 //............................................................. 771 //.............................................................
818 // 772 //
819 // KeyboardRandomnessSource 773 // CryptoRandomRandomnessSource
820 // 774 //
821 //............................................................. 775 //.............................................................
822 { 776 {
823 varnewRandomnessSource; 777 varnewRandomnessSource;
778 varbrowserCrypto;
824 779
825 newRandomnessSource = new Clipperz.Crypto.PRNG.KeyboardRandomnessSource(); 780 if (window.crypto && window.crypto.getRandomValues) {
826 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource); 781 browserCrypto = window.crypto;
782 } else if (window.msCrypto && window.msCrypto.getRandomValues) {
783 browserCrypto = window.msCrypto;
784 } else {
785 browserCrypto = null;
786 }
787
788 if (browserCrypto != null) {
789 newRandomnessSource = new Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource({'browserCrypto':browserCrypto});
790 _clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
791 }
827 } 792 }
828
829 } 793 }
830 794
831 return _clipperz_crypt_prng_defaultPRNG; 795 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
@@ -44,6 +44,8 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
44 44
45 '_n': null, 45 '_n': null,
46 '_g': null, 46 '_g': null,
47 '_k': null,
48
47 //------------------------------------------------------------------------- 49 //-------------------------------------------------------------------------
48 50
49 'n': function() { 51 'n': function() {
@@ -64,6 +66,15 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
64 return Clipperz.Crypto.SRP._g; 66 return Clipperz.Crypto.SRP._g;
65 }, 67 },
66 68
69 'k': function() {
70 if (Clipperz.Crypto.SRP._k == null) {
71 // Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt(this.stringHash(this.n().asString() + this.g().asString()), 16);
72 Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt("64398bff522814e306a97cb9bfc4364b7eed16a8c17c5208a40a2bad2933c8e", 16);
73 }
74
75 return Clipperz.Crypto.SRP._k;
76 },
77
67 //----------------------------------------------------------------------------- 78 //-----------------------------------------------------------------------------
68 79
69 'exception': { 80 'exception': {
@@ -138,10 +149,9 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
138 149
139 'A': function () { 150 'A': function () {
140 if (this._A == null) { 151 if (this._A == null) {
141 //Warning: this value should be strictly greater than zero: how should we perform this check? 152 //Warning: this value should be strictly greater than zero
142 this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n()); 153 this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n());
143 154 if (this._A.equals(0) || negative(this._A)) {
144 if (this._A.equals(0)) {
145 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0."); 155 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
146 throw Clipperz.Crypto.SRP.exception.InvalidValue; 156 throw Clipperz.Crypto.SRP.exception.InvalidValue;
147 } 157 }
@@ -167,10 +177,9 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
167 }, 177 },
168 178
169 'set_B': function(aValue) { 179 'set_B': function(aValue) {
170 //Warning: this value should be strictly greater than zero: how should we perform this check? 180 //Warning: this value should be strictly greater than zero
171 if (! aValue.equals(0)) { 181 this._B = aValue;
172 this._B = aValue; 182 if (this._B.equals(0) || negative(this._B)) {
173 } else {
174 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0."); 183 Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
175 throw Clipperz.Crypto.SRP.exception.InvalidValue; 184 throw Clipperz.Crypto.SRP.exception.InvalidValue;
176 } 185 }
@@ -190,7 +199,7 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
190 199
191 'u': function () { 200 'u': function () {
192 if (this._u == null) { 201 if (this._u == null) {
193 this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.B().asString()), 16); 202 this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.A().asString() + this.B().asString()), 16);
194 } 203 }
195 204
196 return this._u; 205 return this._u;
@@ -207,9 +216,15 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
207 srp = Clipperz.Crypto.SRP; 216 srp = Clipperz.Crypto.SRP;
208 217
209 this._S =bigint.powerModule( 218 this._S =bigint.powerModule(
210 bigint.subtract(this.B(), bigint.powerModule(srp.g(), this.x(), srp.n())), 219 bigint.subtract(
211 bigint.add(this.a(), bigint.multiply(this.u(), this.x())), 220 this.B(),
212 srp.n() 221 bigint.multiply(
222 Clipperz.Crypto.SRP.k(),
223 bigint.powerModule(srp.g(), this.x(), srp.n())
224 )
225 ),
226 bigint.add(this.a(), bigint.multiply(this.u(), this.x())),
227 srp.n()
213 ) 228 )
214 } 229 }
215 230
@@ -230,7 +245,20 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
230 245
231 'M1': function () { 246 'M1': function () {
232 if (this._M1 == null) { 247 if (this._M1 == null) {
233 this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K()); 248 // this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
249
250 //http://srp.stanford.edu/design.html
251 //User -> Host: M = H(H(N) xor H(g), H(I), s, A, B, K)
252
253 this._M1 = this.stringHash(
254 "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
255 this.stringHash(this.C()) +
256 this.s().asString() +
257 this.A().asString() +
258 this.B().asString() +
259 this.K()
260 );
261//console.log("M1", this._M1);
234 } 262 }
235 263
236 return this._M1; 264 return this._M1;
@@ -241,6 +269,7 @@ Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
241 'M2': function () { 269 'M2': function () {
242 if (this._M2 == null) { 270 if (this._M2 == null) {
243 this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K()); 271 this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
272//console.log("M2", this._M2);
244 } 273 }
245 274
246 return this._M2; 275 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
@@ -36,7 +36,7 @@ Clipperz.PM.Proxy.Offline.DataStore = function(args) {
36 36
37 this._tolls = {}; 37 this._tolls = {};
38 this._currentStaticConnection = null; 38 this._currentStaticConnection = null;
39 39
40 return this; 40 return this;
41} 41}
42 42
@@ -291,14 +291,14 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
291 throw "user already exists"; 291 throw "user already exists";
292 } 292 }
293 } else { 293 } else {
294 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly; 294 throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
295 } 295 }
296 296
297 result = { 297 result = {
298 result: { 298 result: {
299 'lock': this.data()['users'][someParameters['credentials']['C']]['lock'], 299 'lock': this.data()['users'][someParameters['credentials']['C']]['lock'],
300 'result':'done' 300 'result':'done'
301 }, 301 },
302 toll: this.getTollForRequestType('CONNECT') 302 toll: this.getTollForRequestType('CONNECT')
303 } 303 }
304 304
@@ -329,7 +329,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
329 randomBytes = Clipperz.Crypto.Base.generateRandomSeed(); 329 randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
330 aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16); 330 aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
331 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16); 331 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
332 aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n())); 332 aConnection['B'] = (Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
333 333
334 aConnection['A'] = someParameters.parameters.A; 334 aConnection['A'] = someParameters.parameters.A;
335 335
@@ -338,20 +338,35 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
338 338
339 nextTollRequestType = 'CONNECT'; 339 nextTollRequestType = 'CONNECT';
340 } else if (someParameters.message == "credentialCheck") { 340 } else if (someParameters.message == "credentialCheck") {
341 var v, u, S, A, K, M1; 341 var v, u, s, S, A, K, M1;
342 342 var stringHash = function (aValue) {
343 return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
344 };
345
343 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16); 346 v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
344 u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
345 A = new Clipperz.Crypto.BigInt(aConnection['A'], 16); 347 A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
348 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);
349 s = new Clipperz.Crypto.BigInt(aConnection['userData']['s'], 16);
346 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()); 350 S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
347 351
348 K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2); 352 K = stringHash(S.asString(10));
349 353
350 M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2); 354 M1 = stringHash(
355 "597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
356 stringHash(aConnection['C']) +
357 s.asString(10) +
358 A.asString(10) +
359 aConnection['B'].asString(10) +
360 K
361 );
351 if (someParameters.parameters.M1 == M1) { 362 if (someParameters.parameters.M1 == M1) {
352 var M2; 363 var M2;
353 364
354 M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2); 365 M2 = stringHash(
366 A.asString(10) +
367 someParameters.parameters.M1 +
368 K
369 );
355 result['M2'] = M2; 370 result['M2'] = M2;
356 } else { 371 } else {
357 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); 372 throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");