vlambda博客
学习文章列表

Java加密与安全11-非对称加密算法

1.  密钥交换算法



2.  非对称加密算法

Java加密与安全11-非对称加密算法


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结果:

Java加密与安全11-非对称加密算法


5.  非对称加密的优点

  • 对称加密需要协商密钥,而非对称加密可以安全地公开各自的公钥

  • N个人之间通信:

    • 使用非对称加密只需要N个密钥对,每个人只管理自己的密钥对

    • 使用对称加密需要N*(N-1)/2个密钥,每个人需要管理N-1个密钥


6.  非对称加密的缺点

  • 运算速度慢


7.  中间人攻击


8.  总结

  • 非对称加密就是加密和解密使用的不是相同的密钥

  • 只有同一个公钥/ 私钥对才能正常加密 / 解密

  • 只使用非对称加密算法不能防止中间人攻击