javascript实现rsa算法(支持微信小程序)
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