-
-
[求助]C# java 的RSA交互
-
发表于: 2010-2-11 06:40 12074
-
C# java 的RSA交互
我在用java做注册码私密加密后用C# RSA做公密解密结果不正确。
然后做了下 java与C#下 RSA加密结果的比较,结果发现加密结果都不同(都是以16进制做比较),
不知道是不是两个平台内部实现编码不同,已知Java的byte是 -128-127;而.Net下面则是0-255,
但我把结果转换为16进制是呼不影响。不知道还有什么其它原因,因为我用php下也失败了~唯一成功的是vc的一个MIRACL库实现的rsa与下面用C#实现的rsa交互成功。
最后在加一个PHP的RSA,如果不跨语言都能正常加解密。
下面是java RSA代码:
下面是C#RSA代码:
PHP 的RSA:
我在用java做注册码私密加密后用C# RSA做公密解密结果不正确。
然后做了下 java与C#下 RSA加密结果的比较,结果发现加密结果都不同(都是以16进制做比较),
不知道是不是两个平台内部实现编码不同,已知Java的byte是 -128-127;而.Net下面则是0-255,
但我把结果转换为16进制是呼不影响。不知道还有什么其它原因,因为我用php下也失败了~唯一成功的是vc的一个MIRACL库实现的rsa与下面用C#实现的rsa交互成功。
最后在加一个PHP的RSA,如果不跨语言都能正常加解密。
下面是java RSA代码:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | package RSA; import java.math.BigInteger; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import javax.crypto.Cipher; import RSA.RSA; public class RSA { private PublicKey getPublicKey(String modulus,String publicExponent) throws Exception { BigInteger m = new BigInteger(modulus); BigInteger e = new BigInteger(publicExponent); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m,e); KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } private PrivateKey getPrivateKey(String modulus,String privateExponent) throws Exception { BigInteger m = new BigInteger(modulus); BigInteger e = new BigInteger(privateExponent); RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m,e); KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } public static String EncryptDecrypt(String str,boolean isEncrypt) throws Exception { // 获取密钥[十进制] String modulus = "5067852929847778527279846709762838074277305151840522384841017913327761244616289848228918977455840565970295302650189674150168014952189332742273427177659617" ; String publicExponent = "105683" ; String privateExponet = "3437535244799428514785309003239395620436291738592657732628032598591074863699067168217305655555146780199222847741841955063573060786645301146163960716630247" ; String re= "" ; RSA key = new RSA(); PublicKey publicKey = key.getPublicKey(modulus, publicExponent); PrivateKey privateKey = key.getPrivateKey(modulus, privateExponet); Cipher cipher = Cipher.getInstance( "RSA" ); // 加解密类 byte[] buff; if (isEncrypt) { cipher.init(Cipher.ENCRYPT_MODE, privateKey); // 加密 buff = cipher.doFinal(str.getBytes()); re = Convert.bytesToHexString(buff); // 转为16进制 } else { cipher.init(Cipher.DECRYPT_MODE, publicKey); byte[] d = Convert.hexStringToBytes(str); //16 转字符串 buff = cipher.doFinal( d ); re = new String(buff); } return re; } public static void main(String[] args) throws Exception { String str = EncryptDecrypt( "aaaa" , true ); System.out.println(str); String s = EncryptDecrypt(str, false ); System.out.println(s); } } package RSA; public class Base64 { private static final byte[] encodingTable = { (byte) 'A' , (byte) 'B' , (byte) 'C' , (byte) 'D' , (byte) 'E' , (byte) 'F' , (byte) 'G' , (byte) 'H' , (byte) 'I' , (byte) 'J' , (byte) 'K' , (byte) 'L' , (byte) 'M' , (byte) 'N' , (byte) 'O' , (byte) 'P' , (byte) 'Q' , (byte) 'R' , (byte) 'S' , (byte) 'T' , (byte) 'U' , (byte) 'V' , (byte) 'W' , (byte) 'X' , (byte) 'Y' , (byte) 'Z' , (byte) 'a' , (byte) 'b' , (byte) 'c' , (byte) 'd' , (byte) 'e' , (byte) 'f' , (byte) 'g' , (byte) 'h' , (byte) 'i' , (byte) 'j' , (byte) 'k' , (byte) 'l' , (byte) 'm' , (byte) 'n' , (byte) 'o' , (byte) 'p' , (byte) 'q' , (byte) 'r' , (byte) 's' , (byte) 't' , (byte) 'u' , (byte) 'v' , (byte) 'w' , (byte) 'x' , (byte) 'y' , (byte) 'z' , (byte) '0' , (byte) '1' , (byte) '2' , (byte) '3' , (byte) '4' , (byte) '5' , (byte) '6' , (byte) '7' , (byte) '8' , (byte) '9' , (byte) '+' , (byte) '/' }; private static final byte[] decodingTable; static { decodingTable = new byte[128]; for (int i = 0; i < 128; i++) { decodingTable[i] = (byte) -1; } for (int i = 'A' ; i <= 'Z' ; i++) { decodingTable[i] = (byte) (i - 'A' ); } for (int i = 'a' ; i <= 'z' ; i++) { decodingTable[i] = (byte) (i - 'a' + 26); } for (int i = '0' ; i <= '9' ; i++) { decodingTable[i] = (byte) (i - '0' + 52); } decodingTable[ '+' ] = 62; decodingTable[ '/' ] = 63; } public static byte[] encode(byte[] data) { byte[] bytes; int modulus = data.length % 3; if (modulus == 0) { bytes = new byte[(4 * data.length) / 3]; } else { bytes = new byte[4 * ((data.length / 3) + 1)]; } int dataLength = (data.length - modulus); int a1; int a2; int a3; for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) { a1 = data[i] & 0xff; a2 = data[i + 1] & 0xff; a3 = data[i + 2] & 0xff; bytes[j] = encodingTable[(a1 >>> 2) & 0x3f]; bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]; bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]; bytes[j + 3] = encodingTable[a3 & 0x3f]; } int b1; int b2; int b3; int d1; int d2; switch (modulus) { case 0: /* nothing left to do */ break ; case 1: d1 = data[data.length - 1] & 0xff; b1 = (d1 >>> 2) & 0x3f; b2 = (d1 << 4) & 0x3f; bytes[bytes.length - 4] = encodingTable[b1]; bytes[bytes.length - 3] = encodingTable[b2]; bytes[bytes.length - 2] = (byte) '=' ; bytes[bytes.length - 1] = (byte) '=' ; break ; case 2: d1 = data[data.length - 2] & 0xff; d2 = data[data.length - 1] & 0xff; b1 = (d1 >>> 2) & 0x3f; b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; b3 = (d2 << 2) & 0x3f; bytes[bytes.length - 4] = encodingTable[b1]; bytes[bytes.length - 3] = encodingTable[b2]; bytes[bytes.length - 2] = encodingTable[b3]; bytes[bytes.length - 1] = (byte) '=' ; break ; } return bytes; } public static byte[] decode(byte[] data) { byte[] bytes; byte b1; byte b2; byte b3; byte b4; data = discardNonBase64Bytes(data); if (data[data.length - 2] == '=' ) { bytes = new byte[(((data.length / 4) - 1) * 3) + 1]; } else if (data[data.length - 1] == '=' ) { bytes = new byte[(((data.length / 4) - 1) * 3) + 2]; } else { bytes = new byte[((data.length / 4) * 3)]; } for (int i = 0, j = 0; i < (data.length - 4); i += 4, j += 3) { b1 = decodingTable[data[i]]; b2 = decodingTable[data[i + 1]]; b3 = decodingTable[data[i + 2]]; b4 = decodingTable[data[i + 3]]; bytes[j] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2)); bytes[j + 2] = (byte) ((b3 << 6) | b4); } if (data[data.length - 2] == '=' ) { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4)); } else if (data[data.length - 1] == '=' ) { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; b3 = decodingTable[data[data.length - 2]]; bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2)); } else { b1 = decodingTable[data[data.length - 4]]; b2 = decodingTable[data[data.length - 3]]; b3 = decodingTable[data[data.length - 2]]; b4 = decodingTable[data[data.length - 1]]; bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2)); bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4); } return bytes; } public static byte[] decode(String data) { byte[] bytes; byte b1; byte b2; byte b3; byte b4; data = discardNonBase64Chars(data); if (data.charAt(data.length() - 2) == '=' ) { bytes = new byte[(((data.length() / 4) - 1) * 3) + 1]; } else if (data.charAt(data.length() - 1) == '=' ) { bytes = new byte[(((data.length() / 4) - 1) * 3) + 2]; } else { bytes = new byte[((data.length() / 4) * 3)]; } for (int i = 0, j = 0; i < (data.length() - 4); i += 4, j += 3) { b1 = decodingTable[data.charAt(i)]; b2 = decodingTable[data.charAt(i + 1)]; b3 = decodingTable[data.charAt(i + 2)]; b4 = decodingTable[data.charAt(i + 3)]; bytes[j] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2)); bytes[j + 2] = (byte) ((b3 << 6) | b4); } if (data.charAt(data.length() - 2) == '=' ) { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4)); } else if (data.charAt(data.length() - 1) == '=' ) { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; b3 = decodingTable[data.charAt(data.length() - 2)]; bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2)); } else { b1 = decodingTable[data.charAt(data.length() - 4)]; b2 = decodingTable[data.charAt(data.length() - 3)]; b3 = decodingTable[data.charAt(data.length() - 2)]; b4 = decodingTable[data.charAt(data.length() - 1)]; bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2)); bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4); } return bytes; } private static byte[] discardNonBase64Bytes(byte[] data) { byte[] temp = new byte[data.length]; int bytesCopied = 0; for (int i = 0; i < data.length; i++) { if (isValidBase64Byte(data[i])) { temp[bytesCopied++] = data[i]; } } byte[] newData = new byte[bytesCopied]; System.arraycopy(temp, 0, newData, 0, bytesCopied); return newData; } private static String discardNonBase64Chars(String data) { StringBuffer sb = new StringBuffer(); int length = data.length(); for (int i = 0; i < length; i++) { if (isValidBase64Byte((byte) (data.charAt(i)))) { sb.append(data.charAt(i)); } } return sb.toString(); } private static boolean isValidBase64Byte(byte b) { if (b == '=' ) { return true ; } else if ((b < 0) || (b >= 128)) { return false ; } else if (decodingTable[b] == -1) { return false ; } return true ; } } package RSA; public class Convert { /** * Convert char to byte * @param c char * @ return byte */ private static byte charToByte(char c) { return (byte) "0123456789ABCDEF" .indexOf(c); } public static String bytesToHexString(byte[] src){ StringBuilder stringBuilder = new StringBuilder( "" ); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString( v ); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } /** * Convert hex string to byte[] * @param hexString the hex string * @ return byte[] */ public static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals( "" )) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } } |
下面是C#RSA代码:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | MyRSA r = new MyRSA(); byte[] privateBuff = r.EncryptByPrivateKey( "aaaa" , nn, dd ); // 私密加密 textBox1.Text = tool.byteToHexStr(privateBuff); #region MyRSA class MyRSA { #region 一、密钥管理 // 取得密钥主要是通过2种方式 // 一种是通过RSACryptoServiceProvider取得: /// <summary> /// RSA算法对象,此处主要用于获取密钥对 /// < /summary > private RSACryptoServiceProvider rsa; /// <summary> /// 取得密钥 /// < /summary > /// <param name= "includPrivateKey" > true :包含私钥 false :不包含私钥< /param > /// <returns>< /returns > public string ToXmlString(bool includPrivateKey) { if (includPrivateKey) { return rsa.ToXmlString( true ); } else { return rsa.ToXmlString( false ); } } /// <summary> /// 通过密钥初始化RSA对象 /// < /summary > /// <param name= "xmlString" >XML格式的密钥信息< /param > public void FromXmlString(string xmlString) { rsa.FromXmlString(xmlString); } // 一种是通过BigInteger中的获取大素数的方法 /// <summary> /// 取得密钥对 /// < /summary > /// <param name= "n" >大整数< /param > /// <param name= "e" >公钥< /param > /// <param name= "d" >密钥< /param > public void GetKey(out string n, out string e, out string d) { byte[] pseudoPrime1 = { (byte)0x85, (byte)0x84, (byte)0x64, (byte)0xFD, (byte)0x70, (byte)0x6A, (byte)0x9F, (byte)0xF0, (byte)0x94, (byte)0x0C, (byte)0x3E, (byte)0x2C, (byte)0x74, (byte)0x34, (byte)0x05, (byte)0xC9, (byte)0x55, (byte)0xB3, (byte)0x85, (byte)0x32, (byte)0x98, (byte)0x71, (byte)0xF9, (byte)0x41, (byte)0x21, (byte)0x5F, (byte)0x02, (byte)0x9E, (byte)0xEA, (byte)0x56, (byte)0x8D, (byte)0x8C, (byte)0x44, (byte)0xCC, (byte)0xEE, (byte)0xEE, (byte)0x3D, (byte)0x2C, (byte)0x9D, (byte)0x2C, (byte)0x12, (byte)0x41, (byte)0x1E, (byte)0xF1, (byte)0xC5, (byte)0x32, (byte)0xC3, (byte)0xAA, (byte)0x31, (byte)0x4A, (byte)0x52, (byte)0xD8, (byte)0xE8, (byte)0xAF, (byte)0x42, (byte)0xF4, (byte)0x72, (byte)0xA1, (byte)0x2A, (byte)0x0D, (byte)0x97, (byte)0xB1, (byte)0x31, (byte)0xB3, }; byte[] pseudoPrime2 = { (byte)0x99, (byte)0x98, (byte)0xCA, (byte)0xB8, (byte)0x5E, (byte)0xD7, (byte)0xE5, (byte)0xDC, (byte)0x28, (byte)0x5C, (byte)0x6F, (byte)0x0E, (byte)0x15, (byte)0x09, (byte)0x59, (byte)0x6E, (byte)0x84, (byte)0xF3, (byte)0x81, (byte)0xCD, (byte)0xDE, (byte)0x42, (byte)0xDC, (byte)0x93, (byte)0xC2, (byte)0x7A, (byte)0x62, (byte)0xAC, (byte)0x6C, (byte)0xAF, (byte)0xDE, (byte)0x74, (byte)0xE3, (byte)0xCB, (byte)0x60, (byte)0x20, (byte)0x38, (byte)0x9C, (byte)0x21, (byte)0xC3, (byte)0xDC, (byte)0xC8, (byte)0xA2, (byte)0x4D, (byte)0xC6, (byte)0x2A, (byte)0x35, (byte)0x7F, (byte)0xF3, (byte)0xA9, (byte)0xE8, (byte)0x1D, (byte)0x7B, (byte)0x2C, (byte)0x78, (byte)0xFA, (byte)0xB8, (byte)0x02, (byte)0x55, (byte)0x80, (byte)0x9B, (byte)0xC2, (byte)0xA5, (byte)0xCB, }; BigInteger bi_p = new BigInteger(pseudoPrime1); BigInteger bi_q = new BigInteger(pseudoPrime2); BigInteger bi_pq = (bi_p - 1) * (bi_q - 1); BigInteger bi_n = bi_p * bi_q; Random rand = new Random(); BigInteger bi_e = bi_pq.genCoPrime(512, rand); BigInteger bi_d = bi_e.modInverse(bi_pq); n = bi_n.ToHexString(); e = bi_e.ToHexString(); d = bi_d.ToHexString(); } #endregion #region 二、加密处理(分别对应两种密钥取得方式) // 公钥加密 /// <summary> /// 通过公钥加密 /// < /summary > /// <param name= "dataStr" >待加密字符串< /param > /// <returns>加密结果< /returns > public byte[] EncryptByPublicKey(string dataStr) { // 取得公钥参数 RSAParameters rsaparameters = rsa.ExportParameters( false ); byte[] keyN = rsaparameters.Modulus; byte[] keyE = rsaparameters.Exponent; // 大整数N BigInteger biN = new BigInteger(keyN); // 公钥大素数 BigInteger biE = new BigInteger(keyE); // 加密 return EncryptString(dataStr, biE, biN); } /// <summary> /// 通过公钥加密 /// < /summary > /// <param name= "dataStr" >待加密字符串< /param > /// <param name= "n" >大整数n< /param > /// <param name= "e" >公钥< /param > /// <returns>加密结果< /returns > public byte[] EncryptByPublicKey(string dataStr, string n, string e) { // 大整数N BigInteger biN = new BigInteger(n, 16); // 公钥大素数 BigInteger biE = new BigInteger(e, 16); // 加密 return EncryptString(dataStr, biE, biN); } #endregion #region 私钥解密 /// <summary> /// 通过私钥解密 /// < /summary > /// <param name= "dataBytes" >待解密字符数组< /param > /// <returns>解密结果< /returns > public string DecryptByPrivateKey(byte[] dataBytes) { // 取得私钥参数 RSAParameters rsaparameters = rsa.ExportParameters( true ); byte[] keyN = rsaparameters.Modulus; byte[] keyD = rsaparameters.D; // 大整数N BigInteger biN = new BigInteger(keyN); // 私钥大素数 BigInteger biD = new BigInteger(keyD); // 解密 return DecryptBytes(dataBytes, biD, biN); } /// <summary> /// 通过私钥解密 /// < /summary > /// <param name= "dataBytes" >待解密字符数组< /param > /// <param name= "n" >大整数n< /param > /// <param name= "d" >私钥< /param > /// <returns>解密结果< /returns > public string DecryptByPrivateKey(byte[] dataBytes, string n, string d) { // 大整数N BigInteger biN = new BigInteger(n, 16); // 私钥大素数 BigInteger biD = new BigInteger(d, 16); // 解密 return DecryptBytes(dataBytes, biD, biN); } #endregion #region 私钥加密 public byte[] EncryptByPrivateKey(string dataStr, string n, string d) { BigInteger biN = new BigInteger(n, 16); BigInteger biD = new BigInteger(d, 16); return EncryptString(dataStr, biD, biN); } #endregion #region 公钥解密 /// <summary> /// 通过公钥解密 /// < /summary > /// <param name= "dataBytes" >待解密字符数组< /param > /// <returns>解密结果< /returns > public string DecryptByPublicKey(byte[] dataBytes) { // 取得公钥参数 RSAParameters rsaparameters = rsa.ExportParameters( false ); byte[] keyN = rsaparameters.Modulus; byte[] keyE = rsaparameters.Exponent; // 大整数N BigInteger biN = new BigInteger(keyN); // 公钥大素数 BigInteger biE = new BigInteger(keyE); // 解密 return DecryptBytes(dataBytes, biE, biN); } /// <summary> /// 通过公钥解密 /// < /summary > /// <param name= "dataBytes" >待加密字符串< /param > /// <param name= "n" >大整数n< /param > /// <param name= "e" >公钥< /param > /// <returns>解密结果< /returns > public string DecryptByPublicKey(byte[] dataBytes, string n, string e) { // 大整数N BigInteger biN = new BigInteger(n, 16); // 公钥大素数 BigInteger biE = new BigInteger(e, 16); // 解密 return DecryptBytes(dataBytes, biE, biN); } #endregion #region 加解密字符串 /// <summary> /// 加密字符串 /// < /summary > /// <param name= "dataStr" >待加密字符串< /param > /// <param name= "keyNmu" >密钥大素数< /param > /// <param name= "nNum" >大整数N< /param > /// <returns>加密结果< /returns > private byte[] EncryptString(string dataStr, BigInteger keyNum, BigInteger nNum) { byte[] bytes = System.Text.Encoding.UTF8.GetBytes(dataStr); int len = bytes.Length; int len1 = 0; int blockLen = 0; if ((len % 120) == 0) len1 = len / 120; else len1 = len / 120 + 1; List<byte> tempbytes = new List<byte>(); for (int i = 0; i < len1; i++) { if (len >= 120) { blockLen = 120; } else { blockLen = len; } byte[] oText = new byte[blockLen]; Array.Copy(bytes, i * 120, oText, 0, blockLen); string res = Encoding.UTF8.GetString(oText); BigInteger biText = new BigInteger(oText); BigInteger biEnText = biText.modPow(keyNum, nNum); // 补位 byte[] testbyte = null; string resultStr = biEnText.ToHexString(); if (resultStr.Length < 256) { while (resultStr.Length != 256) { resultStr = "0" + resultStr; } } byte[] returnBytes = new byte[128]; for (int j = 0; j < returnBytes.Length; j++) returnBytes[j] = Convert.ToByte(resultStr.Substring(j * 2, 2), 16); tempbytes.AddRange(returnBytes); len -= blockLen; } return tempbytes.ToArray(); } // 注:分块大小最大理论值是128位。但是考虑到实际使用中可能会有位溢出的情况,所以此处使用120 // 将biginteger对象转为byte数组时,原本采用的是BigIneger类提供的GetBytes()方法,但是实际使用中发现,此方法取得的byte数组有一定的几率会出现偏差。所以改成使用ToHexString()方法取得16进制字符串再转成byte数组。 // 为了解密时byte数组块长度固定,补位操作必须执行。 // 解密 /// <summary> /// 解密字符数组 /// < /summary > /// <param name= "dataBytes" >待解密字符数组< /param > /// <param name= "KeyNum" >密钥大素数< /param > /// <param name= "nNum" >大整数N< /param > /// <returns>解密结果< /returns > private string DecryptBytes(byte[] dataBytes, BigInteger KeyNum, BigInteger nNum) { int len = dataBytes.Length; int len1 = 0; int blockLen = 0; if (len % 128 == 0) { len1 = len / 128; } else { len1 = len / 128 + 1; } List<byte> tempbytes = new List<byte>(); for (int i = 0; i < len1; i++) { if (len >= 128) { blockLen = 128; } else { blockLen = len; } byte[] oText = new byte[blockLen]; Array.Copy(dataBytes, i * 128, oText, 0, blockLen); BigInteger biText = new BigInteger(oText); BigInteger biEnText = biText.modPow(KeyNum, nNum); byte[] testbyte = biEnText.getBytes(); string str = Encoding.UTF8.GetString(testbyte); tempbytes.AddRange(testbyte); len -= blockLen; } return System.Text.Encoding.UTF8.GetString(tempbytes.ToArray()); } #endregion } #endregion #region tool /// <summary> /// Class1 的摘要说明 /// < /summary > public class tool { /// <summary> /// 字符串转byte[] /// < /summary > /// <param name= "hexString" >< /param > /// <returns>< /returns > public static byte[] strToToHexByte(string hexString) { byte[] returnBytes; try { hexString = hexString.Replace( " " , "" ); // 去掉所有空格 if ((hexString.Length % 2) != 0) // 两位表示一个byte hexString += " " ; // 如果不是双数实空 returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); } catch { return null; } return returnBytes; } /// <summary> /// 字节数组转16进制字符串 /// < /summary > /// <param name= "bytes" >要转的字节数据< /param > /// <returns>返回转换后的字符串< /returns > public static string byteToHexStr(string strbytes) { byte[] bytes = new byte[strbytes.Length]; for (int i = 0; i < strbytes.Length; i++) { bytes[i] = (byte)strbytes[i]; } string returnStr = "" ; if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString( "X2" ); } } return returnStr; } /// <summary> /// 字节数组转16进制字符串 /// < /summary > /// <param name= "bytes" >要转的字节数据< /param > /// <returns>返回转换后的字符串< /returns > public static string byteToHexStr(byte[] bytes) { string returnStr = "" ; if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString( "X2" ); } } return returnStr; } /// <summary> /// 从汉字转换到16进制字符串 /// < /summary > /// <param name= "s" >要转化的汉字字符串< /param > /// <param name= "charset" >?< /param > /// <param name= "fenge" >?< /param > /// <returns>返回转换后的16进字字符串< /returns > public static string ToHex(string s, string charset, bool fenge) { if ((s.Length % 2) != 0) { s += " " ; // 空格 //throw new ArgumentException( "s is not valid chinese string!" ); } System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset); byte[] bytes = chs.GetBytes(s); string str = "" ; for (int i = 0; i < bytes.Length; i++) { str += string.Format( "{0:X}" , bytes[i]); if (fenge && (i != bytes.Length - 1)) { str += string.Format( "{0}" , "," ); } } return str.ToLower(); } /// <summary> /// 从16进制转换成汉字 /// < /summary > /// <param name= "hex" >< /param > /// <param name= "charset" >< /param > /// <returns>< /returns > public static string UnHex(string hex, string charset) { if (hex == null) throw new ArgumentNullException( "hex" ); hex = hex.Replace( "," , "" ); hex = hex.Replace( "\n" , "" ); hex = hex.Replace( "\\" , "" ); hex = hex.Replace( " " , "" ); if (hex.Length % 2 != 0) { hex += "20" ; // 空格 } // 需要将 hex 转换成 byte 数组。 byte[] bytes = new byte[hex.Length / 2]; for (int i = 0; i < bytes.Length; i++) { try { // 每两个字符是一个 byte。 bytes[i] = byte.Parse(hex.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); } catch { // Rethrow an exception with custom message. throw new ArgumentException( "hex is not a valid hex number!" , "hex" ); } } System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset); return chs.GetString(bytes); } } #endregion |
PHP 的RSA:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | <? header( "content-type:text/html; charset=utf-8" ); // 字符串转16进制 function strToHex($string) { $hex= "" ; for ($i=0;$i<strlen($string);$i++) $hex.=dechex(ord($string[$i])); $hex=strtoupper($hex); return $hex; } //16 进制转字符串 function hexToStr($hex) { $string= "" ; for ($i=0;$i<strlen($hex)-1;$i+=2) $string.=chr(hexdec($hex[$i].$hex[$i+1])); return $string; } // 十进制转字符串 function BIntDecToStr($A) { while ($A>0) { $Result=Chr(bcmod($A, 256)).$Result; $A=bcdiv($A, 256); } return $Result; } // 字符串转十进制 function BIntStrToDec($A) { for ($i=0; $i<StrLen($A); $i++) { $T= "1" ; for ($j=$i+1; $j<StrLen($A); $j++) $T=bcmul($T, "256" ); $Result=bcadd($Result, bcmul(Ord($A[$i]), $T)); } return $Result; } // 十进制转十六进制 function BIntDecToHex($A) { while ($A>0) { $Result=base_convert( bcmod($A, 16), 10, 16 ).$Result; $A=bcdiv($A, 16); } return $Result; } // 十六进制转十进制 function BIntHexToDec($A) { for ($i=0; $i<StrLen($A); $i++) { $T= "1" ; for ($j=$i+1; $j<StrLen($A); $j++) $T=bcmul($T, "16" ); $Result=bcadd($Result, bcmul(base_convert($A[$i], 16, 10), $T)); } return $Result; } // 十进制转三十二进制 function BIntDecToBase32($A) { while ($A>0) { $Result=base_convert( bcmod($A, 32), 10, 32 ).$Result; $A=bcdiv($A, 32); } return $Result; } // 三十二进制转十进制 function BIntBase32ToDec($A) { for ($i=0; $i<StrLen($A); $i++) { $T= "1" ; for ($j=$i+1; $j<StrLen($A); $j++) $T=bcmul($T, "32" ); $Result=bcadd($Result, bcmul(base_convert($A[$i], 32, 10), $T)); } return $Result; } // 十进制转六十四进制 function BIntDecToBase64($A) { return base64_encode( BIntDecToStr($A) ); } // 六十四进制转十进制 function BIntBase64ToDec($A) { return BIntStrToDec( base64_decode($A) ); } // 十进制转二进制 function BIntDecToBin($A) { while ($A>0) { $Result=bcmod($A, 2).$Result; $A=bcdiv($A, 2); } return $Result; } // 十六进制转二进制 function BIntHexToBin($A) { $Result= "" ; $Len=StrLen($A); for ($i=0; $i<$Len; $i++) { $T=base_convert($A[$i], 16, 2); if ($i>0) { $n=StrLen($T); if ($n==1) $T= "000" .$T; elseif ($n==2) $T= "00" .$T; elseif ($n==3) $T= "0" .$T; } $Result=$Result.$T; } return $Result; } function rsa_encrypt($message, $public_key, $modulus, $keylength) { $padded = add_PKCS1_padding($message, true , $keylength / 8); $number = binary_to_number($padded); $encrypted = pow_mod($number, $public_key, $modulus); $result = number_to_binary($encrypted, $keylength / 8); return $result; } function rsa_decrypt($message, $private_key, $modulus, $keylength) { $number = binary_to_number($message); $decrypted = pow_mod($number, $private_key, $modulus); $result = number_to_binary($decrypted, $keylength / 8); return remove_PKCS1_padding($result, $keylength / 8); } function rsa_sign($message, $private_key, $modulus, $keylength) { $padded = add_PKCS1_padding($message, false , $keylength / 8); $number = binary_to_number($padded); $signed = pow_mod($number, $private_key, $modulus); $result = number_to_binary($signed, $keylength / 8); return $result; } function rsa_verify($message, $public_key, $modulus, $keylength) { return rsa_decrypt($message, $public_key, $modulus, $keylength); } /* * Some constants */ define( "BCCOMP_LARGER" , 1); /* * The actual implementation. * Requires BCMath support in PHP (compile with -- enable -bcmath) */ //-- // Calculate (p ^ q) mod r // // We need some trickery to [2]: // (a) Avoid calculating (p ^ q) before (p ^ q) mod r, because for typical RSA // applications, (p ^ q) is going to be _WAY_ too large. // (I mean, __WAY__ too large - won 't fit in your computer' s memory.) // (b) Still be reasonably efficient. // // We assume p, q and r are all positive, and that r is non-zero. // // Note that the more simple algorithm of multiplying $p by itself $q times , and // applying "mod $r" at every step is also valid, but is O($q), whereas this // algorithm is O(log $q). Big difference. // // As far as I can see, the algorithm I use is optimal; there is no redundancy // in the calculation of the partial results. //-- function pow_mod($p, $q, $r) { // Extract powers of 2 from $q $factors = array(); $div = $q; $power_of_two = 0; while (bccomp($div, "0" ) == BCCOMP_LARGER) { $rem = bcmod($div, 2); $div = bcdiv($div, 2); if ($rem) array_push($factors, $power_of_two); $power_of_two++; } // Calculate partial results for each factor, using each partial result as a // starting point for the next. This depends of the factors of two being // generated in increasing order. $partial_results = array(); $part_res = $p; $idx = 0; foreach($factors as $factor) { while ($idx < $factor) { $part_res = bcpow($part_res, "2" ); $part_res = bcmod($part_res, $r); $idx++; } array_push($partial_results, $part_res); } // Calculate final result $result = "1" ; foreach($partial_results as $part_res) { $result = bcmul($result, $part_res); $result = bcmod($result, $r); } return $result; } //-- // Function to add padding to a decrypted string // We need to know if this is a private or a public key operation [4] //-- function add_PKCS1_padding($data, $isPublicKey, $blocksize) { $pad_length = $blocksize - 3 - strlen($data); if ($isPublicKey) { $block_type = "\x02" ; $padding = "" ; for ($i = 0; $i < $pad_length; $i++) { $rnd = mt_rand(1, 255); $padding .= chr($rnd); } } else { $block_type = "\x01" ; $padding = str_repeat( "\xFF" , $pad_length); } return "\x00" . $block_type . $padding . "\x00" . $data; } //-- // Remove padding from a decrypted string // See [4] for more details. //-- function remove_PKCS1_padding($data, $blocksize) { //assert (strlen($data) == $blocksize); $data = substr($data, 1); // We cannot deal with block type 0 if ($data{0} == '\0' ) die( "Block type 0 not implemented." ); // Then the block type must be 1 or 2 //assert (($data{0} == "\x01" ) || ($data{0} == "\x02" )); // Remove the padding $offset = strpos($data, "\0" , 1); return substr($data, $offset + 1); } //-- // Convert binary data to a decimal number //-- function binary_to_number($data) { $base = "256" ; $radix = "1" ; $result = "0" ; for ($i = strlen($data) - 1; $i >= 0; $i--) { $digit = ord($data{$i}); $part_res = bcmul($digit, $radix); $result = bcadd($result, $part_res); $radix = bcmul($radix, $base); } return $result; } //-- // Convert a number back into binary form //-- function number_to_binary($number, $blocksize) { $base = "256" ; $result = "" ; $div = $number; while ($div > 0) { $mod = bcmod($div, $base); $div = bcdiv($div, $base); $result = chr($mod) . $result; } return str_pad($result, $blocksize, "\x00" , STR_PAD_LEFT); } ?> <?php $nn = "60C3262CC16DD0B9E504BF313F48C6C2BB9F9A87527BDD9DBE7D1C4C95FF0E57F046DBC517ED2E4F31A38ED03577D03ABD8E72884E306750354E2F0BAAF2DCE1" ; $ dd = "41A252806EF65384B2CB5ECFD0B5F0FF86778CCC69DDB895935A2A4D54644005CED77C39D0A795B4A6FD660E3D7C46C0C9F5D7197059D90F1677F7F4B92E98E7" ; $ee = "19CD3" ; $str = "aaaa" ; $str1 = BIntDecToBin( BIntStrToDec($str) ); // 字符串转十进制 在转二进制; $temp = rsa_encrypt($str1, $ee, BIntHexToDec($nn), strlen($str)); // 加密 $hex = strToHex($temp); echo "加密后的16进制值 = " .$hex. "<br>" ; $out = rsa_decrypt($str1, $ee, BIntHexToDec($nn), strlen($str1)); // 解密 echo "原字符串 = " .strToHex($out). "<br>" ; ?> |
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
赞赏
雪币:
留言: