Java加密与安全11-非对称加密算法
1. 密钥交换算法
2. 非对称加密算法
3. 概念
非对称加密就是加密和解密使用的不是相同的密钥:
只有同一个公钥 / 私钥对才能正常加密 / 解密
加密:用自己的私钥加密,然后发送给对方
encrypt(privateKeyA, message) -> encrypted
解密:对方用自己的公钥解密
decrypt(publicKeyA,encrypted) -> message
4. 非对称加密典型算法
RSA(Ron Rivest, Adi Shamir, Leonard Adleman)
【经典例子】
RSAKeyPair.java
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAKeyPair {
// 私钥:
PrivateKey sk;
// 公钥:
PublicKey pk;
// 生成公钥/私钥对:
public RSAKeyPair() throws GeneralSecurityException {
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
kpGen.initialize(1024);
KeyPair kp = kpGen.generateKeyPair();
this.sk = kp.getPrivate();
this.pk = kp.getPublic();
}
// 从已保存的字节中(例如:读取文件)恢复公钥/私钥:
public RSAKeyPair(byte[] pk, byte[] sk) throws GeneralSecurityException{
KeyFactory kf = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(pk);
this.pk = kf.generatePublic(pkSpec);
PKCS8EncodedKeySpec skSpec = new PKCS8EncodedKeySpec(sk);
this.sk = kf.generatePrivate(skSpec);
}
// 把私钥导出为字节
public byte[] getPrivateKey(){
return this.sk.getEncoded();
}
// 把公钥导出为字节
public byte[] getPublicKey(){
return this.pk.getEncoded();
}
// 用公钥加密:
public byte[] encrypt(byte[] message) throws GeneralSecurityException{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, this.pk);
return cipher.doFinal(message);
}
// 用私钥解密:
public byte[] decrypt(byte[] input) throws GeneralSecurityException{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, this.sk);
return cipher.doFinal(input);
}
public static void main(String[] args) throws Exception{
// 明文:
byte[] plain = "Hello,使用RSA非对称加密算法对数据进行加密!".getBytes();
// 创建公钥/私钥对:
RSAKeyPair rsa = new RSAKeyPair();
// 加密:
byte[] encrypted = rsa.encrypt(plain);
System.out.println("encrypted: " + Base64.getEncoder().encodeToString(encrypted));
// 解密:
byte[] decrypted = rsa.decrypt(encrypted);
System.out.println("decrypted: " + new String(decrypted, "UTF-8"));
// 保存公钥/私钥:
byte[] pk = rsa.getPublicKey();
byte[] sk = rsa.getPrivateKey();
System.out.println("pk: " + Base64.getEncoder().encodeToString(pk));
System.out.println("sk: " + Base64.getEncoder().encodeToString(sk));
// 重新恢复公钥/私钥:
RSAKeyPair rsa2 = new RSAKeyPair(pk, sk);
// 加密:
byte[] encrypted2 = rsa2.encrypt(plain);
System.out.println("encrypted: " + Base64.getEncoder().encodeToString(encrypted2));
// 解密:
byte[] decrypted2 = rsa2.decrypt(encrypted2);
System.out.println("decrypted: " + new String(decrypted2, "UTF-8"));
}
}
运行RSAKeyPair.java结果:
5. 非对称加密的优点
对称加密需要协商密钥,而非对称加密可以安全地公开各自的公钥
N个人之间通信:
使用非对称加密只需要N个密钥对,每个人只管理自己的密钥对
使用对称加密需要N*(N-1)/2个密钥,每个人需要管理N-1个密钥
6. 非对称加密的缺点
运算速度慢
7. 中间人攻击
8. 总结
非对称加密就是加密和解密使用的不是相同的密钥
只有同一个公钥/ 私钥对才能正常加密 / 解密
只使用非对称加密算法不能防止中间人攻击