zoukankan      html  css  js  c++  java
  • 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);
        }
    }

  • 相关阅读:
    .net测试篇之Moq行为配置
    .net测试篇之Moq框架简单使用
    .net测试篇之测试神器Autofixture在几个复杂场景下的使用示例以及与Moq结合
    .net测试篇之测试神器Autofixture Generator使用与自定义builder
    .net测试篇之测试神器Autofixture基本配置一
    .net测试篇之单元测试/集成测试神器Autofixture
    .netcore持续集成测试篇之web项目验收测试
    .netcore持续集成测试篇之 .net core 2.1项目集成测试
    .netcore持续集成测试篇之MVC层单元测试
    .netcore持续集成测试篇之测试方法改造
  • 原文地址:https://www.cnblogs.com/BINGJJFLY/p/7470577.html
Copyright © 2011-2022 走看看