首页
社区
课程
招聘
[求助]C# java 的RSA交互
发表于: 2010-2-11 06:40 12074

[求助]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代码:
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直播授课

收藏
免费
支持
分享
最新回复 (3)
雪    币: 84
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
.Net似乎也分有符号与无符号的byte
如果你的java代码是没有问题的,那马C#应该也是没有问题的
2010-2-21 16:02
0
雪    币: 79
活跃值: (35)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
3
这个一直以来都是头疼的问题,关键点在于它们表示密钥的方式不一样。

如果要通用,就让P Q E等参数吧,直接点,只要是RSA,必然可行
2010-3-19 09:52
0
雪    币: 1731
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
也许可以从 C# 先著手,编译后再用 Reflector 反编译成 J#,再丢给 javac 看看这样解决会不会快些?
2010-3-31 12:22
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册