加密算法---RSA 非对称加密原理及使用

一 非对称加密原理介绍

非对称加密算法中,有两个密钥:公钥和私钥。它们是一对,如果用公钥进行加密,只有用对应的私钥才能解密;如果用私钥进行加密,只有用对应的公钥才能解密。
    非对称加密算法实现机密信息的交换过程为:甲方生成一对密钥并将其中一个作为公钥向其他方公开;得到该公钥的乙方使用该密钥对机密信息进行加密后发送给甲方;甲方再用自己的另一个专用密钥对加密后的信息进行解密。
    最有名的非对称加密算法当属 RSA 了,本文将对 RSA 算法的加/解密过程进行详细剖析。
    非对称加密拥有两把密钥。
    
RSA —— 经典的非对称加密算法

二 加密解密测试

2.1 加密解密工具类

import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
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.Base64;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class EncryptUtils {

    /**
     * sha 加密
     *
     * @param str
     * @return
     */
    public static String sha(String str) {
        String sha256Str = "";

        try {
            MessageDigest sha256Deget = MessageDigest.getInstance("SHA-256");
            byte[] sha256Encode = sha256Deget.digest(str.getBytes());
            sha256Str = ByteToHexStr(sha256Encode);
        } catch (Exception e) {
            log.info("FRLOG:SHA256加密异常::", e.getMessage());
        }

        return sha256Str;
    }

    /**
     * byte数组转16进制字符串
     *
     * @param bytes
     * @return
     */
    private static String ByteToHexStr(byte[] bytes) {
        String hexStr = "";

        for (int i = 0; i < bytes.length; i++) {
            int temp = bytes[i] & 0xff;
            String tempHex = Integer.toHexString(temp);
            if (tempHex.length() < 2) {
                hexStr += "0" + tempHex;
            } else {
                hexStr += tempHex;
            }
        }

        return hexStr;
    }
/**--------------------------对称加密aes----------------------------------*/
    /**
     * aes 加密
     *
     * @param str
     * @param privateKey
     * @return
     */
    public static String aesEncrypt(String str, String privateKey) {
        try {
            // 生成密钥对象
            SecretKey secKey = generateAesKey(privateKey.getBytes());

            // 获取 AES 密码器
            Cipher cipher = Cipher.getInstance("AES");
            // 初始化密码器(加密模型)
            cipher.init(Cipher.ENCRYPT_MODE, secKey);

            // 加密数据, 返回密文
            byte[] cipherBytes = cipher.doFinal(str.getBytes());
//            return new BASE64Encoder().encodeBuffer(cipherBytes);
            return Base64.getEncoder().encodeToString(cipherBytes);
        } catch (Throwable e) {
            log.info("aes 加密异常", e.getMessage());
        }

        return null;
    }


    /**
     * aes 解密
     *
     * @param str
     * @param privateKey
     * @return
     */
    public static String aesDecrypt(String str, String privateKey) {
        try {
            // 生成密钥对象
            SecretKey secKey = generateAesKey(privateKey.getBytes());

            // 获取 AES 密码器
            Cipher cipher = Cipher.getInstance("AES");
            // 初始化密码器(加密模型)
            cipher.init(Cipher.DECRYPT_MODE, secKey);
            byte[] decode = Base64.getDecoder().decode(str);
            // 加密数据, 返回密文
            byte[] cipherBytes = cipher.doFinal(decode);
            return new String(cipherBytes);
        } catch (Throwable e) {
            log.info("aes 解密异常 ", e.getMessage());
        }

        return null;
    }

    /**
     * 生成密钥对象
     */
    private static SecretKey generateAesKey(byte[] key) throws Exception {
        // 创建安全随机数生成器
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        // 设置 密钥key的字节数组 作为安全随机数生成器的种子
        random.setSeed(key);

        // 创建 AES算法生成器
        KeyGenerator gen = KeyGenerator.getInstance("AES");
        // 初始化算法生成器
        gen.init(128, random);

        // 生成 AES密钥对象, 也可以直接创建密钥对象: return new SecretKeySpec(key, ALGORITHM);
        return gen.generateKey();
    }
/**-------------------------- base64加密 ----------------------------------*/
    /**
     * base64加密
     *
     * @param key
     * @return
     */
    public static String base64Encode(byte[] key) {
        String result = Base64.getEncoder().encodeToString(key);
        return result;
    }


    /**
     * base64解密
     *
     * @param key
     * @return
     */
    public static byte[] base64DecodeB(String key) {
        byte[] result = null;
        result = Base64.getDecoder().decode(key);
        return result;
    }

    /**
     * 是否被base64加密过
     *
     * @param str
     * @return
     */
    public static boolean isBase64(String str) {
        if (str == null || str.trim().length() == 0) {
            return false;
        } else {
            if (str.length() % 4 != 0) {
                return false;
            }

            char[] strChars = str.toCharArray();

            for (char c : strChars) {
                if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || c == '=') {
                    continue;
                } else {
                    return false;
                }
            }

            return true;
        }
    }
/**-------------------------- 对称加密des ----------------------------------*/
    /**
     * des加密
     *
     * @param datasource
     * @param password
     * @return
     */
    public static String desEncrypt(String datasource, String password) {
        try {
            SecureRandom random = new SecureRandom();
            DESKeySpec desKey = new DESKeySpec(password.getBytes());
            // 创建一个密匙工厂,然后用它把DESKeySpec转换成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey securekey = keyFactory.generateSecret(desKey);
            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
            // 现在,获取数据并加密
            // 正式执行加密操作
            return base64Encode(cipher.doFinal(datasource.getBytes()));
        } catch (Throwable e) {
            log.info("des 加密异常", e.getMessage());
        }

        return null;
    }

    /**
     * des 解密
     *
     * @param src
     * @param password
     * @return
     * @throws Exception
     */
    public static String desDecrypt(String src, String password) {
        try {
            // DES算法要求有一个可信任的随机数源
            SecureRandom random = new SecureRandom();
            // 创建一个DESKeySpec对象
            DESKeySpec desKey = new DESKeySpec(password.getBytes("UTF-8"));
            // 创建一个密匙工厂
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey securekey = keyFactory.generateSecret(desKey);
            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, random);
            // 真正开始解密操作
            return new String(cipher.doFinal(base64DecodeB(src)));
        } catch (Throwable e) {
            log.info("des 解密异常", e.getMessage());
        }
        return null;
    }
/**-------------------------- 非对称加密RSA ----------------------------------*/
    /**
     * 随机生成RSA密钥对
     *
     * @return privateKey, publicKey
     * @throws NoSuchAlgorithmException
     */
    public static Map<String, String> genRSAKeyPair() throws NoSuchAlgorithmException {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器,密钥大小为96-1024位
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        String publicKeyString = base64Encode(publicKey.getEncoded());
        // 得到私钥字符串
        String privateKeyString = base64Encode(privateKey.getEncoded());
        // 将公钥和私钥保存到Map
        Map<String, String> result = new HashMap<String, String>();
        result.put("publicKey", publicKeyString.replaceAll("\n", "").replace("\r", "").trim());
        result.put("privateKey", privateKeyString.replaceAll("\n", "").replace("\r", "").trim());

        return result;
    }

    /**
     * rsa 加密
     *
     * @param str
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String rsaEncrypt(String str, String publicKey) throws Exception {
        //base64编码的公钥
        byte[] decoded = base64DecodeB(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr = base64Encode(cipher.doFinal(str.getBytes("UTF-8")));
        return outStr;
    }

    /**
     * rsa解密
     *
     * @param str
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static String rsaDecrypt(String str, String privateKey) throws Exception {
        //64位解码加密后的字符串
        byte[] inputByte = base64DecodeB(str);
        //base64编码的私钥
        byte[] decoded = base64DecodeB(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte));
        return outStr;
    }

}

2.2 测试

1、生成公钥私钥
2、用公钥加密、私钥解密

 @Test
    void rsaTest() throws Exception {
        //生成公钥私钥
        Map<String, String> keys = EncryptUtils.genRSAKeyPair();
        String publicKey = keys.get("publicKey");
        String privateKey = keys.get("privateKey");
        System.out.println(publicKey);
        System.out.println(privateKey);


        Map<String, java.io.Serializable> map = new HashMap<>(2);
        map.put("username", "xiamaofa");
        map.put("timestamp", 111111111);
        //公钥加密
        String encrypt = EncryptUtils.rsaEncrypt(map.toString(), publicKey);
        //私钥解密
        String decrypt = EncryptUtils.rsaDecrypt(encrypt, privateKey);
        System.out.println(encrypt);
        System.out.println(decrypt);

    }
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtzSxX6dlQZoF9nH6zC8pffKAdzZTa8DuJ5a3Vvp5B6+zRgRObF234Za2FpAjiC8MMVKHekXfhxZhRROTB+1POsGS0lyR+JoBbYRb+ou+LNXKkP9wCsMRl4wbkM4wc4A1uFmnxQKm66VUV7ZxNXKh6ID/N/atkEriNCFiBYWzC6wIDAQAB
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK3NLFfp2VBmgX2cfrMLyl98oB3NlNrwO4nlrdW+nkHr7NGBE5sXbfhlrYWkCOILwwxUod6Rd+HFmFFE5MH7U86wZLSXJH4mgFthFv6i74s1cqQ/3AKwxGXjBuQzjBzgDW4WafFAqbrpVRXtnE1cqHogP839q2QSuI0IWIFhbMLrAgMBAAECgYArKc1deAI0aYC3RWph5Qe5dyX8wNW7GfZvZM8rSk/bZ1BFJ51K4yK4kefqTLa4DNu/8DTTJaV0OLJ/XHDDjDtfqzTsWzaHhhTbrqhw0NfZ7YcxSzMQmiEyC35pAY420Ba1vILyeHBZm7z3I2qhhmCrGI+mDL+MiHJaqgAcJarmYQJBAPp1zD4mZuehg0t8T8UUcASn7f0t1RFwU+5d6wa9DaxS1AWgK4Yj0v0scGlD50dMI5xWWnWjHrR1jz/qyYskCIUCQQCxpU3jzMkYjKZTksObuNZG+62agPIWFUdL6mWT4Bp9kRzAb3Fen4r+/iJFVv/0/O+hYDF29Q/T7gHuAgmJCjCvAkAEkR9PRs37jUNinfqqYkwEmbdKNYq8DatKHmZJsirMqJn7HEeO45pWSXgnQzi1YRsJH734hSfrLHWXOcXBBsAtAkEAoPWLho1F5FWEWxMO46jtljFyUhzlvLaY/CMs2Hjk58M1DvOrADaE5Zh0iulST7NimJClIQjYx4jO/M2hwCaYhwJAVzgz6a9DKv7KctpaBu/l8EJtoY8C1iBVQ4QxfB3HxmM+O01InjZf7lE1FIuYFjIIRwdiCStFN0NyMJnC27/Dmg==
cmjRO+bvz0bPW5TSRTVSbLnQdyI0ITWHGiTErf8ufepnscpHsOr8ax2wmSIHsKBb6r0ysD0dcWV4I1R02rqmdSoPc/JlT4V6yhQ20ZlumiSZ8GIn+rN3aQ8exmQp3f8Sh10mmTOwtMmLS8Vd++HutAEThn26b87jJ6R4e82uS4k=
{username=xiamaofa, timestamp=111111111}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值