diff options
Diffstat (limited to 'javascript')
| -rw-r--r-- | javascript/srp.js | 626 | ||||
| -rw-r--r-- | javascript/srp_register.js | 90 | 
2 files changed, 358 insertions, 358 deletions
diff --git a/javascript/srp.js b/javascript/srp.js index 9aa47b9..f2ee4d5 100644 --- a/javascript/srp.js +++ b/javascript/srp.js @@ -1,355 +1,355 @@  function SRP()  { -    // Variables that will be used in the SRP protocol -    var Nstr = "115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3"; -    var N = new BigInteger(Nstr, 16); -    var g = new BigInteger("2"); -    var k = new BigInteger("c46d46600d87fef149bd79b81119842f3c20241fda67d06ef412d8f6d9479c58", 16); -    var rng = new SecureRandom(); -    var a = new BigInteger(32, rng); -    var A = g.modPow(a, N); -    while(A.mod(N) == 0) -    { -        a = new BigInteger(32, rng); -        A = g.modPow(a, N); -    } -    var Astr = A.toString(16); -    var S = null; -    var K = null; -    var M = null; -    var M2 = null; -    var url = document.getElementById("srp_url").value; -    var server = document.getElementById("srp_server").value; -    var that = this; -    var authenticated = false; -    var I = document.getElementById("srp_username").value; -    var p = document.getElementById("srp_password").value; -    var xhr = null; +  // Variables that will be used in the SRP protocol +  var Nstr = "115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3"; +  var N = new BigInteger(Nstr, 16); +  var g = new BigInteger("2"); +  var k = new BigInteger("c46d46600d87fef149bd79b81119842f3c20241fda67d06ef412d8f6d9479c58", 16); +  var rng = new SecureRandom(); +  var a = new BigInteger(32, rng); +  var A = g.modPow(a, N); +  while(A.mod(N) == 0) +  { +    a = new BigInteger(32, rng); +    A = g.modPow(a, N); +  } +  var Astr = A.toString(16); +  var S = null; +  var K = null; +  var M = null; +  var M2 = null; +  var url = document.getElementById("srp_url").value; +  var server = document.getElementById("srp_server").value; +  var that = this; +  var authenticated = false; +  var I = document.getElementById("srp_username").value; +  var p = document.getElementById("srp_password").value; +  var xhr = null; -    // *** Accessor methods *** +  // *** Accessor methods *** -    // allows setting the random number A for testing -     -    this.calculateAndSetA = function(_a) -    { -      a = new BigInteger(_a, 16); -      A = g.modPow(a, N); -      Astr = A.toString(16); -      return Astr; -    }; +  // allows setting the random number A for testing -    // Returns the user's identity -    this.getI = function() -    { -        return I; -    }; +  this.calculateAndSetA = function(_a) +  { +    a = new BigInteger(_a, 16); +    A = g.modPow(a, N); +    Astr = A.toString(16); +    return Astr; +  }; -    // Returns the XMLHttpRequest object -    this.getxhr = function() -    { -        return xhr; -    }; +  // Returns the user's identity +  this.getI = function() +  { +    return I; +  }; -    // Returns the base URL -    this.geturl = function() -    { -        return url; -    }; -    // Returns the BigInteger, g -    this.getg = function() -    { -        return g; -    }; +  // Returns the XMLHttpRequest object +  this.getxhr = function() +  { +    return xhr; +  }; -    // Returns the BigInteger, N -    this.getN = function() -    { -        return N; -    }; +  // Returns the base URL +  this.geturl = function() +  { +    return url; +  }; +  // Returns the BigInteger, g +  this.getg = function() +  { +    return g; +  }; -    // Calculates the X value and return it as a BigInteger -    this.calcX = function(s) -    { -        return new BigInteger(SHA256(s + SHA256(I + ":" + p)), 16); -    }; +  // Returns the BigInteger, N +  this.getN = function() +  { +    return N; +  }; -    // Translates the django path to PHP and ASP.NET paths -    this.paths = function(str) -    { -        // For now, str will be the django path -        // This function will translate for other backends. -        if(server == "django") -        { -            return str; -        } -    }; +  // Calculates the X value and return it as a BigInteger +  this.calcX = function(s) +  { +    return new BigInteger(SHA256(s + SHA256(I + ":" + p)), 16); +  }; -    // Get the text content of an XML node -    this.innerxml = function(node) +  // Translates the django path to PHP and ASP.NET paths +  this.paths = function(str) +  { +    // For now, str will be the django path +    // This function will translate for other backends. +    if(server == "django")      { -        return node.firstChild.nodeValue; -    }; +      return str; +    } +  }; -    // Check whether or not a variable is defined -    function isdefined ( variable) -    { -        return (typeof(window[variable]) != "undefined"); -    };     +  // Get the text content of an XML node +  this.innerxml = function(node) +  { +    return node.firstChild.nodeValue; +  }; + +  // Check whether or not a variable is defined +  function isdefined ( variable) +  { +    return (typeof(window[variable]) != "undefined"); +  };     -    // *** Actions *** +  // *** Actions *** -    // Perform ajax requests at the specified url, with the specified parameters -    // Calling back the specified function. -    this.ajaxRequest = function(full_url, params, callback) +  // 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 = callback; +      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      { -        if( window.XMLHttpRequest) -            xhr = new XMLHttpRequest(); -        else if (window.ActiveXObject){ -            try{ -                xhr = new ActiveXObject("Microsoft.XMLHTTP"); -            }catch (e){} +      that.error_message("Ajax failed."); +    }         +  }; + +  // Start the login process by identifying the user +  this.identify = function() +  { +    var handshake_url = url + that.paths("handshake/"); +    var params = "I="+I+"&A="+Astr; +    that.ajaxRequest(handshake_url, params, receive_salts); +  }; + +  // Receive login salts from the server, start calculations +  function receive_salts() +  { +    if(xhr.readyState == 4 && xhr.status == 200) { +      if(xhr.responseXML.getElementsByTagName("r").length > 0) +      { +        var response = xhr.responseXML.getElementsByTagName("r")[0]; +        // If there is no algorithm specified, calculate M given s, B, and P +        if(!response.getAttribute("a")) +        { +          calculations(response.getAttribute("s"), response.getAttribute("B"), p); +          that.ajaxRequest(url+that.paths("authenticate/"), "M="+M, confirm_authentication);          } +        // If there is an algorithm specified, start the login process          else +          upgrade(response.getAttribute("s"), response.getAttribute("B"), response.getAttribute("a"), response.getAttribute("d")); +      } +      else if(xhr.responseXML.getElementsByTagName("error").length > 0) +        that.error_message(xhr.responseXML.getElementsByTagName("error")[0]); +    } +  }; +  // Calculate S, M, and M2 +  // This is the client side of the SRP specification +  function calculations(s, ephemeral, pass) +  {     +    //S -> C: s | B +    var B = new BigInteger(ephemeral, 16);  +    var Bstr = ephemeral; +    // u = H(A,B) +    var u = new BigInteger(SHA256(Astr + Bstr), 16);  +    // x = H(s, H(I:p)) +    var x = new BigInteger(SHA256(s + SHA256(I + ":" + pass)), 16); +    //S = (B - kg^x) ^ (a + ux) +    var kgx = k.multiply(g.modPow(x, N));   +    var aux = a.add(u.multiply(x));  +    S = B.subtract(kgx).modPow(aux, N);  +    // M = H(H(N) xor H(g), H(I), s, A, B, K) +    var Mstr = A.toString(16) + B.toString(16) + S.toString(16);  +    M = SHA256(Mstr); +    M2 = SHA256(A.toString(16) + M + S.toString(16));  +    //M2 = H(A, M, K) +  }; + +  // Receive M2 from the server and verify it +  function confirm_authentication() +  { +    if(xhr.readyState == 4 && xhr.status == 200) { +      if(xhr.responseXML.getElementsByTagName("M").length > 0) +      { +        if(that.innerxml(xhr.responseXML.getElementsByTagName("M")[0]) == M2)          { -            that.error_message("Ajax not supported."); -            return; -        } -        if(xhr){ -            xhr.onreadystatechange = callback; -            xhr.open("POST", full_url, true); -            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); -            xhr.setRequestHeader("Content-length", params.length); -            xhr.send(params); +          authenticated = true; +          success();          }          else -        { -            that.error_message("Ajax failed."); -        }         -    }; +          that.error_message("Server key does not match"); +      } +      else if (xhr.responseXML.getElementsByTagName("error").length > 0) +        that.error_message(that.innerxml(xhr.responseXML.getElementsByTagName("error")[0])); +    } +  }; -    // Start the login process by identifying the user -    this.identify = function() -    { -        var handshake_url = url + that.paths("handshake/"); -        var params = "I="+I+"&A="+Astr; -        that.ajaxRequest(handshake_url, params, receive_salts); -    }; +  // *** Upgrades *** -    // Receive login salts from the server, start calculations -    function receive_salts() -    { -        if(xhr.readyState == 4 && xhr.status == 200) { -		    if(xhr.responseXML.getElementsByTagName("r").length > 0) -		    { -		        var response = xhr.responseXML.getElementsByTagName("r")[0]; -                // If there is no algorithm specified, calculate M given s, B, and P -                if(!response.getAttribute("a")) -                { -		            calculations(response.getAttribute("s"), response.getAttribute("B"), p); -                    that.ajaxRequest(url+that.paths("authenticate/"), "M="+M, confirm_authentication); -                } -                // If there is an algorithm specified, start the login process -                else -                    upgrade(response.getAttribute("s"), response.getAttribute("B"), response.getAttribute("a"), response.getAttribute("d")); -		    } -		    else if(xhr.responseXML.getElementsByTagName("error").length > 0) -                that.error_message(xhr.responseXML.getElementsByTagName("error")[0]); -	    } -    }; -    // Calculate S, M, and M2 -    // This is the client side of the SRP specification -    function calculations(s, ephemeral, pass) -    {     -        //S -> C: s | B -        var B = new BigInteger(ephemeral, 16);  -        var Bstr = ephemeral; -        // u = H(A,B) -        var u = new BigInteger(SHA256(Astr + Bstr), 16);  -        // x = H(s, H(I:p)) -        var x = new BigInteger(SHA256(s + SHA256(I + ":" + pass)), 16); -        //S = (B - kg^x) ^ (a + ux) -        var kgx = k.multiply(g.modPow(x, N));   -        var aux = a.add(u.multiply(x));  -        S = B.subtract(kgx).modPow(aux, N);  -        // M = H(H(N) xor H(g), H(I), s, A, B, K) -        var Mstr = A.toString(16) + B.toString(16) + S.toString(16);  -        M = SHA256(Mstr); -        M2 = SHA256(A.toString(16) + M + S.toString(16));  -        //M2 = H(A, M, K) -    }; +  // Start the process to upgrade the user's account +  function upgrade(s,ephemeral,algo,dsalt) +  { +    // First we need to import the hash functions +    import_hashes(); -    // Receive M2 from the server and verify it -    function confirm_authentication() +    // Once the hash functions are imported, do the calculations using the hashpass as the password +    function do_upgrade()      { -        if(xhr.readyState == 4 && xhr.status == 200) { -            if(xhr.responseXML.getElementsByTagName("M").length > 0) -		    { -		        if(that.innerxml(xhr.responseXML.getElementsByTagName("M")[0]) == M2) -		        { -                    authenticated = true; -		            success(); -	            } -		        else -		            that.error_message("Server key does not match"); -		    } -		    else if (xhr.responseXML.getElementsByTagName("error").length > 0) -		        that.error_message(that.innerxml(xhr.responseXML.getElementsByTagName("error")[0])); -        } +      // If sha1 and md5 are still undefined, sleep again +      if(!isdefined("SHA1") || !isdefined("MD5")) +      { +        window.setTimeout(do_upgrade, 10); +        return; +      } +      if(algo == "sha1") +        hashfun = SHA1; +      else if(algo == "md5") +        hashfun = MD5; +      //alert(hashfun(dsalt+p)); +      calculations(s, ephemeral, hashfun(dsalt+p)); +      that.ajaxRequest(url+that.paths("upgrade/authenticate/"), "M="+M, confirm_upgrade);      }; +    window.setTimeout(do_upgrade,10); +  }; -    // *** Upgrades *** - -    // Start the process to upgrade the user's account -    function upgrade(s,ephemeral,algo,dsalt) -    { -        // First we need to import the hash functions -        import_hashes(); +  // Encrypt plaintext using slowAES +  function encrypt(plaintext) +  { +    var key = cryptoHelpers.toNumbers(that.key()); +    var byteMessage = cryptoHelpers.convertStringToByteArray(plaintext); +    var iv = new Array(16); +    rng.nextBytes(iv); +    var paddedByteMessage = slowAES.getPaddedBlock(byteMessage, 0, byteMessage.length, slowAES.modeOfOperation.CFB); +    var ciphertext = slowAES.encrypt(paddedByteMessage, slowAES.modeOfOperation.CFB, key, key.length, iv).cipher; +    var retstring = cryptoHelpers.base64.encode(iv.concat(ciphertext)); +    while(retstring.indexOf("+",0) > -1) +      retstring = retstring.replace("+", "_"); +    return retstring; +  }; -        // Once the hash functions are imported, do the calculations using the hashpass as the password -        function do_upgrade() +  // Receive the server's M, confirming that 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() +  { +    if(xhr.readyState == 4 && xhr.status == 200) { +      if(xhr.responseXML.getElementsByTagName("M").length > 0) +      { +        if(that.innerxml(xhr.responseXML.getElementsByTagName("M")[0]) == M2)          { -            // If sha1 and md5 are still undefined, sleep again -            if(!isdefined("SHA1") || !isdefined("MD5")) -            { -                window.setTimeout(do_upgrade, 10); -                return; -            } -            if(algo == "sha1") -                hashfun = SHA1; -            else if(algo == "md5") -                hashfun = MD5; -            //alert(hashfun(dsalt+p)); -            calculations(s, ephemeral, hashfun(dsalt+p)); -            that.ajaxRequest(url+that.paths("upgrade/authenticate/"), "M="+M, confirm_upgrade); -        }; -        window.setTimeout(do_upgrade,10); -    }; - -    // Encrypt plaintext using slowAES -    function encrypt(plaintext) -    { -        var key = cryptoHelpers.toNumbers(that.key()); -        var byteMessage = cryptoHelpers.convertStringToByteArray(plaintext); -        var iv = new Array(16); -        rng.nextBytes(iv); -        var paddedByteMessage = slowAES.getPaddedBlock(byteMessage, 0, byteMessage.length, slowAES.modeOfOperation.CFB); -        var ciphertext = slowAES.encrypt(paddedByteMessage, slowAES.modeOfOperation.CFB, key, key.length, iv).cipher; -        var retstring = cryptoHelpers.base64.encode(iv.concat(ciphertext)); -        while(retstring.indexOf("+",0) > -1) -            retstring = retstring.replace("+", "_"); -        return retstring; -    }; - -    // Receive the server's M, confirming that 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() -    { -        if(xhr.readyState == 4 && xhr.status == 200) { -            if(xhr.responseXML.getElementsByTagName("M").length > 0) -		    { -		        if(that.innerxml(xhr.responseXML.getElementsByTagName("M")[0]) == M2) -		        { -                    K = SHA256(S.toString(16)); -                    var auth_url = url + that.paths("upgrade/verifier/"); -                    that.ajaxRequest(auth_url, "p="+encrypt(p)+"&l="+p.length, confirm_verifier); -	            } -		        else -		            that.error_message("Server key does not match"); -		    } -		    else if (xhr.responseXML.getElementsByTagName("error").length > 0) -		    { -		        that.error_message(that.innerxml(xhr.responseXML.getElementsByTagName("error")[0])); -		    } +          K = SHA256(S.toString(16)); +          var auth_url = url + that.paths("upgrade/verifier/"); +          that.ajaxRequest(auth_url, "p="+encrypt(p)+"&l="+p.length, confirm_verifier);          } -    }; - -    // After sending the password, check that the response is OK, then reidentify -    function confirm_verifier() -    { -        if(xhr.readyState == 4 && xhr.status == 200) { -            K = null; -            if(xhr.responseXML.getElementsByTagName("ok").length > 0) -                that.identify(); -            else -                that.error_message("Verifier could not be confirmed"); -        } -    }; - -    // This loads javascript libraries. Fname is the path to the library to be imported -    function import_file(fname) -    { -        var scriptElt = document.createElement('script'); -        scriptElt.type = 'text/javascript'; -        scriptElt.src = fname; -        document.getElementsByTagName('head')[0].appendChild(scriptElt); -    }; -    // 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 -        if(isdefined("SHA1") && isdefined("MD5")) return; -        // Get the directory that this javascript file was loaded from -        var arr=that.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") -            import_file(path+"/crypto.min.js"); -        // Otherwise, this file is presumably srp.js, and we will load individual hash files          else -        { -            import_file(path+"/MD5.js"); -            import_file(path+"/SHA1.js"); -            import_file(path+"/cryptoHelpers.js"); -            import_file(path+"/aes.js"); -        }         +          that.error_message("Server key does not match"); +      } +      else if (xhr.responseXML.getElementsByTagName("error").length > 0) +      { +        that.error_message(that.innerxml(xhr.responseXML.getElementsByTagName("error")[0])); +      }      } +  }; -    function success() +  // After sending the password, check that the response is OK, then reidentify +  function confirm_verifier() +  { +    if(xhr.readyState == 4 && xhr.status == 200) { +      K = null; +      if(xhr.responseXML.getElementsByTagName("ok").length > 0) +        that.identify(); +      else +        that.error_message("Verifier could not be confirmed"); +    } +  }; + +  // This loads javascript libraries. Fname is the path to the library to be imported +  function import_file(fname) +  { +    var scriptElt = document.createElement('script'); +    scriptElt.type = 'text/javascript'; +    scriptElt.src = fname; +    document.getElementsByTagName('head')[0].appendChild(scriptElt); +  }; +  // 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 +    if(isdefined("SHA1") && isdefined("MD5")) return; +    // Get the directory that this javascript file was loaded from +    var arr=that.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") +      import_file(path+"/crypto.min.js"); +    // Otherwise, this file is presumably srp.js, and we will load individual hash files +    else      { -        var forward_url = document.getElementById("srp_forward").value; -        if(forward_url.charAt(0) != "#") -            window.location = forward_url; -        else -        { -            window.location = forward_url; -            that.success(); -        } -    }; -    this.success = function() +      import_file(path+"/MD5.js"); +      import_file(path+"/SHA1.js"); +      import_file(path+"/cryptoHelpers.js"); +      import_file(path+"/aes.js"); +    }         +  } + +  function success() +  { +    var forward_url = document.getElementById("srp_forward").value; +    if(forward_url.charAt(0) != "#") +      window.location = forward_url; +    else      { -        alert("Login successful."); -    }; -    // If someone wants to use the session key for encrypting traffic, they can -    // access the key with this function. -    this.key = function() +      window.location = forward_url; +      that.success(); +    } +  }; +  this.success = function() +  { +    alert("Login successful."); +  }; +  // If someone wants to use the session key for encrypting traffic, they can +  // access the key with this function. +  this.key = function() +  { +    if(K == null) +      if(authenticated)      { -        if(K == null) -            if(authenticated) -            { -                K = SHA256(S.toString(16)); -                return K; -            } -            else -                that.error_message("User has not been authenticated."); -        else -            return K; -    }; +      K = SHA256(S.toString(16)); +      return K; +    } +    else +      that.error_message("User has not been authenticated."); +    else +      return K; +  }; -    // This function is called when authentication is successful. -    // Developers can set this to other functions in specific implementations -    // and change the functionality. -    /*this.success = function() -    { -        alert("Authentication successful."); -    };*/ +  // This function is called when authentication is successful. +  // Developers can set this to other functions in specific implementations +  // and change the functionality. +  /*this.success = function() +   { +     alert("Authentication successful."); +     };*/      // 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); +      alert(t);      }; -}; -// 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. -SRP.prototype.srpPath = document.getElementsByTagName('script')[document.getElementsByTagName('script').length-1].getAttribute("src"); +  }; +  // 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. +  SRP.prototype.srpPath = document.getElementsByTagName('script')[document.getElementsByTagName('script').length-1].getAttribute("src"); diff --git a/javascript/srp_register.js b/javascript/srp_register.js index 31b8ab8..670e59d 100644 --- a/javascript/srp_register.js +++ b/javascript/srp_register.js @@ -1,52 +1,52 @@  function SRP_REGISTER()  { -    var that; +  var that; -    // 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); -    }; +  // 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); +  }; -    // Receive the salt for registration -    SRP.prototype.register_receive_salt = function() -    { -        var xhr = that.getxhr(); -        if(xhr.readyState == 4 && xhr.status == 200) { -            if(xhr.responseXML.getElementsByTagName("salt").length > 0) -            { -                var s = that.innerxml(xhr.responseXML.getElementsByTagName("salt")[0]); -                var x = that.calcX(s); -                var v = that.getg().modPow(x, that.getN()); -                that.register_send_verifier(v.toString(16)); -            } -            else if(xhr.responseXML.getElementsByTagName("error").length > 0) -            { -                that.error_message(that.innerxml(xhr.responseXML.getElementsByTagName("error")[0])); -            } -        } -    }; -        // 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.register_user); -    }; +  // Receive the salt for registration +  SRP.prototype.register_receive_salt = function() +  { +    var xhr = that.getxhr(); +    if(xhr.readyState == 4 && xhr.status == 200) { +      if(xhr.responseXML.getElementsByTagName("salt").length > 0) +      { +        var s = that.innerxml(xhr.responseXML.getElementsByTagName("salt")[0]); +        var x = that.calcX(s); +        var v = that.getg().modPow(x, that.getN()); +        that.register_send_verifier(v.toString(16)); +      } +      else if(xhr.responseXML.getElementsByTagName("error").length > 0) +      { +        that.error_message(that.innerxml(xhr.responseXML.getElementsByTagName("error")[0])); +      } +    } +  }; +  // 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.register_user); +  }; -    // The user has been registered successfully, now login -    SRP.prototype.register_user = function() -    { -        var xhr = that.getxhr(); -        if(xhr.readyState == 4 && xhr.status == 200) { -	        if(xhr.responseXML.getElementsByTagName("ok").length > 0) -	        { -	            that.identify(); -            } -        } -    };   +  // The user has been registered successfully, now login +  SRP.prototype.register_user = function() +  { +    var xhr = that.getxhr(); +    if(xhr.readyState == 4 && xhr.status == 200) { +      if(xhr.responseXML.getElementsByTagName("ok").length > 0) +      { +        that.identify(); +      } +    } +  };    };  SRP_REGISTER();  | 
