RSA 请求数据加解密及安全校验

对称加密算法在加密和解密时使用的是同一个秘钥,加解密双方必须使用同一个密钥才能进行正常的沟通。
而非对称加密则不然,非对称加密算法需要两个密钥来进行加密和解密,分别是公钥和私钥。
 
需要注意的一点,这个公钥和私钥必须是一对的,如果用公钥对数据进行加密,那么只有使用对应的私钥才能解密,反之亦然。由于加密和解密使用的是两个不同的密钥,因此,这种算法叫做非对称加密算法。
 

甲乙之间使用非对称加密的方式传输数据。

乙方生成一对密钥(公钥和私钥)并将公钥向其它方公开;
得到该公钥的甲方使用该密钥对机密信息进行加密后再发送给乙方;
乙方再用自己保存的另一把专用密钥(私钥)对加密后的信息进行解密;
乙方只能用其专用密钥(私钥)解密由对应的公钥加密后的信息;
在传输过程中,即使攻击者截获了传输的密文,并得到了乙的公钥,也无法破解密文,因为只有乙的私钥才能解密密文。

适用于请求信息中包含隐私信息如用户银行卡账号,手机号等

package com.wjz.security;

import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class RSADemo {
    
    private static final Logger logger = LoggerFactory.getLogger(RSADemo.class);
    /** 
     * 定义加密方式 
     */  
    private final static String KEY_RSA = "RSA";  
    /** 
     * 定义签名算法 
     */  
    private final static String KEY_RSA_SIGNATURE = "MD5withRSA";  
    /** 
     * 定义公钥算法 
     */  
    private final static String KEY_RSA_PUBLICKEY = "RSAPublicKey";  
    /** 
     * 定义私钥算法 
     */  
    private final static String KEY_RSA_PRIVATEKEY = "RSAPrivateKey";
    
    public static Map<String, Object> init() {
        Map<String, Object> map = null;
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_RSA);
            keyPairGenerator.initialize(1024);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            map = new HashMap<>();
            map.put(KEY_RSA_PRIVATEKEY, privateKey);
            map.put(KEY_RSA_PUBLICKEY, publicKey);
        } catch (Exception e) {
            logger.error("初始化私、公钥时出现异常");
        }
        return map;
    }

    public KeyFactory createKeyFactory() throws NoSuchAlgorithmException {
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA);
        return keyFactory;
    }
    
    /**
     * 创建签名对象
     * @return
     * @throws NoSuchAlgorithmException
     */
    public Signature createSignature() throws NoSuchAlgorithmException {
        Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
        return signature;
    }
    
    /**
     * 组建公钥对象
     * @param publicKeyStr
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException 
     * @throws InvalidKeySpecException 
     */
    public PublicKey buildPublicKey(String publicKeyStr) {
        PublicKey publicKey = null;
        try {
            byte[] publicKeyBytes = BASE64decode(publicKeyStr);
            // 创建编码说明对象
            EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);
            publicKey = createKeyFactory().generatePublic(encodedKeySpec);
        } catch (Exception e) {
            logger.error("创建公钥失败");
        }
        return publicKey;
    }
    
    /**
     * 组建私钥对象
     * @param privateKeyStr
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public PrivateKey buildPrivateKey(String privateKeyStr) {
        PrivateKey privateKey = null;
        try {
            byte[] privateKeyBytes = BASE64decode(privateKeyStr);
            EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            privateKey = createKeyFactory().generatePrivate(encodedKeySpec);
        } catch (Exception e) {
            logger.error("创建私钥失败");
        }
        return privateKey;
    }
    
    /**
     * RSA使用私钥对象加密数据生成数字签名
     * @param encryptData 要加密的数据
     * @param privateKey
     */
    public String sign(byte[] encryptData, PrivateKey privateKey) {
        String signData = null;
        try {
            Signature signature = createSignature();
            signature.initSign(privateKey);
            signature.update(encryptData);
            signData = BASE64ecode(signature.sign());
        } catch (Exception e) {
            logger.error("使用私钥对象加密数据生成数字签名时出现异常");
        }
        return signData; 
    }
    
    /**
     * RSA使用公钥对象对返回数据和数字签名进行校验
     * @param retunData 返回的数据
     * @param publicKey
     * @param signData 数字签名
     * @return
     */
    public boolean verify(byte[] retunData, PublicKey publicKey, String signData) {
        boolean flag = false;
        try {
            Signature signature = createSignature();
            signature.initVerify(publicKey);
            signature.update(retunData);
            // 返回数据和数字签名进行校验
            flag = signature.verify(BASE64decode(signData));
        } catch (Exception e) {
            logger.error("使用公钥对象对返回数据和数字签名进行校验时出现问题");
        }
        return flag;
    }
    
    /**
     * 根据私、公钥加密数据
     * @param data 待加密数据
     * @param privateKey
     * @return
     */
    public byte[] encryptByKey(byte[] data, Key key) {
        byte[] result = null;
        try {
            KeyFactory keyFactory = createKeyFactory();
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, key);
            result = cipher.doFinal(data);
        } catch (Exception e) {
            logger.error("根据私、公钥加密数据时出现异常");
        }
        return result;
    }
    
    /**
     * 根据私、公钥解密数据
     * @param data 加密数据
     * @param key
     * @return
     * @throws NoSuchAlgorithmException 
     * @throws NoSuchPaddingException 
     */
    public String decryptByKey(byte[] data, Key key) {
        String result = null;
        try {
            KeyFactory keyFactory = createKeyFactory();
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, key);
            result = new String(cipher.doFinal(data));
        } catch (Exception e) {
            logger.error("根据私、公钥解密数据时出现异常", e);
        }
        return result;
    }
    
    /**
     * 获得私钥串
     * @param map
     * @return
     */
    public String getPrivateKeyStr(Map<String, Object> map) {
        Key privateKey = (Key) map.get(KEY_RSA_PRIVATEKEY);
        return BASE64ecode(privateKey.getEncoded());
    }
    
    /**
     * 获得公钥串
     * @param map
     * @return
     */
    public String getPublicKeyStr(Map<String, Object> map) {
        Key publicKey = (Key) map.get(KEY_RSA_PUBLICKEY);
        return BASE64ecode(publicKey.getEncoded());
    }
    
    /**
     * base64加密
     * @param sign
     * @return
     */
    private String BASE64ecode(byte[] sign) {
        return new BASE64Encoder().encode(sign);
    }

    /**
     * base64解码
     * @param publicKeyStr
     * @return
     * @throws IOException
     */
    private byte[] BASE64decode(String data) throws IOException {
        return new BASE64Decoder().decodeBuffer(data);
    }

    @Test
    public void test() {
        Map<String, Object> map = init();
        String privateKeyStr = getPrivateKeyStr(map);
        String publicKeyStr = getPublicKeyStr(map);
        PrivateKey privateKey = buildPrivateKey(privateKeyStr);
        PublicKey publicKey = buildPublicKey(publicKeyStr);
        System.out.println("私钥: 
" + privateKeyStr);
        System.out.println("公钥: 
" + publicKeyStr);  
        
        System.out.println("公钥加密--------私钥解密");  
        String word = "127.0.0.1:8888/rsa/person/list";         
        byte[] encryptWord = encryptByKey(word.getBytes(), publicKey);
        String decryptWord = decryptByKey(encryptWord, privateKey);
        System.out.println("加密前: " + word + "
" + "解密后: " + decryptWord);
        
        System.out.println("私钥加密--------公钥解密");
        String hello = "大家好";         
        byte[] encryptHello = encryptByKey(hello.getBytes(), privateKey);
        String decryptHello = decryptByKey(encryptHello, publicKey);
        System.out.println("加密前: " + decryptHello + "
" + "解密后: " + decryptHello);
        
        String sign = sign("127.0.0.1:8888/rsa/person/list".getBytes(), privateKey);
        System.out.println("签名:" + sign);
        
        boolean flag = verify("127.0.0.1:8888/rsa/person/list".getBytes(), publicKey, sign);
        System.out.println("状态:" + flag);
    }
}

原文地址:https://www.cnblogs.com/BINGJJFLY/p/7470577.html