LoadRunner 12 模拟 RSA加密 登录的实现(JS)

LR 12 中 web_js_run API 非常坑,只能调用一个 JS 文件;更坑的是,不能通用 一个JS调用另外一个JS;(可能有,但在网上找了N个国家,都没有找到!如有,还请朋友告之,谢谢。)

现大部分的前端登录都有使用到RSA加密,以保障用户在登录的时候,账号密码不直接以明文方式传输,经过加密的账号密码即使被截取,也难以破解出真实的账号密码;
RSA 相关信息请自行搜索了解或下载, RSA加密算法在网上有N多开源的现成库可用(前、后端库);

经RSA加密的登录流程大致为:

1、前端在登录时会向服务端请求 RSA 四个关键值: PublicKey , Exponent ,rKey , Modulus;
2、前端使用获取到的 Exponent , Modulus ( 通过 RSA 库在前端执行)计算出私钥,然后使用获得的公钥以及私钥 对 用户的账号密码 进行加密,并生成加密后的字符串;
3、最后前端将完成加密的字符串发送给服务端,服务端解密成功后,返回登录成功的状态;
以下将以RSA加密登录为例,演示在Loadrunner 中的如何实现;

  1 Action()
  2 {
  3     //char cliEncrypt[1000]; //用于保存需要加密的拼接好的字符串
  4     int rc=0;
  5     lr_save_string("19000000026","mobileNumberSet");//参数化的正确姿势 lr_save_string(lr_eval_string("{user_mobile}"),"mobileNumberSet");
  6     lr_save_string("123456","pwdSet");
  7     lr_save_string("","imgVerifyCodeSet");
  8 
  9     web_reg_save_param("SerJsonData", "LB=", "RB=", "Search=Body", LAST);
 10     
 11     web_submit_data("encryptKey.action",
 12         "Action=http://192.168.1.16/surperman/login/encryptKey.action", 
 13         "Method=GET", 
 14         "RecContentType=text/html", 
 15         "Referer=", 
 16         "Snapshot=t19.inf", 
 17         "Mode=HTML", 
 18         ITEMDATA, 
 19         LAST);
 20     
 21     lr_output_message("# 获取密钥响应内容体:\n%s", lr_eval_string("{SerJsonData}"));
 22         
 23     web_js_run(
 24         "Code=getPublicKey(LR.getParam('SerJsonData'));",
 25         "ResultParam=getDataPublicKey",
 26         SOURCES,
 27         "File=getkey.js",ENDITEM,
 28         LAST);
 29     
 30     web_js_run(
 31         "Code=getExponent(LR.getParam('SerJsonData'));",
 32         "ResultParam=getDataExponent",
 33         SOURCES,
 34         "File=getkey.js",ENDITEM,
 35         LAST);
 36     
 37     web_js_run(
 38         "Code=getrKey(LR.getParam('SerJsonData'));",
 39         "ResultParam=getDatarKey",
 40         SOURCES,
 41         "File=getkey.js",ENDITEM,
 42         LAST);
 43     
 44     web_js_run(
 45         "Code=getModulus(LR.getParam('SerJsonData'));",
 46         "ResultParam=getDataModulus",
 47         SOURCES,
 48         "File=getkey.js",ENDITEM,
 49         LAST);
 50     
 51     lr_output_message("# getDataPublicKey 的值为:\n%s", lr_eval_string("{getDataPublicKey}"));
 52     lr_output_message("# getDataExponent 的值为:\n%s", lr_eval_string("{getDataExponent}"));
 53     lr_output_message("# getDatarKey 的值为:\n%s", lr_eval_string("{getDatarKey}"));
 54     lr_output_message("# getDataModulus 的值为:\n%s", lr_eval_string("{getDataModulus}"));
 55     
 56 /*
 57     lr_output_message("# mobileNumberSet 的值为:\n%s", lr_eval_string("{mobileNumberSet}"));
 58     lr_output_message("# pwdSet 的值为:\n%s", lr_eval_string("{pwdSet}"));
 59     lr_output_message("# imgVerifyCodeSet 的值为:\n%s", lr_eval_string("{imgVerifyCodeSet}"));
 60 */
 61     //拼接 输入的手机号、密码等 需要加密字符串
 62     //sprintf(cliEncrypt,"mobileNumber=%s&pwd=%s&imgVerifyCode=%s",lr_eval_string("{mobileNumberSet}"),lr_eval_string("{pwdSet}"),lr_eval_string("{imgVerifyCodeSet}"));
 63 
 64     //将拼接好的字符串赋值给参数 parCliEncrypt
 65     //lr_save_string(cliEncrypt,"parCliEncrypt");
 66     //lr_output_message(lr_eval_string("{parCliEncrypt}"));
 67 
 68        web_js_run(
 69         "Code=createEncrypt();",
 70         "ResultParam=NewkeyEncrypt",
 71         SOURCES,
 72         "File=loginEncryptStr.js",
 73         ENDITEM,
 74         LAST);
 75  
 76     lr_output_message("# NewkeyEncrypt 的值为:\n%s", lr_eval_string("{NewkeyEncrypt}"));
 77  
 78     /*输入账号密码后,点击登录*/
 79 
 80     web_reg_save_param("newTokenJson", "LB=", "RB=", "Search=Body", LAST);
 81     
 82     rc=web_custom_request("userPwdLogin.action", 
 83         "URL=http://192.168.1.16/surperman/login/userPwdLogin.action", 
 84         "Method=POST", 
 85         "Resource=0", 
 86         "RecContentType=text/html", 
 87         "Referer=", 
 88         "Snapshot=t21.inf", 
 89         "Mode=HTML", 
 90         "Body=encrypt={NewkeyEncrypt}&rKey={getDatarKey}",
 91         LAST);
 92 
 93     // 返回的字符串需要做编码转换处理,否则中文会显示为乱码
 94     lr_convert_string_encoding(lr_eval_string("{newTokenJson}"),"utf-8",NULL,"newTokenJsonUTF");
 95     
 96     lr_output_message("# newTokenJson 的值为:\n%s", lr_eval_string("{newTokenJson}"));
 97     lr_output_message("# newTokenJsonUTF 的值为:\n%s\nJS执行结果:%d", lr_eval_string("{newTokenJsonUTF}"), rc);
 98 
 99     return 0;
100 }

LR 中 web_js_run 所调用的 getkey.js 长这样:

 1 function getPublicKey(stringData)
 2 { 
 3     var data = JSON.parse(stringData);
 4     return data.publicKey;
 5 } 
 6 
 7 function getExponent(stringData)
 8 { 
 9     var data = JSON.parse(stringData);
10     return data.exponent;
11 } 
12 
13 function getrKey(stringData)
14 { 
15     var data = JSON.parse(stringData);
16     return data.rKey;
17 } 
18 
19 function getModulus(stringData)
20 { 
21     var data = JSON.parse(stringData);
22     return data.modulus;
23 } 

LR 中 web_js_run 所调用的 loginEncryptStr.js 长这样(RSA 库前端开源部分代码可以直接跳过):

  1 // RSA 库前端开源部分 - 开始
  2 var RSAUtils = {};
  3 
  4 var biRadixBase = 2;
  5 var biRadixBits = 16;
  6 var bitsPerDigit = biRadixBits;
  7 var biRadix = 1 << 16; // = 2^16 = 65536
  8 var biHalfRadix = biRadix >>> 1;
  9 var biRadixSquared = biRadix * biRadix;
 10 var maxDigitVal = biRadix - 1;
 11 var maxInteger = 9999999999999998;
 12 
 13 //maxDigits:
 14 //Change this to accommodate your largest number size. Use setMaxDigits()
 15 //to change it!
 16 //
 17 //In general, if you're working with numbers of size N bits, you'll need 2*N
 18 //bits of storage. Each digit holds 16 bits. So, a 1024-bit key will need
 19 //
 20 //1024 * 2 / 16 = 128 digits of storage.
 21 //
 22 var maxDigits;
 23 var ZERO_ARRAY;
 24 var bigZero,
 25 bigOne;
 26 
 27 var BigInt = window.BigInt = function (flag) {
 28     if (typeof flag == "boolean" && flag == true) {
 29         this.digits = null;
 30     } else {
 31         this.digits = ZERO_ARRAY.slice(0);
 32     }
 33     this.isNeg = false;
 34 };
 35 
 36 RSAUtils.setMaxDigits = function (value) {
 37     maxDigits = value;
 38     ZERO_ARRAY = new Array(maxDigits);
 39     for (var iza = 0; iza < ZERO_ARRAY.length; iza++)
 40         ZERO_ARRAY[iza] = 0;
 41     bigZero = new BigInt();
 42     bigOne = new BigInt();
 43     bigOne.digits[0] = 1;
 44 };
 45 RSAUtils.setMaxDigits(20);
 46 
 47 //The maximum number of digits in base 10 you can convert to an
 48 //integer without JavaScript throwing up on you.
 49 var dpl10 = 15;
 50 
 51 RSAUtils.biFromNumber = function (i) {
 52     var result = new BigInt();
 53     result.isNeg = i < 0;
 54     i = Math.abs(i);
 55     var j = 0;
 56     while (i > 0) {
 57         result.digits[j++] = i & maxDigitVal;
 58         i = Math.floor(i / biRadix);
 59     }
 60     return result;
 61 };
 62 
 63 //lr10 = 10 ^ dpl10
 64 var lr10 = RSAUtils.biFromNumber(1000000000000000);
 65 
 66 RSAUtils.biFromDecimal = function (s) {
 67     var isNeg = s.charAt(0) == '-';
 68     var i = isNeg ? 1 : 0;
 69     var result;
 70     // Skip leading zeros.
 71     while (i < s.length && s.charAt(i) == '0')
 72         ++i;
 73     if (i == s.length) {
 74         result = new BigInt();
 75     } else {
 76         var digitCount = s.length - i;
 77         var fgl = digitCount % dpl10;
 78         if (fgl == 0)
 79             fgl = dpl10;
 80         result = RSAUtils.biFromNumber(Number(s.substr(i, fgl)));
 81         i += fgl;
 82         while (i < s.length) {
 83             result = RSAUtils.biAdd(RSAUtils.biMultiply(result, lr10),
 84                     RSAUtils.biFromNumber(Number(s.substr(i, dpl10))));
 85             i += dpl10;
 86         }
 87         result.isNeg = isNeg;
 88     }
 89     return result;
 90 };
 91 
 92 RSAUtils.biCopy = function (bi) {
 93     var result = new BigInt(true);
 94     result.digits = bi.digits.slice(0);
 95     result.isNeg = bi.isNeg;
 96     return result;
 97 };
 98 
 99 RSAUtils.reverseStr = function (s) {
100     var result = "";
101     for (var i = s.length - 1; i > -1; --i) {
102         result += s.charAt(i);
103     }
104     return result;
105 };
106 
107 var hexatrigesimalToChar = [
108     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
109     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
110     'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
111     'u', 'v', 'w', 'x', 'y', 'z'
112 ];
113 
114 RSAUtils.biToString = function (x, radix) { // 2 <= radix <= 36
115     var b = new BigInt();
116     b.digits[0] = radix;
117     var qr = RSAUtils.biDivideModulo(x, b);
118     var result = hexatrigesimalToChar[qr[1].digits[0]];
119     while (RSAUtils.biCompare(qr[0], bigZero) == 1) {
120         qr = RSAUtils.biDivideModulo(qr[0], b);
121         digit = qr[1].digits[0];
122         result += hexatrigesimalToChar[qr[1].digits[0]];
123     }
124     return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result);
125 };
126 
127 RSAUtils.biToDecimal = function (x) {
128     var b = new BigInt();
129     b.digits[0] = 10;
130     var qr = RSAUtils.biDivideModulo(x, b);
131     var result = String(qr[1].digits[0]);
132     while (RSAUtils.biCompare(qr[0], bigZero) == 1) {
133         qr = RSAUtils.biDivideModulo(qr[0], b);
134         result += String(qr[1].digits[0]);
135     }
136     return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result);
137 };
138 
139 var hexToChar = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
140     'a', 'b', 'c', 'd', 'e', 'f'];
141 
142 RSAUtils.digitToHex = function (n) {
143     var mask = 0xf;
144     var result = "";
145     for (i = 0; i < 4; ++i) {
146         result += hexToChar[n & mask];
147         n >>>= 4;
148     }
149     return RSAUtils.reverseStr(result);
150 };
151 
152 RSAUtils.biToHex = function (x) {
153     var result = "";
154     var n = RSAUtils.biHighIndex(x);
155     for (var i = RSAUtils.biHighIndex(x); i > -1; --i) {
156         result += RSAUtils.digitToHex(x.digits[i]);
157     }
158     return result;
159 };
160 
161 RSAUtils.charToHex = function (c) {
162     var ZERO = 48;
163     var NINE = ZERO + 9;
164     var littleA = 97;
165     var littleZ = littleA + 25;
166     var bigA = 65;
167     var bigZ = 65 + 25;
168     var result;
169 
170     if (c >= ZERO && c <= NINE) {
171         result = c - ZERO;
172     } else if (c >= bigA && c <= bigZ) {
173         result = 10 + c - bigA;
174     } else if (c >= littleA && c <= littleZ) {
175         result = 10 + c - littleA;
176     } else {
177         result = 0;
178     }
179     return result;
180 };
181 
182 RSAUtils.hexToDigit = function (s) {
183     var result = 0;
184     var sl = Math.min(s.length, 4);
185     for (var i = 0; i < sl; ++i) {
186         result <<= 4;
187         result |= RSAUtils.charToHex(s.charCodeAt(i));
188     }
189     return result;
190 };
191 
192 RSAUtils.biFromHex = function (s) {
193     var result = new BigInt();
194     var sl = s.length;
195     for (var i = sl, j = 0; i > 0; i -= 4, ++j) {
196         result.digits[j] = RSAUtils.hexToDigit(s.substr(Math.max(i - 4, 0), Math.min(i, 4)));
197     }
198     return result;
199 };
200 
201 RSAUtils.biFromString = function (s, radix) {
202     var isNeg = s.charAt(0) == '-';
203     var istop = isNeg ? 1 : 0;
204     var result = new BigInt();
205     var place = new BigInt();
206     place.digits[0] = 1; // radix^0
207     for (var i = s.length - 1; i >= istop; i--) {
208         var c = s.charCodeAt(i);
209         var digit = RSAUtils.charToHex(c);
210         var biDigit = RSAUtils.biMultiplyDigit(place, digit);
211         result = RSAUtils.biAdd(result, biDigit);
212         place = RSAUtils.biMultiplyDigit(place, radix);
213     }
214     result.isNeg = isNeg;
215     return result;
216 };
217 
218 RSAUtils.biDump = function (b) {
219     return (b.isNeg ? "-" : "") + b.digits.join(" ");
220 };
221 
222 RSAUtils.biAdd = function (x, y) {
223     var result;
224 
225     if (x.isNeg != y.isNeg) {
226         y.isNeg = !y.isNeg;
227         result = RSAUtils.biSubtract(x, y);
228         y.isNeg = !y.isNeg;
229     } else {
230         result = new BigInt();
231         var c = 0;
232         var n;
233         for (var i = 0; i < x.digits.length; ++i) {
234             n = x.digits[i] + y.digits[i] + c;
235             result.digits[i] = n % biRadix;
236             c = Number(n >= biRadix);
237         }
238         result.isNeg = x.isNeg;
239     }
240     return result;
241 };
242 
243 RSAUtils.biSubtract = function (x, y) {
244     var result;
245     if (x.isNeg != y.isNeg) {
246         y.isNeg = !y.isNeg;
247         result = RSAUtils.biAdd(x, y);
248         y.isNeg = !y.isNeg;
249     } else {
250         result = new BigInt();
251         var n,
252         c;
253         c = 0;
254         for (var i = 0; i < x.digits.length; ++i) {
255             n = x.digits[i] - y.digits[i] + c;
256             result.digits[i] = n % biRadix;
257             // Stupid non-conforming modulus operation.
258             if (result.digits[i] < 0)
259                 result.digits[i] += biRadix;
260             c = 0 - Number(n < 0);
261         }
262         // Fix up the negative sign, if any.
263         if (c == -1) {
264             c = 0;
265             for (var i = 0; i < x.digits.length; ++i) {
266                 n = 0 - result.digits[i] + c;
267                 result.digits[i] = n % biRadix;
268                 // Stupid non-conforming modulus operation.
269                 if (result.digits[i] < 0)
270                     result.digits[i] += biRadix;
271                 c = 0 - Number(n < 0);
272             }
273             // Result is opposite sign of arguments.
274             result.isNeg = !x.isNeg;
275         } else {
276             // Result is same sign.
277             result.isNeg = x.isNeg;
278         }
279     }
280     return result;
281 };
282 
283 RSAUtils.biHighIndex = function (x) {
284     var result = x.digits.length - 1;
285     while (result > 0 && x.digits[result] == 0)
286         --result;
287     return result;
288 };
289 
290 RSAUtils.biNumBits = function (x) {
291     var n = RSAUtils.biHighIndex(x);
292     var d = x.digits[n];
293     var m = (n + 1) * bitsPerDigit;
294     var result;
295     for (result = m; result > m - bitsPerDigit; --result) {
296         if ((d & 0x8000) != 0)
297             break;
298         d <<= 1;
299     }
300     return result;
301 };
302 
303 RSAUtils.biMultiply = function (x, y) {
304     var result = new BigInt();
305     var c;
306     var n = RSAUtils.biHighIndex(x);
307     var t = RSAUtils.biHighIndex(y);
308     var u,
309     uv,
310     k;
311 
312     for (var i = 0; i <= t; ++i) {
313         c = 0;
314         k = i;
315         for (j = 0; j <= n; ++j, ++k) {
316             uv = result.digits[k] + x.digits[j] * y.digits[i] + c;
317             result.digits[k] = uv & maxDigitVal;
318             c = uv >>> biRadixBits;
319             //c = Math.floor(uv / biRadix);
320         }
321         result.digits[i + n + 1] = c;
322     }
323     // Someone give me a logical xor, please.
324     result.isNeg = x.isNeg != y.isNeg;
325     return result;
326 };
327 
328 RSAUtils.biMultiplyDigit = function (x, y) {
329     var n,
330     c,
331     uv;
332 
333     result = new BigInt();
334     n = RSAUtils.biHighIndex(x);
335     c = 0;
336     for (var j = 0; j <= n; ++j) {
337         uv = result.digits[j] + x.digits[j] * y + c;
338         result.digits[j] = uv & maxDigitVal;
339         c = uv >>> biRadixBits;
340         //c = Math.floor(uv / biRadix);
341     }
342     result.digits[1 + n] = c;
343     return result;
344 };
345 
346 RSAUtils.arrayCopy = function (src, srcStart, dest, destStart, n) {
347     var m = Math.min(srcStart + n, src.length);
348     for (var i = srcStart, j = destStart; i < m; ++i, ++j) {
349         dest[j] = src[i];
350     }
351 };
352 
353 var highBitMasks = [0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800,
354     0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
355     0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF];
356 
357 RSAUtils.biShiftLeft = function (x, n) {
358     var digitCount = Math.floor(n / bitsPerDigit);
359     var result = new BigInt();
360     RSAUtils.arrayCopy(x.digits, 0, result.digits, digitCount,
361         result.digits.length - digitCount);
362     var bits = n % bitsPerDigit;
363     var rightBits = bitsPerDigit - bits;
364     for (var i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) {
365         result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) |
366         ((result.digits[i1] & highBitMasks[bits]) >>>
367             (rightBits));
368     }
369     result.digits[0] = ((result.digits[i] << bits) & maxDigitVal);
370     result.isNeg = x.isNeg;
371     return result;
372 };
373 
374 var lowBitMasks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
375     0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
376     0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF];
377 
378 RSAUtils.biShiftRight = function (x, n) {
379     var digitCount = Math.floor(n / bitsPerDigit);
380     var result = new BigInt();
381     RSAUtils.arrayCopy(x.digits, digitCount, result.digits, 0,
382         x.digits.length - digitCount);
383     var bits = n % bitsPerDigit;
384     var leftBits = bitsPerDigit - bits;
385     for (var i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) {
386         result.digits[i] = (result.digits[i] >>> bits) |
387         ((result.digits[i1] & lowBitMasks[bits]) << leftBits);
388     }
389     result.digits[result.digits.length - 1] >>>= bits;
390     result.isNeg = x.isNeg;
391     return result;
392 };
393 
394 RSAUtils.biMultiplyByRadixPower = function (x, n) {
395     var result = new BigInt();
396     RSAUtils.arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n);
397     return result;
398 };
399 
400 RSAUtils.biDivideByRadixPower = function (x, n) {
401     var result = new BigInt();
402     RSAUtils.arrayCopy(x.digits, n, result.digits, 0, result.digits.length - n);
403     return result;
404 };
405 
406 RSAUtils.biModuloByRadixPower = function (x, n) {
407     var result = new BigInt();
408     RSAUtils.arrayCopy(x.digits, 0, result.digits, 0, n);
409     return result;
410 };
411 
412 RSAUtils.biCompare = function (x, y) {
413     if (x.isNeg != y.isNeg) {
414         return 1 - 2 * Number(x.isNeg);
415     }
416     for (var i = x.digits.length - 1; i >= 0; --i) {
417         if (x.digits[i] != y.digits[i]) {
418             if (x.isNeg) {
419                 return 1 - 2 * Number(x.digits[i] > y.digits[i]);
420             } else {
421                 return 1 - 2 * Number(x.digits[i] < y.digits[i]);
422             }
423         }
424     }
425     return 0;
426 };
427 
428 RSAUtils.biDivideModulo = function (x, y) {
429     var nb = RSAUtils.biNumBits(x);
430     var tb = RSAUtils.biNumBits(y);
431     var origYIsNeg = y.isNeg;
432     var q,
433     r;
434     if (nb < tb) {
435         // |x| < |y|
436         if (x.isNeg) {
437             q = RSAUtils.biCopy(bigOne);
438             q.isNeg = !y.isNeg;
439             x.isNeg = false;
440             y.isNeg = false;
441             r = biSubtract(y, x);
442             // Restore signs, 'cause they're references.
443             x.isNeg = true;
444             y.isNeg = origYIsNeg;
445         } else {
446             q = new BigInt();
447             r = RSAUtils.biCopy(x);
448         }
449         return [q, r];
450     }
451 
452     q = new BigInt();
453     r = x;
454 
455     // Normalize Y.
456     var t = Math.ceil(tb / bitsPerDigit) - 1;
457     var lambda = 0;
458     while (y.digits[t] < biHalfRadix) {
459         y = RSAUtils.biShiftLeft(y, 1);
460         ++lambda;
461         ++tb;
462         t = Math.ceil(tb / bitsPerDigit) - 1;
463     }
464     // Shift r over to keep the quotient constant. We'll shift the
465     // remainder back at the end.
466     r = RSAUtils.biShiftLeft(r, lambda);
467     nb += lambda; // Update the bit count for x.
468     var n = Math.ceil(nb / bitsPerDigit) - 1;
469 
470     var b = RSAUtils.biMultiplyByRadixPower(y, n - t);
471     while (RSAUtils.biCompare(r, b) != -1) {
472         ++q.digits[n - t];
473         r = RSAUtils.biSubtract(r, b);
474     }
475     for (var i = n; i > t; --i) {
476         var ri = (i >= r.digits.length) ? 0 : r.digits[i];
477         var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1];
478         var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2];
479         var yt = (t >= y.digits.length) ? 0 : y.digits[t];
480         var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1];
481         if (ri == yt) {
482             q.digits[i - t - 1] = maxDigitVal;
483         } else {
484             q.digits[i - t - 1] = Math.floor((ri * biRadix + ri1) / yt);
485         }
486 
487         var c1 = q.digits[i - t - 1] * ((yt * biRadix) + yt1);
488         var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2);
489         while (c1 > c2) {
490             --q.digits[i - t - 1];
491             c1 = q.digits[i - t - 1] * ((yt * biRadix) | yt1);
492             c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2);
493         }
494 
495         b = RSAUtils.biMultiplyByRadixPower(y, i - t - 1);
496         r = RSAUtils.biSubtract(r, RSAUtils.biMultiplyDigit(b, q.digits[i - t - 1]));
497         if (r.isNeg) {
498             r = RSAUtils.biAdd(r, b);
499             --q.digits[i - t - 1];
500         }
501     }
502     r = RSAUtils.biShiftRight(r, lambda);
503     // Fiddle with the signs and stuff to make sure that 0 <= r < y.
504     q.isNeg = x.isNeg != origYIsNeg;
505     if (x.isNeg) {
506         if (origYIsNeg) {
507             q = RSAUtils.biAdd(q, bigOne);
508         } else {
509             q = RSAUtils.biSubtract(q, bigOne);
510         }
511         y = RSAUtils.biShiftRight(y, lambda);
512         r = RSAUtils.biSubtract(y, r);
513     }
514     // Check for the unbelievably stupid degenerate case of r == -0.
515     if (r.digits[0] == 0 && RSAUtils.biHighIndex(r) == 0)
516         r.isNeg = false;
517 
518     return [q, r];
519 };
520 
521 RSAUtils.biDivide = function (x, y) {
522     return RSAUtils.biDivideModulo(x, y)[0];
523 };
524 
525 RSAUtils.biModulo = function (x, y) {
526     return RSAUtils.biDivideModulo(x, y)[1];
527 };
528 
529 RSAUtils.biMultiplyMod = function (x, y, m) {
530     return RSAUtils.biModulo(RSAUtils.biMultiply(x, y), m);
531 };
532 
533 RSAUtils.biPow = function (x, y) {
534     var result = bigOne;
535     var a = x;
536     while (true) {
537         if ((y & 1) != 0)
538             result = RSAUtils.biMultiply(result, a);
539         y >>= 1;
540         if (y == 0)
541             break;
542         a = RSAUtils.biMultiply(a, a);
543     }
544     return result;
545 };
546 
547 RSAUtils.biPowMod = function (x, y, m) {
548     var result = bigOne;
549     var a = x;
550     var k = y;
551     while (true) {
552         if ((k.digits[0] & 1) != 0)
553             result = RSAUtils.biMultiplyMod(result, a, m);
554         k = RSAUtils.biShiftRight(k, 1);
555         if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0)
556             break;
557         a = RSAUtils.biMultiplyMod(a, a, m);
558     }
559     return result;
560 };
561 
562 window.BarrettMu = function (m) {
563     this.modulus = RSAUtils.biCopy(m);
564     this.k = RSAUtils.biHighIndex(this.modulus) + 1;
565     var b2k = new BigInt();
566     b2k.digits[2 * this.k] = 1; // b2k = b^(2k)
567     this.mu = RSAUtils.biDivide(b2k, this.modulus);
568     this.bkplus1 = new BigInt();
569     this.bkplus1.digits[this.k + 1] = 1; // bkplus1 = b^(k+1)
570     this.modulo = BarrettMu_modulo;
571     this.multiplyMod = BarrettMu_multiplyMod;
572     this.powMod = BarrettMu_powMod;
573 };
574 
575 function BarrettMu_modulo(x) {
576     var $dmath = RSAUtils;
577     var q1 = $dmath.biDivideByRadixPower(x, this.k - 1);
578     var q2 = $dmath.biMultiply(q1, this.mu);
579     var q3 = $dmath.biDivideByRadixPower(q2, this.k + 1);
580     var r1 = $dmath.biModuloByRadixPower(x, this.k + 1);
581     var r2term = $dmath.biMultiply(q3, this.modulus);
582     var r2 = $dmath.biModuloByRadixPower(r2term, this.k + 1);
583     var r = $dmath.biSubtract(r1, r2);
584     if (r.isNeg) {
585         r = $dmath.biAdd(r, this.bkplus1);
586     }
587     var rgtem = $dmath.biCompare(r, this.modulus) >= 0;
588     while (rgtem) {
589         r = $dmath.biSubtract(r, this.modulus);
590         rgtem = $dmath.biCompare(r, this.modulus) >= 0;
591     }
592     return r;
593 }
594 
595 function BarrettMu_multiplyMod(x, y) {
596     /*
597     x = this.modulo(x);
598     y = this.modulo(y);
599      */
600     var xy = RSAUtils.biMultiply(x, y);
601     return this.modulo(xy);
602 }
603 
604 function BarrettMu_powMod(x, y) {
605     var result = new BigInt();
606     result.digits[0] = 1;
607     var a = x;
608     var k = y;
609     while (true) {
610         if ((k.digits[0] & 1) != 0)
611             result = this.multiplyMod(result, a);
612         k = RSAUtils.biShiftRight(k, 1);
613         if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0)
614             break;
615         a = this.multiplyMod(a, a);
616     }
617     return result;
618 }
619 
620 var RSAKeyPair = function (encryptionExponent, decryptionExponent, modulus) {
621     alert(1);
622     var $dmath = RSAUtils;
623     this.e = $dmath.biFromHex(encryptionExponent);
624     this.d = $dmath.biFromHex(decryptionExponent);
625     this.m = $dmath.biFromHex(modulus);
626     // We can do two bytes per digit, so
627     // chunkSize = 2 * (number of digits in modulus - 1).
628     // Since biHighIndex returns the high index, not the number of digits, 1 has
629     // already been subtracted.
630     this.chunkSize = 2 * $dmath.biHighIndex(this.m);
631     this.radix = 16;
632     this.barrett = new window.BarrettMu(this.m);
633 };
634 
635 RSAUtils.getKeyPair = function (encryptionExponent, decryptionExponent, modulus) {
636     return new RSAKeyPair(encryptionExponent, decryptionExponent, modulus);
637 };
638 
639 if (typeof window.twoDigit === 'undefined') {
640     window.twoDigit = function (n) {
641         return (n < 10 ? "0" : "") + String(n);
642     };
643 }
644 
645 // Altered by Rob Saunders (rob@robsaunders.net). New routine pads the
646 // string after it has been converted to an array. This fixes an
647 // incompatibility with Flash MX's ActionScript.
648 RSAUtils.encryptedString = function (key, s) {
649     var a = [];
650     var sl = s.length;
651     var i = 0;
652     while (i < sl) {
653         a[i] = s.charCodeAt(i);
654         i++;
655     }
656     while (a.length % key.chunkSize != 0) {
657         a[i++] = 0;
658     }
659 
660     var al = a.length;
661     var result = "";
662     var j,
663     k,
664     block;
665     for (i = 0; i < al; i += key.chunkSize) {
666         block = new BigInt();
667         j = 0;
668         for (k = i; k < i + key.chunkSize; ++j) {
669             block.digits[j] = a[k++];
670             block.digits[j] += a[k++] << 8;
671         }
672         var crypt = key.barrett.powMod(block, key.e);
673         var text = key.radix == 16 ? RSAUtils.biToHex(crypt) : RSAUtils.biToString(crypt, key.radix);
674         result += text + " ";
675     }
676     return result.substring(0, result.length - 1); // Remove last space.
677 };
678 
679 RSAUtils.decryptedString = function (key, s) {
680     var blocks = s.split(" ");
681     var result = "";
682     var i,
683     j,
684     block;
685     for (i = 0; i < blocks.length; ++i) {
686         var bi;
687         if (key.radix == 16) {
688             bi = RSAUtils.biFromHex(blocks[i]);
689         } else {
690             bi = RSAUtils.biFromString(blocks[i], key.radix);
691         }
692         block = key.barrett.powMod(bi, key.d);
693         for (j = 0; j <= RSAUtils.biHighIndex(block); ++j) {
694             result += String.fromCharCode(block.digits[j] & 255,
695                 block.digits[j] >> 8);
696         }
697     }
698     // Remove trailing null, if any.
699     if (result.charCodeAt(result.length - 1) == 0) {
700         result = result.substring(0, result.length - 1);
701     }
702     return result;
703 };
704 
705 RSAUtils.setMaxDigits(130);
706 // RSA 库前端开源部分 - 结束
707 
708 // 以下为LR调用RSA加密实现的关键代码
709 function createEncrypt() {
710     //LR.loadLibrary('rsaiutil.js');
711     //mobileNumberSet;//输入的手机号
712     //pwdSet;//输入的密码
713     //imgVerifyCodeSet;//输入的图形验证码
714 
715     // 通过 LR.getParam('mobileNumberSet') 可以在 JS 脚本中直接获取 LR 脚本的参数
716     var cliPublicKey = new RSAUtils.getKeyPair(LR.getParam('getDataExponent'), "", LR.getParam('getDataModulus'));
717     var encrypt = "mobileNumber=" + LR.getParam('mobileNumberSet') + "&pwd=" + LR.getParam('pwdSet') + "&imgVerifyCode=" + LR.getParam('imgVerifyCodeSet');//
718     encrypt = encrypt.split("").reverse().join("");//将需要加密的字符串反序排列
719     encrypt = RSAUtils.encryptedString(cliPublicKey, encrypt); //获得加密后的字符串
720     return encrypt;
721 }

运行 Action 的结果:

 1 虚拟用户脚本已于 : 2018/2/24 Saturday PM 4:05:06 启动
 2 正在开始操作 vuser_init。
 3 LoadRunner 12.53.0 (Windows 7) 的 Web Turbo 回放;内部版本 1203 (二月 24 2018 19:13:20)      [MsgId: MMSG-26983]
 4 运行模式: HTML      [MsgId: MMSG-26993]
 5 回放用户代理: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)      [MsgId: MMSG-26988]
 6 运行时设置文件: "C:\Users\VuGen\Scripts\WebHttpHtml6\\default.cfg"      [MsgId: MMSG-27141]
 7 正在结束操作 vuser_init。
 8 正在运行 Vuser...
 9 正在开始迭代 110 每个服务器的最大并发连接数: 6      [MsgId: MMSG-26989]
11 正在开始操作 Action。
12 Action.c(24): web_reg_save_param 已启动      [MsgId: MMSG-26355]
13 Action.c(24): 注册 web_reg_save_param 成功      [MsgId: MMSG-26390]
14 Action.c(26): web_submit_data("encryptKey.action") 已启动      [MsgId: MMSG-26355]
15 Action.c(26): web_submit_data("encryptKey.action") 已成功,613 个正文字节,155 个标头字节      [MsgId: MMSG-26386]
16 Action.c(36): # 获取密钥响应内容体:
17 {"publicKey":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBEZM4rLUDmybC9qFGLUwTFNsAbUFxyb\/SDTPr\nfVVgrkg1PL4yTOFyHgJe5oMcZyR0hqdz8fGpkesiN20dWwUem67tAszHgIHcVuswwyT2nV7pUNMj\nz53v5QWHsZ6\/oW1LXVnGYwvjVATHc1p2VOuATGw28XDEukWyGcKzTtcwzwIDAQAB\n","error_msg":"ok","error_code":0,"exponent":"010001","rKey":"5406701c505548beb3c1043bbcee5229","modulus":"00c1119338acb5039b26c2f6a1462d4c1314db006d4171c9bfd20d33eb7d5560ae48353cbe324ce1721e025ee6831c67247486a773f1f1a991eb22376d1d5b051e9baeed02ccc78081dc56eb30c324f69d5ee950d323cf9defe50587b19ebfa16d4b5d59c6630be35404c7735a7654eb804c6c36f170c4ba45b219c2b34ed730cf"}
18 Action.c(38): web_js_run 已启动      [MsgId: MMSG-26355]
19 Action.c(38): web_js_run 已成功      [MsgId: MMSG-26392]
20 Action.c(45): web_js_run 已启动      [MsgId: MMSG-26355]
21 Action.c(45): web_js_run 已成功      [MsgId: MMSG-26392]
22 Action.c(52): web_js_run 已启动      [MsgId: MMSG-26355]
23 Action.c(52): web_js_run 已成功      [MsgId: MMSG-26392]
24 Action.c(59): web_js_run 已启动      [MsgId: MMSG-26355]
25 Action.c(59): web_js_run 已成功      [MsgId: MMSG-26392]
26 Action.c(66): # getDataPublicKey 的值为:
27 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBEZM4rLUDmybC9qFGLUwTFNsAbUFxyb/SDTPr\nfVVgrkg1PL4yTOFyHgJe5oMcZyR0hqdz8fGpkesiN20dWwUem67tAszHgIHcVuswwyT2nV7pUNMj\nz53v5QWHsZ6/oW1LXVnGYwvjVATHc1p2VOuATGw28XDEukWyGcKzTtcwzwIDAQAB\n
28 Action.c(67): # getDataExponent 的值为:
29 010001
30 Action.c(68): # getDatarKey 的值为:
31 5406701c505548beb3c1043bbcee5229
32 Action.c(69): # getDataModulus 的值为:
33 00c1119338acb5039b26c2f6a1462d4c1314db006d4171c9bfd20d33eb7d5560ae48353cbe324ce1721e025ee6831c67247486a773f1f1a991eb22376d1d5b051e9baeed02ccc78081dc56eb30c324f69d5ee950d323cf9defe50587b19ebfa16d4b5d59c6630be35404c7735a7654eb804c6c36f170c4ba45b219c2b34ed730cf
34 Action.c(109): web_js_run 已启动      [MsgId: MMSG-26355]
35 Alert from JS (len=1): 1
36 Action.c(109): web_js_run 已成功      [MsgId: MMSG-26392]
37 Action.c(117): # NewkeyEncrypt 的值为:
38 4ea861aa44b8d90b08677e525ebd2607a992b87108308329fb01afd518bf4104344cb26e149ec43416a8181ad4cfc7e358e9ca2a2eab0a9072e5d86182e91f524376a3414b268244c62a2e149ac905679f66dd455ea386537136660508a3af71b479df9dc7beaf21ef5f2e70edfad8e88c64af35415e68258599c4b09791e43e
39 Action.c(121): web_reg_save_param 已启动      [MsgId: MMSG-26355]
40 Action.c(121): 注册 web_reg_save_param 成功      [MsgId: MMSG-26390]
41 Action.c(123): web_custom_request("userPwdLogin.action") 已启动      [MsgId: MMSG-26355]
42 Action.c(123): web_custom_request("userPwdLogin.action") 已成功,490 个正文字节,155 个标头字节      [MsgId: MMSG-26386]
43 Action.c(137): # newTokenJson 的值为:
44 {"portraitUrl":"http:\/\/test.666.com\/pt\/com\/img\/default-doctor-portrait.jpg","userGuideStat":null,"error_msg":"鐧诲綍鎴愬姛","nickname":"鍖昏€?6","alias":"dev473002","token":"cbc70505fccd4866aa88f3404a4ab8d1","error_code":0,"tag":"dev鍖荤敓","user_id":473002,"portraitUuid":"","type":"鍖荤敓","statistics":{"dtOnlinePrescOrdersPaid":0,"userId":473002,"role":"dt","dtOnlinePrescOrders":170,"lastLoginTime":"201802","registerTime":"2017-05-16 10:47:51","dtQualified":true}}
45 Action.c(138): # newTokenJsonUTF 的值为:
46 {"portraitUrl":"http:\/\/test.666.com\/pt\/com\/img\/default-doctor-portrait.jpg","userGuideStat":null,"error_msg":"登录成功","nickname":"医者26","alias":"dev473002","token":"cbc70505fccd4866aa88f3404a4ab8d1","error_code":0,"tag":"dev侵权者","user_id":473002,"portraitUuid":"","type":"侵权者","statistics":{"dtOnlinePrescOrdersPaid":0,"userId":473002,"role":"dt","dtOnlinePrescOrders":170,"lastLoginTime":"201802","registerTime":"2017-05-16 10:47:51","dtQualified":true}}
47 JS执行结果:0
48 正在结束操作 Action。
49 正在结束迭代 150 正在结束 Vuser...
51 正在开始操作 vuser_end。
52 正在结束操作 vuser_end。
53 Vuser 已终止。

另:开源的 RSA库 在未修改时,是独立的一个 JS 文件;未修改前是长这样:

  1 /*
  2  * RSA, a suite of routines for performing RSA public-key computations in JavaScript.
  3  * Copyright 1998-2005 David Shapiro.
  4  * Dave Shapiro
  5  * dave@ohdave.com
  6  * changed by Fuchun, 2010-05-06
  7  * fcrpg2005@gmail.com
  8  */
  9 
 10 (function ($w) {
 11 
 12     if (typeof $w.RSAUtils === 'undefined')
 13         var RSAUtils = $w.RSAUtils = {};
 14 
 15     var biRadixBase = 2;
 16     var biRadixBits = 16;
 17     var bitsPerDigit = biRadixBits;
 18     var biRadix = 1 << 16; // = 2^16 = 65536
 19     var biHalfRadix = biRadix >>> 1;
 20     var biRadixSquared = biRadix * biRadix;
 21     var maxDigitVal = biRadix - 1;
 22     var maxInteger = 9999999999999998;
 23 
 24     //maxDigits:
 25     //Change this to accommodate your largest number size. Use setMaxDigits()
 26     //to change it!
 27     //
 28     //In general, if you're working with numbers of size N bits, you'll need 2*N
 29     //bits of storage. Each digit holds 16 bits. So, a 1024-bit key will need
 30     //
 31     //1024 * 2 / 16 = 128 digits of storage.
 32     //
 33     var maxDigits;
 34     var ZERO_ARRAY;
 35     var bigZero,
 36     bigOne;
 37 
 38     var BigInt = $w.BigInt = function (flag) {
 39         if (typeof flag == "boolean" && flag == true) {
 40             this.digits = null;
 41         } else {
 42             this.digits = ZERO_ARRAY.slice(0);
 43         }
 44         this.isNeg = false;
 45     };
 46 
 47     RSAUtils.setMaxDigits = function (value) {
 48         maxDigits = value;
 49         ZERO_ARRAY = new Array(maxDigits);
 50         for (var iza = 0; iza < ZERO_ARRAY.length; iza++)
 51             ZERO_ARRAY[iza] = 0;
 52         bigZero = new BigInt();
 53         bigOne = new BigInt();
 54         bigOne.digits[0] = 1;
 55     };
 56     RSAUtils.setMaxDigits(20);
 57 
 58     //The maximum number of digits in base 10 you can convert to an
 59     //integer without JavaScript throwing up on you.
 60     var dpl10 = 15;
 61 
 62     RSAUtils.biFromNumber = function (i) {
 63         var result = new BigInt();
 64         result.isNeg = i < 0;
 65         i = Math.abs(i);
 66         var j = 0;
 67         while (i > 0) {
 68             result.digits[j++] = i & maxDigitVal;
 69             i = Math.floor(i / biRadix);
 70         }
 71         return result;
 72     };
 73 
 74     //lr10 = 10 ^ dpl10
 75     var lr10 = RSAUtils.biFromNumber(1000000000000000);
 76 
 77     RSAUtils.biFromDecimal = function (s) {
 78         var isNeg = s.charAt(0) == '-';
 79         var i = isNeg ? 1 : 0;
 80         var result;
 81         // Skip leading zeros.
 82         while (i < s.length && s.charAt(i) == '0')
 83             ++i;
 84         if (i == s.length) {
 85             result = new BigInt();
 86         } else {
 87             var digitCount = s.length - i;
 88             var fgl = digitCount % dpl10;
 89             if (fgl == 0)
 90                 fgl = dpl10;
 91             result = RSAUtils.biFromNumber(Number(s.substr(i, fgl)));
 92             i += fgl;
 93             while (i < s.length) {
 94                 result = RSAUtils.biAdd(RSAUtils.biMultiply(result, lr10),
 95                         RSAUtils.biFromNumber(Number(s.substr(i, dpl10))));
 96                 i += dpl10;
 97             }
 98             result.isNeg = isNeg;
 99         }
100         return result;
101     };
102 
103     RSAUtils.biCopy = function (bi) {
104         var result = new BigInt(true);
105         result.digits = bi.digits.slice(0);
106         result.isNeg = bi.isNeg;
107         return result;
108     };
109 
110     RSAUtils.reverseStr = function (s) {
111         var result = "";
112         for (var i = s.length - 1; i > -1; --i) {
113             result += s.charAt(i);
114         }
115         return result;
116     };
117 
118     var hexatrigesimalToChar = [
119         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
120         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
121         'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
122         'u', 'v', 'w', 'x', 'y', 'z'
123     ];
124 
125     RSAUtils.biToString = function (x, radix) { // 2 <= radix <= 36
126         var b = new BigInt();
127         b.digits[0] = radix;
128         var qr = RSAUtils.biDivideModulo(x, b);
129         var result = hexatrigesimalToChar[qr[1].digits[0]];
130         while (RSAUtils.biCompare(qr[0], bigZero) == 1) {
131             qr = RSAUtils.biDivideModulo(qr[0], b);
132             digit = qr[1].digits[0];
133             result += hexatrigesimalToChar[qr[1].digits[0]];
134         }
135         return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result);
136     };
137 
138     RSAUtils.biToDecimal = function (x) {
139         var b = new BigInt();
140         b.digits[0] = 10;
141         var qr = RSAUtils.biDivideModulo(x, b);
142         var result = String(qr[1].digits[0]);
143         while (RSAUtils.biCompare(qr[0], bigZero) == 1) {
144             qr = RSAUtils.biDivideModulo(qr[0], b);
145             result += String(qr[1].digits[0]);
146         }
147         return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result);
148     };
149 
150     var hexToChar = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
151         'a', 'b', 'c', 'd', 'e', 'f'];
152 
153     RSAUtils.digitToHex = function (n) {
154         var mask = 0xf;
155         var result = "";
156         for (i = 0; i < 4; ++i) {
157             result += hexToChar[n & mask];
158             n >>>= 4;
159         }
160         return RSAUtils.reverseStr(result);
161     };
162 
163     RSAUtils.biToHex = function (x) {
164         var result = "";
165         var n = RSAUtils.biHighIndex(x);
166         for (var i = RSAUtils.biHighIndex(x); i > -1; --i) {
167             result += RSAUtils.digitToHex(x.digits[i]);
168         }
169         return result;
170     };
171 
172     RSAUtils.charToHex = function (c) {
173         var ZERO = 48;
174         var NINE = ZERO + 9;
175         var littleA = 97;
176         var littleZ = littleA + 25;
177         var bigA = 65;
178         var bigZ = 65 + 25;
179         var result;
180 
181         if (c >= ZERO && c <= NINE) {
182             result = c - ZERO;
183         } else if (c >= bigA && c <= bigZ) {
184             result = 10 + c - bigA;
185         } else if (c >= littleA && c <= littleZ) {
186             result = 10 + c - littleA;
187         } else {
188             result = 0;
189         }
190         return result;
191     };
192 
193     RSAUtils.hexToDigit = function (s) {
194         var result = 0;
195         var sl = Math.min(s.length, 4);
196         for (var i = 0; i < sl; ++i) {
197             result <<= 4;
198             result |= RSAUtils.charToHex(s.charCodeAt(i));
199         }
200         return result;
201     };
202 
203     RSAUtils.biFromHex = function (s) {
204         var result = new BigInt();
205         var sl = s.length;
206         for (var i = sl, j = 0; i > 0; i -= 4, ++j) {
207             result.digits[j] = RSAUtils.hexToDigit(s.substr(Math.max(i - 4, 0), Math.min(i, 4)));
208         }
209         return result;
210     };
211 
212     RSAUtils.biFromString = function (s, radix) {
213         var isNeg = s.charAt(0) == '-';
214         var istop = isNeg ? 1 : 0;
215         var result = new BigInt();
216         var place = new BigInt();
217         place.digits[0] = 1; // radix^0
218         for (var i = s.length - 1; i >= istop; i--) {
219             var c = s.charCodeAt(i);
220             var digit = RSAUtils.charToHex(c);
221             var biDigit = RSAUtils.biMultiplyDigit(place, digit);
222             result = RSAUtils.biAdd(result, biDigit);
223             place = RSAUtils.biMultiplyDigit(place, radix);
224         }
225         result.isNeg = isNeg;
226         return result;
227     };
228 
229     RSAUtils.biDump = function (b) {
230         return (b.isNeg ? "-" : "") + b.digits.join(" ");
231     };
232 
233     RSAUtils.biAdd = function (x, y) {
234         var result;
235 
236         if (x.isNeg != y.isNeg) {
237             y.isNeg = !y.isNeg;
238             result = RSAUtils.biSubtract(x, y);
239             y.isNeg = !y.isNeg;
240         } else {
241             result = new BigInt();
242             var c = 0;
243             var n;
244             for (var i = 0; i < x.digits.length; ++i) {
245                 n = x.digits[i] + y.digits[i] + c;
246                 result.digits[i] = n % biRadix;
247                 c = Number(n >= biRadix);
248             }
249             result.isNeg = x.isNeg;
250         }
251         return result;
252     };
253 
254     RSAUtils.biSubtract = function (x, y) {
255         var result;
256         if (x.isNeg != y.isNeg) {
257             y.isNeg = !y.isNeg;
258             result = RSAUtils.biAdd(x, y);
259             y.isNeg = !y.isNeg;
260         } else {
261             result = new BigInt();
262             var n,
263             c;
264             c = 0;
265             for (var i = 0; i < x.digits.length; ++i) {
266                 n = x.digits[i] - y.digits[i] + c;
267                 result.digits[i] = n % biRadix;
268                 // Stupid non-conforming modulus operation.
269                 if (result.digits[i] < 0)
270                     result.digits[i] += biRadix;
271                 c = 0 - Number(n < 0);
272             }
273             // Fix up the negative sign, if any.
274             if (c == -1) {
275                 c = 0;
276                 for (var i = 0; i < x.digits.length; ++i) {
277                     n = 0 - result.digits[i] + c;
278                     result.digits[i] = n % biRadix;
279                     // Stupid non-conforming modulus operation.
280                     if (result.digits[i] < 0)
281                         result.digits[i] += biRadix;
282                     c = 0 - Number(n < 0);
283                 }
284                 // Result is opposite sign of arguments.
285                 result.isNeg = !x.isNeg;
286             } else {
287                 // Result is same sign.
288                 result.isNeg = x.isNeg;
289             }
290         }
291         return result;
292     };
293 
294     RSAUtils.biHighIndex = function (x) {
295         var result = x.digits.length - 1;
296         while (result > 0 && x.digits[result] == 0)
297             --result;
298         return result;
299     };
300 
301     RSAUtils.biNumBits = function (x) {
302         var n = RSAUtils.biHighIndex(x);
303         var d = x.digits[n];
304         var m = (n + 1) * bitsPerDigit;
305         var result;
306         for (result = m; result > m - bitsPerDigit; --result) {
307             if ((d & 0x8000) != 0)
308                 break;
309             d <<= 1;
310         }
311         return result;
312     };
313 
314     RSAUtils.biMultiply = function (x, y) {
315         var result = new BigInt();
316         var c;
317         var n = RSAUtils.biHighIndex(x);
318         var t = RSAUtils.biHighIndex(y);
319         var u,
320         uv,
321         k;
322 
323         for (var i = 0; i <= t; ++i) {
324             c = 0;
325             k = i;
326             for (j = 0; j <= n; ++j, ++k) {
327                 uv = result.digits[k] + x.digits[j] * y.digits[i] + c;
328                 result.digits[k] = uv & maxDigitVal;
329                 c = uv >>> biRadixBits;
330                 //c = Math.floor(uv / biRadix);
331             }
332             result.digits[i + n + 1] = c;
333         }
334         // Someone give me a logical xor, please.
335         result.isNeg = x.isNeg != y.isNeg;
336         return result;
337     };
338 
339     RSAUtils.biMultiplyDigit = function (x, y) {
340         var n,
341         c,
342         uv;
343 
344         result = new BigInt();
345         n = RSAUtils.biHighIndex(x);
346         c = 0;
347         for (var j = 0; j <= n; ++j) {
348             uv = result.digits[j] + x.digits[j] * y + c;
349             result.digits[j] = uv & maxDigitVal;
350             c = uv >>> biRadixBits;
351             //c = Math.floor(uv / biRadix);
352         }
353         result.digits[1 + n] = c;
354         return result;
355     };
356 
357     RSAUtils.arrayCopy = function (src, srcStart, dest, destStart, n) {
358         var m = Math.min(srcStart + n, src.length);
359         for (var i = srcStart, j = destStart; i < m; ++i, ++j) {
360             dest[j] = src[i];
361         }
362     };
363 
364     var highBitMasks = [0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800,
365         0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
366         0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF];
367 
368     RSAUtils.biShiftLeft = function (x, n) {
369         var digitCount = Math.floor(n / bitsPerDigit);
370         var result = new BigInt();
371         RSAUtils.arrayCopy(x.digits, 0, result.digits, digitCount,
372             result.digits.length - digitCount);
373         var bits = n % bitsPerDigit;
374         var rightBits = bitsPerDigit - bits;
375         for (var i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) {
376             result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) |
377             ((result.digits[i1] & highBitMasks[bits]) >>>
378                 (rightBits));
379         }
380         result.digits[0] = ((result.digits[i] << bits) & maxDigitVal);
381         result.isNeg = x.isNeg;
382         return result;
383     };
384 
385     var lowBitMasks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
386         0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
387         0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF];
388 
389     RSAUtils.biShiftRight = function (x, n) {
390         var digitCount = Math.floor(n / bitsPerDigit);
391         var result = new BigInt();
392         RSAUtils.arrayCopy(x.digits, digitCount, result.digits, 0,
393             x.digits.length - digitCount);
394         var bits = n % bitsPerDigit;
395         var leftBits = bitsPerDigit - bits;
396         for (var i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) {
397             result.digits[i] = (result.digits[i] >>> bits) |
398             ((result.digits[i1] & lowBitMasks[bits]) << leftBits);
399         }
400         result.digits[result.digits.length - 1] >>>= bits;
401         result.isNeg = x.isNeg;
402         return result;
403     };
404 
405     RSAUtils.biMultiplyByRadixPower = function (x, n) {
406         var result = new BigInt();
407         RSAUtils.arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n);
408         return result;
409     };
410 
411     RSAUtils.biDivideByRadixPower = function (x, n) {
412         var result = new BigInt();
413         RSAUtils.arrayCopy(x.digits, n, result.digits, 0, result.digits.length - n);
414         return result;
415     };
416 
417     RSAUtils.biModuloByRadixPower = function (x, n) {
418         var result = new BigInt();
419         RSAUtils.arrayCopy(x.digits, 0, result.digits, 0, n);
420         return result;
421     };
422 
423     RSAUtils.biCompare = function (x, y) {
424         if (x.isNeg != y.isNeg) {
425             return 1 - 2 * Number(x.isNeg);
426         }
427         for (var i = x.digits.length - 1; i >= 0; --i) {
428             if (x.digits[i] != y.digits[i]) {
429                 if (x.isNeg) {
430                     return 1 - 2 * Number(x.digits[i] > y.digits[i]);
431                 } else {
432                     return 1 - 2 * Number(x.digits[i] < y.digits[i]);
433                 }
434             }
435         }
436         return 0;
437     };
438 
439     RSAUtils.biDivideModulo = function (x, y) {
440         var nb = RSAUtils.biNumBits(x);
441         var tb = RSAUtils.biNumBits(y);
442         var origYIsNeg = y.isNeg;
443         var q,
444         r;
445         if (nb < tb) {
446             // |x| < |y|
447             if (x.isNeg) {
448                 q = RSAUtils.biCopy(bigOne);
449                 q.isNeg = !y.isNeg;
450                 x.isNeg = false;
451                 y.isNeg = false;
452                 r = biSubtract(y, x);
453                 // Restore signs, 'cause they're references.
454                 x.isNeg = true;
455                 y.isNeg = origYIsNeg;
456             } else {
457                 q = new BigInt();
458                 r = RSAUtils.biCopy(x);
459             }
460             return [q, r];
461         }
462 
463         q = new BigInt();
464         r = x;
465 
466         // Normalize Y.
467         var t = Math.ceil(tb / bitsPerDigit) - 1;
468         var lambda = 0;
469         while (y.digits[t] < biHalfRadix) {
470             y = RSAUtils.biShiftLeft(y, 1);
471             ++lambda;
472             ++tb;
473             t = Math.ceil(tb / bitsPerDigit) - 1;
474         }
475         // Shift r over to keep the quotient constant. We'll shift the
476         // remainder back at the end.
477         r = RSAUtils.biShiftLeft(r, lambda);
478         nb += lambda; // Update the bit count for x.
479         var n = Math.ceil(nb / bitsPerDigit) - 1;
480 
481         var b = RSAUtils.biMultiplyByRadixPower(y, n - t);
482         while (RSAUtils.biCompare(r, b) != -1) {
483             ++q.digits[n - t];
484             r = RSAUtils.biSubtract(r, b);
485         }
486         for (var i = n; i > t; --i) {
487             var ri = (i >= r.digits.length) ? 0 : r.digits[i];
488             var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1];
489             var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2];
490             var yt = (t >= y.digits.length) ? 0 : y.digits[t];
491             var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1];
492             if (ri == yt) {
493                 q.digits[i - t - 1] = maxDigitVal;
494             } else {
495                 q.digits[i - t - 1] = Math.floor((ri * biRadix + ri1) / yt);
496             }
497 
498             var c1 = q.digits[i - t - 1] * ((yt * biRadix) + yt1);
499             var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2);
500             while (c1 > c2) {
501                 --q.digits[i - t - 1];
502                 c1 = q.digits[i - t - 1] * ((yt * biRadix) | yt1);
503                 c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2);
504             }
505 
506             b = RSAUtils.biMultiplyByRadixPower(y, i - t - 1);
507             r = RSAUtils.biSubtract(r, RSAUtils.biMultiplyDigit(b, q.digits[i - t - 1]));
508             if (r.isNeg) {
509                 r = RSAUtils.biAdd(r, b);
510                 --q.digits[i - t - 1];
511             }
512         }
513         r = RSAUtils.biShiftRight(r, lambda);
514         // Fiddle with the signs and stuff to make sure that 0 <= r < y.
515         q.isNeg = x.isNeg != origYIsNeg;
516         if (x.isNeg) {
517             if (origYIsNeg) {
518                 q = RSAUtils.biAdd(q, bigOne);
519             } else {
520                 q = RSAUtils.biSubtract(q, bigOne);
521             }
522             y = RSAUtils.biShiftRight(y, lambda);
523             r = RSAUtils.biSubtract(y, r);
524         }
525         // Check for the unbelievably stupid degenerate case of r == -0.
526         if (r.digits[0] == 0 && RSAUtils.biHighIndex(r) == 0)
527             r.isNeg = false;
528 
529         return [q, r];
530     };
531 
532     RSAUtils.biDivide = function (x, y) {
533         return RSAUtils.biDivideModulo(x, y)[0];
534     };
535 
536     RSAUtils.biModulo = function (x, y) {
537         return RSAUtils.biDivideModulo(x, y)[1];
538     };
539 
540     RSAUtils.biMultiplyMod = function (x, y, m) {
541         return RSAUtils.biModulo(RSAUtils.biMultiply(x, y), m);
542     };
543 
544     RSAUtils.biPow = function (x, y) {
545         var result = bigOne;
546         var a = x;
547         while (true) {
548             if ((y & 1) != 0)
549                 result = RSAUtils.biMultiply(result, a);
550             y >>= 1;
551             if (y == 0)
552                 break;
553             a = RSAUtils.biMultiply(a, a);
554         }
555         return result;
556     };
557 
558     RSAUtils.biPowMod = function (x, y, m) {
559         var result = bigOne;
560         var a = x;
561         var k = y;
562         while (true) {
563             if ((k.digits[0] & 1) != 0)
564                 result = RSAUtils.biMultiplyMod(result, a, m);
565             k = RSAUtils.biShiftRight(k, 1);
566             if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0)
567                 break;
568             a = RSAUtils.biMultiplyMod(a, a, m);
569         }
570         return result;
571     };
572 
573     $w.BarrettMu = function (m) {
574         this.modulus = RSAUtils.biCopy(m);
575         this.k = RSAUtils.biHighIndex(this.modulus) + 1;
576         var b2k = new BigInt();
577         b2k.digits[2 * this.k] = 1; // b2k = b^(2k)
578         this.mu = RSAUtils.biDivide(b2k, this.modulus);
579         this.bkplus1 = new BigInt();
580         this.bkplus1.digits[this.k + 1] = 1; // bkplus1 = b^(k+1)
581         this.modulo = BarrettMu_modulo;
582         this.multiplyMod = BarrettMu_multiplyMod;
583         this.powMod = BarrettMu_powMod;
584     };
585 
586     function BarrettMu_modulo(x) {
587         var $dmath = RSAUtils;
588         var q1 = $dmath.biDivideByRadixPower(x, this.k - 1);
589         var q2 = $dmath.biMultiply(q1, this.mu);
590         var q3 = $dmath.biDivideByRadixPower(q2, this.k + 1);
591         var r1 = $dmath.biModuloByRadixPower(x, this.k + 1);
592         var r2term = $dmath.biMultiply(q3, this.modulus);
593         var r2 = $dmath.biModuloByRadixPower(r2term, this.k + 1);
594         var r = $dmath.biSubtract(r1, r2);
595         if (r.isNeg) {
596             r = $dmath.biAdd(r, this.bkplus1);
597         }
598         var rgtem = $dmath.biCompare(r, this.modulus) >= 0;
599         while (rgtem) {
600             r = $dmath.biSubtract(r, this.modulus);
601             rgtem = $dmath.biCompare(r, this.modulus) >= 0;
602         }
603         return r;
604     }
605 
606     function BarrettMu_multiplyMod(x, y) {
607         /*
608         x = this.modulo(x);
609         y = this.modulo(y);
610          */
611         var xy = RSAUtils.biMultiply(x, y);
612         return this.modulo(xy);
613     }
614 
615     function BarrettMu_powMod(x, y) {
616         var result = new BigInt();
617         result.digits[0] = 1;
618         var a = x;
619         var k = y;
620         while (true) {
621             if ((k.digits[0] & 1) != 0)
622                 result = this.multiplyMod(result, a);
623             k = RSAUtils.biShiftRight(k, 1);
624             if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0)
625                 break;
626             a = this.multiplyMod(a, a);
627         }
628         return result;
629     }
630 
631     var RSAKeyPair = function (encryptionExponent, decryptionExponent, modulus) {
632         var $dmath = RSAUtils;
633         this.e = $dmath.biFromHex(encryptionExponent);
634         this.d = $dmath.biFromHex(decryptionExponent);
635         this.m = $dmath.biFromHex(modulus);
636         // We can do two bytes per digit, so
637         // chunkSize = 2 * (number of digits in modulus - 1).
638         // Since biHighIndex returns the high index, not the number of digits, 1 has
639         // already been subtracted.
640         this.chunkSize = 2 * $dmath.biHighIndex(this.m);
641         this.radix = 16;
642         this.barrett = new $w.BarrettMu(this.m);
643     };
644 
645     RSAUtils.getKeyPair = function (encryptionExponent, decryptionExponent, modulus) {
646         return new RSAKeyPair(encryptionExponent, decryptionExponent, modulus);
647     };
648 
649     if (typeof $w.twoDigit === 'undefined') {
650         $w.twoDigit = function (n) {
651             return (n < 10 ? "0" : "") + String(n);
652         };
653     }
654 
655     // Altered by Rob Saunders (rob@robsaunders.net). New routine pads the
656     // string after it has been converted to an array. This fixes an
657     // incompatibility with Flash MX's ActionScript.
658     RSAUtils.encryptedString = function (key, s) {
659         var a = [];
660         var sl = s.length;
661         var i = 0;
662         while (i < sl) {
663             a[i] = s.charCodeAt(i);
664             i++;
665         }
666         while (a.length % key.chunkSize != 0) {
667             a[i++] = 0;
668         }
669 
670         var al = a.length;
671         var result = "";
672         var j,
673         k,
674         block;
675         for (i = 0; i < al; i += key.chunkSize) {
676             block = new BigInt();
677             j = 0;
678             for (k = i; k < i + key.chunkSize; ++j) {
679                 block.digits[j] = a[k++];
680                 block.digits[j] += a[k++] << 8;
681             }
682             var crypt = key.barrett.powMod(block, key.e);
683             var text = key.radix == 16 ? RSAUtils.biToHex(crypt) : RSAUtils.biToString(crypt, key.radix);
684             result += text + " ";
685         }
686         return result.substring(0, result.length - 1); // Remove last space.
687     };
688 
689     RSAUtils.decryptedString = function (key, s) {
690         var blocks = s.split(" ");
691         var result = "";
692         var i,
693         j,
694         block;
695         for (i = 0; i < blocks.length; ++i) {
696             var bi;
697             if (key.radix == 16) {
698                 bi = RSAUtils.biFromHex(blocks[i]);
699             } else {
700                 bi = RSAUtils.biFromString(blocks[i], key.radix);
701             }
702             block = key.barrett.powMod(bi, key.d);
703             for (j = 0; j <= RSAUtils.biHighIndex(block); ++j) {
704                 result += String.fromCharCode(block.digits[j] & 255,
705                     block.digits[j] >> 8);
706             }
707         }
708         // Remove trailing null, if any.
709         if (result.charCodeAt(result.length - 1) == 0) {
710             result = result.substring(0, result.length - 1);
711         }
712         return result;
713     };
714 
715     RSAUtils.setMaxDigits(130);
716 
717 })(window);
View Code

 

posted @ 2018-02-28 10:44  Snooper  阅读(3681)  评论(0编辑  收藏  举报