├── README.md └── rsa_encrypt_decrypt_demo ├── .classpath ├── .gitignore ├── .project ├── .settings ├── .jsdtscope ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs ├── org.eclipse.m2e.core.prefs ├── org.eclipse.wst.common.component ├── org.eclipse.wst.common.project.facet.core.xml ├── org.eclipse.wst.jsdt.ui.superType.container └── org.eclipse.wst.jsdt.ui.superType.name ├── WebContent ├── META-INF │ └── MANIFEST.MF ├── WEB-INF │ ├── ftl │ │ └── rsa.ftl │ ├── spring-context.xml │ └── web.xml └── js │ ├── Barrett.js │ ├── BigInt.js │ └── RSA.js ├── pom.xml └── src └── seamonster └── demo ├── InitializeService.java ├── MyDemo.java └── RSAUtils.java /README.md: -------------------------------------------------------------------------------- 1 | # rsa_javaweb_javascript 2 | 3 | 很简单的前端+后端,使用RSA加密解密,找了网上很多文章,居然没有一个完整的能跑通的例子,只好自己动手写一个。 4 | 5 | RSA加密的内容长度有限,所以要么是只加密敏感内容,要么是结合其他对称加密例如AES使用(使用对称加密方式来加解密内容,用RSA来加解密对称加密的密钥) 6 | 7 | 参考 8 | http://www.justabug.net/door-1-rsa/ 这个已经说得挺详细了,也解决了其中遇到的一些问题,但竟然也有部分是错的 9 | 10 | 11 | http://sunxboy.iteye.com/blog/209156 本demo使用到的js就是这里提供的 12 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /target/ 3 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | rsa_encrypt_decrypt_demo 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.wst.validation.validationbuilder 25 | 26 | 27 | 28 | 29 | org.eclipse.m2e.core.maven2Builder 30 | 31 | 32 | 33 | 34 | 35 | org.eclipse.m2e.core.maven2Nature 36 | org.eclipse.jem.workbench.JavaEMFNature 37 | org.eclipse.wst.common.modulecore.ModuleCoreNature 38 | org.eclipse.wst.common.project.facet.core.nature 39 | org.eclipse.jdt.core.javanature 40 | org.eclipse.wst.jsdt.core.jsNature 41 | 42 | 43 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.compliance=1.6 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 8 | org.eclipse.jdt.core.compiler.source=1.6 9 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/WebContent/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/WebContent/WEB-INF/ftl/rsa.ftl: -------------------------------------------------------------------------------- 1 | <#import "spring.ftl" as spring /> 2 | 3 | 4 | 5 | 6 | 7 | RSA Demo 8 | 9 | 10 | 11 |

请输入要加密的内容:

12 |

13 |

14 |

服务端返回的内容

15 |

16 | 17 | 18 | 19 | 20 | 21 | 22 | 65 | 66 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/WebContent/WEB-INF/spring-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | application/json;charset=UTF-8 22 | text/plain;charset=UTF-8 23 | 24 | 25 | 26 | 27 | 28 | 29 | application/json;charset=UTF8 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/WebContent/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | rsa_encrypt_decrypt_demo 4 | 5 | index.html 6 | index.htm 7 | index.jsp 8 | default.html 9 | default.htm 10 | default.jsp 11 | 12 | 13 | 14 | contextConfigLocation 15 | 16 | /WEB-INF/spring-context.xml 17 | 18 | 19 | 20 | 21 | org.springframework.web.context.ContextLoaderListener 22 | 23 | 24 | 25 | action 26 | org.springframework.web.servlet.DispatcherServlet 27 | 28 | contextConfigLocation 29 | /WEB-INF/spring-context.xml 30 | 31 | 1 32 | 33 | 34 | action 35 | /s/* 36 | 37 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/WebContent/js/Barrett.js: -------------------------------------------------------------------------------- 1 | // BarrettMu, a class for performing Barrett modular reduction computations in 2 | // JavaScript. 3 | // 4 | // Requires BigInt.js. 5 | // 6 | // Copyright 2004-2005 David Shapiro. 7 | // 8 | // You may use, re-use, abuse, copy, and modify this code to your liking, but 9 | // please keep this header. 10 | // 11 | // Thanks! 12 | // 13 | // Dave Shapiro 14 | // dave@ohdave.com 15 | 16 | function BarrettMu(m) 17 | { 18 | this.modulus = biCopy(m); 19 | this.k = biHighIndex(this.modulus) + 1; 20 | var b2k = new BigInt(); 21 | b2k.digits[2 * this.k] = 1; // b2k = b^(2k) 22 | this.mu = biDivide(b2k, this.modulus); 23 | this.bkplus1 = new BigInt(); 24 | this.bkplus1.digits[this.k + 1] = 1; // bkplus1 = b^(k+1) 25 | this.modulo = BarrettMu_modulo; 26 | this.multiplyMod = BarrettMu_multiplyMod; 27 | this.powMod = BarrettMu_powMod; 28 | } 29 | 30 | function BarrettMu_modulo(x) 31 | { 32 | var q1 = biDivideByRadixPower(x, this.k - 1); 33 | var q2 = biMultiply(q1, this.mu); 34 | var q3 = biDivideByRadixPower(q2, this.k + 1); 35 | var r1 = biModuloByRadixPower(x, this.k + 1); 36 | var r2term = biMultiply(q3, this.modulus); 37 | var r2 = biModuloByRadixPower(r2term, this.k + 1); 38 | var r = biSubtract(r1, r2); 39 | if (r.isNeg) { 40 | r = biAdd(r, this.bkplus1); 41 | } 42 | var rgtem = biCompare(r, this.modulus) >= 0; 43 | while (rgtem) { 44 | r = biSubtract(r, this.modulus); 45 | rgtem = biCompare(r, this.modulus) >= 0; 46 | } 47 | return r; 48 | } 49 | 50 | function BarrettMu_multiplyMod(x, y) 51 | { 52 | /* 53 | x = this.modulo(x); 54 | y = this.modulo(y); 55 | */ 56 | var xy = biMultiply(x, y); 57 | return this.modulo(xy); 58 | } 59 | 60 | function BarrettMu_powMod(x, y) 61 | { 62 | var result = new BigInt(); 63 | result.digits[0] = 1; 64 | var a = x; 65 | var k = y; 66 | while (true) { 67 | if ((k.digits[0] & 1) != 0) result = this.multiplyMod(result, a); 68 | k = biShiftRight(k, 1); 69 | if (k.digits[0] == 0 && biHighIndex(k) == 0) break; 70 | a = this.multiplyMod(a, a); 71 | } 72 | return result; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/WebContent/js/BigInt.js: -------------------------------------------------------------------------------- 1 | // BigInt, a suite of routines for performing multiple-precision arithmetic in 2 | // JavaScript. 3 | // 4 | // Copyright 1998-2005 David Shapiro. 5 | // 6 | // You may use, re-use, abuse, 7 | // copy, and modify this code to your liking, but please keep this header. 8 | // Thanks! 9 | // 10 | // Dave Shapiro 11 | // dave@ohdave.com 12 | 13 | // IMPORTANT THING: Be sure to set maxDigits according to your precision 14 | // needs. Use the setMaxDigits() function to do this. See comments below. 15 | // 16 | // Tweaked by Ian Bunning 17 | // Alterations: 18 | // Fix bug in function biFromHex(s) to allow 19 | // parsing of strings of length != 0 (mod 4) 20 | 21 | // Changes made by Dave Shapiro as of 12/30/2004: 22 | // 23 | // The BigInt() constructor doesn't take a string anymore. If you want to 24 | // create a BigInt from a string, use biFromDecimal() for base-10 25 | // representations, biFromHex() for base-16 representations, or 26 | // biFromString() for base-2-to-36 representations. 27 | // 28 | // biFromArray() has been removed. Use biCopy() instead, passing a BigInt 29 | // instead of an array. 30 | // 31 | // The BigInt() constructor now only constructs a zeroed-out array. 32 | // Alternatively, if you pass , it won't construct any array. See the 33 | // biCopy() method for an example of this. 34 | // 35 | // Be sure to set maxDigits depending on your precision needs. The default 36 | // zeroed-out array ZERO_ARRAY is constructed inside the setMaxDigits() 37 | // function. So use this function to set the variable. DON'T JUST SET THE 38 | // VALUE. USE THE FUNCTION. 39 | // 40 | // ZERO_ARRAY exists to hopefully speed up construction of BigInts(). By 41 | // precalculating the zero array, we can just use slice(0) to make copies of 42 | // it. Presumably this calls faster native code, as opposed to setting the 43 | // elements one at a time. I have not done any timing tests to verify this 44 | // claim. 45 | 46 | // Max number = 10^16 - 2 = 9999999999999998; 47 | // 2^53 = 9007199254740992; 48 | 49 | var biRadixBase = 2; 50 | var biRadixBits = 16; 51 | var bitsPerDigit = biRadixBits; 52 | var biRadix = 1 << 16; // = 2^16 = 65536 53 | var biHalfRadix = biRadix >>> 1; 54 | var biRadixSquared = biRadix * biRadix; 55 | var maxDigitVal = biRadix - 1; 56 | var maxInteger = 9999999999999998; 57 | 58 | // maxDigits: 59 | // Change this to accommodate your largest number size. Use setMaxDigits() 60 | // to change it! 61 | // 62 | // In general, if you're working with numbers of size N bits, you'll need 2*N 63 | // bits of storage. Each digit holds 16 bits. So, a 1024-bit key will need 64 | // 65 | // 1024 * 2 / 16 = 128 digits of storage. 66 | // 67 | 68 | var maxDigits; 69 | var ZERO_ARRAY; 70 | var bigZero, bigOne; 71 | 72 | function setMaxDigits(value) 73 | { 74 | maxDigits = value; 75 | ZERO_ARRAY = new Array(maxDigits); 76 | for (var iza = 0; iza < ZERO_ARRAY.length; iza++) ZERO_ARRAY[iza] = 0; 77 | bigZero = new BigInt(); 78 | bigOne = new BigInt(); 79 | bigOne.digits[0] = 1; 80 | } 81 | 82 | setMaxDigits(20); 83 | 84 | // The maximum number of digits in base 10 you can convert to an 85 | // integer without JavaScript throwing up on you. 86 | var dpl10 = 15; 87 | // lr10 = 10 ^ dpl10 88 | var lr10 = biFromNumber(1000000000000000); 89 | 90 | function BigInt(flag) 91 | { 92 | if (typeof flag == "boolean" && flag == true) { 93 | this.digits = null; 94 | } 95 | else { 96 | this.digits = ZERO_ARRAY.slice(0); 97 | } 98 | this.isNeg = false; 99 | } 100 | 101 | function biFromDecimal(s) 102 | { 103 | var isNeg = s.charAt(0) == '-'; 104 | var i = isNeg ? 1 : 0; 105 | var result; 106 | // Skip leading zeros. 107 | while (i < s.length && s.charAt(i) == '0') ++i; 108 | if (i == s.length) { 109 | result = new BigInt(); 110 | } 111 | else { 112 | var digitCount = s.length - i; 113 | var fgl = digitCount % dpl10; 114 | if (fgl == 0) fgl = dpl10; 115 | result = biFromNumber(Number(s.substr(i, fgl))); 116 | i += fgl; 117 | while (i < s.length) { 118 | result = biAdd(biMultiply(result, lr10), 119 | biFromNumber(Number(s.substr(i, dpl10)))); 120 | i += dpl10; 121 | } 122 | result.isNeg = isNeg; 123 | } 124 | return result; 125 | } 126 | 127 | function biCopy(bi) 128 | { 129 | var result = new BigInt(true); 130 | result.digits = bi.digits.slice(0); 131 | result.isNeg = bi.isNeg; 132 | return result; 133 | } 134 | 135 | function biFromNumber(i) 136 | { 137 | var result = new BigInt(); 138 | result.isNeg = i < 0; 139 | i = Math.abs(i); 140 | var j = 0; 141 | while (i > 0) { 142 | result.digits[j++] = i & maxDigitVal; 143 | i = Math.floor(i / biRadix); 144 | } 145 | return result; 146 | } 147 | 148 | function reverseStr(s) 149 | { 150 | var result = ""; 151 | for (var i = s.length - 1; i > -1; --i) { 152 | result += s.charAt(i); 153 | } 154 | return result; 155 | } 156 | 157 | var hexatrigesimalToChar = new Array( 158 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 159 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 160 | 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 161 | 'u', 'v', 'w', 'x', 'y', 'z' 162 | ); 163 | 164 | function biToString(x, radix) 165 | // 2 <= radix <= 36 166 | { 167 | var b = new BigInt(); 168 | b.digits[0] = radix; 169 | var qr = biDivideModulo(x, b); 170 | var result = hexatrigesimalToChar[qr[1].digits[0]]; 171 | while (biCompare(qr[0], bigZero) == 1) { 172 | qr = biDivideModulo(qr[0], b); 173 | digit = qr[1].digits[0]; 174 | result += hexatrigesimalToChar[qr[1].digits[0]]; 175 | } 176 | return (x.isNeg ? "-" : "") + reverseStr(result); 177 | } 178 | 179 | function biToDecimal(x) 180 | { 181 | var b = new BigInt(); 182 | b.digits[0] = 10; 183 | var qr = biDivideModulo(x, b); 184 | var result = String(qr[1].digits[0]); 185 | while (biCompare(qr[0], bigZero) == 1) { 186 | qr = biDivideModulo(qr[0], b); 187 | result += String(qr[1].digits[0]); 188 | } 189 | return (x.isNeg ? "-" : "") + reverseStr(result); 190 | } 191 | 192 | var hexToChar = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 193 | 'a', 'b', 'c', 'd', 'e', 'f'); 194 | 195 | function digitToHex(n) 196 | { 197 | var mask = 0xf; 198 | var result = ""; 199 | for (i = 0; i < 4; ++i) { 200 | result += hexToChar[n & mask]; 201 | n >>>= 4; 202 | } 203 | return reverseStr(result); 204 | } 205 | 206 | function biToHex(x) 207 | { 208 | var result = ""; 209 | var n = biHighIndex(x); 210 | for (var i = biHighIndex(x); i > -1; --i) { 211 | result += digitToHex(x.digits[i]); 212 | } 213 | return result; 214 | } 215 | 216 | function charToHex(c) 217 | { 218 | var ZERO = 48; 219 | var NINE = ZERO + 9; 220 | var littleA = 97; 221 | var littleZ = littleA + 25; 222 | var bigA = 65; 223 | var bigZ = 65 + 25; 224 | var result; 225 | 226 | if (c >= ZERO && c <= NINE) { 227 | result = c - ZERO; 228 | } else if (c >= bigA && c <= bigZ) { 229 | result = 10 + c - bigA; 230 | } else if (c >= littleA && c <= littleZ) { 231 | result = 10 + c - littleA; 232 | } else { 233 | result = 0; 234 | } 235 | return result; 236 | } 237 | 238 | function hexToDigit(s) 239 | { 240 | var result = 0; 241 | var sl = Math.min(s.length, 4); 242 | for (var i = 0; i < sl; ++i) { 243 | result <<= 4; 244 | result |= charToHex(s.charCodeAt(i)) 245 | } 246 | return result; 247 | } 248 | 249 | function biFromHex(s) 250 | { 251 | var result = new BigInt(); 252 | var sl = s.length; 253 | for (var i = sl, j = 0; i > 0; i -= 4, ++j) { 254 | result.digits[j] = hexToDigit(s.substr(Math.max(i - 4, 0), Math.min(i, 4))); 255 | } 256 | return result; 257 | } 258 | 259 | function biFromString(s, radix) 260 | { 261 | var isNeg = s.charAt(0) == '-'; 262 | var istop = isNeg ? 1 : 0; 263 | var result = new BigInt(); 264 | var place = new BigInt(); 265 | place.digits[0] = 1; // radix^0 266 | for (var i = s.length - 1; i >= istop; i--) { 267 | var c = s.charCodeAt(i); 268 | var digit = charToHex(c); 269 | var biDigit = biMultiplyDigit(place, digit); 270 | result = biAdd(result, biDigit); 271 | place = biMultiplyDigit(place, radix); 272 | } 273 | result.isNeg = isNeg; 274 | return result; 275 | } 276 | 277 | function biDump(b) 278 | { 279 | return (b.isNeg ? "-" : "") + b.digits.join(" "); 280 | } 281 | 282 | function biAdd(x, y) 283 | { 284 | var result; 285 | 286 | if (x.isNeg != y.isNeg) { 287 | y.isNeg = !y.isNeg; 288 | result = biSubtract(x, y); 289 | y.isNeg = !y.isNeg; 290 | } 291 | else { 292 | result = new BigInt(); 293 | var c = 0; 294 | var n; 295 | for (var i = 0; i < x.digits.length; ++i) { 296 | n = x.digits[i] + y.digits[i] + c; 297 | result.digits[i] = n % biRadix; 298 | c = Number(n >= biRadix); 299 | } 300 | result.isNeg = x.isNeg; 301 | } 302 | return result; 303 | } 304 | 305 | function biSubtract(x, y) 306 | { 307 | var result; 308 | if (x.isNeg != y.isNeg) { 309 | y.isNeg = !y.isNeg; 310 | result = biAdd(x, y); 311 | y.isNeg = !y.isNeg; 312 | } else { 313 | result = new BigInt(); 314 | var n, c; 315 | c = 0; 316 | for (var i = 0; i < x.digits.length; ++i) { 317 | n = x.digits[i] - y.digits[i] + c; 318 | result.digits[i] = n % biRadix; 319 | // Stupid non-conforming modulus operation. 320 | if (result.digits[i] < 0) result.digits[i] += biRadix; 321 | c = 0 - Number(n < 0); 322 | } 323 | // Fix up the negative sign, if any. 324 | if (c == -1) { 325 | c = 0; 326 | for (var i = 0; i < x.digits.length; ++i) { 327 | n = 0 - result.digits[i] + c; 328 | result.digits[i] = n % biRadix; 329 | // Stupid non-conforming modulus operation. 330 | if (result.digits[i] < 0) result.digits[i] += biRadix; 331 | c = 0 - Number(n < 0); 332 | } 333 | // Result is opposite sign of arguments. 334 | result.isNeg = !x.isNeg; 335 | } else { 336 | // Result is same sign. 337 | result.isNeg = x.isNeg; 338 | } 339 | } 340 | return result; 341 | } 342 | 343 | 344 | function biHighIndex(x) 345 | { 346 | var result = x.digits.length - 1; 347 | while (result > 0 && x.digits[result] == 0) --result; 348 | return result; 349 | } 350 | 351 | function biNumBits(x) 352 | { 353 | var n = biHighIndex(x); 354 | var d = x.digits[n]; 355 | var m = (n + 1) * bitsPerDigit; 356 | var result; 357 | for (result = m; result > m - bitsPerDigit; --result) { 358 | if ((d & 0x8000) != 0) break; 359 | d <<= 1; 360 | } 361 | return result; 362 | } 363 | 364 | function biMultiply(x, y) 365 | { 366 | var result = new BigInt(); 367 | var c; 368 | var n = biHighIndex(x); 369 | var t = biHighIndex(y); 370 | var u, uv, k; 371 | 372 | for (var i = 0; i <= t; ++i) { 373 | c = 0; 374 | k = i; 375 | for (j = 0; j <= n; ++j, ++k) { 376 | uv = result.digits[k] + x.digits[j] * y.digits[i] + c; 377 | result.digits[k] = uv & maxDigitVal; 378 | c = uv >>> biRadixBits; 379 | //c = Math.floor(uv / biRadix); 380 | } 381 | result.digits[i + n + 1] = c; 382 | } 383 | // Someone give me a logical xor, please. 384 | result.isNeg = x.isNeg != y.isNeg; 385 | return result; 386 | } 387 | 388 | function biMultiplyDigit(x, y) 389 | { 390 | var n, c, uv; 391 | 392 | result = new BigInt(); 393 | n = biHighIndex(x); 394 | c = 0; 395 | for (var j = 0; j <= n; ++j) { 396 | uv = result.digits[j] + x.digits[j] * y + c; 397 | result.digits[j] = uv & maxDigitVal; 398 | c = uv >>> biRadixBits; 399 | //c = Math.floor(uv / biRadix); 400 | } 401 | result.digits[1 + n] = c; 402 | return result; 403 | } 404 | 405 | function arrayCopy(src, srcStart, dest, destStart, n) 406 | { 407 | var m = Math.min(srcStart + n, src.length); 408 | for (var i = srcStart, j = destStart; i < m; ++i, ++j) { 409 | dest[j] = src[i]; 410 | } 411 | } 412 | 413 | var highBitMasks = new Array(0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800, 414 | 0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0, 415 | 0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF); 416 | 417 | function biShiftLeft(x, n) 418 | { 419 | var digitCount = Math.floor(n / bitsPerDigit); 420 | var result = new BigInt(); 421 | arrayCopy(x.digits, 0, result.digits, digitCount, 422 | result.digits.length - digitCount); 423 | var bits = n % bitsPerDigit; 424 | var rightBits = bitsPerDigit - bits; 425 | for (var i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) { 426 | result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) | 427 | ((result.digits[i1] & highBitMasks[bits]) >>> 428 | (rightBits)); 429 | } 430 | result.digits[0] = ((result.digits[i] << bits) & maxDigitVal); 431 | result.isNeg = x.isNeg; 432 | return result; 433 | } 434 | 435 | var lowBitMasks = new Array(0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 436 | 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 437 | 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF); 438 | 439 | function biShiftRight(x, n) 440 | { 441 | var digitCount = Math.floor(n / bitsPerDigit); 442 | var result = new BigInt(); 443 | arrayCopy(x.digits, digitCount, result.digits, 0, 444 | x.digits.length - digitCount); 445 | var bits = n % bitsPerDigit; 446 | var leftBits = bitsPerDigit - bits; 447 | for (var i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) { 448 | result.digits[i] = (result.digits[i] >>> bits) | 449 | ((result.digits[i1] & lowBitMasks[bits]) << leftBits); 450 | } 451 | result.digits[result.digits.length - 1] >>>= bits; 452 | result.isNeg = x.isNeg; 453 | return result; 454 | } 455 | 456 | function biMultiplyByRadixPower(x, n) 457 | { 458 | var result = new BigInt(); 459 | arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n); 460 | return result; 461 | } 462 | 463 | function biDivideByRadixPower(x, n) 464 | { 465 | var result = new BigInt(); 466 | arrayCopy(x.digits, n, result.digits, 0, result.digits.length - n); 467 | return result; 468 | } 469 | 470 | function biModuloByRadixPower(x, n) 471 | { 472 | var result = new BigInt(); 473 | arrayCopy(x.digits, 0, result.digits, 0, n); 474 | return result; 475 | } 476 | 477 | function biCompare(x, y) 478 | { 479 | if (x.isNeg != y.isNeg) { 480 | return 1 - 2 * Number(x.isNeg); 481 | } 482 | for (var i = x.digits.length - 1; i >= 0; --i) { 483 | if (x.digits[i] != y.digits[i]) { 484 | if (x.isNeg) { 485 | return 1 - 2 * Number(x.digits[i] > y.digits[i]); 486 | } else { 487 | return 1 - 2 * Number(x.digits[i] < y.digits[i]); 488 | } 489 | } 490 | } 491 | return 0; 492 | } 493 | 494 | function biDivideModulo(x, y) 495 | { 496 | var nb = biNumBits(x); 497 | var tb = biNumBits(y); 498 | var origYIsNeg = y.isNeg; 499 | var q, r; 500 | if (nb < tb) { 501 | // |x| < |y| 502 | if (x.isNeg) { 503 | q = biCopy(bigOne); 504 | q.isNeg = !y.isNeg; 505 | x.isNeg = false; 506 | y.isNeg = false; 507 | r = biSubtract(y, x); 508 | // Restore signs, 'cause they're references. 509 | x.isNeg = true; 510 | y.isNeg = origYIsNeg; 511 | } else { 512 | q = new BigInt(); 513 | r = biCopy(x); 514 | } 515 | return new Array(q, r); 516 | } 517 | 518 | q = new BigInt(); 519 | r = x; 520 | 521 | // Normalize Y. 522 | var t = Math.ceil(tb / bitsPerDigit) - 1; 523 | var lambda = 0; 524 | while (y.digits[t] < biHalfRadix) { 525 | y = biShiftLeft(y, 1); 526 | ++lambda; 527 | ++tb; 528 | t = Math.ceil(tb / bitsPerDigit) - 1; 529 | } 530 | // Shift r over to keep the quotient constant. We'll shift the 531 | // remainder back at the end. 532 | r = biShiftLeft(r, lambda); 533 | nb += lambda; // Update the bit count for x. 534 | var n = Math.ceil(nb / bitsPerDigit) - 1; 535 | 536 | var b = biMultiplyByRadixPower(y, n - t); 537 | while (biCompare(r, b) != -1) { 538 | ++q.digits[n - t]; 539 | r = biSubtract(r, b); 540 | } 541 | for (var i = n; i > t; --i) { 542 | var ri = (i >= r.digits.length) ? 0 : r.digits[i]; 543 | var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1]; 544 | var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2]; 545 | var yt = (t >= y.digits.length) ? 0 : y.digits[t]; 546 | var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1]; 547 | if (ri == yt) { 548 | q.digits[i - t - 1] = maxDigitVal; 549 | } else { 550 | q.digits[i - t - 1] = Math.floor((ri * biRadix + ri1) / yt); 551 | } 552 | 553 | var c1 = q.digits[i - t - 1] * ((yt * biRadix) + yt1); 554 | var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2); 555 | while (c1 > c2) { 556 | --q.digits[i - t - 1]; 557 | c1 = q.digits[i - t - 1] * ((yt * biRadix) | yt1); 558 | c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2); 559 | } 560 | 561 | b = biMultiplyByRadixPower(y, i - t - 1); 562 | r = biSubtract(r, biMultiplyDigit(b, q.digits[i - t - 1])); 563 | if (r.isNeg) { 564 | r = biAdd(r, b); 565 | --q.digits[i - t - 1]; 566 | } 567 | } 568 | r = biShiftRight(r, lambda); 569 | // Fiddle with the signs and stuff to make sure that 0 <= r < y. 570 | q.isNeg = x.isNeg != origYIsNeg; 571 | if (x.isNeg) { 572 | if (origYIsNeg) { 573 | q = biAdd(q, bigOne); 574 | } else { 575 | q = biSubtract(q, bigOne); 576 | } 577 | y = biShiftRight(y, lambda); 578 | r = biSubtract(y, r); 579 | } 580 | // Check for the unbelievably stupid degenerate case of r == -0. 581 | if (r.digits[0] == 0 && biHighIndex(r) == 0) r.isNeg = false; 582 | 583 | return new Array(q, r); 584 | } 585 | 586 | function biDivide(x, y) 587 | { 588 | return biDivideModulo(x, y)[0]; 589 | } 590 | 591 | function biModulo(x, y) 592 | { 593 | return biDivideModulo(x, y)[1]; 594 | } 595 | 596 | function biMultiplyMod(x, y, m) 597 | { 598 | return biModulo(biMultiply(x, y), m); 599 | } 600 | 601 | function biPow(x, y) 602 | { 603 | var result = bigOne; 604 | var a = x; 605 | while (true) { 606 | if ((y & 1) != 0) result = biMultiply(result, a); 607 | y >>= 1; 608 | if (y == 0) break; 609 | a = biMultiply(a, a); 610 | } 611 | return result; 612 | } 613 | 614 | function biPowMod(x, y, m) 615 | { 616 | var result = bigOne; 617 | var a = x; 618 | var k = y; 619 | while (true) { 620 | if ((k.digits[0] & 1) != 0) result = biMultiplyMod(result, a, m); 621 | k = biShiftRight(k, 1); 622 | if (k.digits[0] == 0 && biHighIndex(k) == 0) break; 623 | a = biMultiplyMod(a, a, m); 624 | } 625 | return result; 626 | } 627 | 628 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/WebContent/js/RSA.js: -------------------------------------------------------------------------------- 1 | // RSA, a suite of routines for performing RSA public-key computations in 2 | // JavaScript. 3 | // 4 | // Requires BigInt.js and Barrett.js. 5 | // 6 | // Copyright 1998-2005 David Shapiro. 7 | // 8 | // You may use, re-use, abuse, copy, and modify this code to your liking, but 9 | // please keep this header. 10 | // 11 | // Thanks! 12 | // 13 | // Dave Shapiro 14 | // dave@ohdave.com 15 | 16 | function RSAKeyPair(encryptionExponent, decryptionExponent, modulus) 17 | { 18 | this.e = biFromHex(encryptionExponent); 19 | this.d = biFromHex(decryptionExponent); 20 | this.m = biFromHex(modulus); 21 | // We can do two bytes per digit, so 22 | // chunkSize = 2 * (number of digits in modulus - 1). 23 | // Since biHighIndex returns the high index, not the number of digits, 1 has 24 | // already been subtracted. 25 | this.chunkSize = 2 * biHighIndex(this.m); 26 | this.radix = 16; 27 | this.barrett = new BarrettMu(this.m); 28 | } 29 | 30 | function twoDigit(n) 31 | { 32 | return (n < 10 ? "0" : "") + String(n); 33 | } 34 | 35 | function encryptedString(key, s) 36 | // Altered by Rob Saunders (rob@robsaunders.net). New routine pads the 37 | // string after it has been converted to an array. This fixes an 38 | // incompatibility with Flash MX's ActionScript. 39 | { 40 | var a = new Array(); 41 | var sl = s.length; 42 | var i = 0; 43 | while (i < sl) { 44 | a[i] = s.charCodeAt(i); 45 | i++; 46 | } 47 | 48 | while (a.length % key.chunkSize != 0) { 49 | a[i++] = 0; 50 | } 51 | 52 | var al = a.length; 53 | var result = ""; 54 | var j, k, block; 55 | for (i = 0; i < al; i += key.chunkSize) { 56 | block = new BigInt(); 57 | j = 0; 58 | for (k = i; k < i + key.chunkSize; ++j) { 59 | block.digits[j] = a[k++]; 60 | block.digits[j] += a[k++] << 8; 61 | } 62 | var crypt = key.barrett.powMod(block, key.e); 63 | var text = key.radix == 16 ? biToHex(crypt) : biToString(crypt, key.radix); 64 | result += text + " "; 65 | } 66 | return result.substring(0, result.length - 1); // Remove last space. 67 | } 68 | 69 | function decryptedString(key, s) 70 | { 71 | var blocks = s.split(" "); 72 | var result = ""; 73 | var i, j, block; 74 | for (i = 0; i < blocks.length; ++i) { 75 | var bi; 76 | if (key.radix == 16) { 77 | bi = biFromHex(blocks[i]); 78 | } 79 | else { 80 | bi = biFromString(blocks[i], key.radix); 81 | } 82 | block = key.barrett.powMod(bi, key.d); 83 | for (j = 0; j <= biHighIndex(block); ++j) { 84 | result += String.fromCharCode(block.digits[j] & 255, 85 | block.digits[j] >> 8); 86 | } 87 | } 88 | // Remove trailing null, if any. 89 | if (result.charCodeAt(result.length - 1) == 0) { 90 | result = result.substring(0, result.length - 1); 91 | } 92 | return result; 93 | } 94 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | rsa_encrypt_decrypt_demo 4 | rsa_encrypt_decrypt_demo 5 | 0.0.1-SNAPSHOT 6 | 7 | src 8 | 9 | 10 | maven-compiler-plugin 11 | 3.1 12 | 13 | 1.6 14 | 1.6 15 | 16 | 17 | 18 | 19 | 20 | 21 | org.bouncycastle 22 | bcprov-jdk16 23 | 1.46 24 | 25 | 26 | org.freemarker 27 | freemarker 28 | 2.3.23 29 | 30 | 31 | org.springframework 32 | spring-webmvc 33 | 4.1.3.RELEASE 34 | 35 | 36 | org.springframework 37 | spring-context-support 38 | 4.1.3.RELEASE 39 | 40 | 41 | com.fasterxml.jackson.core 42 | jackson-databind 43 | 2.9.9.3 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/src/seamonster/demo/InitializeService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package seamonster.demo; 5 | 6 | import org.springframework.beans.factory.InitializingBean; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author Dovahkiin 11 | * 12 | */ 13 | @Service 14 | public class InitializeService implements InitializingBean { 15 | 16 | /* (non-Javadoc) 17 | * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() 18 | */ 19 | @Override 20 | public void afterPropertiesSet() throws Exception { 21 | //服务初始化时生成公钥密钥对 22 | RSAUtils.generateKeyPair(); //生成公钥密钥对 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/src/seamonster/demo/MyDemo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package seamonster.demo; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.ui.Model; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestMethod; 15 | import org.springframework.web.bind.annotation.ResponseBody; 16 | import org.springframework.web.context.request.WebRequest; 17 | 18 | 19 | /** 20 | * @author Dovahkiin 21 | * 22 | */ 23 | @Controller 24 | @RequestMapping(value = "/rsa") 25 | public class MyDemo { 26 | 27 | @RequestMapping(method=RequestMethod.GET) 28 | public String doGet(HttpServletRequest req, Model model){ 29 | try{ 30 | 31 | 32 | //返回n和e到页面上,有这两个值就能得出公钥 33 | model.addAttribute("n", RSAUtils.getModulus()); 34 | model.addAttribute("e", RSAUtils.getPublicExponent()); 35 | 36 | }catch(Exception e){ 37 | e.printStackTrace(); 38 | } 39 | 40 | return "rsa";// rsa.ftl 41 | 42 | } 43 | 44 | @RequestMapping(params = "action=test") 45 | @ResponseBody 46 | public Map test(WebRequest req) { 47 | try{ 48 | Map resultMap = new HashMap(); 49 | String str = req.getParameter("data"); 50 | String decryptResult = RSAUtils.decryptPrivate(str); 51 | 52 | //以上是前端js加密,后端java解密 53 | 54 | //以下是后端java加密,前端js解密 55 | String encryptResult = RSAUtils.encryptPrivate(decryptResult); 56 | resultMap.put("encryptResult", encryptResult); 57 | return resultMap; 58 | }catch(Exception e){ 59 | e.printStackTrace(); 60 | return null; 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /rsa_encrypt_decrypt_demo/src/seamonster/demo/RSAUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package seamonster.demo; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.math.BigInteger; 8 | import java.net.URLDecoder; 9 | import java.net.URLEncoder; 10 | import java.security.Key; 11 | import java.security.KeyPair; 12 | import java.security.KeyPairGenerator; 13 | import java.security.SecureRandom; 14 | 15 | import javax.crypto.Cipher; 16 | 17 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 18 | import org.bouncycastle.jce.provider.JCERSAPrivateKey; 19 | import org.bouncycastle.jce.provider.JCERSAPublicKey; 20 | 21 | 22 | /** 23 | * @author Dovahkiin 24 | * 25 | */ 26 | public class RSAUtils { 27 | public static KeyPair KEY_PAIR = null; 28 | private static BouncyCastleProvider bouncyCastleProvider = new BouncyCastleProvider(); 29 | 30 | /** 31 | * 生成公钥私钥 32 | */ 33 | public static KeyPair generateKeyPair() throws Exception { 34 | try { 35 | KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", bouncyCastleProvider); 36 | final int KEY_SIZE = 1024;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低 37 | // final int KEY_SIZE = 4096; 38 | keyPairGen.initialize(KEY_SIZE, new SecureRandom()); 39 | KeyPair keyPair = keyPairGen.generateKeyPair(); 40 | 41 | System.out.println(keyPair.getPrivate()); 42 | System.out.println(keyPair.getPublic()); 43 | KEY_PAIR = keyPair; 44 | return keyPair; 45 | } catch (Exception e) { 46 | throw new Exception(e.getMessage()); 47 | } 48 | } 49 | 50 | /** 51 | * 用私钥加密 52 | */ 53 | public static String encryptPrivate(String data) throws Exception { 54 | return encrypt(KEY_PAIR.getPrivate(), data); 55 | } 56 | 57 | /** 58 | * 用私钥解密 59 | */ 60 | public static String decryptPrivate(String data) throws Exception { 61 | return decrypt(KEY_PAIR.getPrivate(), data); 62 | } 63 | 64 | private static String encrypt(Key pk, String data) throws Exception { 65 | 66 | System.out.println("需要加密的:" + data); 67 | String encodeStr = URLEncoder.encode(data, "UTF-8"); 68 | System.out.println("Encode后的:" + encodeStr); 69 | String encodeStr2 = encodeStr.replace("+", "%20"); 70 | System.out.println("+替换为%20:" + encodeStr2); 71 | byte[] b1 = encodeStr2.getBytes(); 72 | byte[] b2 = encrypt(pk, b1); 73 | String encryptedString = byteToString(b2); 74 | System.out.println("加密后的:" + encryptedString); 75 | return encryptedString; 76 | } 77 | 78 | private static String decrypt(Key pk, String data) throws Exception { 79 | System.out.println("需要解密的:" + data); 80 | byte[] b1 = hexStringToBytes(data); 81 | byte[] b2 = decrypt(pk, b1); 82 | String decryptedString = new String(b2); 83 | System.out.println("解密后的:" + decryptedString); 84 | String reverseDecryptedString = new StringBuffer(decryptedString).reverse().toString(); 85 | System.out.println("解密后再倒序:" + reverseDecryptedString); 86 | String resultString = URLDecoder.decode(reverseDecryptedString, "UTF-8"); 87 | System.out.println("最后URLDecoder一下:" + resultString); 88 | return resultString; 89 | } 90 | 91 | /** 92 | * 返回公钥指数e 93 | */ 94 | public static String getPublicExponent() { 95 | BigInteger b = ((JCERSAPublicKey) KEY_PAIR.getPublic()).getPublicExponent(); 96 | return b.toString(16); 97 | } 98 | 99 | /** 100 | * 返回模值n 101 | */ 102 | public static String getModulus() { 103 | BigInteger b = ((JCERSAPublicKey) KEY_PAIR.getPublic()).getModulus(); 104 | return b.toString(16); 105 | } 106 | 107 | /** 108 | * 返回私钥指数d 109 | * 110 | * @return 111 | */ 112 | public static String getPrivateExponent() { 113 | BigInteger b = ((JCERSAPrivateKey) KEY_PAIR.getPrivate()).getPrivateExponent(); 114 | return b.toString(16); 115 | } 116 | 117 | /** 118 | * 加密 119 | * 120 | * @param key 121 | * 加密的密钥 (也可以是公钥) 122 | * @param data 123 | * 待加密的明文数据 124 | * @return 加密后的数据 125 | */ 126 | private static byte[] encrypt(Key pk, byte[] data) throws Exception { 127 | try { 128 | Cipher cipher = Cipher.getInstance("RSA", bouncyCastleProvider); 129 | cipher.init(Cipher.ENCRYPT_MODE, pk); 130 | int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024 131 | // 加密块大小为127 132 | // byte,加密后为128个byte;因此共有2个加密块,第一个127 133 | // byte第二个为1个byte 134 | int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小 135 | int leavedSize = data.length % blockSize; 136 | int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize; 137 | byte[] raw = new byte[outputSize * blocksSize]; 138 | int i = 0; 139 | while (data.length - i * blockSize > 0) { 140 | if (data.length - i * blockSize > blockSize) 141 | cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize); 142 | else 143 | cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize); 144 | // 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到 145 | // ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了 146 | // OutputSize所以只好用dofinal方法。 147 | i++; 148 | } 149 | return raw; 150 | } catch (Exception e) { 151 | throw new Exception(e.getMessage()); 152 | } 153 | } 154 | 155 | /** 156 | * 解密 157 | * 158 | * @param key 159 | * 解密的密钥 (也可以是公钥) 160 | * @param raw 161 | * 已经加密的数据 162 | * @return 解密后的明文 163 | */ 164 | private static byte[] decrypt(Key pk, byte[] raw) throws Exception { 165 | try { 166 | Cipher cipher = Cipher.getInstance("RSA", bouncyCastleProvider); 167 | cipher.init(Cipher.DECRYPT_MODE, pk); 168 | int blockSize = cipher.getBlockSize(); 169 | ByteArrayOutputStream bout = new ByteArrayOutputStream(64); 170 | int j = 0; 171 | while (raw.length - j * blockSize > 0) { 172 | bout.write(cipher.doFinal(raw, j * blockSize, blockSize)); 173 | j++; 174 | } 175 | return bout.toByteArray(); 176 | } catch (Exception e) { 177 | throw new Exception(e.getMessage()); 178 | } 179 | } 180 | 181 | private static byte[] hexStringToBytes(String hexString) { 182 | if (hexString == null || hexString.equals("")) { 183 | return null; 184 | } 185 | hexString = hexString.toUpperCase(); 186 | int length = hexString.length() / 2; 187 | char[] hexChars = hexString.toCharArray(); 188 | byte[] d = new byte[length]; 189 | for (int i = 0; i < length; i++) { 190 | int pos = i * 2; 191 | d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); 192 | } 193 | return d; 194 | } 195 | 196 | /** * Convert char to byte * @param c char * @return byte */ 197 | private static byte charToByte(char c) { 198 | return (byte) "0123456789ABCDEF".indexOf(c); 199 | } 200 | 201 | /** 202 | * 把byte数组变换为16進数的字符串。 203 | * 204 | * @param bytes 205 | * byte数组 206 | * @return 16進数的字符串 207 | */ 208 | private static String byteToString(byte[] bytes) { 209 | StringBuffer buf = new StringBuffer(); 210 | for (int i = 0; i < bytes.length; i++) { 211 | int d = bytes[i]; 212 | if (d < 0) { 213 | d += 256; 214 | } 215 | if (d < 16) { 216 | buf.append("0"); 217 | } 218 | buf.append(Integer.toString(d, 16)); 219 | } 220 | return buf.toString(); 221 | } 222 | 223 | /** 224 | * 用公钥加密 225 | */ 226 | public static String encryptPublic(String data) throws Exception { 227 | return encrypt(KEY_PAIR.getPublic(), data); 228 | } 229 | 230 | /** 231 | * 用公钥解密 232 | */ 233 | public static String decryptPublic(String data) throws Exception { 234 | return decrypt(KEY_PAIR.getPublic(), data); 235 | } 236 | 237 | 238 | } 239 | --------------------------------------------------------------------------------