javascript实现rsa算法(支持微信小程序)
概述:
本代码是本人从c代码上转换成的javascript代码,本人踏踏实实改了一个星期(累死我了),反反复复测试验证通过的。公钥计算快,私钥计算很慢。
在微信小程序上测试验证通过的,和我们常用的文件wxapp_rsa.js对比
1、代码少,才30k左右,而wxapp_rsa.js有400k;
2、功能少了对公钥文件解析(很麻烦,我基本上不会在前端用到),取代直接传密钥的各个部分(公钥指数模,私钥指数模);
3、功能少了base64处理,这功能简单很容易其他地方找到;
测试平台:
已经在如下环境中测试通过,其他平台(浏览器)应该也不会有问题:
1、nodejs中node.exe运行
2、微信小程序
功能代码:
function strRsaCtxParams() {
this.keyn;
this.keye;
this.keyd;
this.keybits;
};
function rsa_pkcs1_pad(orgdata, mode/*0:0填充,1:F填充, 2:不为0随机数填充*/, bits) {
var outData = new Uint8Array(parseInt((bits + 7) / 8));
var i = 0;
var j = 0;
for (i = 0; i < outData.length; i++) {
outData[i] = 0;
}
//return outData;
//mode = 1;
if (orgdata.length > outData.length - 4) {
throw Error('数据长度过长导致不能填充');
}
if (mode != 0 && mode != 1 && mode != 2) {
throw Error('填充模式必须在0,1,2中选择');
}
outData[0] = 0x00;
outData[1] = mode;
for (i = 2; i < outData.length - orgdata.length - 1; i++) {
if (mode == 0) {
outData[i] = 0;
} else if (mode == 1) {
outData[i] = 0xFF;
} else if (mode == 2) {
outData[i] = parseInt(Math.random() * 256) & 0xff;
if (outData[i] == 0) {
/* 简单点,为0改为1 */
outData[i] = 1;
}
}
}
//console.log("i1 = %d", i);
outData[i] = 0;
i++;
j = 0;
while (i < outData.length && j < orgdata.length) {
outData[i] = orgdata[j];
i++;
j++;
}
//console.log("i2 = %d", i);
return outData;
}
function rsa_set_key(keyNArray, keyEArray, keyDArray) {
var rsaCtxParams = new strRsaCtxParams();
//var i = 0;
if (keyNArray == null || keyNArray.length <= 0) {
throw Error('n的值不能为空');
}
rsaCtxParams.keybits = CalArrayBits(keyNArray, keyNArray.length);
rsaCtxParams.keyn = NN_Decode(keyNArray, keyNArray.length);
//console.log("rsaCtxParams.keyn len = %d index0=%d index1=%d index63=%d", rsaCtxParams.keyn.length, rsaCtxParams.keyn[0], rsaCtxParams.keyn[1], rsaCtxParams.keyn[63]);
if (keyEArray != null) {
rsaCtxParams.keye = NN_Decode(keyEArray, keyEArray.length);
}
if (keyDArray != null) {
rsaCtxParams.keyd = NN_Decode(keyDArray, keyDArray.length);
}
return rsaCtxParams;
}
function rsa_pub_cal(rsaCtxParams, lpIn) {
var m = null;
var c = null;
var eDigits, nDigits;
var outResult = null;
var tmpInt = 0;
if (rsaCtxParams.keyn == null || rsaCtxParams.keyn.length <= 0) {
throw Error('n的值不能为空');
}
if (rsaCtxParams.keye == null || rsaCtxParams.keye.length <= 0) {
throw Error('e的值不能为空');
}
m = NN_Decode(lpIn, lpIn.length);
if (BignumCmp(m, rsaCtxParams.keyn) >= 0) {
throw Error('输入数据不能大于等于n');
}
//console.log("m len = %d", m.length);
//printfInts("m", m, m.length);
nDigits = NN_Digits(rsaCtxParams.keyn, 0, rsaCtxParams.keyn.length);
eDigits = NN_Digits(rsaCtxParams.keye, 0, rsaCtxParams.keye.length);
//console.log("nDigits = %d eDigits = %d", nDigits, eDigits);
c = new Array(parseInt(((rsaCtxParams.keybits) + 31) / 32));
init_u32array(c, c.length);
NN_ModExp(c, m, rsaCtxParams.keye, eDigits, rsaCtxParams.keyn, nDigits, rsaCtxParams);
tmpInt = parseInt((rsaCtxParams.keybits + 7) / 8);
outResult = new Uint8Array(tmpInt);
NN_Encode(outResult, 0, tmpInt, c, 0, nDigits);
return outResult;
}
function rsa_pri_cal(rsaCtxParams, lpIn) {
var m = null;
var c = null;
var nDigits = 0;
var dDigits = 0;
var outResult = null;
var tmpInt = 0;
if (rsaCtxParams.keyn == null || rsaCtxParams.keyn.length <= 0) {
throw Error('n的值不能为空');
}
if (rsaCtxParams.keyd == null || rsaCtxParams.keyd.length <= 0) {
throw Error('e的值不能为空');
}
c = NN_Decode(lpIn, lpIn.length);
if (BignumCmp(c, rsaCtxParams.keyn) >= 0) {
throw Error('输入数据不能大于等于n');
}
nDigits = NN_Digits(rsaCtxParams.keyn, 0, rsaCtxParams.keyn.length);
dDigits = NN_Digits(rsaCtxParams.keyd, 0, rsaCtxParams.keyd.length);
m = new Array(parseInt(((rsaCtxParams.keybits) + 31) / 32));
//console.log("pro0");
NN_ModExp(m, c, rsaCtxParams.keyd, dDigits, rsaCtxParams.keyn, nDigits, rsaCtxParams);
//console.log("pro1");
tmpInt = parseInt((rsaCtxParams.keybits + 7) / 8);
outResult = new Uint8Array(tmpInt);
NN_Encode(outResult, 0, tmpInt, m, 0, nDigits);
return outResult;
}
function NN_Encode(a, aindex, len, b, bindex, digits) {
var t;
var j;
var i, u;
for (i = 0, j = len - 1; i < digits && j >= 0; i++) {
t = b[i + bindex];
for (u = 0; j >= 0 && u < 32; j--, u += 8) {
a[j + aindex] = (t >>> u) & 0xffffffff;
}
}
for (; j >= 0; j--) {
a[j + aindex] = 0;
}
}
function NN_ASSIGN_DIGIT(a, aindex, b, digits) {
NN_AssignZero(a, aindex, digits);
a[0] = b;
}
function DIGIT_2MSB(x) {
//(unsigned int)(((x) >> (NN_DIGIT_BITS - 2)) & 3)
return ((((x) >>> (32 - 2)) & 3) & 0xffffffff) >>> 0;
}
//var testI = 0;
function NN_ModExp(a, b, c, cDigits, d, dDigits, rsaCtxParams) {
var uPowerLen = parseInt((rsaCtxParams.keybits + 31) / 32);
var bPower = new Array(3 * uPowerLen);
var t = new Array(uPowerLen);
var i = 0, j = 0, s = 0;
var ci = 0;
var ciBits = 0;
init_u32array(bPower, bPower.length);
//for (i = 0; i < bPower.length; i++) {
// bPower[i] = 0;
//}
//console.log("dDigits = %d", dDigits);
//printfInts("bPower", bPower, bPower.length);
//printfInts("b", b, b.length);
//throw Error("11");
//console.log("pro2");
NN_Assign(bPower, 0, b, 0, dDigits);
//printfInts("bPower", bPower, bPower.length);
//printfInts("b", b, b.length);
//throw Error("223");
//console.log("pro3");
NN_ModMult(bPower, uPowerLen, bPower, 0, b, 0, d, 0, dDigits, rsaCtxParams);
//console.log("pro4");
NN_ModMult(bPower, uPowerLen * 2, bPower, uPowerLen, b, 0, d, 0, dDigits, rsaCtxParams);
//NN_Assign(bPower, uPowerLen, b, 0, dDigits);
//NN_Assign(bPower, uPowerLen * 2, b, 0, dDigits);
//printfIntsIndex("bPower0", bPower, 0, uPowerLen);
//printfIntsIndex("bPower1", bPower, uPowerLen, uPowerLen);
//printfIntsIndex("bPower2", bPower, uPowerLen * 2, uPowerLen);
//console.log("pro5");
NN_ASSIGN_DIGIT(t, 0, 1, dDigits);
//console.log("pro6");
cDigits = NN_Digits(c, 0, cDigits);
//console.log("pro7");
for (i = cDigits - 1; i >= 0; i--) {
//console.log("pro8");
ci = c[i];
ciBits = 32;
if (i == (cDigits - 1)) {
while (0 == DIGIT_2MSB(ci)) {
//console.log("pro9");
ci <<= 2;
ci &= 0xffffffff;
//ciBits -= 2;
ciBits = bn_u32_minus(ciBits, 2);
}
}
for (j = 0; j < ciBits; j += 2, ci = (ci << 2) & 0xffffffff) {
//console.log("pro10");
/* Compute t = t^4 * b^s mod d, where s = two MSB's of ci. */
NN_ModMult(t, 0, t, 0, t, 0, d, 0, dDigits, rsaCtxParams);
//console.log("pro11");
NN_ModMult(t, 0, t, 0, t, 0, d, 0, dDigits, rsaCtxParams);
//console.log("pro12");
s = DIGIT_2MSB(ci);
//console.log("pro13");
if ((s) != 0) {
//console.log("pro14");
//testI++;
//console.log("testI = %d s = %d dDigits = %d", testI, s, dDigits);
/*if (testI >= 412) {
printfInts("t", t, 129);
printfInts("d", d, 128);
printfIntsIndex("bPower0", bPower, 0, 128);
printfIntsIndex("bPower1", bPower, uPowerLen, 128);
printfIntsIndex("bPower2", bPower, uPowerLen * 2, 128);
exit(0);
}*/
NN_ModMult(t, 0, t, 0, bPower, (s - 1) * uPowerLen, d, 0, dDigits, rsaCtxParams);
//console.log("pro15");
}
}
}
NN_Assign(a, 0, t, 0, dDigits);
//printfInts("a", a, a.length);
//printfInts("b", b, b.length);
//printfInts("c", c, c.length);
//printfInts("t", t, t.length);
}
function bn_u32_compare(uint1, uint2) {
uint1 &= 0xffffffff;
uint2 &= 0xffffffff;
if ((uint1 & 0x80000000) == 0 && (uint2 & 0x80000000) == 0) {
return uint1 > uint2 ? 1 : (uint1 == uint2 ? 0 : (-1));
}
if ((uint1 & 0x80000000) != 0 && (uint2 & 0x80000000) != 0) {
uint1 &= 0x7fffffff;
uint2 &= 0x7fffffff;
return uint1 > uint2 ? 1 : (uint1 == uint2 ? 0 : (-1));
}
if ((uint1 & 0x80000000) != 0) {
return 1;
} else {
return -1;
}
}
function bn_u32_add(add1, add2) {
var i = 0;
var tmp = 0;
var result = 0;
for (i = 0; i < 4; i++) {
tmp = ((add1 >>> (i * 8)) & 0xff) + ((add2 >>> (i * 8)) & 0xff) + tmp;
result |= ((tmp & 0xff) << (i * 8));
tmp = tmp >>> 8;
}
return result & 0xffffffff;
}
function bn_u32_minus(minuend, subtractor) {
var a = (minuend & 0xffffffff) >>> 0;
var b = (subtractor & 0xffffffff) >>> 0;
return (a - b) & 0xffffffff;
}
function NN_ModMult(a, aindex, b, bindex, c, cindex, d, dindex, digits, rsaCtxParams) {
var t = new Array(2 * parseInt((rsaCtxParams.keybits + 31) / 32));
init_u32array(t, t.length);
//console.log("pp0");
NN_Mult(t, 0, b, bindex, c, cindex, digits, rsaCtxParams);
//printfIntsIndex("t", t, 0, 128);
//printfIntsIndex("b", b, bindex, 128);
//printfIntsIndex("c", c, cindex, 128);
//console.log("pp1");
NN_Mod(a, aindex, t, 0, 2 * digits, d, dindex, digits, rsaCtxParams);
}
function NN_Mod(a, aindex, b, bindex, bDigits, c, cindex, cDigits, rsaCtxParams) {
//NN_DIGIT t[2 * MAX_NN_DIGITS];
var t = new Array(2 * parseInt((rsaCtxParams.keybits + 31) / 32));
init_u32array(t, t.length);
NN_Div(t, 0, a, aindex, b, bindex, bDigits, c, cindex, cDigits, rsaCtxParams);
}
function NN_DigitBits(a) {
var i;
for (i = 0; i < 32; i++, a = ((a >>> 1) & 0xffffffff)) {
if (a == 0) {
break;
}
}
return (i);
}
function NN_LShift(a, aindex, b, bindex, c, digits) {
var temp, carry = 0;
var tmpbindex = 0;
var tmpaindex = 0;
var t;
if (c < 32 && digits != 0) {
t = 32 - c;
do {
temp = b[tmpbindex + bindex];
//b++;
tmpbindex++;
//*a = (temp << c) | carry;
a[tmpaindex + aindex] = ((temp << c) | carry) & 0xffffffff;
//a++;
tmpaindex++;
carry = (c != 0 ? (temp >>> t) : 0) & 0xffffffff;
digits--;
if (digits == 0) {
break;
}
} while (true);
}
return (carry) & 0xffffffff;
}
function NN_RShift(a, aindex, b, bindex, c, digits) {
var temp = 0,
carry = 0;
var tmpbindex = 0;
var tmpaindex = 0;
var t = 0;
if (c < 32 && digits != 0) {
//if(digits) {
t = 32 - c;
do {
digits--;
//temp = *(b+digits);
temp = b[digits + bindex];
//*(a+digits) = ((temp >> c) | carry);
a[digits + aindex] = ((temp >>> c) | carry) & 0xffffffff;
carry = (c != 0 ? (temp << t) : 0) & 0xffffffff;
} while (digits != 0);
}
return ((carry) & 0xffffffff) >>> 0;
}
function TO_HIGH_HALF(x) {
return ((x << 16) & 0xffffffff) >>> 0;
}
function subdigitmult(a, aindex, b, bindex, c, d, dindex, digits) {
var borrow = 0,
thigh = 0,
tlow = 0;
var i = 0;
var arr = new Array(2);
borrow = 0;
if (c != 0) {
for (i = 0; i < digits; i++) {
//function dmult(a, b, high, highindex, low, lowindex)
//dmult(c, d[i], &thigh, &tlow);
arr[0] = thigh;
arr[1] = tlow;
dmult(c, d[i + dindex], arr, 0, arr, 1);
thigh = arr[0];
tlow = arr[1];
//a[i] = b[i] - borrow;
a[i + aindex] = bn_u32_minus(b[i + bindex], borrow);
//if((a[i]) > (MAX_NN_DIGIT - borrow)) {
if (bn_u32_compare(a[i + aindex], bn_u32_minus(0xffffffff, borrow)) > 0) {
borrow = 1;
} else {
borrow = 0;
}
//a[i] -= tlow;
a[i + aindex] = bn_u32_minus(a[i + aindex], tlow);
//if((a[i]) > (MAX_NN_DIGIT - tlow)) {
if (bn_u32_compare(a[i + aindex], bn_u32_minus(0xffffffff, tlow)) > 0) {
//borrow++;
borrow = bn_u32_add(borrow, 1);
}
//borrow += thigh;
borrow = bn_u32_add(borrow, thigh);
}
}
return (borrow) & 0xffffffff;
}
function NN_Cmp(a, aindex, b, bindex, digits) {
if (digits != 0) {
do {
digits--;
if ((a[digits + aindex] >>> 16) > (b[digits + bindex] >>> 16)) {
return 1;
}
if ((a[digits + aindex] >>> 16) < (b[digits + bindex] >>> 16)) {
return -1;
}
if ((a[digits + aindex] & 0xffff) > (b[digits + bindex] & 0xffff)) {
return 1;
}
if ((a[digits + aindex] & 0xffff) < (b[digits + bindex] & 0xffff)) {
return -1;
}
//if(*(a+digits) > *(b+digits))
// return(1);
//if(*(a+digits) < *(b+digits))
// return(-1);
} while (digits != 0);
}
return (0);
}
function NN_Sub(a, aindex, b, bindex, c, cindex, digits) {
var temp = 0,
borrow = 0;
var tmpaindex = 0,
tmpbindex = 0,
tmpcindex = 0;
if (digits != 0)
do {
//temp = (*b) - borrow;
temp = bn_u32_minus(b[tmpbindex + bindex], borrow);
//b++;
//b = bn_u32_add(b, 1);
tmpbindex++;
//if(temp == MAX_NN_DIGIT) {
if (bn_u32_compare(temp, 0xffffffff) == 0) {
//temp = MAX_NN_DIGIT - (*c);
temp = bn_u32_minus(0xffffffff, c[tmpcindex + cindex]);
//c++;
tmpcindex++;
} else {
//temp -= (*c);
temp = bn_u32_minus(temp, c[tmpcindex + cindex]);
//if((temp) > (MAX_NN_DIGIT - (*c))) {
if (bn_u32_compare(temp, bn_u32_minus(0xffffffff, c[tmpcindex + cindex])) > 0) {
borrow = 1;
} else {
borrow = 0;
}
//c++;
tmpcindex++;
}
//*a = temp;
a[tmpaindex + aindex] = temp & 0xffffffff;
//a++;
tmpaindex++;
digits--;
if (digits == 0) {
break;
}
} while (true);
return (borrow);
}
//var test2 = 0;
//var testI = 0;
function NN_Div(a, aindex, b, bindex, c, cindex, cDigits, d, dindex, dDigits, rsaCtxParams) {
//NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], s;
//NN_DIGIT t[2], u, v, *ccptr;
//NN_HALF_DIGIT aHigh, aLow, cHigh, cLow;
//int i;
//unsigned int ddDigits, shift;
var cc = new Array(2 * parseInt((rsaCtxParams.keybits + 31) / 32) + 1);
var dd = new Array(2 * parseInt((rsaCtxParams.keybits + 31) / 32));
var t = new Array(2);
var ddDigits = 0;
var shift = 0;
var s, u, v;
var ai;
var cHigh, cLow, aHigh, aLow;
var i = 0;
//var ccptrindex = 0;
init_u32array(cc, cc.length);
init_u32array(dd, dd.length);
NN_AssignZero(dd, 0, dd.length);
ddDigits = NN_Digits(d, dindex, dDigits);
if (ddDigits == 0) {
return;
}
shift = 32 - NN_DigitBits(d[dindex + ddDigits - 1]);
//console.log("shift = %d", shift);
NN_AssignZero(cc, 0, ddDigits);
cc[cDigits] = NN_LShift(cc, 0, c, 0, shift, cDigits);
//console.log("cc[cDigits] = %d", cc[cDigits]);
NN_LShift(dd, 0, d, 0, shift, ddDigits);
s = dd[ddDigits - 1];
//console.log("s = %d", s);
//printfInts("cc", cc, cc.length);
//printfInts("dd", dd, dd.length);
//throw Error("111");
NN_AssignZero(a, aindex, cDigits);
//throw Error("11222");
//test2 = 0;
for (i = cDigits - ddDigits; i >= 0; i--) {
test2++;
//if (testI >= 412) {
// console.log("test2 = %d", test2);
//}
if (bn_u32_compare(s, 0xffffffff) == 0) {
ai = (cc[i + ddDigits]) & 0xffffffff;
} else {
s = bn_u32_add(s, 1);
cHigh = HIGH_HALF(s);
cLow = LOW_HALF(s);
t[0] = cc[i + ddDigits - 1];
t[1] = cc[i + ddDigits];
//if (testI >= 412 && test2 >= 13) console.log("t10 = %d %d", t[0], t[1]);
if (cHigh == 0xffff) {
aHigh = HIGH_HALF(t[1]);
//if (testI >= 412 && test2 >= 13) console.log("aHigh1=%d", aHigh);
} else {
aHigh = parseInt((t[1] >>> 0) / ((cHigh >>> 0) + 1));
//if (testI >= 412 && test2 >= 13) console.log("aHigh2=%d", aHigh);
}
u = ((aHigh >>> 0) * (cLow >>> 0)) & 0xffffffff;
v = ((aHigh >>> 0) * (cHigh >>> 0)) & 0xffffffff;
//if (testI >= 412 && test2 >= 13) console.log("u = %d v = %d aHigh = %d cLow = %d cHigh = %d", u, v, aHigh, cLow, cHigh);
//if (testI >= 412 && test2 >= 13) console.log("t9 = %d %d", t[0], t[1]);
t[0] = bn_u32_minus(t[0], TO_HIGH_HALF(u));
//if (testI >= 412 && test2 >= 13) console.log("t91 = %d %d u = %d", t[0], t[1], u);
if (bn_u32_compare(t[0], bn_u32_minus(0xffffffff, TO_HIGH_HALF(u))) > 0) {
t[1] = bn_u32_minus(t[1], 1);
}
//if (testI >= 412 && test2 >= 13) console.log("t8 = %d %d", t[0], t[1]);
//if (testI >= 412 && test2 >= 13) console.log("t[0] = %d t[1] = %d", t[0], t[1]);
t[1] = bn_u32_minus(t[1], HIGH_HALF(u));
//if (testI >= 412 && test2 >= 13) console.log("t[0] = %d t[1] = %d", t[0], t[1]);
t[1] = bn_u32_minus(t[1], v);
//if (testI >= 412 && test2 >= 13) console.log("t[0] = %d t[1] = %d", t[0], t[1]);
//eeeek;
//if (testI >= 412 && test2 >= 13) console.log("t7 = %d %d cHigh = %d, cLow = %d bn_u32_compare(t[0], cLow) = %d", t[0], t[1], cHigh, cLow, bn_u32_compare(t[0], cLow));
while (bn_u32_compare(t[1], cHigh) > 0 || (bn_u32_compare(t[1], cHigh) == 0 && bn_u32_compare(t[0], TO_HIGH_HALF(cLow)) >= 0)) {
//if (testI >= 412 && test2 >= 13) {
// console.log("rd t[0] = %d t[1] = %d cLow = %d cHigh = %d", t[0], t[1], cLow, cHigh);
// throw Error("");
//}
t[0] = bn_u32_minus(t[0], TO_HIGH_HALF(cLow));
if (bn_u32_compare(t[0], bn_u32_minus(0xffffffff, TO_HIGH_HALF(cLow))) > 0) {
t[1] = bn_u32_minus(t[1], 1);
}
t[1] = bn_u32_minus(t[1], cHigh);
aHigh = bn_u32_add(aHigh, 1);
}
//if (testI >= 412 && test2 >= 13)console.log("t6 = %d %d cHigh = %d, cLow = %d", t[0], t[1], cHigh, cLow);
if (bn_u32_compare(cHigh, 0xffff) == 0) {
aLow = LOW_HALF(t[1]) & 0xffffffff;
//console.log("aLow1 = %d ", aLow);
} else {
//aLow = parseInt((((TO_HIGH_HALF (t[1]) + HIGH_HALF (t[0])) >>> 0) & 0xffffffff) / bn_u32_add(cHigh, 1));
aLow = (TO_HIGH_HALF(t[1]) >>> 0) + ((HIGH_HALF(t[0]) & 0xffffffff) >>> 0);
aLow = parseInt(aLow / bn_u32_add(cHigh, 1)) & 0xffffffff;
aLow &= 0xffffffff;
//console.log("aLow2 = %d ", aLow);
}
u = ((aLow >>> 0) * (cLow >>> 0)) & 0xffffffff;
v = ((aLow >>> 0) * (cHigh >>> 0)) & 0xffffffff;
//(*t) -= u;
//console.log("t5 = %d %d u = %d aLow = %d cLow = %d cHigh = %d", t[0], t[1], u, aLow, cLow, cHigh);
t[0] = bn_u32_minus(t[0], u);
//console.log("t4 = %d %d", t[0], t[1]);
//if ((*t) > (MAX_NN_DIGIT - u)) {
if (bn_u32_compare(t[0], bn_u32_minus(0xffffffff, u)) > 0) {
//t[1]--;
t[1] = bn_u32_minus(t[1], 1);
}
//console.log("t3 = %d %d", t[0], t[1]);
//(*t) -= TO_HIGH_HALF (v);
t[0] = bn_u32_minus(t[0], TO_HIGH_HALF(v));
//console.log("t2 = %d %d", t[0], t[1]);
//if ((*t) > (MAX_NN_DIGIT - TO_HIGH_HALF (v))) {
if (bn_u32_compare(t[0], bn_u32_minus(0xffffffff, TO_HIGH_HALF(v))) > 0) {
//t[1]--;
t[1] = bn_u32_minus(t[1], 1);
}
//console.log("t1 = %d %d", t[0], t[1]);
//*(t+1) -= HIGH_HALF (v);
t[1] = bn_u32_minus(t[1], HIGH_HALF(v));
//console.log("t0 = %d %d", t[0], t[1]);
//console.log("ai1=%d aHigh = %d aLow = %d t[0] = %d t[1] = %d", ai, aHigh, aLow, t[0], t[1]);
//while ((*(t+1) > 0) || ((*(t+1) == 0) && (*t) >= s)) {
while (bn_u32_compare(t[1], 0) > 0 || (t[1] == 0 && bn_u32_compare(t[0], s) >= 0)) {
//(*t) -= s;
t[0] = bn_u32_minus(t[0], s);
//if ((*t) > (MAX_NN_DIGIT - s)) {
if (bn_u32_compare(t[0], bn_u32_minus(0xffffffff, s)) > 0) {
t[1]--;
}
//aLow++;
aLow = bn_u32_add(aLow, 1);
}
//ai = TO_HIGH_HALF (aHigh) + aLow;
ai = bn_u32_add(TO_HIGH_HALF(aHigh), aLow);
//console.log("ai0=%d aHigh = %d aLow = %d", ai, aHigh, aLow);
//s--;
s = bn_u32_minus(s, 1);
//console.log("cHigh = %d cLow = %d", cHigh, cLow);
//console.log("s = %d ai = %d t[0] = %d t[1] = %d cHigh = %d cLow = %d aHigh = %d aLow = %d u = %d v = %d",
// s, ai, t[0], t[1], cHigh, cLow, aHigh, aLow, u, v);
//cc[i+ddDigits] -= subdigitmult(&cc[i], &cc[i], ai, dd, ddDigits);
//printfIntsIndex("cc", cc, 0, cc.length);
//printfIntsIndex("dd", dd, 0, dd.length);
//console.log("ai = %d ddDigits = %d i = %d", ai, ddDigits, i);
cc[i + ddDigits] = bn_u32_minus(cc[i + ddDigits], subdigitmult(cc, i, cc, i, ai, dd, 0, ddDigits));
//console.log("cc[i+ddDigits] = %d", cc[i+ddDigits]);
//printfIntsIndex("cc", cc, 0, cc.length);
//printfIntsIndex("dd", dd, 0, dd.length);
//console.log("ddDigits = %d", ddDigits);
//testI++
//console.log("testI = %d", testI);
//console.log("NN_Cmp(cc, i, dd, 0, ddDigits) = %d", NN_Cmp(cc, i, dd, 0, ddDigits));
//if (testI > 2) {
//throw Error("988");
//}
//console.log("testI = %d", testI);
while (cc[i + ddDigits] != 0 || NN_Cmp(cc, i, dd, 0, ddDigits) >= 0) {
// console.log("0 cc[i+ddDigits] = %d ai\n", cc[i+ddDigits]);
ai = bn_u32_add(ai, 1);
cc[i + ddDigits] = bn_u32_minus(cc[i + ddDigits], NN_Sub(cc, i, cc, i, dd, 0, ddDigits));
//console.log("1 cc[i+ddDigits] = %d ai\n", cc[i+ddDigits]);
//console.log("ai");
//throw Error("9612332");
}
a[i + aindex] = ai & 0xffffffff;
//throw Error("9632");
}
}
//throw Error("987412");
NN_AssignZero(b, bindex, dDigits);
NN_RShift(b, bindex, cc, 0, shift, ddDigits);
//console.log("shift = %d ddDigits = %d", shift, ddDigits);
//printfIntsIndex("b", b, bindex, ddDigits);
//throw Error("888");
}
//var testi = 0;
function NN_Mult(a, aindex, b, bindex, c, cindex, digits, rsaCtxParams) {
var t = new Array(2 * parseInt((rsaCtxParams.keybits + 31) / 32));
var dhigh = 0xffffffff >>> 0,
dlow = 0xffffffff >>> 0,
carry = 0xffffffff >>> 0;
var bDigits, cDigits, i, j;
var tmpAr = new Array(2);
init_u32array(t, t.length);
init_u32array(tmpAr, tmpAr.length);
//printfIntsIndex("a", a, aindex, parseInt((rsaCtxParams.keybits + 31) / 32));
//printfIntsIndex("b", b, bindex, parseInt((rsaCtxParams.keybits + 31) / 32));
//printfIntsIndex("c", c, cindex, parseInt((rsaCtxParams.keybits + 31) / 32));
//throw Error("9988");
tmpAr[0] = 0xffffffff >>> 0;
tmpAr[1] = 0xffffffff >>> 0;
for (i = 0; i < t.length; i++) {
t[i] = 0xffffffff >>> 0;
}
NN_AssignZero(t, 0, t.length);
bDigits = NN_Digits(b, bindex, digits);
cDigits = NN_Digits(c, cindex, digits);
for (i = 0; i < bDigits; i++) {
carry = 0;
if (b[i + bindex] != 0) {
for (j = 0; j < cDigits; j++) {
tmpAr[0] = dhigh;
tmpAr[1] = dlow;
//console.log("%d %d", b[i + bindex], c[j + cindex]);
dmult(b[i + bindex], c[j + cindex], tmpAr, 0, tmpAr, 1);
dhigh = tmpAr[0];
dlow = tmpAr[1];
//*(t+(i+j)) = *(t+(i+j)) + carry;
//console.log("0t%d=%d dlow = %d dhigh = %d carry = %d", i + j, t[i + j], dlow, dhigh, carry);
//testi++;
//if (testi > 1) {
// throw Error("ll");
//}
t[i + j] += carry;
t[i + j] &= 0xffffffff;
//console.log("1t%d=%d dlow = %d dhigh = %d carry = %d", i + j, t[i + j], dlow, dhigh, carry);
//if((*(t+(i+j))) < carry) {
//if (t[i + j] < carry) {
if (bn_u32_compare(t[i + j], carry) < 0) {
carry = 1;
} else {
carry = 0;
}
//*(t+(i+j)) += dlow;
t[i + j] += dlow;
t[i + j] &= 0xffffffff;
//console.log("2t%d=%d dlow = %d dhigh = %d carry = %d", i + j, t[i + j], dlow, dhigh, carry);
//if((*(t+(i+j))) < dlow) {
//if (t[i + j] < dlow) {
if (bn_u32_compare(t[i + j], dlow) < 0) {
//console.log("carry add");
carry++;
}
carry += dhigh;
carry &= 0xffffffff
}
//throw Error("aaa");
}
//*(t+(i+cDigits)) += carry;
t[i + cDigits] += carry;
t[i + cDigits] &= 0xffffffff;
}
//printfIntsIndex("t", t, 0, t.length);
//throw Error("9986");
NN_Assign(a, 0, t, 0, 2 * digits);
//printfIntsIndex("a", a, aindex, parseInt((rsaCtxParams.keybits + 31) / 32));
//printfIntsIndex("b", b, bindex, parseInt((rsaCtxParams.keybits + 31) / 32));
//printfIntsIndex("c", c, cindex, parseInt((rsaCtxParams.keybits + 31) / 32));
//throw Error("3356");
}
function LOW_HALF(val) {
return val & 0xffff;
}
function HIGH_HALF(val) {
return (val >>> 16) & 0xffff;
}
function init_u32array(array, len) {
var i = 0;
for (i = 0; i < len; i++) {
array[i] = 0xffffffff >>> 0;
}
}
function dmult(a, b, high, highindex, low, lowindex) {
var al = 0xffffffff >>> 0;
var ah = 0xffffffff >>> 0;
var bl = 0xffffffff >>> 0;
var bh = 0xffffffff >>> 0;
var m1 = 0xffffffff >>> 0;
var m2 = 0xffffffff >>> 0;
var m = 0xffffffff >>> 0;
var ml = 0xffffffff >>> 0;
var mh = 0xffffffff >>> 0;
var carry = 0xffffffff >>> 0;
carry = 0;
al = LOW_HALF(a);
ah = HIGH_HALF(a);
bl = LOW_HALF(b);
bh = HIGH_HALF(b);
low[lowindex] = (al * bl) & 0xffffffff;
high[highindex] = (ah * bh) & 0xffffffff;
//console.log("low[lowindex] = %d high[highindex] = %d", low[lowindex], high[highindex]);
m1 = (al * bh) & 0xffffffff;
m2 = (ah * bl) & 0xffffffff;
m = (m1 + m2) & 0xffffffff;
if (bn_u32_compare(m, m1) < 0) {
carry = (1 << 16) & 0xffffffff; //(NN_DIGIT_BITS / 2);
}
ml = (m & 0xffff) << 16; //(NN_DIGIT_BITS / 2);
mh = (m >> 16) & 0xffff; //(NN_DIGIT_BITS / 2);
low[lowindex] += ml;
if (bn_u32_compare(low[lowindex], ml) < 0) {
carry = (carry + 1) & 0xffffffff;
}
high[highindex] += (carry + mh);
low[lowindex] &= 0xffffffff;
high[lowindex] &= 0xffffffff;
}
function NN_AssignZero(a, aindex, digits) {
var tmpaindex = 0;
if (digits != 0) {
do {
//*a++ = 0;
//(*a) = 0;
a[tmpaindex + aindex] = 0;
//a++;
tmpaindex++;
digits--;
if (digits == 0) {
break;
}
} while (true);
}
}
function NN_Assign(a, aindex, b, bindex, digits) {
var tmpaindex = 0;
var tmpbindex = 0;
if (digits != 0) {
/*do {
*a++ = *b++;
}while(--digits);*/
do {
a[tmpaindex + aindex] = b[tmpbindex + bindex];
//a++;
//b++;
tmpaindex++;
tmpbindex++;
digits--;
if (digits == 0) {
break;
}
} while (true);
}
}
function printfInts(title, data, len) {
printfIntsIndex(title, data, 0, len);
/*var i = 0;
for (i = 0; i < len; i++) {
console.log("%d %s %d", i, title == null ? "":title, data[i]);
}*/
}
function printfIntsIndex(title, data, index, len) {
var i = 0;
for (i = 0; i < len; i++) {
console.log("%d %s %d", i, title == null ? "" : title, data[i + index]);
}
}
function NN_Digits(a, aindex, len) {
var i = 0;
for (i = len - 1; i >= 0; i--) {
if (a[i + aindex] != 0) {
return i + 1;
}
}
return i;
}
function BignumCmp(a, b) {
var amax = a.length - 1;
var bmax = b.length - 1;
var i = (amax > bmax ? amax : bmax);
var aval = 0;
var bval = 0;
while (i) {
aval = i > amax ? 0 : a[i];
bval = i > bmax ? 0 : b[i];
if (((aval >> 16) & 0xffff) < ((bval >> 16) & 0xffff)) {
return -1;
}
if (((aval >> 16) & 0xffff) > ((bval >> 16) & 0xffff)) {
return 1;
}
if ((aval & 0xffff) < (bval & 0xffff)) {
return -1;
}
if ((aval & 0xffff) > (bval & 0xffff)) {
return 1;
}
i--;
}
return 0;
}
function NN_Decode(bytesArray, len) {
var bits = CalArrayBits(bytesArray, len);
var i = 0;
var j = 0;
var outArray = new Array(parseInt((bits + 31) / 32));
init_u32array(outArray, outArray.length);
for (i = 0; i < outArray.length; i++) {
j = bytesArray.length - (i + 1) * 4;
//console.log("j = " + j);
if (j >= 0) {
outArray[i] = ((parseInt(bytesArray[j]) & 0xff) << 24) |
((parseInt(bytesArray[j + 1]) & 0xff) << 16) |
((parseInt(bytesArray[j + 2]) & 0xff) << 8) |
((parseInt(bytesArray[j + 3]) & 0xff) << 0);
} else {
outArray[i] = 0;
if (j + 1 >= 0) {
outArray[i] |= ((parseInt(bytesArray[j + 1]) & 0xff) << 16);
}
if (j + 2 >= 0) {
outArray[i] |= ((parseInt(bytesArray[j + 2]) & 0xff) << 8);
}
if (j + 3 >= 0) {
outArray[i] |= ((parseInt(bytesArray[j + 3]) & 0xff) << 0);
}
}
}
return outArray;
}
function CalArrayBits(arrayData, len) {
var i = 0;
var j = 0;
for (i = 0; i < len; i++) {
if (arrayData[i] != 0) {
j = -1;
break;
}
}
if (j >= 0) {
return 0;
}
for (j = 0; j < 8; j++) {
if ((arrayData[i] & (0x80 >>> j)) != 0) {
break;
}
}
return 8 - j + (len - i - 1) * 8;
}
function rsa_hex_to_array(hexStrIn) {
var i = 0;
var cnt = 0;
var ele = 0;
var bytesArray = null;
cnt = 0;
for (i = 0; i < hexStrIn.length; i++) {
ele = hexStrIn.charCodeAt(i);
if (ele >= 48 && ele < 48 + 10) {
cnt++;
}
if (ele >= 65 && ele < 65 + 6) {
cnt++;
}
if (ele >= 97 && ele < 97 + 6) {
cnt++;
}
}
bytesArray = new Uint8Array(parseInt((cnt + 1) / 2));
cnt = 0;
for (i = 0; i < hexStrIn.length; i++) {
ele = hexStrIn.charCodeAt(i);
if (ele >= 48 && ele < 48 + 10) {
ele -= 48;
cnt++;
} else if (ele >= 65 && ele < 65 + 6) {
ele = ele - 65 + 10;
cnt++;
} else if (ele >= 97 && ele < 97 + 6) {
ele = ele - 97 + 10;
cnt++;
} else {
continue;
}
if ((cnt % 2) == 1) {
bytesArray[parseInt((cnt - 1) / 2)] = (ele << 4) & 0xF0;
} else {
bytesArray[parseInt((cnt - 1) / 2)] |= ele;
}
}
return bytesArray;
}
function rsa_hex_to_str(data, len) {
var sha256_hex_digits = "0123456789abcdef";
var output = new String();
var i = 0;
//console.log("ou1t = " + output);
for (i = 0; i < len; i++) {
// console.log("out = " + output);
output += sha256_hex_digits.charAt((data[i] >>> 4) & 0x0f);
output += sha256_hex_digits.charAt((data[i]) & 0x0f);
}
return output;
}
module.exports = {
rsa_set_key: rsa_set_key,
rsa_pub_cal: rsa_pub_cal,
rsa_pri_cal: rsa_pri_cal,
rsa_hex_to_array: rsa_hex_to_array,
rsa_hex_to_str: rsa_hex_to_str,
rsa_pkcs1_pad:rsa_pkcs1_pad
}
测试代码:
如下在微信小程序中测试验证
var js_rsa = require('../../crypto/rsa.js');
testRsa() {
var rsaCtx = null;
var keyN = "BEC631E3067608D5065846573408462E4912D5EA343F0FB45DB7F2A1673D5A6D070DE518EBD4420A44E32188313A8B3321FFFC981FEA277BA833E224B9B21A036CE102047DFCBB0F4907EB670C9603E9FD9753681AA74873F47765B03B57E5EB184F4BAB576E4C03FAC8261A560B3EC79EBAFA92DE644362C8D79A7AD858F06CD3DA850ED467F0168B2FB49455A01CCE950ED110C78A90163B315D9C96368AE78F75B0813BEA33B50DFCDCF61D14AF8EB1313A53E3F90C43324EFB315D1FEC64851517C0068257953EE066F305410B2D729753E8D0F7F6D7089B89986B3A9A6109BCB66D4D1FFFF1DFFB347CE0C04019473FC88FA94C4C629A25460BFA900291";
var keyD = "6D26C6FA470317D0927DC559358B1A647728D0BDDCC0CC027DB0B6A10489C50826861BB363932169F0BA27C05DB24A5CAA3265DAC03FDFF14F6EC8100D334AD0F4E5D49AAF5EFFC4221BE6E321FF5F23ED153D028E6571FDEE3CB630DBF351B86E43485F337A07022BE5826F85159008F4D7B4707DCFCE02623981C891AA697C4D746DD007330F697F8739392E9001D4FC2993C5E78D1A283C38AAED24EF4C672A1C4E72B2781759080CAE8383EEB69C8BC232360850FEBEF9D862DBC7225A9FE13F98F6BD072C7A027DEA9F9C9CDAB4D3F5F37B03B2375DA9BEF8CF1AD3CCB4C24B236685DDC82F10BA9584FA9A34D545B528B213675E969D7CA3839418AB95";
var keyE = "010001";
var txt = "00888888889999999999999AAAAAAAAABBBBBBBBCEDFFFFFFFFFFFFFFFFFFFFFFFFF966666666666666666666666666666666666666666666666666633333333333333333333333333333333300000000000000000000000666EEEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFDDDDDDDDDDDDBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAA88888888644444444444777777777777777799999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999555555555555555555555555555555555555555522222222222222222222222222222222222222";
var result, result2;
var tmpdata = null;
rsaCtx = js_rsa.rsa_set_key(js_rsa.rsa_hex_to_array(keyN), js_rsa.rsa_hex_to_array(keyE), js_rsa.rsa_hex_to_array(keyD));
result = js_rsa.rsa_pub_cal(rsaCtx, js_rsa.rsa_hex_to_array(txt));
console.log("rsa_pub_cal:" + js_rsa.rsa_hex_to_str(result, result.length));
result2 = js_rsa.rsa_pri_cal(rsaCtx, result);
console.log("rsa_pri_cal:" + js_rsa.rsa_hex_to_str(result2, result2.length));
/* 下面的用pkcs1填充然后公玥计算,可以在后台用对应的私玥解密出来 */
tmpdata = js_rsa.rsa_pkcs1_pad(js_rsa.rsa_hex_to_array("1122334455667788"), 2, rsaCtx.keybits);
result = js_rsa.rsa_pub_cal(rsaCtx, tmpdata);
console.log("rsa_pub_cal:" + js_rsa.rsa_hex_to_str(result, result.length));
result2 = js_rsa.rsa_pri_cal(rsaCtx, result);
console.log("rsa_pri_cal:" + js_rsa.rsa_hex_to_str(result2, result2.length));
},
测试结果:
rsa_pub_cal:2fac299b8f780e12a331a73ca61551deb3cd41127d76d5c855624eb6d02eac9581be481fec0ec3c882e1cb26de31dffa19a689cd36a5255021fc44ab3399385f91db7352701bca8f1955237085ef2e0d216831653367799cddaf8c4b77611287fedfcc93de93d3c28461d29d609322f1b1d1b4543d1cc2921b50253fd1da15f9174a94ff8cb70cab180d56d00dd4f28e3a914abc28f770623af2eed11c560a26fe1187050038da28ad897068373b5bdfe14fb44905fcdc0cbeefde21a155ecf238423a2c967b710cbab39a235a6385c285535707c20bab1ae7601def49959cd42aa700389423fdcf17f2c42a00f2b1da8320586d24ef5d5dfe92cc203047020b
rsa_pri_cal:00888888889999999999999aaaaaaaaabbbbbbbbcedfffffffffffffffffffffffff966666666666666666666666666666666666666666666666666633333333333333333333333333333333300000000000000000000000666eeeeeeeeeeeeeeeeeeeeeefffffffffffffffffffddddddddddddbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccaaaaaaaaaaaaaaaaaaaaaaaaaa88888888644444444444777777777777777799999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999555555555555555555555555555555555555555522222222222222222222222222222222222222
rsa_pub_cal:0c0b82faa9ea15227d77e043db0467261bf4957450ff3342a51f0ebc41112a0a62f509c4d8c6d6554e4d95997f89f6b4ff6ea728287bd6324f9989cdbfe9057740184eca47cb1d07bb082e8e09f4fb9e6befba4765b06fc0ddf4b9ddfa744fde3404ef5106bd772373a41bbc463c63808c972790bed8991089f62ee9f20ab638d177c0abe9b0b706639e782186515418a1bc743513051cd562a8b081b9d25b70eea813a7a48ede372833723fe4bbf7d8b4b20dc1457ae9277f4f4ff4c35873933bdb5eb99fc1bf9b1ec37a3e0ee542eadbdf89340dc90888747b221a35a43107fcdd2eeed2b9962277032b711d3713f7a1ce63318bae02ca462584850a182b32
rsa_pri_cal:0002c30f4202dcace6f9d5e2ff47c9014a4f8c7ca2dcd0fd54ee7d3eead63eb67ca9b76980a7b5d1cd72cab7c56e9aa142b59a79dcf07e5d1189ee09727b5ca372697be5cf6fda20a7cefab1c558c1a6e57609773c0355f407198250d252a4f8d01785f9271e9d160aae2ba2dc2314714fb4cca0b20320b6329224c5ba154b086d479ccd27353d9d9eaa48f5e1743b2fd44e0f46b85d894a41e239c696f1e9a71a22c83c9f69ce1541ebcd1106446c1f5c5b074ec5b580f4263930ffdf9bbdc7bf1cd6d86971744173a15d3eefbe7f1ab8c5363c5d62eccce5c404c3cb954a7f7c09a61dd75e56dcef2fbc98593dbe52f0e317ee5a5f65001122334455667788