常用加密解密——非对称加密

Posted ITBusTech

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用加密解密——非对称加密相关的知识,希望对你有一定的参考价值。

最常用的非对称加密算法应该就是RSA,而且非对称加密算法的实现比较复杂,所以这里只介绍RSA。

密钥长度 密钥默认长度 工作模式 填充方式
512~65536(必须是64的倍数) 密钥默认长度:1024 工作模式:ECB 填充方式:NoPadding,PKCS1Padding等其他

RSA加密有两种方式,一种是私钥加密,公钥解密:

另一种是公钥加密,私钥解密:

 
   
   
 
  1. import javax.crypto.BadPaddingException;

  2. import javax.crypto.Cipher;

  3. import javax.crypto.IllegalBlockSizeException;

  4. import javax.crypto.NoSuchPaddingException;

  5. import java.security.InvalidKeyException;

  6. import java.security.KeyFactory;

  7. import java.security.NoSuchAlgorithmException;

  8. import java.security.PrivateKey;

  9. import java.security.PublicKey;

  10. import java.security.spec.InvalidKeySpecException;

  11. import java.security.spec.PKCS8EncodedKeySpec;

  12. import java.security.spec.X509EncodedKeySpec;


  13. /**

  14. * 密钥长度:512~65536

  15. * 密钥默认长度:1024

  16. * 工作模式:ECB

  17. * 填充方式:NoPadding,PKCS1Padding等其他

  18. */

  19. public class RSA {


  20.    private static final String key_algorithm = "RSA";


  21.    private static final String cipher_algorithm = "RSA/ECB/PKCS1Padding";


  22.    public static byte[] encryptWithPrivateKey(byte[] keyBytes, byte[] dataBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {

  23.        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);

  24.        KeyFactory keyFactory = KeyFactory.getInstance(key_algorithm);

  25.        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);


  26.        Cipher cipher = Cipher.getInstance(cipher_algorithm);

  27.        cipher.init(Cipher.ENCRYPT_MODE, privateKey);

  28.        return cipher.doFinal(dataBytes);

  29.    }


  30.    public static byte[] decryptWithPrivateKey(byte[] keyBytes, byte[] dataBytes) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {

  31.        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);

  32.        KeyFactory keyFactory = KeyFactory.getInstance(key_algorithm);

  33.        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);


  34.        Cipher cipher = Cipher.getInstance(cipher_algorithm);

  35.        cipher.init(Cipher.DECRYPT_MODE, privateKey);

  36.        return cipher.doFinal(dataBytes);

  37.    }


  38.    public static byte[] encryptWithPublicKey(byte[] keyBytes, byte[] dataBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {

  39.        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);

  40.        KeyFactory keyFactory = KeyFactory.getInstance(key_algorithm);

  41.        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);


  42.        Cipher cipher = Cipher.getInstance(cipher_algorithm);

  43.        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

  44.        return cipher.doFinal(dataBytes);

  45.    }


  46.    public static byte[] decryptWithPublicKey(byte[] keyBytes, byte[] dataBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {

  47.        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);

  48.        KeyFactory keyFactory = KeyFactory.getInstance(key_algorithm);

  49.        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);


  50.        Cipher cipher = Cipher.getInstance(cipher_algorithm);

  51.        cipher.init(Cipher.DECRYPT_MODE, publicKey);

  52.        return cipher.doFinal(dataBytes);

  53.    }

  54. }

测试代码:

 
   
   
 
  1. import org.junit.Assert;

  2. import org.junit.Test;


  3. import javax.crypto.BadPaddingException;

  4. import javax.crypto.IllegalBlockSizeException;

  5. import javax.crypto.NoSuchPaddingException;

  6. import java.nio.charset.Charset;

  7. import java.security.InvalidKeyException;

  8. import java.security.KeyPair;

  9. import java.security.KeyPairGenerator;

  10. import java.security.NoSuchAlgorithmException;

  11. import java.security.interfaces.RSAPrivateKey;

  12. import java.security.interfaces.RSAPublicKey;

  13. import java.security.spec.InvalidKeySpecException;

  14. import java.util.Base64;


  15. public class RSATest {


  16.    private static final String key_algorithm = "RSA";


  17.    private static final int key_size = 1024;


  18.    private static final String data = "Hello, Dubby";


  19.    @Test

  20.    public void test() throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidKeySpecException, NoSuchPaddingException {

  21.        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(key_algorithm);

  22.        keyPairGenerator.initialize(key_size);


  23.        KeyPair keyPair = keyPairGenerator.generateKeyPair();

  24.        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

  25.        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();


  26.        //公钥加密,私钥解密

  27.        {

  28.            byte[] encryptBytes = RSA.encryptWithPublicKey(publicKey.getEncoded(), data.getBytes(Charset.forName("UTF-8")));

  29.            System.out.println(Base64.getEncoder().encodeToString(encryptBytes));

  30.            byte[] decryptBytes = RSA.decryptWithPrivateKey(privateKey.getEncoded(), encryptBytes);

  31.            String result = new String(decryptBytes, Charset.forName("UTF-8"));

  32.            System.out.println(result);

  33.            Assert.assertEquals(result, data);

  34.        }


  35.        //私钥加密,公钥解密

  36.        {

  37.            byte[] encryptBytes = RSA.encryptWithPrivateKey(privateKey.getEncoded(), data.getBytes(Charset.forName("UTF-8")));

  38.            System.out.println(Base64.getEncoder().encodeToString(encryptBytes));

  39.            byte[] decryptBytes = RSA.decryptWithPublicKey(publicKey.getEncoded(), encryptBytes);

  40.            String result = new String(decryptBytes, Charset.forName("UTF-8"));

  41.            System.out.println(result);

  42.            Assert.assertEquals(result, data);

  43.        }

  44.    }

  45. }


要注意,RSA对待加密的明文长度限制很大,如key长度是1024,那么最多可加密1024/8 - 11 = 117bytes,如果密钥长度是2048 ,那么2048/8 - 11 = 245bytes。而这很容易超出限制,这在使用时要特别注意。事实上,一般只用非对称加密来传递密钥,之后的传输就直接密钥来做对称加密即可,比如HTTPS。

以上是关于常用加密解密——非对称加密的主要内容,如果未能解决你的问题,请参考以下文章

目前常用的加密方式主要有哪两种

常用的加密算法--非对称加密

常用安全算法之对称加密算法与非对称加密算法

对称加密算法以及使用方法

使用Python处理非对称加密-测试大佬常用的处理方式

golang:常用加密算法学习总结之非对称加密