1 非对称加密简介

  https://www.cnblogs.com/jthr/p/15137222.html

  公开密钥加密(public-key cryptography),也成为非对称加密,是密码学的一种算法,他需要两个密钥,一个是公开密钥,另一个是私有密钥,一个用作加密的时候,另一个则用作解密。

  • 明文:需要加密的内容,成为明文。
  • 密文:使用密钥把明文加密后的内容。只能用相应的另一个密钥才能解密得到原来的明文。甚至连最初用来加密的密钥也不能用作解密。

 对称加密&&非对称加密

  • 对称加密:加密和解密都是用同一个密钥的算法,称作对称加密。
  • 非对称加密:加密和解密需要不同的密钥。

    因为公钥加密的信息只用私钥才能解的开,所以只要私钥不泄露,通信就是安全的

   

2 RSA工具类

  下面是一个RSA工具类,包含了一下方法

  1)initKey() 用于生成一对密匙对(一个公钥和一个私钥,它们是一一对应的)

  2)sign() 用私钥对数据进行数字签名

  3)verify()用公钥校验数据签名,对应方法sign()

  4)encryptByPublicKey()使用公钥对数据进行加密

  5) decryptByPrivateKey()使用私钥对加密数据解密,对应方法encryptByPublicKey()

package com.example.springboottest.common.util;
 
import javax.crypto.Cipher;
import java.security.*;
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;
 
/**
 * RSA安全编码组件
 *
 * @version 1.0
 * @desc 公钥和私钥存放在properties文件的时候每行的末尾加上“\r\n\” <br/>
 * “\r\n” 起到换行的作用,最后的“\”在properties在里表示连接
 * 
 * @author Neo 
 * @date 2018-4-15 22:23:19
 * @since 1.0
 */
public class RSAUtils extends Base64Utils {
 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(String data, String privateKey) throws Exception {
  return sign(data.getBytes(), privateKey);
 }
 
 /**
  * 用私钥对信息生成数字签名
  *
  * @param data  加密数据
  * @param privateKey 私钥
  * @return
  * @throws Exception
  */
 public static String sign(byte[] data, String privateKey) throws Exception {
  // 解密由base64编码的私钥
  byte[] keyBytes = decryptBASE64(privateKey);
 
  // 构造PKCS8EncodedKeySpec对象
  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
 
  // KEY_ALGORITHM 指定的加密算法
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 
  // 取私钥匙对象
  PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
  // 用私钥对信息生成数字签名
  Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  signature.initSign(priKey);
  signature.update(data);
 
  return encryptBASE64(signature.sign());
 }
 
 /**
  * 校验数字签名
  *
  * @param data  加密数据
  * @param publicKey 公钥
  * @param sign  数字签名
  * @return 校验成功返回true 失败返回false
  * @throws Exception
  */
 public static boolean verify(String data, String publicKey, String sign) throws Exception {
  return verify(data.getBytes(), publicKey, sign);
 }
 
 /**
  * 校验数字签名
  *
  * @param data  加密数据
  * @param publicKey 公钥
  * @param sign  数字签名
  * @return 校验成功返回true 失败返回false
  * @throws Exception
  */
 public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
 
  // 解密由base64编码的公钥
  byte[] keyBytes = decryptBASE64(publicKey);
 
  // 构造X509EncodedKeySpec对象
  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
 
  // KEY_ALGORITHM 指定的加密算法
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 
  // 取公钥匙对象
  PublicKey pubKey = keyFactory.generatePublic(keySpec);
 
  Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  signature.initVerify(pubKey);
  signature.update(data);
 
  // 验证签名是否正常
  return signature.verify(decryptBASE64(sign));
 }
 
 /**
  * 解密<br>
  * 用私钥解密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static String decryptByPrivateKey(String data, String key) throws Exception {
  return new String(decryptByPrivateKey(Base64Utils.decryptBASE64(data), key));
 }
 
 /**
  * 解密<br>
  * 用私钥解密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
  // 对密钥解密
  byte[] keyBytes = decryptBASE64(key);
 
  // 取得私钥
  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
  // 对数据解密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.DECRYPT_MODE, privateKey);
 
  return cipher.doFinal(data);
 }
 
 /**
  * 解密<br>
  * 用公钥解密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static String decryptByPublicKey(String data, String key) throws Exception {
  return new String(decryptByPublicKey(Base64Utils.decryptBASE64(data), key));
 }
 
 /**
  * 解密<br>
  * 用公钥解密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {
  // 对密钥解密
  byte[] keyBytes = decryptBASE64(key);
 
  // 取得公钥
  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key publicKey = keyFactory.generatePublic(x509KeySpec);
 
  // 对数据解密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.DECRYPT_MODE, publicKey);
  return cipher.doFinal(data);
 }
 
 /**
  * 加密<br>
  * 用公钥加密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static String encryptByPublicKey(String data, String key) throws Exception {
  return Base64Utils.encryptBASE64(encryptByPublicKey(data.getBytes(), key));
 }
 
 /**
  * 加密<br>
  * 用公钥加密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception {
  // 对公钥解密
  byte[] keyBytes = decryptBASE64(key);
 
  // 取得公钥
  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key publicKey = keyFactory.generatePublic(x509KeySpec);
 
  // 对数据加密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  return cipher.doFinal(data);
 }
 
 /**
  * 加密<br>
  * 用私钥加密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static String encryptByPrivateKey(String data, String key) throws Exception {
  return Base64Utils.encryptBASE64(encryptByPrivateKey(data.getBytes(), key));
 }
 
 /**
  * 加密<br>
  * 用私钥加密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
 public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {
  // 对密钥解密
  byte[] keyBytes = decryptBASE64(key);
 
  // 取得私钥
  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
  // 对数据加密
  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 keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  keyPairGen.initialize(1024);
 
  KeyPair keyPair = keyPairGen.generateKeyPair();
 
  // 公钥
  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 
  // 私钥
  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 
  Map<String, Object> keyMap = new HashMap<String, Object>(2);
  keyMap.put(PUBLIC_KEY, publicKey);
  keyMap.put(PRIVATE_KEY, privateKey);
  return keyMap;
 }
}

 

3 Base64Utils

package com.example.springboottest.common.util;
 
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.security.MessageDigest;
 
/**
 * BASE64的加解密
 * @author Neo
 * @date 2018-4-15 22:21:51
 *
 */
@SuppressWarnings("restriction")
public class Base64Utils { 
 public static final String KEY_SHA = "SHA"; 
 public static final String KEY_MD5 = "MD5"; 
 
 /** 
  * 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(); 
 
 } 
} 

 

4 测试

public static void main(String[] args) {
        try {
            //创建密匙对
            Map<String, Object> map = RSAUtils.initKey();
            String publicKey = RSAUtils.getPublicKey(map);
            String privateKey = RSAUtils.getPrivateKey(map);
            System.out.println("公钥:" + publicKey);
            System.out.println("私钥:" + privateKey);


            String data = "Java是世界上最好的编程语言";

            //加密
            String encryptData = RSAUtils.encryptByPublicKey(data, publicKey);
            System.out.println("加密后:" + encryptData);

            //解密
            String decryptData = RSAUtils.decryptByPrivateKey(encryptData, privateKey);
            System.out.println("解密后:" + decryptData);

            //加签和验签的操作是为了防止传输的数据被篡改  
            // 私钥加签  
            String sign = sign(data, privateKey);

            //公钥验签,true  
            boolean verify = verify(data, publicKey, sign);
            System.out.println("没有被篡改验签:" + verify);
            
            //对数据进行篡改后,验签失败false  
            boolean verify2 = verify((data + "a"), publicKey, sign);
            System.out.println("被篡改验签:" +verify2);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

执行结果

公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjdUX0gzZ9KBx60shWov8KL5ep2feQnNbjZmVP
uCReneNlmUIF2LcljWq+WJ/6IVlqWlPxpu14SUPlVVJ4hqLpodBRc26kSfk2nRK81mA0T7Js/EcW
pJ0uX9uf27f4qn60ihB0GplSjUHGCAmV24SKkuis4KesvPdz3xj9Hx6YEQIDAQAB

私钥:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAON1RfSDNn0oHHrSyFai/wovl6nZ
95Cc1uNmZU+4JF6d42WZQgXYtyWNar5Yn/ohWWpaU/Gm7XhJQ+VVUniGoumh0FFzbqRJ+TadErzW
YDRPsmz8RxaknS5f25/bt/iqfrSKEHQamVKNQcYICZXbhIqS6Kzgp6y893PfGP0fHpgRAgMBAAEC
gYBXn9L+OhogpvYpvs/cyFgV9XWowkZj2HfUDJtU1ax1Ir/6YMsVc4JCnjMT9xJSCszmcrvJ6TOs
VhUo4PCva7aQLnngOfb0wemAj2DW3mw67EQmJEfmOrZc+zgrYlk5z2QQUmpZineM2WXL/ER2hgFQ
ST2H2ihRHldff50+OWjsAQJBAPj1QedWzBZDYeQm/L0LcqhnntfcB3PqNzqk/S/Pm4T6V2TxzMv+
ezF3H88aA2Y6EkmXbz+6SPRQjXQZo869WdECQQDp5FTf8pVhxdjZuBsUtNFN6LLH2fQPXQ3IG6rj
wGlO3lZd4sIRYTQME3BuFY7X+SfcpABBZfrXE3A1ROjghqpBAkEA0CIKtONFwB8ZSeqmRU26z7vB
emmC+Y+IGMkyurPwKt44DjZwpuLcD2CuATCYQvCttUSbR0XwFAD8IWIGJqL64QJAJWXkCFbyecq3
zMA6XEo5OVre00PPWXGIlZmO7pHChODaMHLkkwDW4KNvE7sQtwnYzNfQTqSuwhsSkwHstpHxwQJB
AKEafzIQ8o13+FWNG9rBdQjUv4J3TB/lkfo2OCyUdI5HIJPekSfoj43Q/BMMAXXFXs/GMfL59ji1
pvZ4wEnCbMs=

加密后:r4THPubDkZRUQn4j3Lo/5LXaNtM4Y1cFQMBSFxTSt5n5f0HN/xnWYmDShpJd2ycxas/p/RJvYXOL
OclFfJWEgetga4DHUFsqYLSPyXCYvWiIu/ydKsMCD/eLYAIUOQdQT904DGRIeHL0oiBuI/EX5R/W
kow7T9uBc+pghIU28Hw=

解密后:Java是世界上最好的编程语言
没有被篡改验签:true
被篡改验签:false