diff options
Diffstat (limited to 'javascript/srp.js')
| -rw-r--r-- | javascript/srp.js | 262 | 
1 files changed, 262 insertions, 0 deletions
| diff --git a/javascript/srp.js b/javascript/srp.js new file mode 100644 index 0000000..9c84aa9 --- /dev/null +++ b/javascript/srp.js @@ -0,0 +1,262 @@ +var srp_N = null; +var srp_Nstr = "115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3"; +var srp_g = null; +var srp_k = null; +var srp_a = null; +var srp_A = null; +var srp_Astr = null; +var srp_b = null; +var srp_B = null; +var srp_Bstr = null; +var srp_I = null; +var srp_u = null; +var srp_p = null; +var srp_x = null; +var srp_S = null; +var srp_K = null; +var srp_M = null; +var srp_M2 = null; +var xhr; +var srp_url = window.location.protocol+"//"+window.location.host+"/srp/"; +function srp_register() +{ +    srp_N = str2bigInt(srp_Nstr, 16, 0); +    srp_g = str2bigInt("2", 10, 0); +    srp_k = str2bigInt("c46d46600d87fef149bd79b81119842f3c20241fda67d06ef412d8f6d9479c58", 16, 0); +    srp_I = document.getElementById("srp_username").value; +    srp_register_salt(srp_I); +    return false; +}; +function srp_register_salt(I) +{ +    if( window.XMLHttpRequest) +        xhr = new XMLHttpRequest(); +    else if (window.ActiveXObject){ +        try{ +            xhr = new ActiveXObject("Microsoft.XMLHTTP"); +        }catch (e){} +    } +    else +    { +        srp_error_message("Ajax not supported."); +        return; +    } +    if(xhr){ +        var srp_handshake_url = srp_url + "register/salt/"; +        var srp_params = "I="+I;         +        xhr.onreadystatechange = srp_register_receive_salt; +        xhr.open("POST", srp_handshake_url, true); +        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); +        xhr.setRequestHeader("Content-length", srp_params.length); +        xhr.setRequestHeader("Connection", "close"); +         +        xhr.send(srp_params); +    } +    else +    { +        srp_error_message("Ajax failed."); +    } +}; +function srp_register_receive_salt() +{ +    if(xhr.readyState == 4 && xhr.status == 200) { +		if(xhr.responseXML.getElementsByTagName("salt").length > 0) +		{ +		    s = innerxml(xhr.responseXML.getElementsByTagName("salt")[0]); +		    srp_x = srp_calculate_x(s); +		    v = powMod(srp_g, srp_x, srp_N); +		    srp_register_send_verifier(bigInt2str(v, 16)); +		} +		else if(xhr.responseXML.getElementsByTagName("error").length > 0) +		{ +		    srp_error_message(innerxml(xhr.responseXML.getElementsByTagName("error")[0])); +		} +	} +}; +function srp_register_send_verifier(v) +{ +    if( window.XMLHttpRequest) +        xhr = new XMLHttpRequest(); +    else if (window.ActiveXObject){ +        try{ +            xhr = new ActiveXObject("Microsoft.XMLHTTP"); +        }catch (e){} +    } +    else +    { +        srp_error_message("Ajax not supported."); +        return; +    } +    if(xhr){ +        var srp_params = "v="+v; +        var srp_auth_url = srp_url+ "register/user/"; + +        xhr.onreadystatechange = srp_register_user; +        xhr.open("POST", srp_auth_url, true); +        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); +        xhr.setRequestHeader("Content-length", srp_params.length); +        xhr.setRequestHeader("Connection", "close"); +         +        xhr.send(srp_params); +    } +    else +    { +        srp_error_message("Ajax failed."); +    } +}; +function srp_register_user() +{ +    if(xhr.readyState == 4 && xhr.status == 200) { +		if(xhr.responseXML.getElementsByTagName("ok").length > 0) +		{ +		    srp_identify(); +        } +    } +}; +function srp_identify() +{ +    srp_N = str2bigInt(srp_Nstr, 16, 0); +    srp_g = str2bigInt("2", 10, 0); +    srp_k = str2bigInt("c46d46600d87fef149bd79b81119842f3c20241fda67d06ef412d8f6d9479c58", 16, 0); +    srp_a = randBigInt(32, 1); +    // A = g**a % N +    srp_A = powMod(srp_g,srp_a,srp_N); +    srp_I = document.getElementById("srp_username").value; + +    srp_Astr = bigInt2str(srp_A, 16) +    // C -> S: A | I +    srp_send_identity(srp_Astr, srp_I); +    return false; +}; +function srp_send_identity(Astr, I) +{ +    if( window.XMLHttpRequest) +        xhr = new XMLHttpRequest(); +    else if (window.ActiveXObject){ +        try{ +            xhr = new ActiveXObject("Microsoft.XMLHTTP"); +        }catch (e){} +    } +    else +    { +        srp_error_message("Ajax not supported."); +        return; +    } +    if(xhr){ +        var srp_handshake_url = srp_url + "handshake/"; +        var srp_params = "I="+I+"&A="+Astr;         +        xhr.onreadystatechange = srp_receive_salts; +        xhr.open("POST", srp_handshake_url, true); +        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); +        xhr.setRequestHeader("Content-length", srp_params.length); +        xhr.setRequestHeader("Connection", "close"); +         +        xhr.send(srp_params); +    } +    else +    { +        srp_error_message("Ajax failed."); +    } +}; +function srp_receive_salts() +{ +    if(xhr.readyState == 4 && xhr.status == 200) { +		if(xhr.responseXML.getElementsByTagName("r").length > 0) +		{ +		    response = xhr.responseXML.getElementsByTagName("r")[0]; +		    srp_calculations(response.getAttribute("s"), response.getAttribute("B")); +		} +		else if(xhr.responseXML.getElementsByTagName("error").length > 0) +		{ +		    // This probably means A % N == 0, which means we need to generate +	        // a new A and reidentify. +            srp_identify(); +		} +	} +}; + +function srp_calculate_x(s) +{ +    var p = document.getElementById("srp_password").value; +    return str2bigInt(SHA256(s + SHA256(srp_I + ":" + p)), 16, 0); +}; + +function srp_calculations(s, B) +{ +     +    //S -> C: s | B +    srp_B = str2bigInt(B, 16, 0); +    srp_Bstr = B; +    // u = H(A,B) +    srp_u = str2bigInt(SHA256(srp_Astr + srp_Bstr), 16, 0);     +    // x = H(s, H(I:p)) +    srp_x = srp_calculate_x(s); +    //S = (B - kg^x) ^ (a + ux) +    var kgx = mult(srp_k, powMod(srp_g, srp_x, srp_N)); +    var aux = add(srp_a, mult(srp_u, srp_x)); +    srp_S = powMod(sub(srp_B, kgx), aux, srp_N); +    // M = H(H(N) xor H(g), H(I), s, A, B, K) +    var Mstr = bigInt2str(srp_A, 16) + bigInt2str(srp_B,16) + bigInt2str(srp_S,16); +    srp_M = SHA256(Mstr); +    srp_send_hash(srp_M); +    //M2 = H(A, M, K) +    srp_M2 = SHA256(bigInt2str(srp_A, 16)+srp_M+bigInt2str(srp_S, 16)); +}; + + +function srp_send_hash(M) +{ +    if( window.XMLHttpRequest) +        xhr = new XMLHttpRequest(); +    else if (window.ActiveXObject){ +        try{ +            xhr = new ActiveXObject("Microsoft.XMLHTTP"); +        }catch (e){} +    } +    else +    { +        srp_error_message("Ajax not supported."); +        return; +    } +    if(xhr){ +        var srp_params = "M="+M; +        var srp_auth_url = srp_url+ "authenticate/"; + +        xhr.onreadystatechange = srp_confirm_authentication; +        xhr.open("POST", srp_auth_url, true); +        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); +        xhr.setRequestHeader("Content-length", srp_params.length); +        xhr.setRequestHeader("Connection", "close"); +         +        xhr.send(srp_params); +    } +    else +    { +        srp_error_message("Ajax failed."); +    } +}; + +function srp_confirm_authentication() +{ +    if(xhr.readyState == 4 && xhr.status == 200) { +        if(xhr.responseXML.getElementsByTagName("M").length > 0) +		{ +		    if(innerxml(xhr.responseXML.getElementsByTagName("M")[0]) == srp_M2) +		        srp_success(); +		    else +		        srp_error_message("Server key does not match"); +		} +		else if (xhr.responseXML.getElementsByTagName("error").length > 0) +		{ +		    srp_error_message(innerxml(xhr.responseXML.getElementsByTagName("error")[0])); +		} +    } +}; +function innerxml (node) +{ +    return node.firstChild.nodeValue; +}; +function srp_error_message(t) +{ +    alert(t); +}; | 
