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
1-------RSAUtils.java---------------- package my.tools.security;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.FileOutputStream;
6import java.io.ObjectInputStream;
7import java.io.ObjectOutputStream;
8import java.math.BigInteger;
9import java.security.KeyPair;
10import java.security.KeyFactory;
11import java.security.KeyPairGenerator;
12import java.security.Provider;
13import java.security.PublicKey;
14import java.security.PrivateKey;
15import java.security.SecureRandom;
16import java.security.NoSuchAlgorithmException;
17import java.security.InvalidParameterException;
18import java.security.interfaces.RSAPublicKey;
19import java.security.interfaces.RSAPrivateKey;
20import java.security.spec.RSAPublicKeySpec;
21import java.security.spec.RSAPrivateKeySpec;
22import java.security.spec.InvalidKeySpecException;
23
24import javax.crypto.Cipher;
25
26import org.apache.commons.io.IOUtils;
27import org.apache.commons.io.FileUtils;
28import org.apache.commons.codec.DecoderException;
29import org.apache.commons.codec.binary.Hex;
30import org.bouncycastle.jce.provider.BouncyCastleProvider;
31import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34import org.apache.commons.lang.StringUtils;
35import org.apache.commons.lang.time.DateFormatUtils;
36
37/**
38 * RSA算法加密/解密工具类。
39 *
40 * @author fuchun
41 * @version 1.0.0, 2010-05-05
42 */
43public abstract class RSAUtils {
44
45    private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);
46
47    /** 算法名称 */
48    private static final String ALGORITHOM = "RSA";
49    /**保存生成的密钥对的文件名称。 */
50    private static final String RSA_PAIR_FILENAME = "/__RSA_PAIR.txt";
51    /** 密钥大小 */
52    private static final int KEY_SIZE = 1024;
53    /** 默认的安全服务提供者 */
54    private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider();
55
56    private static KeyPairGenerator keyPairGen = null;
57    private static KeyFactory keyFactory = null;
58    /** 缓存的密钥对。 */
59    private static KeyPair oneKeyPair = null;
60
61    private static File rsaPairFile = null;
62
63    static {
64        try {
65            keyPairGen = KeyPairGenerator.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
66            keyFactory = KeyFactory.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
67        } catch (NoSuchAlgorithmException ex) {
68            LOGGER.error(ex.getMessage());
69        }
70        rsaPairFile = new File(getRSAPairFilePath());
71    }
72
73    private RSAUtils() {
74    }
75
76    /**
77     * 生成并返回RSA密钥对。
78     */
79    private static synchronized KeyPair generateKeyPair() {
80        try {
81            keyPairGen.initialize(KEY_SIZE, new SecureRandom(DateFormatUtils.format("yyyyMMdd").getBytes()));
82            oneKeyPair = keyPairGen.generateKeyPair();
83            saveKeyPair(oneKeyPair);
84            return oneKeyPair;
85        } catch (InvalidParameterException ex) {
86            LOGGER.error("KeyPairGenerator does not support a key length of " + KEY_SIZE + ".", ex);
87        } catch (NullPointerException ex) {
88            LOGGER.error("RSAUtils#KEY_PAIR_GEN is null, can not generate KeyPairGenerator instance.",
89                    ex);
90        }
91        return null;
92    }
93
94    /**
95     * 返回生成/读取的密钥对文件的路径。
96     */
97    private static String getRSAPairFilePath() {
98        String urlPath = RSAUtils.class.getResource("/").getPath();
99        return (new File(urlPath).getParent() + RSA_PAIR_FILENAME);
100    }
101
102    /**
103     * 若需要创建新的密钥对文件,则返回 {@code true},否则 {@code false}。
104     */
105    private static boolean isCreateKeyPairFile() {
106        // 是否创建新的密钥对文件
107        boolean createNewKeyPair = false;
108        if (!rsaPairFile.exists() || rsaPairFile.isDirectory()) {
109            createNewKeyPair = true;
110        }
111        return createNewKeyPair;
112    }
113
114    /**
115     * 将指定的RSA密钥对以文件形式保存。
116     *
117     * @param keyPair 要保存的密钥对。
118     */
119    private static void saveKeyPair(KeyPair keyPair) {
120        FileOutputStream fos = null;
121        ObjectOutputStream oos = null;
122        try {
123            fos = FileUtils.openOutputStream(rsaPairFile);
124            oos = new ObjectOutputStream(fos);
125            oos.writeObject(keyPair);
126        } catch (Exception ex) {
127            ex.printStackTrace();
128        } finally {
129         IOUtils.closeQuietly(oos);
130            IOUtils.closeQuietly(fos);
131        }
132    }
133
134    /**
135     * 返回RSA密钥对。
136     */
137    public static KeyPair getKeyPair() {
138        // 首先判断是否需要重新生成新的密钥对文件
139        if (isCreateKeyPairFile()) {
140            // 直接强制生成密钥对文件,并存入缓存。
141            return generateKeyPair();
142        }
143        if (oneKeyPair != null) {
144            return oneKeyPair;
145        }
146        return readKeyPair();
147    }
148    
149    // 同步读出保存的密钥对
150    private static KeyPair readKeyPair() {
151        FileInputStream fis = null;
152        ObjectInputStream ois = null;
153        try {
154            fis = FileUtils.openInputStream(rsaPairFile);
155            ois = new ObjectInputStream(fis);
156            oneKeyPair = (KeyPair) ois.readObject();
157            return oneKeyPair;
158        } catch (Exception ex) {
159            ex.printStackTrace();
160        } finally {
161            IOUtils.closeQuietly(ois);
162            IOUtils.closeQuietly(fis);
163        }
164        return null;
165    }
166
167    /**
168     * 根据给定的系数和专用指数构造一个RSA专用的公钥对象。
169     *
170     * @param modulus 系数。
171     * @param publicExponent 专用指数。
172     * @return RSA专用公钥对象。
173     */
174    public static RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) {
175        RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(modulus),
176                new BigInteger(publicExponent));
177        try {
178            return (RSAPublicKey) keyFactory.generatePublic(publicKeySpec);
179        } catch (InvalidKeySpecException ex) {
180            LOGGER.error("RSAPublicKeySpec is unavailable.", ex);
181        } catch (NullPointerException ex) {
182            LOGGER.error("RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance.", ex);
183        }
184        return null;
185    }
186
187    /**
188     * 根据给定的系数和专用指数构造一个RSA专用的私钥对象。
189     *
190     * @param modulus 系数。
191     * @param privateExponent 专用指数。
192     * @return RSA专用私钥对象。
193     */
194    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) {
195        RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus),
196                new BigInteger(privateExponent));
197        try {
198            return (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);
199        } catch (InvalidKeySpecException ex) {
200            LOGGER.error("RSAPrivateKeySpec is unavailable.", ex);
201        } catch (NullPointerException ex) {
202            LOGGER.error("RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance.", ex);
203        }
204        return null;
205    }
206    
207    /**
208     * 根据给定的16进制系数和专用指数字符串构造一个RSA专用的私钥对象。
209     *
210     * @param modulus 系数。
211     * @param privateExponent 专用指数。
212     * @return RSA专用私钥对象。
213     */
214    public static RSAPrivateKey getRSAPrivateKey(String hexModulus, String hexPrivateExponent) {
215        if(StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPrivateExponent)) {
216            if(LOGGER.isDebugEnabled()) {
217                LOGGER.debug("hexModulus and hexPrivateExponent cannot be empty. RSAPrivateKey value is null to return.");
218            }
219            return null;
220        }
221        byte[] modulus = null;
222        byte[] privateExponent = null;
223        try {
224            modulus = Hex.decodeHex(hexModulus.toCharArray());
225            privateExponent = Hex.decodeHex(hexPrivateExponent.toCharArray());
226        } catch(DecoderException ex) {
227            LOGGER.error("hexModulus or hexPrivateExponent value is invalid. return null(RSAPrivateKey).");
228        }
229        if(modulus != null && privateExponent != null) {
230            return generateRSAPrivateKey(modulus, privateExponent);
231        }
232        return null;
233    }
234    
235    /**
236     * 根据给定的16进制系数和专用指数字符串构造一个RSA专用的公钥对象。
237     *
238     * @param modulus 系数。
239     * @param publicExponent 专用指数。
240     * @return RSA专用公钥对象。
241     */
242    public static RSAPublicKey getRSAPublidKey(String hexModulus, String hexPublicExponent) {
243        if(StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPublicExponent)) {
244            if(LOGGER.isDebugEnabled()) {
245                LOGGER.debug("hexModulus and hexPublicExponent cannot be empty. return null(RSAPublicKey).");
246            }
247            return null;
248        }
249        byte[] modulus = null;
250        byte[] publicExponent = null;
251        try {
252            modulus = Hex.decodeHex(hexModulus.toCharArray());
253            publicExponent = Hex.decodeHex(hexPublicExponent.toCharArray());
254        } catch(DecoderException ex) {
255            LOGGER.error("hexModulus or hexPublicExponent value is invalid. return null(RSAPublicKey).");
256        }
257        if(modulus != null && publicExponent != null) {
258            return generateRSAPublicKey(modulus, publicExponent);
259        }
260        return null;
261    }
262
263    /**
264     * 使用指定的公钥加密数据。
265     *
266     * @param publicKey 给定的公钥。
267     * @param data 要加密的数据。
268     * @return 加密后的数据。
269     */
270    public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {
271        Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
272        ci.init(Cipher.ENCRYPT_MODE, publicKey);
273        return ci.doFinal(data);
274    }
275
276    /**
277     * 使用指定的私钥解密数据。
278     *
279     * @param privateKey 给定的私钥。
280     * @param data 要解密的数据。
281     * @return 原数据。
282     */
283    public static byte[] decrypt(PrivateKey privateKey, byte[] data) throws Exception {
284        Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);
285        ci.init(Cipher.DECRYPT_MODE, privateKey);
286        return ci.doFinal(data);
287    }
288
289    /**
290     * 使用给定的公钥加密给定的字符串。
291     * <p />
292     * 若 {@code publicKey} 为 {@code null},或者 {@code plaintext} 为 {@code null} 则返回 {@code
293     * null}。
294     *
295     * @param publicKey 给定的公钥。
296     * @param plaintext 字符串。
297     * @return 给定字符串的密文。
298     */
299    public static String encryptString(PublicKey publicKey, String plaintext) {
300        if (publicKey == null || plaintext == null) {
301            return null;
302        }
303        byte[] data = plaintext.getBytes();
304        try {
305            byte[] en_data = encrypt(publicKey, data);
306            return new String(Hex.encodeHex(en_data));
307        } catch (Exception ex) {
308            LOGGER.error(ex.getCause().getMessage());
309        }
310        return null;
311    }
312    
313    /**
314     * 使用默认的公钥加密给定的字符串。
315     * <p />
316     * 若{@code plaintext} 为 {@code null} 则返回 {@code null}。
317     *
318     * @param plaintext 字符串。
319     * @return 给定字符串的密文。
320     */
321    public static String encryptString(String plaintext) {
322        if(plaintext == null) {
323            return null;
324        }
325        byte[] data = plaintext.getBytes();
326        KeyPair keyPair = getKeyPair();
327        try {
328            byte[] en_data = encrypt((RSAPublicKey)keyPair.getPublic(), data);
329            return new String(Hex.encodeHex(en_data));
330        } catch(NullPointerException ex) {
331            LOGGER.error("keyPair cannot be null.");
332        } catch(Exception ex) {
333            LOGGER.error(ex.getCause().getMessage());
334        }
335        return null;
336

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
1}
2
3    /**
4     * 使用给定的私钥解密给定的字符串。
5     * <p />
6     * 若私钥为 {@code null},或者 {@code encrypttext} 为 {@code null}或空字符串则返回 {@code null}。
7     * 私钥不匹配时,返回 {@code null}。
8     *
9     * @param privateKey 给定的私钥。
10     * @param encrypttext 密文。
11     * @return 原文字符串。
12     */
13    public static String decryptString(PrivateKey privateKey, String encrypttext) {
14        if (privateKey == null || StringUtils.isBlank(encrypttext)) {
15            return null;
16        }
17        try {
18            byte[] en_data = Hex.decodeHex(encrypttext.toCharArray());
19            byte[] data = decrypt(privateKey, en_data);
20            return new String(data);
21        } catch (Exception ex) {
22            LOGGER.error(String.format("\"%s\" Decryption failed. Cause: %s", encrypttext, ex.getCause().getMessage()));
23        }
24        return null;
25    }
26    
27    /**
28     * 使用默认的私钥解密给定的字符串。
29     * <p />
30     * 若{@code encrypttext} 为 {@code null}或空字符串则返回 {@code null}。
31     * 私钥不匹配时,返回 {@code null}。
32     *
33     * @param encrypttext 密文。
34     * @return 原文字符串。
35     */
36    public static String decryptString(String encrypttext) {
37        if(StringUtils.isBlank(encrypttext)) {
38            return null;
39        }
40        KeyPair keyPair = getKeyPair();
41        try {
42            byte[] en_data = Hex.decodeHex(encrypttext.toCharArray());
43            byte[] data = decrypt((RSAPrivateKey)keyPair.getPrivate(), en_data);
44            return new String(data);
45        } catch(NullPointerException ex) {
46            LOGGER.error("keyPair cannot be null.");
47        } catch (Exception ex) {
48            LOGGER.error(String.format("\"%s\" Decryption failed. Cause: %s", encrypttext, ex.getMessage()));
49        }
50        return null;
51    }
52    
53    /**
54     * 使用默认的私钥解密由JS加密(使用此类提供的公钥加密)的字符串。
55     *
56     * @param encrypttext 密文。
57     * @return {@code encrypttext} 的原文字符串。
58     */
59    public static String decryptStringByJs(String encrypttext) {
60        String text = decryptString(encrypttext);
61        if(text == null) {
62            return null;
63        }
64        return StringUtils.reverse(text);
65    }
66    
67    /** 返回已初始化的默认的公钥。*/
68    public static RSAPublicKey getDefaultPublicKey() {
69        KeyPair keyPair = getKeyPair();
70        if(keyPair != null) {
71            return (RSAPublicKey)keyPair.getPublic();
72        }
73        return null;
74    }
75    
76    /** 返回已初始化的默认的私钥。*/
77    public static RSAPrivateKey getDefaultPrivateKey() {
78        KeyPair keyPair = getKeyPair();
79        if(keyPair != null) {
80            return (RSAPrivateKey)keyPair.getPrivate();
81        }
82        return null;
83    }
84} 文档:
85

// Struts2 Action方法中:

// 将公钥的 modulus 和 exponent 传给页面。

// Hex -> apache commons-codec

RSAPublicKey publicKey = RSAUtils.getDefaultPublicKey();

ActionContext.getContext().put("modulus", new String(Hex.encodeHex(publicKey.getModulus().toByteArray())));

ActionContext.getContext().put("exponent", new String(Hex.encodeHex(publicKey.getPublicExponent().toByteArray())));

 

// 页面里,Javascript对明文进行加密:

var modulus = $('#hid_modulus').val(), exponent = $('#hid_exponent').val();

var key = RSAUtils.getKeyPair(exponent, '', modulus);

pwd1 = RSAUtils.encryptedString(key, pwd1);

pwd2 = RSAUtils.encryptedString(key, pwd2);

13

14 // 服务器端,使用RSAUtils工具类对密文进行解密

15 RSAUtils.decryptStringByJs(password1);


1
2
1所需的jar包 及 js文件 :
2

1
2
1                      ![](http://img.5iqiqu.com/images2/b4/b42abb5654e836d77425785cfc25ce6d.jpg)  
2

 

 

————-security.js——————-

/*
* RSA, a suite of routines for performing RSA public-key computations in JavaScript.
* Copyright 1998-2005 David Shapiro.
* Dave Shapiro
* dave@ohdave.com
* changed by Fuchun, 2010-05-06
* fcrpg2005@gmail.com
*/

(function($w) {

if(typeof $w.RSAUtils === 'undefined')
var RSAUtils = $w.RSAUtils = {};

var biRadixBase = 2;
var biRadixBits = 16;
var bitsPerDigit = biRadixBits;
var biRadix = 1 << 16; // = 2^16 = 65536
var biHalfRadix = biRadix >>> 1;
var biRadixSquared = biRadix * biRadix;
var maxDigitVal = biRadix – 1;
var maxInteger = 9999999999999998;

//maxDigits:
//Change this to accommodate your largest number size. Use setMaxDigits()
//to change it!
//
//In general, if you're working with numbers of size N bits, you'll need 2*N
//bits of storage. Each digit holds 16 bits. So, a 1024-bit key will need
//
//1024 * 2 / 16 = 128 digits of storage.
//
var maxDigits;
var ZERO_ARRAY;
var bigZero, bigOne;

var BigInt = $w.BigInt = function(flag) {
if (typeof flag == "boolean" && flag == true) {
this.digits = null;
} else {
this.digits = ZERO_ARRAY.slice(0);
}
this.isNeg = false;
};

RSAUtils.setMaxDigits = function(value) {
maxDigits = value;
ZERO_ARRAY = new Array(maxDigits);
for (var iza = 0; iza < ZERO_ARRAY.length; iza++) ZERO_ARRAY[iza] = 0;
bigZero = new BigInt();
bigOne = new BigInt();
bigOne.digits[0] = 1;
};
RSAUtils.setMaxDigits(20);

//The maximum number of digits in base 10 you can convert to an
//integer without JavaScript throwing up on you.
var dpl10 = 15;

RSAUtils.biFromNumber = function(i) {
var result = new BigInt();
result.isNeg = i < 0;
i = Math.abs(i);
var j = 0;
while (i > 0) {
result.digits[j++] = i & maxDigitVal;
i = Math.floor(i / biRadix);
}
return result;
};

//lr10 = 10 ^ dpl10
var lr10 = RSAUtils.biFromNumber(1000000000000000);

RSAUtils.biFromDecimal = function(s) {
var isNeg = s.charAt(0) == '-';
var i = isNeg ? 1 : 0;
var result;
// Skip leading zeros.
while (i < s.length && s.charAt(i) == '0') ++i;
if (i == s.length) {
result = new BigInt();
}
else {
var digitCount = s.length – i;
var fgl = digitCount % dpl10;
if (fgl == 0) fgl = dpl10;
result = RSAUtils.biFromNumber(Number(s.substr(i, fgl)));
i += fgl;
while (i < s.length) {
result = RSAUtils.biAdd(RSAUtils.biMultiply(result, lr10),
RSAUtils.biFromNumber(Number(s.substr(i, dpl10))));
i += dpl10;
}
result.isNeg = isNeg;
}
return result;
};

RSAUtils.biCopy = function(bi) {
var result = new BigInt(true);
result.digits = bi.digits.slice(0);
result.isNeg = bi.isNeg;
return result;
};

RSAUtils.reverseStr = function(s) {
var result = "";
for (var i = s.length – 1; i > -1; –i) {
result += s.charAt(i);
}
return result;
};

var hexatrigesimalToChar = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z'
];

RSAUtils.biToString = function(x, radix) { // 2 <= radix <= 36
var b = new BigInt();
b.digits[0] = radix;
var qr = RSAUtils.biDivideModulo(x, b);
var result = hexatrigesimalToChar[qr[1].digits[0]];
while (RSAUtils.biCompare(qr[0], bigZero) == 1) {
qr = RSAUtils.biDivideModulo(qr[0], b);
digit = qr[1].digits[0];
result += hexatrigesimalToChar[qr[1].digits[0]];
}
return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result);
};

RSAUtils.biToDecimal = function(x) {
var b = new BigInt();
b.digits[0] = 10;
var qr = RSAUtils.biDivideModulo(x, b);
var result = String(qr[1].digits[0]);
while (RSAUtils.biCompare(qr[0], bigZero) == 1) {
qr = RSAUtils.biDivideModulo(qr[0], b);
result += String(qr[1].digits[0]);
}
return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result);
};

var hexToChar = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'];

RSAUtils.digitToHex = function(n) {
var mask = 0xf;
var result = "";
for (i = 0; i < 4; ++i) {
result += hexToChar[n & mask];
n >>>= 4;
}
return RSAUtils.reverseStr(result);
};

RSAUtils.biToHex = function(x) {
var result = "";
var n = RSAUtils.biHighIndex(x);
for (var i = RSAUtils.biHighIndex(x); i > -1; –i) {
result += RSAUtils.digitToHex(x.digits[i]);
}
return result;
};

RSAUtils.charToHex = function(c) {
var ZERO = 48;
var NINE = ZERO + 9;
var littleA = 97;
var littleZ = littleA + 25;
var bigA = 65;
var bigZ = 65 + 25;
var result;

if (c >= ZERO && c <= NINE) {
result = c – ZERO;
} else if (c >= bigA && c <= bigZ) {
result = 10 + c – bigA;
} else if (c >= littleA && c <= littleZ) {
result = 10 + c – littleA;
} else {
result = 0;
}
return result;
};

RSAUtils.hexToDigit = function(s) {
var result = 0;
var sl = Math.min(s.length, 4);
for (var i = 0; i < sl; ++i) {
result <<= 4;
result |= RSAUtils.charToHex(s.charCodeAt(i));
}
return result;
};

RSAUtils.biFromHex = function(s) {
var result = new BigInt();
var sl = s.length;
for (var i = sl, j = 0; i > 0; i -= 4, ++j) {
result.digits[j] = RSAUtils.hexToDigit(s.substr(Math.max(i – 4, 0), Math.min(i, 4)));
}
return result;
};

RSAUtils.biFromString = function(s, radix) {
var isNeg = s.charAt(0) == '-';
var istop = isNeg ? 1 : 0;
var result = new BigInt();
var place = new BigInt();
place.digits[0] = 1; // radix^0
for (var i = s.length – 1; i >= istop; i–) {
var c = s.charCodeAt(i);
var digit = RSAUtils.charToHex(c);
var biDigit = RSAUtils.biMultiplyDigit(place, digit);
result = RSAUtils.biAdd(result, biDigit);
place = RSAUtils.biMultiplyDigit(place, radix);
}
result.isNeg = isNeg;
return result;
};

RSAUtils.biDump = function(b) {
return (b.isNeg ? "-" : "") + b.digits.join(" ");
};

RSAUtils.biAdd = function(x, y) {
var result;

if (x.isNeg != y.isNeg) {
y.isNeg = !y.isNeg;
result = RSAUtils.biSubtract(x, y);
y.isNeg = !y.isNeg;
}
else {
result = new BigInt();
var c = 0;
var n;
for (var i = 0; i < x.digits.length; ++i) {
n = x.digits[i] + y.digits[i] + c;
result.digits[i] = n % biRadix;
c = Number(n >= biRadix);
}
result.isNeg = x.isNeg;
}
return result;
};

RSAUtils.biSubtract = function(x, y) {
var result;
if (x.isNeg != y.isNeg) {
y.isNeg = !y.isNeg;
result = RSAUtils.biAdd(x, y);
y.isNeg = !y.isNeg;
} else {
result = new BigInt();
var n, c;
c = 0;
for (var i = 0; i < x.digits.length; ++i) {
n = x.digits[i] – y.digits[i] + c;
result.digits[i] = n % biRadix;
// Stupid non-conforming modulus operation.
if (result.digits[i] < 0) result.digits[i] += biRadix;
c = 0 – Number(n < 0);
}
// Fix up the negative sign, if any.
if (c == -1) {
c = 0;
for (var i = 0; i < x.digits.length; ++i) {
n = 0 – result.digits[i] + c;
result.digits[i] = n % biRadix;
// Stupid non-conforming modulus operation.
if (result.digits[i] < 0) result.digits[i] += biRadix;
c = 0 – Number(n < 0);
}
// Result is opposite sign of arguments.
result.isNeg = !x.isNeg;
} else {
// Result is same sign.
result.isNeg = x.isNeg;
}
}
return result;
};

RSAUtils.biHighIndex = function(x) {
var result = x.digits.length – 1;
while (result > 0 && x.digits[result] == 0) –result;
return result;
};

RSAUtils.biNumBits = function(x) {
var n = RSAUtils.biHighIndex(x);
var d = x.digits[n];
var m = (n + 1) * bitsPerDigit;
var result;
for (result = m; result > m – bitsPerDigit; –result) {
if ((d & 0x8000) != 0) break;
d <<= 1;
}
return result;
};

RSAUtils.biMultiply = function(x, y) {
var result = new BigInt();
var c;
var n = RSAUtils.biHighIndex(x);
var t = RSAUtils.biHighIndex(y);
var u, uv, k;

for (var i = 0; i <= t; ++i) {
c = 0;
k = i;
for (j = 0; j <= n; ++j, ++k) {
uv = result.digits[k] + x.digits[j] * y.digits[i] + c;
result.digits[k] = uv & maxDigitVal;
c = uv >>> biRadixBits;
//c = Math.floor(uv / biRadix);
}
result.digits[i + n + 1] = c;
}
// Someone give me a logical xor, please.
result.isNeg = x.isNeg != y.isNeg;
return result;
};

RSAUtils.biMultiplyDigit = function(x, y) {
var n, c, uv;

result = new BigInt();
n = RSAUtils.biHighIndex(x);
c = 0;
for (var j = 0; j <= n; ++j) {
uv = result.digits[j] + x.digits[j] * y + c;
result.digits[j] = uv & maxDigitVal;
c = uv >>> biRadixBits;
//c = Math.floor(uv / biRadix);
}
result.digits[1 + n] = c;
return result;
};

RSAUtils.arrayCopy = function(src, srcStart, dest, destStart, n) {
var m = Math.min(srcStart + n, src.length);
for (var i = srcStart, j = destStart; i < m; ++i, ++j) {
dest[j] = src[i];
}
};

var highBitMasks = [0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800,
0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF];

RSAUtils.biShiftLeft = function(x, n) {
var digitCount = Math.floor(n / bitsPerDigit);
var result = new BigInt();
RSAUtils.arrayCopy(x.digits, 0, result.digits, digitCount,
result.digits.length – digitCount);
var bits = n % bitsPerDigit;
var rightBits = bitsPerDigit – bits;
for (var i = result.digits.length – 1, i1 = i – 1; i > 0; –i, –i1) {
result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) |
((result.digits[i1] & highBitMasks[bits]) >>>
(rightBits));
}
result.digits[0] = ((result.digits[i] << bits) & maxDigitVal);
result.isNeg = x.isNeg;
return result;
};

var lowBitMasks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF];

RSAUtils.biShiftRight = function(x, n) {
var digitCount = Math.floor(n / bitsPerDigit);
var result = new BigInt();
RSAUtils.arrayCopy(x.digits, digitCount, result.digits, 0,
x.digits.length – digitCount);
var bits = n % bitsPerDigit;
var leftBits = bitsPerDigit – bits;
for (var i = 0, i1 = i + 1; i < result.digits.length – 1; ++i, ++i1) {
result.digits[i] = (result.digits[i] >>> bits) |
((result.digits[i1] & lowBitMasks[bits]) << leftBits);
}
result.digits[result.digits.length – 1] >>>= bits;
result.isNeg = x.isNeg;
return result;
};

RSAUtils.biMultiplyByRadixPower = function(x, n) {
var result = new BigInt();
RSAUtils.arrayCopy(x.digits, 0, result.digits, n, result.digits.length – n);
return result;
};

RSAUtils.biDivideByRadixPower = function(x, n) {
var result = new BigInt();
RSAUtils.arrayCopy(x.digits, n, result.digits, 0, result.digits.length – n);
return result;
};

RSAUtils.biModuloByRadixPower = function(x, n) {
var result = new BigInt();
RSAUtils.arrayCopy(x.digits, 0, result.digits, 0, n);
return result;
};

RSAUtils.biCompare = function(x, y) {
if (x.isNeg != y.isNeg) {
return 1 – 2 * Number(x.isNeg);
}
for (var i = x.digits.length – 1; i >= 0; –i) {
if (x.digits[i] != y.digits[i]) {
if (x.isNeg) {
return 1 – 2 * Number(x.digits[i] > y.digits[i]);
} else {
return 1 – 2 * Number(x.digits[i] < y.digits[i]);
}
}
}
return 0;
};

RSAUtils.biDivideModulo = function(x, y) {
var nb = RSAUtils.biNumBits(x);
var tb = RSAUtils.biNumBits(y);
var origYIsNeg = y.isNeg;
var q, r;
if (nb < tb) {
// |x| < |y|
if (x.isNeg) {
q = RSAUtils.biCopy(bigOne);
q.isNeg = !y.isNeg;
x.isNeg = false;
y.isNeg = false;
r = biSubtract(y, x);
// Restore signs, 'cause they're references.
x.isNeg = true;
y.isNeg = origYIsNeg;
} else {
q = new BigInt();
r = RSAUtils.biCopy(x);
}
return [q, r];
}

q = new BigInt();
r = x;

// Normalize Y.
var t = Math.ceil(tb / bitsPerDigit) – 1;
var lambda = 0;
while (y.digits[t] < biHalfRadix) {
y = RSAUtils.biShiftLeft(y, 1);
++lambda;
++tb;
t = Math.ceil(tb / bitsPerDigit) – 1;
}
// Shift r over to keep the quotient constant. We'll shift the
// remainder back at the end.
r = RSAUtils.biShiftLeft(r, lambda);
nb += lambda; // Update the bit count for x.
var n = Math.ceil(nb / bitsPerDigit) – 1;

var b = RSAUtils.biMultiplyByRadixPower(y, n – t);
while (RSAUtils.biCompare(r, b) != -1) {
++q.digits[n – t];
r = RSAUtils.biSubtract(r, b);
}
for (var i = n; i > t; –i) {
var ri = (i >= r.digits.length) ? 0 : r.digits[i];
var ri1 = (i – 1 >= r.digits.length) ? 0 : r.digits[i – 1];
var ri2 = (i – 2 >= r.digits.length) ? 0 : r.digits[i – 2];
var yt = (t >= y.digits.length) ? 0 : y.digits[t];
var yt1 = (t – 1 >= y.digits.length) ? 0 : y.digits[t – 1];
if (ri == yt) {
q.digits[i – t – 1] = maxDigitVal;
} else {
q.digits[i – t – 1] = Math.floor((ri * biRadix + ri1) / yt);
}

var c1 = q.digits[i – t – 1] * ((yt * biRadix) + yt1);
var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2);
while (c1 > c2) {
–q.digits[i – t – 1];
c1 = q.digits[i – t – 1] * ((yt * biRadix) | yt1);
c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2);
}

b = RSAUtils.biMultiplyByRadixPower(y, i – t – 1);
r = RSAUtils.biSubtract(r, RSAUtils.biMultiplyDigit(b, q.digits[i – t – 1]));
if (r.isNeg) {
r = RSAUtils.biAdd(r, b);
–q.digits[i – t – 1];
}
}
r = RSAUtils.biShiftRight(r, lambda);
// Fiddle with the signs and stuff to make sure that 0 <= r < y.
q.isNeg = x.isNeg != origYIsNeg;
if (x.isNeg) {
if (origYIsNeg) {
q = RSAUtils.biAdd(q, bigOne);
} else {
q = RSAUtils.biSubtract(q, bigOne);
}
y = RSAUtils.biShiftRight(y, lambda);
r = RSAUtils.biSubtract(y, r);
}
// Check for the unbelievably stupid degenerate case of r == -0.
if (r.digits[0] == 0 && RSAUtils.biHighIndex(r) == 0) r.isNeg = false;

return [q, r];
};

RSAUtils.biDivide = function(x, y) {
return RSAUtils.biDivideModulo(x, y)[0];
};

RSAUtils.biModulo = function(x, y) {
return RSAUtils.biDivideModulo(x, y)[1];
};

RSAUtils.biMultiplyMod = function(x, y, m) {
return RSAUtils.biModulo(RSAUtils.biMultiply(x, y), m);
};

RSAUtils.biPow = function(x, y) {
var result = bigOne;
var a = x;
while (true) {
if ((y & 1) != 0) result = RSAUtils.biMultiply(result, a);
y >>= 1;
if (y == 0) break;
a = RSAUtils.biMultiply(a, a);
}
return result;
};

RSAUtils.biPowMod = function(x, y, m) {
var result = bigOne;
var a = x;
var k = y;
while (true) {
if ((k.digits[0] & 1) != 0) result = RSAUtils.biMultiplyMod(result, a, m);
k = RSAUtils.biShiftRight(k, 1);
if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0) break;
a = RSAUtils.biMultiplyMod(a, a, m);
}
return result;
};

$w.BarrettMu = function(m) {
this.modulus = RSAUtils.biCopy(m);
this.k = RSAUtils.biHighIndex(this.modulus) + 1;
var b2k = new BigInt();
b2k.digits[2 * this.k] = 1; // b2k = b^(2k)
this.mu = RSAUtils.biDivide(b2k, this.modulus);
this.bkplus1 = new BigInt();
this.bkplus1.digits[this.k + 1] = 1; // bkplus1 = b^(k+1)
this.modulo = BarrettMu_modulo;
this.multiplyMod = BarrettMu_multiplyMod;
this.powMod = BarrettMu_powMod;
};

function BarrettMu_modulo(x) {
var $dmath = RSAUtils;
var q1 = $dmath.biDivideByRadixPower(x, this.k – 1);
var q2 = $dmath.biMultiply(q1, this.mu);
var q3 = $dmath.biDivideByRadixPower(q2, this.k + 1);
var r1 = $dmath.biModuloByRadixPower(x, this.k + 1);
var r2term = $dmath.biMultiply(q3, this.modulus);
var r2 = $dmath.biModuloByRadixPower(r2term, this.k + 1);
var r = $dmath.biSubtract(r1, r2);
if (r.isNeg) {
r = $dmath.biAdd(r, this.bkplus1);
}
var rgtem = $dmath.biCompare(r, this.modulus) >= 0;
while (rgtem) {
r = $dmath.biSubtract(r, this.modulus);
rgtem = $dmath.biCompare(r, this.modulus) >= 0;
}
return r;
}

function BarrettMu_multiplyMod(x, y) {
/*
x = this.modulo(x);
y = this.modulo(y);
*/
var xy = RSAUtils.biMultiply(x, y);
return this.modulo(xy);
}

function BarrettMu_powMod(x, y) {
var result = new BigInt();
result.digits[0] = 1;
var a = x;
var k = y;
while (true) {
if ((k.digits[0] & 1) != 0) result = this.multiplyMod(result, a);
k = RSAUtils.biShiftRight(k, 1);
if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0) break;
a = this.multiplyMod(a, a);
}
return result;
}

var RSAKeyPair = function(encryptionExponent, decryptionExponent, modulus) {
var $dmath = RSAUtils;
this.e = $dmath.biFromHex(encryptionExponent);
this.d = $dmath.biFromHex(decryptionExponent);
this.m = $dmath.biFromHex(modulus);
// We can do two bytes per digit, so
// chunkSize = 2 * (number of digits in modulus – 1).
// Since biHighIndex returns the high index, not the number of digits, 1 has
// already been subtracted.
this.chunkSize = 2 * $dmath.biHighIndex(this.m);
this.radix = 16;
this.barrett = new $w.BarrettMu(this.m);
};

RSAUtils.getKeyPair = function(encryptionExponent, decryptionExponent, modulus) {
return new RSAKeyPair(encryptionExponent, decryptionExponent, modulus);
};

if(typeof $w.twoDigit === 'undefined') {
$w.twoDigit = function(n) {
return (n < 10 ? "0" : "") + String(n);
};
}

// Altered by Rob Saunders (rob@robsaunders.net). New routine pads the
// string after it has been converted to an array. This fixes an
// incompatibility with Flash MX's ActionScript.
RSAUtils.encryptedString = function(key, s) {
var a = [];
var sl = s.length;
var i = 0;
while (i < sl) {
a[i] = s.charCodeAt(i);
i++;
}

while (a.length % key.chunkSize != 0) {
a[i++] = 0;
}

var al = a.length;
var result = "";
var j, k, block;
for (i = 0; i < al; i += key.chunkSize) {
block = new BigInt();
j = 0;
for (k = i; k < i + key.chunkSize; ++j) {
block.digits[j] = a[k++];
block.digits[j] += a[k++] << 8;
}
var crypt = key.barrett.powMod(block, key.e);
var text = key.radix == 16 ? RSAUtils.biToHex(crypt) : RSAUtils.biToString(crypt, key.radix);
result += text + " ";
}
return result.substring(0, result.length – 1); // Remove last space.
};

RSAUtils.decryptedString = function(key, s) {
var blocks = s.split(" ");
var result = "";
var i, j, block;
for (i = 0; i < blocks.length; ++i) {
var bi;
if (key.radix == 16) {
bi = RSAUtils.biFromHex(blocks[i]);
}
else {
bi = RSAUtils.biFromString(blocks[i], key.radix);
}
block = key.barrett.powMod(bi, key.d);
for (j = 0; j <= RSAUtils.biHighIndex(block); ++j) {
result += String.fromCharCode(block.digits[j] & 255,
block.digits[j] >> 8);
}
}
// Remove trailing null, if any.
if (result.charCodeAt(result.length – 1) == 0) {
result = result.substring(0, result.length – 1);
}
return result;
};

RSAUtils.setMaxDigits(130);

})(window);

给TA打赏
共{{data.count}}人
人已打赏
安全技术安全运维

Windows服务器如何发现被黑

2018-5-20 12:24:31

安全技术

详解Node.js API系列 Crypto加密模块(2) Hmac

2021-12-21 16:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索