summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAzul <azul@leap.se>2012-08-03 20:37:11 +0200
committerAzul <azul@leap.se>2012-08-03 20:37:11 +0200
commit94d1938e2e5d0ee5e8e7b9a8ed44a067677e0133 (patch)
treeffdae863dda3b197d6e165bffa5a782e9e1ab338 /lib
parent0da31f678580649415cb0487c830f21d7e163253 (diff)
moved all xhr related stuff to a seperate class
We can replace this if we want to use jquery ajax or similar. Also this has all the urls so it's super easy to overwrite
Diffstat (limited to 'lib')
-rw-r--r--lib/plainXHR.js124
-rw-r--r--lib/srp.js173
-rw-r--r--lib/srp_register.js22
3 files changed, 170 insertions, 149 deletions
diff --git a/lib/plainXHR.js b/lib/plainXHR.js
new file mode 100644
index 0000000..44ee5df
--- /dev/null
+++ b/lib/plainXHR.js
@@ -0,0 +1,124 @@
+plainXHR = function() {
+
+ function getUrl()
+ {
+ return "";
+ }
+
+ function paths(path)
+ {
+ return path
+ }
+
+ // Perform ajax requests at the specified path, with the specified parameters
+ // Calling back the specified function.
+ function ajaxRequest(relative_path, params, callback)
+ {
+ var full_url = this.geturl() + this.paths(relative_path);
+ if( window.XMLHttpRequest)
+ xhr = new XMLHttpRequest();
+ else if (window.ActiveXObject){
+ try{
+ xhr = new ActiveXObject("Microsoft.XMLHTTP");
+ }catch (e){}
+ }
+ else
+ {
+ session.error_message("Ajax not supported.");
+ return;
+ }
+ if(xhr){
+ xhr.onreadystatechange = function() {
+ if(xhr.readyState == 4 && xhr.status == 200) {
+ callback(parseResponse());
+ }
+ };
+ xhr.open("POST", full_url, true);
+ xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ xhr.setRequestHeader("Content-length", params.length);
+ xhr.send(params);
+ }
+ else
+ {
+ session.error_message("Ajax failed.");
+ }
+ };
+
+ function parseResponse() {
+ if (responseIsXML()) {
+ return parseXML(xhr.responseXML);
+ } else if (responseIsJSON()) {
+ return JSON.parse(xhr.responseText);
+ }
+ };
+
+ function responseIsXML() {
+ return (xhr.responseType == 'document') ||
+ (xhr.getResponseHeader("Content-Type").indexOf('application/xml') >= 0)
+ }
+
+ function responseIsJSON() {
+ return (xhr.responseType == 'json') ||
+ (xhr.getResponseHeader("Content-Type").indexOf('application/json') >= 0)
+ }
+
+ function parseXML(xml) {
+ if (xml.getElementsByTagName("r").length > 0) {
+ return parseAttributesOfElement(xml.getElementsByTagName("r")[0]);
+ } else {
+ return parseNodes(xml.childNodes);
+ }
+ };
+
+ function parseAttributesOfElement(elem) {
+ var response = {};
+ for (var i = 0; i < elem.attributes.length; i++) {
+ var attrib = elem.attributes[i];
+ if (attrib.specified) {
+ response[attrib.name] = attrib.value;
+ }
+ }
+ return response;
+ };
+
+ function parseNodes(nodes) {
+ var response = {};
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes[i];
+ response[node.tagName] = node.textContent || true;
+ }
+ return response;
+ };
+
+ function register(I, callback)
+ {
+ this.ajaxRequest("register/salt/", "I="+I, callback);
+ }
+
+ function sendVerifier(v, callback) {
+ this.ajaxRequest("register/user/", "v="+v, callback);
+ }
+
+ function handshake(I, Astr, callback) {
+ this.ajaxRequest("handshake/", "I="+I+"&A="+Astr, callback);
+ }
+
+ function authenticate(M, callback) {
+ this.ajaxRequest("authenticate/", "M="+M, callback);
+ }
+
+ function upgrade(M, callback) {
+ this.ajaxRequest("upgrade/authenticate/", "M="+M, callback);
+ }
+
+ return {
+ geturl: getUrl,
+ paths: paths,
+ ajaxRequest: ajaxRequest,
+ register: register,
+ register_send_verifier: sendVerifier,
+ handshake: handshake,
+ authenticate: authenticate,
+ upgrade: upgrade
+ }
+}
diff --git a/lib/srp.js b/lib/srp.js
index 0f6889b..9ef75f5 100644
--- a/lib/srp.js
+++ b/lib/srp.js
@@ -1,6 +1,6 @@
function SRP()
{
- // Variables that will be used in the SRP protocol
+ // Variables session will be used in the SRP protocol
var Nstr = "115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3";
var N = new BigInteger(Nstr, 16);
var g = new BigInteger("2");
@@ -18,11 +18,11 @@ function SRP()
var K = null;
var M = null;
var M2 = null;
- var that = this;
+ var session = this;
var authenticated = false;
var I = document.getElementById("srp_username").value;
var p = document.getElementById("srp_password").value;
- var xhr = null;
+ var remote = plainXHR();
// *** Accessor methods ***
@@ -47,18 +47,6 @@ function SRP()
return new BigInteger(64, rng).toString(16);
}
- // Returns the XMLHttpRequest object
- this.getxhr = function()
- {
- return xhr;
- };
-
- // Returns the base URL - overwrite to use a different one
- this.geturl = function()
- {
- return "";
- };
-
// Returns the BigInteger, g
this.getg = function()
{
@@ -82,129 +70,43 @@ function SRP()
return this.getg().modPow(this.calcX(salt), this.getN());
}
- // Overwrite this if you want to change the paths
- this.paths = function(str)
- {
- return str;
- };
-
// Check whether or not a variable is defined
function isdefined ( variable)
{
return (typeof(window[variable]) != "undefined");
};
-
+
// *** Actions ***
- // Perform ajax requests at the specified url, with the specified parameters
- // Calling back the specified function.
- this.ajaxRequest = function(full_url, params, callback)
- {
- if( window.XMLHttpRequest)
- xhr = new XMLHttpRequest();
- else if (window.ActiveXObject){
- try{
- xhr = new ActiveXObject("Microsoft.XMLHTTP");
- }catch (e){}
- }
- else
- {
- that.error_message("Ajax not supported.");
- return;
- }
- if(xhr){
- xhr.onreadystatechange = function() {
- if(xhr.readyState == 4 && xhr.status == 200) {
- callback(parseResponse());
- }
- };
- xhr.open("POST", full_url, true);
- xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
- xhr.setRequestHeader("Content-length", params.length);
- xhr.send(params);
- }
- else
- {
- that.error_message("Ajax failed.");
- }
- };
-
- function parseResponse() {
- if (responseIsXML()) {
- return parseXML(xhr.responseXML);
- } else if (responseIsJSON()) {
- return JSON.parse(xhr.responseText);
- }
- };
-
- function responseIsXML() {
- return (xhr.responseType == 'document') ||
- (xhr.getResponseHeader("Content-Type").indexOf('application/xml') >= 0)
- }
-
- function responseIsJSON() {
- return (xhr.responseType == 'json') ||
- (xhr.getResponseHeader("Content-Type").indexOf('application/json') >= 0)
- }
-
- function parseXML(xml) {
- if (xml.getElementsByTagName("r").length > 0) {
- return parseAttributesOfElement(xml.getElementsByTagName("r")[0]);
- } else {
- return parseNodes(xml.childNodes);
- }
- };
-
- function parseAttributesOfElement(elem) {
- var response = {};
- for (var i = 0; i < elem.attributes.length; i++) {
- var attrib = elem.attributes[i];
- if (attrib.specified) {
- response[attrib.name] = attrib.value;
- }
- }
- return response;
- };
-
- function parseNodes(nodes) {
- var response = {};
- for (var i = 0; i < nodes.length; i++) {
- var node = nodes[i];
- response[node.tagName] = node.textContent || true;
- }
- return response;
- };
-
// Start the login process by identifying the user
this.identify = function()
{
- var handshake_url = that.geturl() + that.paths("handshake/");
- var params = "I="+I+"&A="+Astr;
- that.ajaxRequest(handshake_url, params, receive_salts);
+ this.remote.handshake(I, Astr, receive_salts);
};
// Receive login salts from the server, start calculations
function receive_salts(response)
{
if(response.error) {
- that.error_message(response.error);
- }
- // B = 0 will make the algorithm always succeed - refuse such a server
- // answer
+ session.error_message(response.error);
+ }
+ // B = 0 will make the algorithm always succeed - refuse such a server
+ // answer
else if(response.B == 0) {
- that.error_message("Server send random number 0 - this is not allowed");
+ session.error_message("Server send random number 0 - this is not allowed");
}
// If there is no algorithm specified, calculate M given s, B, and P
else if(!response.a)
{
calculations(response.s, response.B, p);
- that.ajaxRequest(that.geturl()+that.paths("authenticate/"), "M="+M, confirm_authentication);
+ remote.authenticate(M, confirm_authentication)
}
// If there is an algorithm specified, start the login process
else {
upgrade(response.s, response.B, response.a, response.d);
}
};
+
// Calculate S, M, and M2
// This is the client side of the SRP specification
function calculations(s, ephemeral, pass)
@@ -235,13 +137,13 @@ function SRP()
if(response.M == M2)
{
authenticated = true;
- that.success();
+ session.success();
}
else
- that.error_message("Server key does not match");
+ session.error_message("Server key does not match");
}
else if (response.error)
- that.error_message(response.error);
+ session.error_message(response.error);
};
// *** Upgrades ***
@@ -267,7 +169,7 @@ function SRP()
hashfun = MD5;
//alert(hashfun(dsalt+p));
calculations(s, ephemeral, hashfun(dsalt+p));
- that.ajaxRequest(that.geturl()+that.paths("upgrade/authenticate/"), "M="+M, confirm_upgrade);
+ remote.upgrade(M, session.confirm_upgrade)
};
window.setTimeout(do_upgrade,10);
};
@@ -275,7 +177,7 @@ function SRP()
// Encrypt plaintext using slowAES
function encrypt(plaintext)
{
- var key = cryptoHelpers.toNumbers(that.key());
+ var key = cryptoHelpers.toNumbers(session.key());
var byteMessage = cryptoHelpers.convertStringToByteArray(plaintext);
var iv = new Array(16);
rng.nextBytes(iv);
@@ -287,7 +189,7 @@ function SRP()
return retstring;
};
- // Receive the server's M, confirming that the server has HASH(p)
+ // Receive the server's M, confirming session the server has HASH(p)
// Next, send P in plaintext (this is the **only** time it should ever be sent plain text)
function confirm_upgrade(response)
{
@@ -296,26 +198,26 @@ function SRP()
if(response.M == M2)
{
K = SHA256(S.toString(16));
- var auth_url = that.geturl() + that.paths("upgrade/verifier/");
- that.ajaxRequest(auth_url, "p="+encrypt(p)+"&l="+p.length, confirm_verifier);
+ var auth_url = session.geturl() + session.paths("upgrade/verifier/");
+ session.ajaxRequest(auth_url, "p="+encrypt(p)+"&l="+p.length, confirm_verifier);
}
else
- that.error_message("Server key does not match");
+ session.error_message("Server key does not match");
}
else if (response.error)
{
- that.error_message(response.error);
+ session.error_message(response.error);
}
};
- // After sending the password, check that the response is OK, then reidentify
+ // After sending the password, check session the response is OK, then reidentify
function confirm_verifier(response)
{
K = null;
if(response.ok)
- that.identify();
+ session.identify();
else
- that.error_message("Verifier could not be confirmed");
+ session.error_message("Verifier could not be confirmed");
};
// This loads javascript libraries. Fname is the path to the library to be imported
@@ -329,10 +231,10 @@ function SRP()
// If we need SHA1 or MD5, we need to load the javascript files
function import_hashes()
{
- // First check that the functions aren't already loaded
+ // First check session the functions aren't already loaded
if(isdefined("SHA1") && isdefined("MD5")) return;
- // Get the directory that this javascript file was loaded from
- var arr=that.srpPath.split("/");
+ // Get the directory session this javascript file was loaded from
+ var arr=session.srpPath.split("/");
var path = arr.slice(0, arr.length-1).join("/");
// If this file is called srp.min.js, we will load the packed hash file
if(arr[arr.length-1] == "srp.min.js")
@@ -372,18 +274,23 @@ function SRP()
return K;
}
else
- that.error_message("User has not been authenticated.");
+ session.error_message("User has not been authenticated.");
else
return K;
};
- // If an error occurs, raise it as an alert.
- // Developers can set this to an alternative function to handle erros differently.
- this.error_message = function(t)
- {
- alert(t);
- };
+ // If an error occurs, raise it as an alert.
+ // Developers can set this to an alternative function to handle erros differently.
+ this.error_message = function(t)
+ {
+ alert(t);
};
+
+
+ // exposing the remote handler so it can be modified
+ this.remote = remote;
+
+};
// This line is run while the document is loading
// It gets a list of all <script> tags and finds the last instance.
// The path to this script is the "src" attribute of that tag.
diff --git a/lib/srp_register.js b/lib/srp_register.js
index 1666476..8365fed 100644
--- a/lib/srp_register.js
+++ b/lib/srp_register.js
@@ -5,10 +5,8 @@ function SRP_REGISTER()
// Initiate the registration process
SRP.prototype.register = function()
{
- that = this;
- var handshake_url = this.geturl() + this.paths("register/salt/");
- var params = "I="+this.getI();
- this.ajaxRequest(handshake_url, params, this.register_receive_salt);
+ session = this;
+ this.remote.register(this.getI(), session.register_receive_salt);
};
// Receive the salt for registration
@@ -17,28 +15,20 @@ function SRP_REGISTER()
if(response.salt)
{
var s = response.salt;
- var v = that.calcV(s);
- that.register_send_verifier(v.toString(16));
+ var v = session.calcV(s);
+ session.remote.register_send_verifier(v.toString(16), session.registered_user);
}
else if(response.error)
{
- that.error_message(response.error);
+ session.error_message(response.error);
}
};
- // Send the verifier to the server
- SRP.prototype.register_send_verifier = function(v)
- {
- var params = "v="+v;
- var auth_url = that.geturl() + that.paths("register/user/");
- that.ajaxRequest(auth_url, params, that.registered_user);
- };
-
// The user has been registered successfully, now login
SRP.prototype.registered_user = function(response)
{
if(response.ok)
{
- that.identify();
+ session.identify();
}
};
};