summaryrefslogtreecommitdiff
path: root/frontend/beta/js/Clipperz/Crypto/SRP.js
Unidiff
Diffstat (limited to 'frontend/beta/js/Clipperz/Crypto/SRP.js') (more/less context) (show whitespace changes)
-rw-r--r--frontend/beta/js/Clipperz/Crypto/SRP.js57
1 files changed, 38 insertions, 19 deletions
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
@@ -1,301 +1,320 @@
1/* 1/*
2 2
3Copyright 2008-2013 Clipperz Srl 3Copyright 2008-2013 Clipperz Srl
4 4
5This file is part of Clipperz, the online password manager. 5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please 6For further information about its features and functionalities please
7refer to http://www.clipperz.com. 7refer to http://www.clipperz.com.
8 8
9* Clipperz is free software: you can redistribute it and/or modify it 9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published 10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or 11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version. 12 (at your option) any later version.
13 13
14* Clipperz is distributed in the hope that it will be useful, but 14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of 15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details. 17 See the GNU Affero General Public License for more details.
18 18
19* You should have received a copy of the GNU Affero General Public 19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/. 20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21 21
22*/ 22*/
23 23
24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) { 24try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!"; 25 throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
26} 26}
27 27
28try { if (typeof(Clipperz.Crypto.BigInt) == 'undefined') { throw ""; }} catch (e) { 28try { if (typeof(Clipperz.Crypto.BigInt) == 'undefined') { throw ""; }} catch (e) {
29 throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.BigInt!"; 29 throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.BigInt!";
30} 30}
31 31
32try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) { 32try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
33 throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.PRNG!"; 33 throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.PRNG!";
34} 34}
35 35
36if (typeof(Clipperz.Crypto.SRP) == 'undefined') { Clipperz.Crypto.SRP = {}; } 36if (typeof(Clipperz.Crypto.SRP) == 'undefined') { Clipperz.Crypto.SRP = {}; }
37 37
38Clipperz.Crypto.SRP.VERSION = "0.1"; 38Clipperz.Crypto.SRP.VERSION = "0.1";
39Clipperz.Crypto.SRP.NAME = "Clipperz.Crypto.SRP"; 39Clipperz.Crypto.SRP.NAME = "Clipperz.Crypto.SRP";
40 40
41//############################################################################# 41//#############################################################################
42 42
43MochiKit.Base.update(Clipperz.Crypto.SRP, { 43MochiKit.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() {
50 if (Clipperz.Crypto.SRP._n == null) { 52 if (Clipperz.Crypto.SRP._n == null) {
51 Clipperz.Crypto.SRP._n = new Clipperz.Crypto.BigInt("115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3", 16); 53 Clipperz.Crypto.SRP._n = new Clipperz.Crypto.BigInt("115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3", 16);
52 } 54 }
53 55
54 return Clipperz.Crypto.SRP._n; 56 return Clipperz.Crypto.SRP._n;
55 }, 57 },
56 58
57 //------------------------------------------------------------------------- 59 //-------------------------------------------------------------------------
58 60
59 'g': function() { 61 'g': function() {
60 if (Clipperz.Crypto.SRP._g == null) { 62 if (Clipperz.Crypto.SRP._g == null) {
61 Clipperz.Crypto.SRP._g = new Clipperz.Crypto.BigInt(2); //eventually 5 (as suggested on the Diffi-Helmann documentation) 63 Clipperz.Crypto.SRP._g = new Clipperz.Crypto.BigInt(2); //eventually 5 (as suggested on the Diffi-Helmann documentation)
62 } 64 }
63 65
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': {
70 'InvalidValue': new MochiKit.Base.NamedError("Clipperz.Crypto.SRP.exception.InvalidValue") 81 'InvalidValue': new MochiKit.Base.NamedError("Clipperz.Crypto.SRP.exception.InvalidValue")
71 }, 82 },
72 83
73 //------------------------------------------------------------------------- 84 //-------------------------------------------------------------------------
74 __syntaxFix__: "syntax fix" 85 __syntaxFix__: "syntax fix"
75 86
76}); 87});
77 88
78//############################################################################# 89//#############################################################################
79// 90//
80 // S R P C o n n e c t i o n version 1.0 91 // S R P C o n n e c t i o n version 1.0
81// 92//
82//============================================================================= 93//=============================================================================
83Clipperz.Crypto.SRP.Connection = function (args) { 94Clipperz.Crypto.SRP.Connection = function (args) {
84 args = args || {}; 95 args = args || {};
85 96
86 this._C = args.C; 97 this._C = args.C;
87 this._P = args.P; 98 this._P = args.P;
88 this.hash = args.hash; 99 this.hash = args.hash;
89 100
90 this._a = null; 101 this._a = null;
91 this._A = null; 102 this._A = null;
92 103
93 this._s = null; 104 this._s = null;
94 this._B = null; 105 this._B = null;
95 106
96 this._x = null; 107 this._x = null;
97 108
98 this._u = null; 109 this._u = null;
99 this._K = null; 110 this._K = null;
100 this._M1 = null; 111 this._M1 = null;
101 this._M2 = null; 112 this._M2 = null;
102 113
103 this._sessionKey = null; 114 this._sessionKey = null;
104 115
105 return this; 116 return this;
106} 117}
107 118
108Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, { 119Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
109 120
110 'toString': function () { 121 'toString': function () {
111 return "Clipperz.Crypto.SRP.Connection (username: " + this.username() + "). Status: " + this.statusDescription(); 122 return "Clipperz.Crypto.SRP.Connection (username: " + this.username() + "). Status: " + this.statusDescription();
112 }, 123 },
113 124
114 //------------------------------------------------------------------------- 125 //-------------------------------------------------------------------------
115 126
116 'C': function () { 127 'C': function () {
117 return this._C; 128 return this._C;
118 }, 129 },
119 130
120 //------------------------------------------------------------------------- 131 //-------------------------------------------------------------------------
121 132
122 'P': function () { 133 'P': function () {
123 return this._P; 134 return this._P;
124 }, 135 },
125 136
126 //------------------------------------------------------------------------- 137 //-------------------------------------------------------------------------
127 138
128 'a': function () { 139 'a': function () {
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;
136 }, 146 },
137 147
138 //------------------------------------------------------------------------- 148 //-------------------------------------------------------------------------
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)) {
146MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0."); 155MochiKit.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;
153 }, 161 },
154 162
155 //------------------------------------------------------------------------- 163 //-------------------------------------------------------------------------
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) {
163 this._s = aValue; 170 this._s = aValue;
164 }, 171 },
165 172
166 //------------------------------------------------------------------------- 173 //-------------------------------------------------------------------------
167 174
168 'B': function () { 175 'B': function () {
169 return this._B; 176 return this._B;
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)) {
175 this._B = aValue; 181 this._B = aValue;
176//MochiKit.Logging.logDebug("SRP B: " + this._B); 182 if (this._B.equals(0) || negative(this._B)) {
177 } else {
178MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0."); 183MochiKit.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 },
182 187
183 //------------------------------------------------------------------------- 188 //-------------------------------------------------------------------------
184 189
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;
192 }, 196 },
193 197
194 //------------------------------------------------------------------------- 198 //-------------------------------------------------------------------------
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;
203 }, 206 },
204 207
205 //------------------------------------------------------------------------- 208 //-------------------------------------------------------------------------
206 209
207 'S': function () { 210 'S': function () {
208 if (this._S == null) { 211 if (this._S == null) {
209 var bigint; 212 var bigint;
210 varsrp; 213 varsrp;
211 214
212 bigint = Clipperz.Crypto.BigInt; 215 bigint = Clipperz.Crypto.BigInt;
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(
220 this.B(),
221 bigint.multiply(
222 Clipperz.Crypto.SRP.k(),
223 bigint.powerModule(srp.g(), this.x(), srp.n())
224 )
225 ),
217 bigint.add(this.a(), bigint.multiply(this.u(), this.x())), 226 bigint.add(this.a(), bigint.multiply(this.u(), this.x())),
218 srp.n() 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;
224 }, 232 },
225 233
226 //------------------------------------------------------------------------- 234 //-------------------------------------------------------------------------
227 235
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;
235 }, 242 },
236 243
237 //------------------------------------------------------------------------- 244 //-------------------------------------------------------------------------
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;
246 }, 265 },
247 266
248 //------------------------------------------------------------------------- 267 //-------------------------------------------------------------------------
249 268
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;
257 }, 276 },
258 277
259 //========================================================================= 278 //=========================================================================
260 279
261 'serverSideCredentialsWithSalt': function(aSalt) { 280 'serverSideCredentialsWithSalt': function(aSalt) {
262 var result; 281 var result;
263 var s, x, v; 282 var s, x, v;
264 283
265 s = aSalt; 284 s = aSalt;
266 x = this.stringHash(s + this.P()); 285 x = this.stringHash(s + this.P());
267 v = Clipperz.Crypto.SRP.g().powerModule(new Clipperz.Crypto.BigInt(x, 16), Clipperz.Crypto.SRP.n()); 286 v = Clipperz.Crypto.SRP.g().powerModule(new Clipperz.Crypto.BigInt(x, 16), Clipperz.Crypto.SRP.n());
268 287
269 result = {}; 288 result = {};
270 result['C'] = this.C(); 289 result['C'] = this.C();
271 result['s'] = s; 290 result['s'] = s;
272 result['v'] = v.asString(16); 291 result['v'] = v.asString(16);
273 292
274 return result; 293 return result;
275 }, 294 },
276 295
277 'serverSideCredentials': function() { 296 'serverSideCredentials': function() {
278 var result; 297 var result;
279 var s; 298 var s;
280 299
281 s = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2); 300 s = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
282 301
283 result = this.serverSideCredentialsWithSalt(s); 302 result = this.serverSideCredentialsWithSalt(s);
284 303
285 return result; 304 return result;
286 }, 305 },
287 306
288 //========================================================================= 307 //=========================================================================
289/* 308/*
290 'computeServerSide_S': function(b) { 309 'computeServerSide_S': function(b) {
291 var result; 310 var result;
292 var v; 311 var v;
293 var bigint; 312 var bigint;
294 varsrp; 313 varsrp;
295 314
296 bigint = Clipperz.Crypto.BigInt; 315 bigint = Clipperz.Crypto.BigInt;
297 srp = Clipperz.Crypto.SRP; 316 srp = Clipperz.Crypto.SRP;
298 317
299 v = new Clipperz.Crypto.BigInt(srpConnection.serverSideCredentialsWithSalt(this.s().asString(16, 64)).v, 16); 318 v = new Clipperz.Crypto.BigInt(srpConnection.serverSideCredentialsWithSalt(this.s().asString(16, 64)).v, 16);
300 // _S = (this.A().multiply(this.v().modPow(this.u(), this.n()))).modPow(this.b(), this.n()); 319 // _S = (this.A().multiply(this.v().modPow(this.u(), this.n()))).modPow(this.b(), this.n());
301 result = bigint.powerModule( 320 result = bigint.powerModule(