# 公钥私钥

# 什么是公钥私钥

1)鲍勃有两把钥匙,一把是公钥,另一把是私钥 img 2)鲍勃把公钥送给他的朋友们----帕蒂、道格、苏珊----每人一把。 img 3)苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密,就可以达到保密的效果。 img 4)鲍勃收信后,用私钥解密,就看到了信件内容。这里要强调的是,只要鲍勃的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密。 img 5)鲍勃给苏珊回信,决定采用"数字签名"。他写完后先用Hash函数,生成信件的摘要(digest)。 img

6)然后,鲍勃使用私钥,对这个摘要加密,生成"数字签名"(signature)。 img

7)鲍勃将这个签名,附在信件下面,一起发给苏珊。 img

8)苏珊收信后,取下数字签名,用鲍勃的公钥解密,得到信件的摘要。由此证明,这封信确实是鲍勃发出的。

img

9)苏珊再对信件本身使用Hash函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。 img

10)复杂的情况出现了。道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成"数字签名",写信给苏珊,让苏珊用假的鲍勃公钥进行解密。 img

11)后来,苏珊感觉不对劲,发现自己无法确定公钥是否真的属于鲍勃。她想到了一个办法,要求鲍勃去找"证书中心"(certificate authority,简称CA),为公钥做认证。证书中心用自己的私钥,对鲍勃的公钥和一些相关信息一起加密,生成"数字证书"(Digital Certificate)。 img

12)鲍勃拿到数字证书以后,就可以放心了。以后再给苏珊写信,只要在签名的同时,再附上数字证书就行了。 img

13)苏珊收信后,用CA的公钥解开数字证书,就可以拿到鲍勃真实的公钥了,然后就能证明"数字签名"是否真的是鲍勃签的。 img

# 公私钥特征

  1. 公钥和私钥是成对存在的,它们互相解密
  2. 公钥加密,私钥解密
  3. 私钥数字签名,公钥验证

# RSA算法

RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

package cn.aizichan.utils.digest;  
  
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.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 class RSACoder {  
    //非对称密钥算法    
    public static final String KEY_ALGORITHM="RSA";    
    /**  
     * 密钥长度,DH算法的默认密钥长度是1024  
     * 密钥长度必须是64的倍数,在512到65536位之间  
     * */    
    private static final int KEY_SIZE=512;    
    //公钥    
    private static final String PUBLIC_KEY="xiaoxiaorenzhe";    
        
    //私钥    
    private static final String PRIVATE_KEY="dadapangzi";    
      
    /**  
     * 初始化密钥对  
     * @return Map 甲方密钥的Map  
     * */    
    public static Map<String,Object> initKey() throws Exception{    
        //实例化密钥生成器    
        KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);    
        //初始化密钥生成器    
        keyPairGenerator.initialize(KEY_SIZE);    
        //生成密钥对    
        KeyPair keyPair=keyPairGenerator.generateKeyPair();   
        //甲方公钥    
        RSAPublicKey publicKey=(RSAPublicKey) keyPair.getPublic();    
        System.out.println("系数:"+publicKey.getModulus()+"  加密指数:"+publicKey.getPublicExponent());  
        //甲方私钥    
        RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();   
        System.out.println("系数:"+privateKey.getModulus()+"解密指数:"+privateKey.getPrivateExponent());  
        //将密钥存储在map中    
        Map<String,Object> keyMap=new HashMap<String,Object>();    
        keyMap.put(PUBLIC_KEY, publicKey);    
        keyMap.put(PRIVATE_KEY, privateKey);    
        return keyMap;    
            
    }    
      
    /**  
     * 私钥加密  
     * @param data待加密数据  
     * @param key 密钥  
     * @return byte[] 加密数据  
     * */    
    public static byte[] encryptByPrivateKey(byte[] data,byte[] key) throws Exception{    
            
        //取得私钥    
        PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);    
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);    
        //生成私钥    
        PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);    
        //数据加密    
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());    
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);    
        return cipher.doFinal(data);    
    }    
      
    /**  
     * 公钥加密  
     * @param data待加密数据  
     * @param key 密钥  
     * @return byte[] 加密数据  
     * */    
    public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{    
            
        //实例化密钥工厂    
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);    
        //初始化公钥    
        //密钥材料转换    
        X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);    
        //产生公钥    
        PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);    
            
        //数据加密    
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());    
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);    
        return cipher.doFinal(data);    
    }    
    /**  
     * 私钥解密  
     * @param data 待解密数据  
     * @param key 密钥  
     * @return byte[] 解密数据  
     * */    
    public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{    
        //取得私钥    
        PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);    
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);    
        //生成私钥    
        PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);    
        //数据解密    
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());    
        cipher.init(Cipher.DECRYPT_MODE, privateKey);    
        return cipher.doFinal(data);    
    }    
      
    /**  
     * 公钥解密  
     * @param data 待解密数据  
     * @param key 密钥  
     * @return byte[] 解密数据  
     * */    
    public static byte[] decryptByPublicKey(byte[] data,byte[] key) throws Exception{    
            
        //实例化密钥工厂    
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);    
        //初始化公钥    
        //密钥材料转换    
        X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);    
        //产生公钥    
        PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);    
        //数据解密    
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());    
        cipher.init(Cipher.DECRYPT_MODE, pubKey);    
        return cipher.doFinal(data);    
    }    
      
    /**  
     * 取得私钥  
     * @param keyMap 密钥map  
     * @return byte[] 私钥  
     * */    
    public static byte[] getPrivateKey(Map<String,Object> keyMap){    
        Key key=(Key)keyMap.get(PRIVATE_KEY);    
        return key.getEncoded();    
    }    
    /**  
     * 取得公钥  
     * @param keyMap 密钥map  
     * @return byte[] 公钥  
     * */    
    public static byte[] getPublicKey(Map<String,Object> keyMap) throws Exception{    
        Key key=(Key) keyMap.get(PUBLIC_KEY);   
        return key.getEncoded();    
    }    
    /**  
     * @param args  
     * @throws Exception   
     */    
    public static void main(String[] args) throws Exception {    
        //初始化密钥    
        //生成密钥对    
        Map<String,Object> keyMap=RSACoder.initKey();    
        //公钥    
        byte[] publicKey=RSACoder.getPublicKey(keyMap);  
        //byte[] publicKey = b;  
        //私钥    
        byte[] privateKey=RSACoder.getPrivateKey(keyMap);    
        System.out.println("公钥:"+Base64.encode(publicKey));         
        System.out.println("私钥:"+Base64.encode(privateKey));    
            
        System.out.println("================密钥对构造完毕,甲方将公钥公布给乙方,开始进行加密数据的传输=============");    
        String str="aattaggcctegthththfef/aat.mp4";    
        System.out.println("===========甲方向乙方发送加密数据==============");    
        System.out.println("原文:"+str);    
        //甲方进行数据的加密    
        byte[] code1=RSACoder.encryptByPublicKey(str.getBytes(), publicKey);  
        System.out.println("甲方 使用乙方公钥加密后的数据:"+Base64.encode(code1));    
        System.out.println("===========乙方使用甲方提供的公钥对数据进行解密==============");    
        //乙方进行数据的解密    
        //byte[] decode1=RSACoder.decryptByPublicKey(code1, publicKey);    
        byte[] decode1=RSACoder.decryptByPrivateKey(code1, privateKey);    
        System.out.println("乙方解密后的数据:"+new String(decode1)+"");    
            
        System.out.println("===========反向进行操作,乙方向甲方发送数据==============");    
            
        str="乙方向甲方发送数据RSA算法";    
            
        System.out.println("原文:"+str);    
            
        //乙方使用公钥对数据进行加密    
        byte[] code2=RSACoder.encryptByPublicKey(str.getBytes(), publicKey);    
        System.out.println("===========乙方使用公钥对数据进行加密==============");    
        System.out.println("加密后的数据:"+Base64.encode(code2));    
            
        System.out.println("=============乙方将数据传送给甲方======================");    
        System.out.println("===========甲方使用私钥对数据进行解密==============");    
            
        //甲方使用私钥对数据进行解密    
        byte[] decode2=RSACoder.decryptByPrivateKey(code2, privateKey);    
            
        System.out.println("甲方解密后的数据:"+new String(decode2));   
          
          
    }    
}  
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
上次更新时间: 2024年2月14日星期三上午10点24分