JAVA 非對稱加密算法RSA

非對稱加密算法 RSA過程 : 以甲乙雙方爲例
  1、初始化密鑰 構建密鑰對,生成公鑰、私鑰保存到keymap中
    KeyPairGenerator ---> KeyPair --> RSAPublicKey、RSAPrivateKey
  2、甲方使用私鑰加密, 加密後在用私鑰對加密數據進行數據簽名,然後發送給乙方
    RSACoder.encryptByPrivateKey(data, privateKey);
    RSACoder.sign(encodedData, privateKey);
  3、乙方則通過公鑰驗證簽名的加密數據,如果驗證正確則在通過公鑰對加密數據進行解密
    RSACoder.verify(encodedData, publicKey, sign);
    RSACoder.decryptByPublicKey(encodedData, publicKey);
   4、乙方在通過公鑰加密發送給甲方
    RSACoder.encryptByPublicKey(decodedData, publicKey);
  5、甲方通過私鑰解密該數據
    RSACoder.decryptPrivateKey(encodedData, privateKey);
流程圖如下:

java代碼實現如下:

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
package com.bank.utils;
 
import java.security.MessageDigest;
 
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
 
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
public abstract class Coder {
    public static final String KEY_SHA = "SHA";
    public static final String KEY_MD5 = "MD5";
     
    /**
     * MAC算法可選以下多種算法
     
     * <pre>
     * HmacMD5 
     * HmacSHA1 
     * HmacSHA256 
     * HmacSHA384 
     * HmacSHA512
     * </pre>
     */ 
    public static final String KEY_MAC = "HmacMD5";
     
    /**
     * BASE64解密
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64( String key ) throws Exception{
        return (new BASE64Decoder()).decodeBuffer(key);
    }
     
    /**
     * BASE64加密
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64( byte[] key) throws Exception{
        return (new BASE64Encoder()).encodeBuffer(key);
    }
     
    /**
     * MD5 加密
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptMD5( byte[] data) throws Exception {
        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data);
         
        return md5.digest();
    }
     
    /**
     * SHA 加密
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptSHA( byte[] data) throws Exception {
        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
        sha.update(data);
         
        return sha.digest();
    }
     
    /**
     * 初始化HMAC密鑰
     
     * @return
     * @throws Exception
     */ 
    public static String initMacKey() throws Exception{
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
         
        SecretKey secretKey = keyGenerator.generateKey();
        return encryptBASE64(secretKey.getEncoded());
    }
     
    /**
     * HMAC  加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptHMAC( byte[] data, String key) throws Exception{
        SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        return mac.doFinal(data);
    }
}

  

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
package com.bank.utils;
 
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
 
import javax.crypto.Cipher;
 
 
public abstract class RSACoder extends Coder{
    public static final String KEY_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
     
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivatekey";
     
    /**
     * 用私鑰對信息生成數字簽名
     * @param data 加密數據
     * @param privateKey 私鑰
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        //解密由base64編碼的私鑰
        byte[] keyBytes = decryptBASE64(privateKey);
         
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
         
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
         
        //取私鑰對象
        PrivateKey pKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
         
        //用私鑰生成數字簽名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(pKey);
        signature.update(data);
         
        return encryptBASE64(signature.sign());
    }
     
    /**
     * 校驗數字簽名
     * @param data 加密數據
     * @param publicKey 公鑰
     * @param sign 數字簽名
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data, String publicKey, String sign) throws Exception{
         
        //解密有base64編碼的公鑰
        byte[] keyBytes = decryptBASE64(publicKey);
         
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
         
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
         
        //取公鑰對象
        PublicKey pKey = keyFactory.generatePublic(keySpec);
         
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(pKey);
        signature.update(data);
        //驗證簽名是否正常
        return signature.verify(decryptBASE64(sign));
    }
     
    /**
     * 解密
     *  用私鑰解密
     * @param data 加密數據
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptPrivateKey(byte[] data, String key) throws Exception{
        byte[] keyBytes = decryptBASE64(key);
         
        //取得私鑰
        PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key pKey = factory.generatePrivate(encodedKeySpec);
         
        //對數據解密
        Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, pKey);
         
        return cipher.doFinal(data);
    }
     
    /**
     * 用公鑰解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey( byte[] data, String key) throws Exception{
         
        //解密
        byte[] keyBytes = decryptBASE64(key);
         
        //取得公鑰
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key pKey = keyFactory.generatePublic(keySpec);
         
        //對數據解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, pKey);
         
        return cipher.doFinal(data);
    }
     
    /**
     * 用公鑰加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey( byte[] data, String key) throws Exception{
         
        byte[] keyBytes = decryptBASE64(key);
         
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key pKey = keyFactory.generatePublic(keySpec);
         
         
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, pKey);
         
        return cipher.doFinal(data);
    }
     
    /**
     * 用私鑰加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception{
         
        byte[] keyBytes = decryptBASE64(key);
         
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(keySpec);
         
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
         
        return cipher.doFinal(data);
    }
     
    /**
     * 取得私鑰
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey( Map<String, Object> keyMap) throws Exception{
 
        Key key = (Key) keyMap.get(PRIVATE_KEY);
         
        return encryptBASE64(key.getEncoded());
    }
     
    /**
     * 取得公鑰
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey( Map<String, Object> keyMap) throws Exception{
 
        Key key = (Key) keyMap.get(PUBLIC_KEY);
         
        return encryptBASE64(key.getEncoded());
    }
    /**
     * 初始化密鑰
     * @return
     * @throws Exception
     */
    public static Map<String, Object> initKey() throws Exception{
         
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGenerator.initialize(1024);
         
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //公鑰
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
         
        //私鑰
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
         
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PRIVATE_KEY, privateKey);
        keyMap.put(PUBLIC_KEY, publicKey);
        return keyMap;
    }
}

  

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
package com.bank.test;
 
import java.util.Map;
 
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
 
import com.bank.utils.RSACoder;
 
public class RSACoderTest {
    private String publicKey;
    private String privateKey;
    /*
     * 非對稱加密算法   RSA過程 : 以甲乙雙方爲例
     *      1、初始化密鑰 構建密鑰對,生成公鑰、私鑰保存到keymap中
     *              KeyPairGenerator --->    KeyPair     -->      RSAPublicKey、RSAPrivateKey
     *      2、甲方使用私鑰加密, 加密後在用私鑰對加密數據進行數據簽名,然後發送給乙方
     *              RSACoder.encryptByPrivateKey(data, privateKey);
     *              RSACoder.sign(encodedData, privateKey);
     *      3、乙方則通過公鑰驗證簽名的加密數據,如果驗證正確則在通過公鑰對加密數據進行解密
     *              RSACoder.verify(encodedData, publicKey, sign);
     *              RSACoder.decryptByPublicKey(encodedData, publicKey);               
     *
     *      4、乙方在通過公鑰加密發送給甲方
     *              RSACoder.encryptByPublicKey(decodedData, publicKey);
     *      5、甲方通過私鑰解密該數據      
     *              RSACoder.decryptPrivateKey(encodedData, privateKey);               
     */
    @Before
    public void setUp() throws Exception {
         
        Map<String , Object> keyMap = RSACoder.initKey();
         
        publicKey = RSACoder.getPublicKey(keyMap);
        privateKey = RSACoder.getPrivateKey(keyMap);
         
        System.out.println("公鑰:\n" + publicKey);
        System.out.println("私鑰:\n" + privateKey);
    }
    @Test
    public void test() throws Exception{
        String inputStr = "abc";
        byte[] data = inputStr.getBytes();//每次的得到的字節數組是不一樣的。
        //第二步 私鑰加密
        byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
        //私鑰進行數據簽名
        String sign = RSACoder.sign(encodedData, privateKey);
         
        //第三步 公鑰驗證數字簽名
        boolean flag = RSACoder.verify(encodedData, publicKey, sign);
        System.out.println("flag:" + flag);
        //用公鑰對數據解密
        byte[] decodedData = RSACoder.decryptByPublicKey(encodedData, publicKey);
         
        System.out.println("data:" + data + "加密數據:" + encodedData + "    解密數據:" + decodedData);
        System.out.println("加密前數據-:" new String(data) + "     解密後數據: " new String(decodedData));
         
        //第四步使用公鑰加密數據
        encodedData = RSACoder.encryptByPublicKey(decodedData, publicKey);
         
        //第五步 使用私鑰解密數據
        decodedData = RSACoder.decryptPrivateKey(encodedData, privateKey);
         
         
        System.out.println("data:" + data + "加密數據:" + encodedData + "    解密數據:" + decodedData);
        System.out.println("加密前數據:" + inputStr + "     解密後數據: " new String(decodedData));
    }
     
     
    @Test
    public void test1() throws Exception{
        System.out.println("私鑰加密-----公鑰解密");
        String inputStr = "abc";
        byte[] data = inputStr.getBytes();
        System.out.println("data:" + data);
         
        byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
        byte[] decodedData = RSACoder.decryptByPublicKey(encodedData, publicKey);
     
        String outputStr = new String( decodedData );
         
        System.out.println("加密前:" + inputStr +"\n 解密後:" + outputStr);
         
        Assert.assertEquals(inputStr, outputStr);
         
         
        System.out.println("私鑰簽名---公鑰驗證簽名");
        //產生簽名
        String sign = RSACoder.sign(encodedData, privateKey);
        System.out.println("簽名:\r" + sign);
         
        //驗證簽名
        boolean flag = RSACoder.verify(encodedData, publicKey, sign);
         
        System.out.println("狀態:\r" + flag);
         
        Assert.assertTrue(flag);
    }
}

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章