Last active
August 10, 2020 09:24
-
-
Save jingyu9575/787e4ab87c0cf01f38955039f084b0c0 to your computer and use it in GitHub Desktop.
Log in to Tsinghua University Network
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var shell = new ActiveXObject("WScript.Shell") | |
var env = shell.Environment('Process') | |
var htmlFile = new ActiveXObject('htmlfile') | |
htmlFile.write('<meta http-equiv="x-ua-compatible" content="IE=9" />') | |
var JSON = htmlFile.parentWindow.JSON | |
htmlFile.close() | |
var username = env('TUNET_USERNAME') | |
var password = env('TUNET_PASSWORD') | |
var ipList = [] | |
var internal = false | |
var opt = new Getopt('u:p:m:i') | |
var c | |
while ((c = opt.getopt()) != null) switch (c) { | |
case '?': | |
WSH.Quit(1) | |
break | |
case 'u': | |
username = opt.optarg | |
break | |
case 'p': | |
password = opt.optarg | |
break | |
case 'm': | |
ipList.push(opt.optarg) | |
break | |
case 'i': | |
internal = true | |
break | |
default: | |
break | |
} | |
var AUTH4 = 'http://auth4.tsinghua.edu.cn/' | |
var NET = 'http://net.tsinghua.edu.cn/' | |
var NET_HTTPS = 'https://net.tsinghua.edu.cn/' | |
if (!ipList.length) ipList = [''] | |
for (var i in ipList) { | |
try { | |
processIp(ipList[i]) | |
} catch (e) { | |
try { | |
WSH.StdOut.WriteLine(e.message) | |
} catch (_) { shell.LogEvent(1, e.message) } | |
WSH.Quit(1) | |
} | |
} | |
function processIp(ip) { | |
var un = username + (internal ? '@tsinghua' : '') | |
var acId = findAcId(ip) | |
var challenge = request(AUTH4 + 'cgi-bin/get_challenge?' + encodeParams({ | |
callback: '_', username: un, ip: ip, double_stack: '1' | |
})) | |
var token = jsonp(challenge.text).challenge | |
var info = "{SRBX1}" + xBase64(xEncode(JSON.stringify({ | |
username: un, password: password, ip: ip, | |
acid: acId, enc_ver: 'srun_bx1' | |
}), token)) | |
var hmd5 = new MD5().hex_hmac(token, password) | |
var n = 200, type = 1 | |
var chksum = new SHA1().hex(token + un + token + hmd5 + token + acId + | |
token + ip + token + n + token + type + token + info) | |
var result = request(AUTH4 + 'cgi-bin/srun_portal?' + encodeParams({ | |
callback: '_', action: 'login', double_stack: '1', | |
username: un, password: "{MD5}" + hmd5, ip: ip, | |
ac_id: acId, info: info, chksum: chksum, n: n, type: type | |
})) | |
var error = jsonp(result.text).error | |
if (error !== 'ok' && error !== 'ip_already_online_error') | |
throw { message: error } | |
if (!ip && !internal) { | |
var netUser = request(NET + 'rad_user_info.php') | |
if (!netUser.text) { | |
var result = request(NET_HTTPS + 'do_login.php?' + encodeParams({ | |
action: 'login', ac_id: '1', | |
username: username, password: password | |
})) | |
if (result.text !== 'Login is successful.' && | |
result.text !== 'IP has been online, please logout.') | |
throw { message: result.text } | |
} | |
} | |
} | |
function findAcId(ip) { | |
if (ip) { | |
var nasId = request('http://usereg.tsinghua.edu.cn/ip_login_import.php', | |
encodeParams({ actionType: 'searchNasId', ip: ip })) | |
return (nasId.text && nasId.text !== 'fail') ? nasId.text : 1 | |
} else { | |
var redir = request('http://info.tsinghua.edu.cn/tunet-redirect-0624.html') | |
return (/\/index_(\d+).html/.exec(redir.url) || | |
/[&?]ac_id=(\d+)(?:$|&)/.exec(redir.url) || | |
/\/index_(\d+).html/.exec(redir.text) || [undefined, 1])[1] | |
} | |
} | |
function request(url, data) { | |
var xhr = new ActiveXObject("WinHttp.WinHttpRequest.5.1") | |
xhr.open(data == null ? "GET" : "POST", url, false) | |
xhr.setProxy(1) | |
if (data != null) | |
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") | |
xhr.send(data) | |
return { text: xhr.responseText, url: xhr.Option(1) } | |
} | |
function encodeParams(obj) { | |
var list = [] | |
for (var k in obj) | |
list.push(encodeURIComponent(k) + '=' + encodeURIComponent(obj[k])) | |
return list.join('&') | |
} | |
function jsonp(response) { | |
return JSON.parse(response.replace(/^\s*\w+\(/, '').replace(/\)\s*$/, '')) | |
} | |
//#region Getopt | |
// https://www.hi-matic.org/distfiles/wsh/getopt/getopt.js | |
/*- | |
* Copyright (c)2005 Takehiko NOZAKI, | |
* All rights reserved. | |
* | |
* Copyright (c) 1987, 1993, 1994 | |
* The Regents of the University of California. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* 3. Neither the name of the University nor the names of its contributors | |
* may be used to endorse or promote products derived from this software | |
* without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
* SUCH DAMAGE. | |
* | |
* Original version ID: | |
* NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp | |
*/ | |
function Getopt(ostr) { | |
this.ostr = ostr; | |
this.opterr = 1; /* if error message should be printed */ | |
this.optind = 0; /* index into parent argv vector */ | |
this.optopt; /* character checked for validity */ | |
this.optreset = 1; /* reset getopt */ | |
this.optarg; /* argument associated with option */ | |
var EMSG = ""; | |
var BADCH = "?"; | |
var BADARG = ":"; | |
var place = EMSG; /* option letter processing */ | |
this.getopt = function () { | |
if (this.optreset != 0 || place.length == 0) { /* update scanning pointer */ | |
this.optreset = 0; | |
if (this.optind >= WScript.Arguments.length) { | |
place = EMSG; | |
return null; | |
} | |
place = WScript.Arguments(this.optind); | |
var c = place.charAt(0); | |
place = place.substr(1); | |
if (c != "-") { | |
place = EMSG; | |
return null; | |
} | |
if (place.length == 0) { | |
/* Solitary '-', treat as a '-' option | |
if the program (eg su) is looking for it. */ | |
place = EMSG; | |
if (this.ostr.indexOf("-") == -1) | |
return null; | |
this.optopt = "-"; | |
} else { | |
this.optopt = place.charAt(0); | |
place = place.substr(1); | |
if (this.optopt == "-" && place.length == 0) { | |
/* "--" => end of options */ | |
++this.optind; | |
place = EMSG; | |
return null; | |
} | |
} | |
} else { | |
this.optopt = place.charAt(0); | |
place = place.substr(1); | |
} | |
/* See if option letter is one the caller wanted... */ | |
var oli = this.ostr.indexOf(this.optopt); /* option letter list index */ | |
if (this.optopt == ":" || oli == -1) { | |
if (place.length == 0) | |
++this.optind; | |
if (this.opterr != 0 && this.ostr.charAt(0) != ":") { | |
WScript.StdErr.Write(WScript.ScriptName); | |
WScript.StdErr.Write(": unknown option -- "); | |
WScript.StdErr.WriteLine(this.optopt); | |
return BADCH; | |
} | |
} | |
/* Does this option need an argument? */ | |
if (this.ostr.charAt(oli + 1) != ":") { | |
/* don't need argument */ | |
this.optarg = null; | |
if (place.length == 0) | |
++this.optind; | |
} else { | |
/* Option-argument is either the rest of this argument or the | |
entire next argument. */ | |
if (place.length != 0) | |
this.optarg = place; | |
else if (WScript.Arguments.length > ++this.optind) | |
this.optarg = WScript.Arguments(this.optind); | |
else { | |
/* option-argument absent */ | |
place = EMSG; | |
if (this.ostr.charAt(0) == ":") | |
return BADARG; | |
if (this.opterr) { | |
WScript.StdErr.Write(WScript.ScriptName); | |
WScript.StdErr.Write(": option requires an argument -- "); | |
WScript.StdErr.WriteLine(this.optopt); | |
return BADCH; | |
} | |
} | |
place = ""; | |
++this.optind; | |
} | |
return this.optopt; /* return option letter */ | |
} | |
} | |
//#endregion | |
//#region MD5 | |
/** | |
* @member Hashes | |
* @class MD5 | |
* @constructor | |
* @param {Object} [config] | |
* | |
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message | |
* Digest Algorithm, as defined in RFC 1321. | |
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* See <http://pajhome.org.uk/crypt/md5> for more infHashes. | |
*/ | |
function MD5(options) { | |
/** | |
* Private config properties. You may need to tweak these to be compatible with | |
* the server-side, but the defaults work in most cases. | |
* See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} | |
*/ | |
var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, | |
// hexadecimal output case format. false - lowercase; true - uppercase | |
b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', | |
// base-64 pad character. Defaults to '=' for strict RFC compliance | |
utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; | |
// enable/disable utf8 encoding | |
// privileged (public) methods | |
this.hex = function (s) { | |
return rstr2hex(rstr(s, utf8), hexcase); | |
}; | |
this.b64 = function (s) { | |
return rstr2b64(rstr(s), b64pad); | |
}; | |
this.any = function (s, e) { | |
return rstr2any(rstr(s, utf8), e); | |
}; | |
this.raw = function (s) { | |
return rstr(s, utf8); | |
}; | |
this.hex_hmac = function (k, d) { | |
return rstr2hex(rstr_hmac(k, d), hexcase); | |
}; | |
this.b64_hmac = function (k, d) { | |
return rstr2b64(rstr_hmac(k, d), b64pad); | |
}; | |
this.any_hmac = function (k, d, e) { | |
return rstr2any(rstr_hmac(k, d), e); | |
}; | |
/** | |
* Perform a simple self-test to see if the VM is working | |
* @return {String} Hexadecimal hash sample | |
*/ | |
this.vm_test = function () { | |
return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; | |
}; | |
/** | |
* Enable/disable uppercase hexadecimal returned string | |
* @param {Boolean} | |
* @return {Object} this | |
*/ | |
this.setUpperCase = function (a) { | |
if (typeof a === 'boolean') { | |
hexcase = a; | |
} | |
return this; | |
}; | |
/** | |
* Defines a base64 pad string | |
* @param {String} Pad | |
* @return {Object} this | |
*/ | |
this.setPad = function (a) { | |
b64pad = a || b64pad; | |
return this; | |
}; | |
/** | |
* Defines a base64 pad string | |
* @param {Boolean} | |
* @return {Object} [this] | |
*/ | |
this.setUTF8 = function (a) { | |
if (typeof a === 'boolean') { | |
utf8 = a; | |
} | |
return this; | |
}; | |
// private methods | |
/** | |
* Calculate the MD5 of a raw string | |
*/ | |
function rstr(s) { | |
s = (utf8) ? utf8Encode(s) : s; | |
return binl2rstr(binl(rstr2binl(s), s.length * 8)); | |
} | |
/** | |
* Calculate the HMAC-MD5, of a key and some data (raw strings) | |
*/ | |
function rstr_hmac(key, data) { | |
var bkey, ipad, opad, hash, i; | |
key = (utf8) ? utf8Encode(key) : key; | |
data = (utf8) ? utf8Encode(data) : data; | |
bkey = rstr2binl(key); | |
if (bkey.length > 16) { | |
bkey = binl(bkey, key.length * 8); | |
} | |
ipad = Array(16), opad = Array(16); | |
for (i = 0; i < 16; i += 1) { | |
ipad[i] = bkey[i] ^ 0x36363636; | |
opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
} | |
hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8); | |
return binl2rstr(binl(opad.concat(hash), 512 + 128)); | |
} | |
/** | |
* Calculate the MD5 of an array of little-endian words, and a bit length. | |
*/ | |
function binl(x, len) { | |
var i, olda, oldb, oldc, oldd, | |
a = 1732584193, | |
b = -271733879, | |
c = -1732584194, | |
d = 271733878; | |
/* append padding */ | |
x[len >> 5] |= 0x80 << ((len) % 32); | |
x[(((len + 64) >>> 9) << 4) + 14] = len; | |
for (i = 0; i < x.length; i += 16) { | |
olda = a; | |
oldb = b; | |
oldc = c; | |
oldd = d; | |
a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); | |
d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); | |
c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); | |
b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); | |
a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); | |
d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); | |
c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); | |
b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); | |
a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); | |
d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); | |
c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); | |
b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); | |
a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); | |
d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); | |
c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); | |
b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); | |
a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); | |
d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); | |
c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); | |
b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); | |
a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); | |
d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); | |
c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); | |
b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); | |
a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); | |
d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); | |
c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); | |
b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); | |
a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); | |
d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); | |
c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); | |
b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); | |
a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); | |
d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); | |
c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); | |
b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); | |
a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); | |
d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); | |
c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); | |
b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); | |
a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); | |
d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); | |
c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); | |
b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); | |
a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); | |
d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); | |
c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); | |
b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); | |
a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); | |
d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); | |
c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); | |
b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); | |
a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); | |
d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); | |
c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); | |
b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); | |
a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); | |
d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); | |
c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); | |
b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); | |
a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); | |
d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); | |
c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); | |
b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); | |
a = safe_add(a, olda); | |
b = safe_add(b, oldb); | |
c = safe_add(c, oldc); | |
d = safe_add(d, oldd); | |
} | |
return Array(a, b, c, d); | |
} | |
/** | |
* These functions implement the four basic operations the algorithm uses. | |
*/ | |
function md5_cmn(q, a, b, x, s, t) { | |
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); | |
} | |
function md5_ff(a, b, c, d, x, s, t) { | |
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); | |
} | |
function md5_gg(a, b, c, d, x, s, t) { | |
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); | |
} | |
function md5_hh(a, b, c, d, x, s, t) { | |
return md5_cmn(b ^ c ^ d, a, b, x, s, t); | |
} | |
function md5_ii(a, b, c, d, x, s, t) { | |
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); | |
} | |
} | |
/** | |
* @member Hashes | |
* @class Hashes.SHA1 | |
* @param {Object} [config] | |
* @constructor | |
* | |
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1 | |
* Version 2.2 Copyright Paul Johnston 2000 - 2009. | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* See http://pajhome.org.uk/crypt/md5 for details. | |
*/ | |
function SHA1(options) { | |
/** | |
* Private config properties. You may need to tweak these to be compatible with | |
* the server-side, but the defaults work in most cases. | |
* See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase} | |
*/ | |
var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, | |
// hexadecimal output case format. false - lowercase; true - uppercase | |
b64pad = (options && typeof options.pad === 'string') ? options.pad : '=', | |
// base-64 pad character. Defaults to '=' for strict RFC compliance | |
utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; | |
// enable/disable utf8 encoding | |
// public methods | |
this.hex = function (s) { | |
return rstr2hex(rstr(s, utf8), hexcase); | |
}; | |
this.b64 = function (s) { | |
return rstr2b64(rstr(s, utf8), b64pad); | |
}; | |
this.any = function (s, e) { | |
return rstr2any(rstr(s, utf8), e); | |
}; | |
this.raw = function (s) { | |
return rstr(s, utf8); | |
}; | |
this.hex_hmac = function (k, d) { | |
return rstr2hex(rstr_hmac(k, d)); | |
}; | |
this.b64_hmac = function (k, d) { | |
return rstr2b64(rstr_hmac(k, d), b64pad); | |
}; | |
this.any_hmac = function (k, d, e) { | |
return rstr2any(rstr_hmac(k, d), e); | |
}; | |
/** | |
* Perform a simple self-test to see if the VM is working | |
* @return {String} Hexadecimal hash sample | |
* @public | |
*/ | |
this.vm_test = function () { | |
return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72'; | |
}; | |
/** | |
* @description Enable/disable uppercase hexadecimal returned string | |
* @param {boolean} | |
* @return {Object} this | |
* @public | |
*/ | |
this.setUpperCase = function (a) { | |
if (typeof a === 'boolean') { | |
hexcase = a; | |
} | |
return this; | |
}; | |
/** | |
* @description Defines a base64 pad string | |
* @param {string} Pad | |
* @return {Object} this | |
* @public | |
*/ | |
this.setPad = function (a) { | |
b64pad = a || b64pad; | |
return this; | |
}; | |
/** | |
* @description Defines a base64 pad string | |
* @param {boolean} | |
* @return {Object} this | |
* @public | |
*/ | |
this.setUTF8 = function (a) { | |
if (typeof a === 'boolean') { | |
utf8 = a; | |
} | |
return this; | |
}; | |
// private methods | |
/** | |
* Calculate the SHA-512 of a raw string | |
*/ | |
function rstr(s) { | |
s = (utf8) ? utf8Encode(s) : s; | |
return binb2rstr(binb(rstr2binb(s), s.length * 8)); | |
} | |
/** | |
* Calculate the HMAC-SHA1 of a key and some data (raw strings) | |
*/ | |
function rstr_hmac(key, data) { | |
var bkey, ipad, opad, i, hash; | |
key = (utf8) ? utf8Encode(key) : key; | |
data = (utf8) ? utf8Encode(data) : data; | |
bkey = rstr2binb(key); | |
if (bkey.length > 16) { | |
bkey = binb(bkey, key.length * 8); | |
} | |
ipad = Array(16), opad = Array(16); | |
for (i = 0; i < 16; i += 1) { | |
ipad[i] = bkey[i] ^ 0x36363636; | |
opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
} | |
hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8); | |
return binb2rstr(binb(opad.concat(hash), 512 + 160)); | |
} | |
/** | |
* Calculate the SHA-1 of an array of big-endian words, and a bit length | |
*/ | |
function binb(x, len) { | |
var i, j, t, olda, oldb, oldc, oldd, olde, | |
w = Array(80), | |
a = 1732584193, | |
b = -271733879, | |
c = -1732584194, | |
d = 271733878, | |
e = -1009589776; | |
/* append padding */ | |
x[len >> 5] |= 0x80 << (24 - len % 32); | |
x[((len + 64 >> 9) << 4) + 15] = len; | |
for (i = 0; i < x.length; i += 16) { | |
olda = a; | |
oldb = b; | |
oldc = c; | |
oldd = d; | |
olde = e; | |
for (j = 0; j < 80; j += 1) { | |
if (j < 16) { | |
w[j] = x[i + j]; | |
} else { | |
w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); | |
} | |
t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), | |
safe_add(safe_add(e, w[j]), sha1_kt(j))); | |
e = d; | |
d = c; | |
c = bit_rol(b, 30); | |
b = a; | |
a = t; | |
} | |
a = safe_add(a, olda); | |
b = safe_add(b, oldb); | |
c = safe_add(c, oldc); | |
d = safe_add(d, oldd); | |
e = safe_add(e, olde); | |
} | |
return Array(a, b, c, d, e); | |
} | |
/** | |
* Perform the appropriate triplet combination function for the current | |
* iteration | |
*/ | |
function sha1_ft(t, b, c, d) { | |
if (t < 20) { | |
return (b & c) | ((~b) & d); | |
} | |
if (t < 40) { | |
return b ^ c ^ d; | |
} | |
if (t < 60) { | |
return (b & c) | (b & d) | (c & d); | |
} | |
return b ^ c ^ d; | |
} | |
/** | |
* Determine the appropriate additive constant for the current iteration | |
*/ | |
function sha1_kt(t) { | |
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : | |
(t < 60) ? -1894007588 : -899497514; | |
} | |
} | |
function utf8Encode(str) { | |
var x, y, output = '', | |
i = -1, | |
l; | |
if (str && str.length) { | |
l = str.length; | |
while ((i += 1) < l) { | |
/* Decode utf-16 surrogate pairs */ | |
x = str.charCodeAt(i); | |
y = i + 1 < l ? str.charCodeAt(i + 1) : 0; | |
if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { | |
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); | |
i += 1; | |
} | |
/* Encode output as utf-8 */ | |
if (x <= 0x7F) { | |
output += String.fromCharCode(x); | |
} else if (x <= 0x7FF) { | |
output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F), | |
0x80 | (x & 0x3F)); | |
} else if (x <= 0xFFFF) { | |
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), | |
0x80 | ((x >>> 6) & 0x3F), | |
0x80 | (x & 0x3F)); | |
} else if (x <= 0x1FFFFF) { | |
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), | |
0x80 | ((x >>> 12) & 0x3F), | |
0x80 | ((x >>> 6) & 0x3F), | |
0x80 | (x & 0x3F)); | |
} | |
} | |
} | |
return output; | |
} | |
/** | |
* Convert an array of little-endian words to a string | |
*/ | |
function binl2rstr(input) { | |
var i, l = input.length * 32, | |
output = ''; | |
for (i = 0; i < l; i += 8) { | |
output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); | |
} | |
return output; | |
} | |
/** | |
* Convert a raw string to an array of little-endian words | |
* Characters >255 have their high-byte silently ignored. | |
*/ | |
function rstr2binl(input) { | |
var i, l = input.length * 8, | |
output = Array(input.length >> 2), | |
lo = output.length; | |
for (i = 0; i < lo; i += 1) { | |
output[i] = 0; | |
} | |
for (i = 0; i < l; i += 8) { | |
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); | |
} | |
return output; | |
} | |
/** | |
* Convert an array of big-endian words to a string | |
*/ | |
function binb2rstr(input) { | |
var i, l = input.length * 32, | |
output = ''; | |
for (i = 0; i < l; i += 8) { | |
output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF); | |
} | |
return output; | |
} | |
/** | |
* Convert a raw string to an array of big-endian words | |
* Characters >255 have their high-byte silently ignored. | |
*/ | |
function rstr2binb(input) { | |
var i, l = input.length * 8, | |
output = Array(input.length >> 2), | |
lo = output.length; | |
for (i = 0; i < lo; i += 1) { | |
output[i] = 0; | |
} | |
for (i = 0; i < l; i += 8) { | |
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); | |
} | |
return output; | |
} | |
/** | |
* Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
* to work around bugs in some JS interpreters. | |
*/ | |
function safe_add(x, y) { | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF), | |
msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
} | |
/** | |
* Bitwise rotate a 32-bit number to the left. | |
*/ | |
function bit_rol(num, cnt) { | |
return (num << cnt) | (num >>> (32 - cnt)); | |
} | |
/** | |
* Convert a raw string to a hex string | |
*/ | |
function rstr2hex(input, hexcase) { | |
var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef', | |
output = '', | |
x, i = 0, | |
l = input.length; | |
for (; i < l; i += 1) { | |
x = input.charCodeAt(i); | |
output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F); | |
} | |
return output; | |
} | |
//#endregion | |
//#region Proprietary encoding functions | |
function xEncode(str, key) { | |
if (str == "") return "" | |
var v = s(str, true), k = s(key, false) | |
if (k.length < 4) k.length = 4 | |
var n = v.length - 1, z = v[n], y = v[0], | |
c = 0x86014019 | 0x183639A0, m, e, p, | |
q = Math.floor(6 + 52 / (n + 1)), d = 0 | |
while (0 < q--) { | |
d = d + c & (0x8CE0D9BF | 0x731F2640) | |
e = d >>> 2 & 3 | |
for (p = 0; p < n; p++) { | |
y = v[p + 1] | |
m = z >>> 5 ^ y << 2 | |
m += (y >>> 3 ^ z << 4) ^ (d ^ y) | |
m += k[(p & 3) ^ e] ^ z | |
z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF) | |
} | |
y = v[0] | |
m = z >>> 5 ^ y << 2 | |
m += (y >>> 3 ^ z << 4) ^ (d ^ y) | |
m += k[(p & 3) ^ e] ^ z | |
z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD) | |
} | |
function s(a, b) { | |
var c = a.length, v = [] | |
for (var i = 0; i < c; i += 4) { | |
v[i >> 2] = a.charCodeAt(i) | a.charCodeAt(i + 1) << 8 | | |
a.charCodeAt(i + 2) << 16 | a.charCodeAt(i + 3) << 24 | |
} | |
if (b) { | |
v[v.length] = c | |
} | |
return v | |
} | |
function l(a, b) { | |
var d = a.length, c = (d - 1) << 2 | |
if (b) { | |
var m = a[d - 1] | |
if ((m < c - 3) || (m > c)) return null | |
c = m | |
} | |
for (var i = 0; i < d; i++) { | |
a[i] = String.fromCharCode(a[i] & 0xff, a[i] >>> 8 & 0xff, | |
a[i] >>> 16 & 0xff, a[i] >>> 24 & 0xff) | |
} | |
return b ? a.join('').substring(0, c) : a.join('') | |
} | |
return l(v, false) | |
} | |
function xBase64(t) { | |
var n = 'LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA', | |
r = '=', | |
f = false | |
var o, | |
i, | |
h, | |
u = '', | |
a = t.length | |
r = r || '=' | |
t = f ? e(t) : t | |
for (o = 0; o < a; o += 3) { | |
h = t.charCodeAt(o) << 16 | (o + 1 < a ? t.charCodeAt(o + 1) << 8 : 0) | | |
(o + 2 < a ? t.charCodeAt(o + 2) : 0) | |
for (i = 0; i < 4; i += 1) { | |
if (o * 8 + i * 6 > a * 8) { | |
u += r | |
} else { | |
u += n.charAt(h >>> 6 * (3 - i) & 63) | |
} | |
} | |
} | |
return u | |
} | |
//#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment