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("私钥: \n" + privateKeyStr); System.out.println("公钥: \n" + 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 + "\n" + "解密后: " + decryptWord); System.out.println("私钥加密--------公钥解密"); String hello = "大家好"; byte[] encryptHello = encryptByKey(hello.getBytes(), privateKey); String decryptHello = decryptByKey(encryptHello, publicKey); System.out.println("加密前: " + decryptHello + "\n" + "解密后: " + 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); } }