summaryrefslogtreecommitdiff
path: root/lib/srp.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/srp.js')
-rw-r--r--lib/srp.js173
1 files changed, 40 insertions, 133 deletions
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.