RSA前台加密后台解密的应用
写在前面
项目安全测试需要将登录功能修改, AES加密不符合要求, 现改为RSA非对称加密.(将登录密码加密后传给后台, 后台解密后再进行一系列的校验) .期间遇到了前台js加密但是后台解密失败的问题https://www.cnblogs.com/yadongliang/p/11638995.html, 下面是看了另一篇博客后正常加解密的步骤及关键代码.
步骤及关键代码
0.pom.xml
<!--RSA--> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.63</version> </dependency> <!--lang3--> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.9</version> </dependency>
1.rsasecurity.js
1 (function ($w) { 2 3 if (typeof $w.RSAUtils === 'undefined') 4 var RSAUtils = $w.RSAUtils = {}; 5 6 var biRadixBase = 2; 7 var biRadixBits = 16; 8 var bitsPerDigit = biRadixBits; 9 var biRadix = 1 << 16; 10 var biHalfRadix = biRadix >>> 1; 11 var biRadixSquared = biRadix * biRadix; 12 var maxDigitVal = biRadix - 1; 13 var maxInteger = 9999999999999998; 14 15 16 var maxDigits; 17 var ZERO_ARRAY; 18 var bigZero, bigOne; 19 20 var BigInt = $w.BigInt = function (flag) { 21 if (typeof flag == "boolean" && flag == true) { 22 this.digits = null; 23 } else { 24 this.digits = ZERO_ARRAY.slice(0); 25 } 26 this.isNeg = false; 27 }; 28 29 RSAUtils.setMaxDigits = function (value) { 30 maxDigits = value; 31 ZERO_ARRAY = new Array(maxDigits); 32 for (var iza = 0; iza < ZERO_ARRAY.length; iza++) ZERO_ARRAY[iza] = 0; 33 bigZero = new BigInt(); 34 bigOne = new BigInt(); 35 bigOne.digits[0] = 1; 36 }; 37 RSAUtils.setMaxDigits(20); 38 39 40 var dpl10 = 15; 41 42 RSAUtils.biFromNumber = function (i) { 43 var result = new BigInt(); 44 result.isNeg = i < 0; 45 i = Math.abs(i); 46 var j = 0; 47 while (i > 0) { 48 result.digits[j++] = i & maxDigitVal; 49 i = Math.floor(i / biRadix); 50 } 51 return result; 52 }; 53 54 55 var lr10 = RSAUtils.biFromNumber(1000000000000000); 56 57 RSAUtils.biFromDecimal = function (s) { 58 var isNeg = s.charAt(0) == '-'; 59 var i = isNeg ? 1 : 0; 60 var result; 61 62 while (i < s.length && s.charAt(i) == '0') ++i; 63 if (i == s.length) { 64 result = new BigInt(); 65 } else { 66 var digitCount = s.length - i; 67 var fgl = digitCount % dpl10; 68 if (fgl == 0) fgl = dpl10; 69 result = RSAUtils.biFromNumber(Number(s.substr(i, fgl))); 70 i += fgl; 71 while (i < s.length) { 72 result = RSAUtils.biAdd(RSAUtils.biMultiply(result, lr10), 73 RSAUtils.biFromNumber(Number(s.substr(i, dpl10)))); 74 i += dpl10; 75 } 76 result.isNeg = isNeg; 77 } 78 return result; 79 }; 80 81 RSAUtils.biCopy = function (bi) { 82 var result = new BigInt(true); 83 result.digits = bi.digits.slice(0); 84 result.isNeg = bi.isNeg; 85 return result; 86 }; 87 88 RSAUtils.reverseStr = function (s) { 89 var result = ""; 90 for (var i = s.length - 1; i > -1; --i) { 91 result += s.charAt(i); 92 } 93 return result; 94 }; 95 96 var hexatrigesimalToChar = [ 97 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 98 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 99 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 100 'u', 'v', 'w', 'x', 'y', 'z' 101 ]; 102 103 RSAUtils.biToString = function (x, radix) { 104 var b = new BigInt(); 105 b.digits[0] = radix; 106 var qr = RSAUtils.biDivideModulo(x, b); 107 var result = hexatrigesimalToChar[qr[1].digits[0]]; 108 while (RSAUtils.biCompare(qr[0], bigZero) == 1) { 109 qr = RSAUtils.biDivideModulo(qr[0], b); 110 digit = qr[1].digits[0]; 111 result += hexatrigesimalToChar[qr[1].digits[0]]; 112 } 113 return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result); 114 }; 115 116 RSAUtils.biToDecimal = function (x) { 117 var b = new BigInt(); 118 b.digits[0] = 10; 119 var qr = RSAUtils.biDivideModulo(x, b); 120 var result = String(qr[1].digits[0]); 121 while (RSAUtils.biCompare(qr[0], bigZero) == 1) { 122 qr = RSAUtils.biDivideModulo(qr[0], b); 123 result += String(qr[1].digits[0]); 124 } 125 return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result); 126 }; 127 128 var hexToChar = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 129 'a', 'b', 'c', 'd', 'e', 'f']; 130 131 RSAUtils.digitToHex = function (n) { 132 var mask = 0xf; 133 var result = ""; 134 for (i = 0; i < 4; ++i) { 135 result += hexToChar[n & mask]; 136 n >>>= 4; 137 } 138 return RSAUtils.reverseStr(result); 139 }; 140 141 RSAUtils.biToHex = function (x) { 142 var result = ""; 143 var n = RSAUtils.biHighIndex(x); 144 for (var i = RSAUtils.biHighIndex(x); i > -1; --i) { 145 result += RSAUtils.digitToHex(x.digits[i]); 146 } 147 return result; 148 }; 149 150 RSAUtils.charToHex = function (c) { 151 var ZERO = 48; 152 var NINE = ZERO + 9; 153 var littleA = 97; 154 var littleZ = littleA + 25; 155 var bigA = 65; 156 var bigZ = 65 + 25; 157 var result; 158 159 if (c >= ZERO && c <= NINE) { 160 result = c - ZERO; 161 } else if (c >= bigA && c <= bigZ) { 162 result = 10 + c - bigA; 163 } else if (c >= littleA && c <= littleZ) { 164 result = 10 + c - littleA; 165 } else { 166 result = 0; 167 } 168 return result; 169 }; 170 171 RSAUtils.hexToDigit = function (s) { 172 var result = 0; 173 var sl = Math.min(s.length, 4); 174 for (var i = 0; i < sl; ++i) { 175 result <<= 4; 176 result |= RSAUtils.charToHex(s.charCodeAt(i)); 177 } 178 return result; 179 }; 180 181 RSAUtils.biFromHex = function (s) { 182 var result = new BigInt(); 183 var sl = s.length; 184 for (var i = sl, j = 0; i > 0; i -= 4, ++j) { 185 result.digits[j] = RSAUtils.hexToDigit(s.substr(Math.max(i - 4, 0), Math.min(i, 4))); 186 } 187 return result; 188 }; 189 190 RSAUtils.biFromString = function (s, radix) { 191 var isNeg = s.charAt(0) == '-'; 192 var istop = isNeg ? 1 : 0; 193 var result = new BigInt(); 194 var place = new BigInt(); 195 place.digits[0] = 1; 196 for (var i = s.length - 1; i >= istop; i--) { 197 var c = s.charCodeAt(i); 198 var digit = RSAUtils.charToHex(c); 199 var biDigit = RSAUtils.biMultiplyDigit(place, digit); 200 result = RSAUtils.biAdd(result, biDigit); 201 place = RSAUtils.biMultiplyDigit(place, radix); 202 } 203 result.isNeg = isNeg; 204 return result; 205 }; 206 207 RSAUtils.biDump = function (b) { 208 return (b.isNeg ? "-" : "") + b.digits.join(" "); 209 }; 210 211 RSAUtils.biAdd = function (x, y) { 212 var result; 213 214 if (x.isNeg != y.isNeg) { 215 y.isNeg = !y.isNeg; 216 result = RSAUtils.biSubtract(x, y); 217 y.isNeg = !y.isNeg; 218 } else { 219 result = new BigInt(); 220 var c = 0; 221 var n; 222 for (var i = 0; i < x.digits.length; ++i) { 223 n = x.digits[i] + y.digits[i] + c; 224 result.digits[i] = n % biRadix; 225 c = Number(n >= biRadix); 226 } 227 result.isNeg = x.isNeg; 228 } 229 return result; 230 }; 231 232 RSAUtils.biSubtract = function (x, y) { 233 var result; 234 if (x.isNeg != y.isNeg) { 235 y.isNeg = !y.isNeg; 236 result = RSAUtils.biAdd(x, y); 237 y.isNeg = !y.isNeg; 238 } else { 239 result = new BigInt(); 240 var n, c; 241 c = 0; 242 for (var i = 0; i < x.digits.length; ++i) { 243 n = x.digits[i] - y.digits[i] + c; 244 result.digits[i] = n % biRadix; 245 246 if (result.digits[i] < 0) result.digits[i] += biRadix; 247 c = 0 - Number(n < 0); 248 } 249 250 if (c == -1) { 251 c = 0; 252 for (var i = 0; i < x.digits.length; ++i) { 253 n = 0 - result.digits[i] + c; 254 result.digits[i] = n % biRadix; 255 256 if (result.digits[i] < 0) result.digits[i] += biRadix; 257 c = 0 - Number(n < 0); 258 } 259 260 result.isNeg = !x.isNeg; 261 } else { 262 263 result.isNeg = x.isNeg; 264 } 265 } 266 return result; 267 }; 268 269 RSAUtils.biHighIndex = function (x) { 270 var result = x.digits.length - 1; 271 while (result > 0 && x.digits[result] == 0) --result; 272 return result; 273 }; 274 275 RSAUtils.biNumBits = function (x) { 276 var n = RSAUtils.biHighIndex(x); 277 var d = x.digits[n]; 278 var m = (n + 1) * bitsPerDigit; 279 var result; 280 for (result = m; result > m - bitsPerDigit; --result) { 281 if ((d & 0x8000) != 0) break; 282 d <<= 1; 283 } 284 return result; 285 }; 286 287 RSAUtils.biMultiply = function (x, y) { 288 var result = new BigInt(); 289 var c; 290 var n = RSAUtils.biHighIndex(x); 291 var t = RSAUtils.biHighIndex(y); 292 var u, uv, k; 293 294 for (var i = 0; i <= t; ++i) { 295 c = 0; 296 k = i; 297 for (j = 0; j <= n; ++j, ++k) { 298 uv = result.digits[k] + x.digits[j] * y.digits[i] + c; 299 result.digits[k] = uv & maxDigitVal; 300 c = uv >>> biRadixBits; 301 302 } 303 result.digits[i + n + 1] = c; 304 } 305 306 result.isNeg = x.isNeg != y.isNeg; 307 return result; 308 }; 309 310 RSAUtils.biMultiplyDigit = function (x, y) { 311 var n, c, uv; 312 313 result = new BigInt(); 314 n = RSAUtils.biHighIndex(x); 315 c = 0; 316 for (var j = 0; j <= n; ++j) { 317 uv = result.digits[j] + x.digits[j] * y + c; 318 result.digits[j] = uv & maxDigitVal; 319 c = uv >>> biRadixBits; 320 321 } 322 result.digits[1 + n] = c; 323 return result; 324 }; 325 326 RSAUtils.arrayCopy = function (src, srcStart, dest, destStart, n) { 327 var m = Math.min(srcStart + n, src.length); 328 for (var i = srcStart, j = destStart; i < m; ++i, ++j) { 329 dest[j] = src[i]; 330 } 331 }; 332 333 var highBitMasks = [0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800, 334 0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0, 335 0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF]; 336 337 RSAUtils.biShiftLeft = function (x, n) { 338 var digitCount = Math.floor(n / bitsPerDigit); 339 var result = new BigInt(); 340 RSAUtils.arrayCopy(x.digits, 0, result.digits, digitCount, 341 result.digits.length - digitCount); 342 var bits = n % bitsPerDigit; 343 var rightBits = bitsPerDigit - bits; 344 for (var i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) { 345 result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) | 346 ((result.digits[i1] & highBitMasks[bits]) >>> 347 (rightBits)); 348 } 349 result.digits[0] = ((result.digits[i] << bits) & maxDigitVal); 350 result.isNeg = x.isNeg; 351 return result; 352 }; 353 354 var lowBitMasks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 355 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 356 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF]; 357 358 RSAUtils.biShiftRight = function (x, n) { 359 var digitCount = Math.floor(n / bitsPerDigit); 360 var result = new BigInt(); 361 RSAUtils.arrayCopy(x.digits, digitCount, result.digits, 0, 362 x.digits.length - digitCount); 363 var bits = n % bitsPerDigit; 364 var leftBits = bitsPerDigit - bits; 365 for (var i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) { 366 result.digits[i] = (result.digits[i] >>> bits) | 367 ((result.digits[i1] & lowBitMasks[bits]) << leftBits); 368 } 369 result.digits[result.digits.length - 1] >>>= bits; 370 result.isNeg = x.isNeg; 371 return result; 372 }; 373 374 RSAUtils.biMultiplyByRadixPower = function (x, n) { 375 var result = new BigInt(); 376 RSAUtils.arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n); 377 return result; 378 }; 379 380 RSAUtils.biDivideByRadixPower = function (x, n) { 381 var result = new BigInt(); 382 RSAUtils.arrayCopy(x.digits, n, result.digits, 0, result.digits.length - n); 383 return result; 384 }; 385 386 RSAUtils.biModuloByRadixPower = function (x, n) { 387 var result = new BigInt(); 388 RSAUtils.arrayCopy(x.digits, 0, result.digits, 0, n); 389 return result; 390 }; 391 392 RSAUtils.biCompare = function (x, y) { 393 if (x.isNeg != y.isNeg) { 394 return 1 - 2 * Number(x.isNeg); 395 } 396 for (var i = x.digits.length - 1; i >= 0; --i) { 397 if (x.digits[i] != y.digits[i]) { 398 if (x.isNeg) { 399 return 1 - 2 * Number(x.digits[i] > y.digits[i]); 400 } else { 401 return 1 - 2 * Number(x.digits[i] < y.digits[i]); 402 } 403 } 404 } 405 return 0; 406 }; 407 408 RSAUtils.biDivideModulo = function (x, y) { 409 var nb = RSAUtils.biNumBits(x); 410 var tb = RSAUtils.biNumBits(y); 411 var origYIsNeg = y.isNeg; 412 var q, r; 413 if (nb < tb) { 414 415 if (x.isNeg) { 416 q = RSAUtils.biCopy(bigOne); 417 q.isNeg = !y.isNeg; 418 x.isNeg = false; 419 y.isNeg = false; 420 r = biSubtract(y, x); 421 422 x.isNeg = true; 423 y.isNeg = origYIsNeg; 424 } else { 425 q = new BigInt(); 426 r = RSAUtils.biCopy(x); 427 } 428 return [q, r]; 429 } 430 431 q = new BigInt(); 432 r = x; 433 434 435 var t = Math.ceil(tb / bitsPerDigit) - 1; 436 var lambda = 0; 437 while (y.digits[t] < biHalfRadix) { 438 y = RSAUtils.biShiftLeft(y, 1); 439 ++lambda; 440 ++tb; 441 t = Math.ceil(tb / bitsPerDigit) - 1; 442 } 443 444 445 r = RSAUtils.biShiftLeft(r, lambda); 446 nb += lambda; 447 var n = Math.ceil(nb / bitsPerDigit) - 1; 448 449 var b = RSAUtils.biMultiplyByRadixPower(y, n - t); 450 while (RSAUtils.biCompare(r, b) != -1) { 451 ++q.digits[n - t]; 452 r = RSAUtils.biSubtract(r, b); 453 } 454 for (var i = n; i > t; --i) { 455 var ri = (i >= r.digits.length) ? 0 : r.digits[i]; 456 var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1]; 457 var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2]; 458 var yt = (t >= y.digits.length) ? 0 : y.digits[t]; 459 var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1]; 460 if (ri == yt) { 461 q.digits[i - t - 1] = maxDigitVal; 462 } else { 463 q.digits[i - t - 1] = Math.floor((ri * biRadix + ri1) / yt); 464 } 465 466 var c1 = q.digits[i - t - 1] * ((yt * biRadix) + yt1); 467 var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2); 468 while (c1 > c2) { 469 --q.digits[i - t - 1]; 470 c1 = q.digits[i - t - 1] * ((yt * biRadix) | yt1); 471 c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2); 472 } 473 474 b = RSAUtils.biMultiplyByRadixPower(y, i - t - 1); 475 r = RSAUtils.biSubtract(r, RSAUtils.biMultiplyDigit(b, q.digits[i - t - 1])); 476 if (r.isNeg) { 477 r = RSAUtils.biAdd(r, b); 478 --q.digits[i - t - 1]; 479 } 480 } 481 r = RSAUtils.biShiftRight(r, lambda); 482 483 q.isNeg = x.isNeg != origYIsNeg; 484 if (x.isNeg) { 485 if (origYIsNeg) { 486 q = RSAUtils.biAdd(q, bigOne); 487 } else { 488 q = RSAUtils.biSubtract(q, bigOne); 489 } 490 y = RSAUtils.biShiftRight(y, lambda); 491 r = RSAUtils.biSubtract(y, r); 492 } 493 494 if (r.digits[0] == 0 && RSAUtils.biHighIndex(r) == 0) r.isNeg = false; 495 496 return [q, r]; 497 }; 498 499 RSAUtils.biDivide = function (x, y) { 500 return RSAUtils.biDivideModulo(x, y)[0]; 501 }; 502 503 RSAUtils.biModulo = function (x, y) { 504 return RSAUtils.biDivideModulo(x, y)[1]; 505 }; 506 507 RSAUtils.biMultiplyMod = function (x, y, m) { 508 return RSAUtils.biModulo(RSAUtils.biMultiply(x, y), m); 509 }; 510 511 RSAUtils.biPow = function (x, y) { 512 var result = bigOne; 513 var a = x; 514 while (true) { 515 if ((y & 1) != 0) result = RSAUtils.biMultiply(result, a); 516 y >>= 1; 517 if (y == 0) break; 518 a = RSAUtils.biMultiply(a, a); 519 } 520 return result; 521 }; 522 523 RSAUtils.biPowMod = function (x, y, m) { 524 var result = bigOne; 525 var a = x; 526 var k = y; 527 while (true) { 528 if ((k.digits[0] & 1) != 0) result = RSAUtils.biMultiplyMod(result, a, m); 529 k = RSAUtils.biShiftRight(k, 1); 530 if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0) break; 531 a = RSAUtils.biMultiplyMod(a, a, m); 532 } 533 return result; 534 }; 535 536 537 $w.BarrettMu = function (m) { 538 this.modulus = RSAUtils.biCopy(m); 539 this.k = RSAUtils.biHighIndex(this.modulus) + 1; 540 var b2k = new BigInt(); 541 b2k.digits[2 * this.k] = 1; 542 this.mu = RSAUtils.biDivide(b2k, this.modulus); 543 this.bkplus1 = new BigInt(); 544 this.bkplus1.digits[this.k + 1] = 1; 545 this.modulo = BarrettMu_modulo; 546 this.multiplyMod = BarrettMu_multiplyMod; 547 this.powMod = BarrettMu_powMod; 548 }; 549 550 function BarrettMu_modulo(x) { 551 var $dmath = RSAUtils; 552 var q1 = $dmath.biDivideByRadixPower(x, this.k - 1); 553 var q2 = $dmath.biMultiply(q1, this.mu); 554 var q3 = $dmath.biDivideByRadixPower(q2, this.k + 1); 555 var r1 = $dmath.biModuloByRadixPower(x, this.k + 1); 556 var r2term = $dmath.biMultiply(q3, this.modulus); 557 var r2 = $dmath.biModuloByRadixPower(r2term, this.k + 1); 558 var r = $dmath.biSubtract(r1, r2); 559 if (r.isNeg) { 560 r = $dmath.biAdd(r, this.bkplus1); 561 } 562 var rgtem = $dmath.biCompare(r, this.modulus) >= 0; 563 while (rgtem) { 564 r = $dmath.biSubtract(r, this.modulus); 565 rgtem = $dmath.biCompare(r, this.modulus) >= 0; 566 } 567 return r; 568 } 569 570 function BarrettMu_multiplyMod(x, y) { 571 572 var xy = RSAUtils.biMultiply(x, y); 573 return this.modulo(xy); 574 } 575 576 function BarrettMu_powMod(x, y) { 577 var result = new BigInt(); 578 result.digits[0] = 1; 579 var a = x; 580 var k = y; 581 while (true) { 582 if ((k.digits[0] & 1) != 0) result = this.multiplyMod(result, a); 583 k = RSAUtils.biShiftRight(k, 1); 584 if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0) break; 585 a = this.multiplyMod(a, a); 586 } 587 return result; 588 } 589 590 var RSAKeyPair = function (encryptionExponent, decryptionExponent, modulus) { 591 var $dmath = RSAUtils; 592 this.e = $dmath.biFromHex(encryptionExponent); 593 this.d = $dmath.biFromHex(decryptionExponent); 594 this.m = $dmath.biFromHex(modulus); 595 596 597 this.chunkSize = 2 * $dmath.biHighIndex(this.m); 598 this.radix = 16; 599 this.barrett = new $w.BarrettMu(this.m); 600 }; 601 602 RSAUtils.getKeyPair = function (encryptionExponent, decryptionExponent, modulus) { 603 return new RSAKeyPair(encryptionExponent, decryptionExponent, modulus); 604 }; 605 606 if (typeof $w.twoDigit === 'undefined') { 607 $w.twoDigit = function (n) { 608 return (n < 10 ? "0" : "") + String(n); 609 }; 610 } 611 612 613 RSAUtils.encryptedString = function (key, s) { 614 var a = []; 615 var sl = s.length; 616 var i = 0; 617 while (i < sl) { 618 a[i] = s.charCodeAt(i); 619 i++; 620 } 621 622 while (a.length % key.chunkSize != 0) { 623 a[i++] = 0; 624 } 625 626 var al = a.length; 627 var result = ""; 628 var j, k, block; 629 for (i = 0; i < al; i += key.chunkSize) { 630 block = new BigInt(); 631 j = 0; 632 for (k = i; k < i + key.chunkSize; ++j) { 633 block.digits[j] = a[k++]; 634 block.digits[j] += a[k++] << 8; 635 } 636 var crypt = key.barrett.powMod(block, key.e); 637 var text = key.radix == 16 ? RSAUtils.biToHex(crypt) : RSAUtils.biToString(crypt, key.radix); 638 result += text + " "; 639 } 640 return result.substring(0, result.length - 1); 641 }; 642 643 RSAUtils.decryptedString = function (key, s) { 644 var blocks = s.split(" "); 645 var result = ""; 646 var i, j, block; 647 for (i = 0; i < blocks.length; ++i) { 648 var bi; 649 if (key.radix == 16) { 650 bi = RSAUtils.biFromHex(blocks[i]); 651 } else { 652 bi = RSAUtils.biFromString(blocks[i], key.radix); 653 } 654 block = key.barrett.powMod(bi, key.d); 655 for (j = 0; j <= RSAUtils.biHighIndex(block); ++j) { 656 result += String.fromCharCode(block.digits[j] & 255, 657 block.digits[j] >> 8); 658 } 659 } 660 661 if (result.charCodeAt(result.length - 1) == 0) { 662 result = result.substring(0, result.length - 1); 663 } 664 return result; 665 }; 666 667 RSAUtils.setMaxDigits(130); 668 669 })(window);
2.login.jsp
将公钥指数和公钥系数从后台controller传过来接收后存入input并隐藏
<%--公钥系数:--%> <input type="hidden" id="hid_modulus" value="${pkModulus}"/> <%--公钥指数:--%> <input type="hidden" id="hid_exponent" value="${pkExponent}"/>
引入rsasecurity.js
<%--引入RSA非对称加密js--%> <script src="<%=basePath%>/plug-in/ace/js/rsasecurity.js"></script>
js代码块进行加密并传到后台
var data = $(":input").each(function() { if (this.name == 'password') { //只加密密码 //获取公钥系数 var modulus = $('#hid_modulus').val(); //获取公钥指数 var exponent = $('#hid_exponent').val(); //获取最终公钥 var key = RSAUtils.getKeyPair(exponent, '', modulus); //获取需加密的值 var passwordVal = $("#" + this.name).val(); //进行数据加密 var ap = RSAUtils.encryptedString(key, encodeURI(passwordVal)); formData[this.name] = ap; } else { formData[this.name] = $("#" + this.name).val(); } }); $.ajax({ async: false, cache: false, type: 'POST', url: checkurl,// 请求的action路径 data: formData, error: function () {// 请求失败处理函数 }, success: function (data) { var d = $.parseJSON(data); if (d.success) { window.location.href = actionurl; } else { showErrorMsg(d.msg); } } });
3.LoginController.java
返回登录视图时即把公钥系数和公钥指数存入request域用于前台接收
// 获取公钥系数和公钥指数 //获取公钥对象--注意:前端那边需要用到公钥系数和指数 RSAPublicKey publicKey = RSAUtils.getDefaultPublicKey(); //公钥-系数(n) System.out.println("public key modulus:" + new String(Hex.encode(publicKey.getModulus().toByteArray()))); request.setAttribute("pkModulus", new String(Hex.encode(publicKey.getModulus().toByteArray()))); //公钥-指数(e1) System.out.println("public key exponent:" + new String(Hex.encode(publicKey.getPublicExponent().toByteArray()))); request.setAttribute("pkExponent", new String(Hex.encode(publicKey.getPublicExponent().toByteArray())));
前台提交ajax请求进行登录参数校验时, 将js加密后的password进行解密(之后的校验就不贴了)
String userName = null; String password = null; try { userName = req.getParameter("userName"); password = req.getParameter("password"); password = RSAUtils.decryptStringByJs(password);//解密后的字符串 } catch (Exception e) { j.setSuccess(false); j.setMsg("用户名或密码错误!"); sendMessage(userName, "用户名或密码错误,登录失败!"); return j; }
4.RSAUtils.java
package org.jeecgframework.web.system.util; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; import javax.crypto.Cipher; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; /** * RSA算法加密/解密工具类。 * 以下代码可以使用,唯一需要注意的是: org.bouncycastle...这个jar包需要找一到放到项目中,RSA所需jar包在java中已经自带了. * * @author liuyan */ public class RSAUtils { /** * 算法名称 */ private static final String ALGORITHOM = "RSA"; /** * 密钥大小 */ private static final int KEY_SIZE = 1024; /** * 默认的安全服务提供者 */ private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider(); private static KeyPairGenerator keyPairGen = null; private static KeyFactory keyFactory = null; /** * 缓存的密钥对。 */ private static KeyPair oneKeyPair = null; //密文种子, 当想更换RSA钥匙的时候,只需要修改密文种子,即可更换 private static final String radamKey = "nari";//你自己随便写上数字或者英文即可 //类加载后进行初始化数据 static { try { keyPairGen = KeyPairGenerator.getInstance(ALGORITHOM, DEFAULT_PROVIDER); keyFactory = KeyFactory.getInstance(ALGORITHOM, DEFAULT_PROVIDER); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); } } /** * 根据指定的密文种子,生成并返回RSA密钥对。 */ private static synchronized KeyPair generateKeyPair() { try { keyPairGen.initialize(KEY_SIZE, new SecureRandom(radamKey.getBytes())); oneKeyPair = keyPairGen.generateKeyPair(); return oneKeyPair; } catch (InvalidParameterException ex) { ex.printStackTrace(); } catch (NullPointerException ex) { ex.printStackTrace(); } return null; } /** * 返回初始化时默认的公钥。 */ public static RSAPublicKey getDefaultPublicKey() { KeyPair keyPair = generateKeyPair(); if (keyPair != null) { return (RSAPublicKey) keyPair.getPublic(); } return null; } /** * 使用指定的私钥解密数据。 * * @param privateKey 给定的私钥。 * @param data 要解密的数据。 * @return 原数据。 */ public static byte[] decrypt(PrivateKey privateKey, byte[] data) throws Exception { Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER); ci.init(Cipher.DECRYPT_MODE, privateKey); return ci.doFinal(data); } /** * 使用默认的私钥解密给定的字符串。 * * @param encryptText 密文。 * @return 原文字符串。 */ public static String decryptString(String encryptText) { if (StringUtils.isBlank(encryptText)) { return null; } KeyPair keyPair = generateKeyPair(); try { byte[] en_data = Hex.decode(encryptText); byte[] data = decrypt((RSAPrivateKey) keyPair.getPrivate(), en_data); return new String(data); } catch (NullPointerException ex) { ex.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } return null; } /** * 使用秘钥 - 对js端传递过来密文进行解密 * * @param encryptText 密文。 * @return {@code encryptText} 的原文字符串。 */ public static String decryptStringByJs(String encryptText) { String text = decryptString(encryptText); if (text == null) { return null; } String reverse = StringUtils.reverse(text); String decode = null; try { //这里需要进行编码转换.注:在前端js对明文加密前需要先进行转码-可自行百度"编码转换" decode = URLDecoder.decode(reverse, "UTF-8"); System.out.println("解密后文字:" + decode); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return decode; } //java端 - 使用公钥进行加密 public static byte[] encrypt(String plaintext) throws Exception { // 获取公钥及参数e,n RSAPublicKey publicKey = RSAUtils.getDefaultPublicKey(); //获取公钥指数 e BigInteger e = publicKey.getPublicExponent(); //获取公钥系数 n BigInteger n = publicKey.getModulus(); //先将明文进行编码 String encode = URLEncoder.encode(plaintext); // 获取明文字节数组 m BigInteger m = new BigInteger(encode.getBytes()); // 进行明文加密 c BigInteger c = m.modPow(e, n); //返回密文字节数组 return c.toByteArray(); } //java端 - 使用私钥进行解密 public static String decrypt(byte[] cipherText) throws Exception { // 读取私钥 KeyPair keyPair = generateKeyPair(); RSAPrivateKey prk = (RSAPrivateKey) keyPair.getPrivate(); // 获取私钥参数-指数/系数 BigInteger d = prk.getPrivateExponent(); BigInteger n = prk.getModulus(); // 读取密文 BigInteger c = new BigInteger(cipherText); // 进行解密 BigInteger m = c.modPow(d, n); // 解密结果-字节数组 byte[] mt = m.toByteArray(); //转成String,此时是乱码 String en = new String(mt); //再进行编码 String result = URLDecoder.decode(en, "UTF-8"); //最后返回解密后得到的明文 return result; } public static void main(String[] args) { /*解密js端传递过来的密文*/ //获取公钥对象--注意:前端那边需要用到公钥系数和指数 RSAPublicKey publicKey = RSAUtils.getDefaultPublicKey(); //公钥-系数(n) System.out.println("public key modulus:" + new String(Hex.encode(publicKey.getModulus().toByteArray()))); //公钥-指数(e1) System.out.println("public key exponent:" + new String(Hex.encode(publicKey.getPublicExponent().toByteArray()))); //JS加密后的字符串 String param = "abd87309c1c01f8eb20e46008e7260d792b336505cccf6e0328a3b35f72ba6cec6f4913aa80e150f3f78529ef8259d04f8fb0cda049e1426b89e2122fae2470039556364cdde128bd1d9068ade1c828172086bc316907b77fe9551edfd0a7e427ecf310f720ee558bc1fee07714401554b0887672053ed9879f6aa895816f368"; //解密后的字符串 String param1 = RSAUtils.decryptStringByJs(param); System.out.println(param1); } }
贴一下公钥系数和公钥指数以及加密后的字符串(明文是123456)
公钥系数:
00e0ffbc04ee1c099b3e898359a12a3d1a307415ec3daaff86e3d1b61a7d434e5073de79bc7de12324d4643fb93923f007897c35b7bb98c2864b8e4d319a5028935f882fad6ba1df8181478a331cf7d59335a603262bf7ad5aa648869ebd348640ad95f389eb603b6e301ea3e7aff24dc58209c2eef449a2bbe8d6d2159cdf1383
公钥指数:
010001
js加密后的字符串:
abd87309c1c01f8eb20e46008e7260d792b336505cccf6e0328a3b35f72ba6cec6f4913aa80e150f3f78529ef8259d04f8fb0cda049e1426b89e2122fae2470039556364cdde128bd1d9068ade1c828172086bc316907b77fe9551edfd0a7e427ecf310f720ee558bc1fee07714401554b0887672053ed9879f6aa895816f368
RSA后台签名前台验签的应用(前台采用jsrsasign库)
关于后台签名前台验签的, 如果有需要可以参考:RSA后台签名前台验签的应用(前台采用jsrsasign库)
感谢
作者:习惯沉淀
如果文中有误或对本文有不同的见解,欢迎在评论区留言。
如果觉得文章对你有帮助,请点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
扫码关注一线码农的学习见闻与思考。
回复"大数据","微服务","架构师","面试总结",获取更多学习资源!