RSA加密算法

1024

🍓 简介:java系列技术分享(👉持续更新中…🔥)
🍓 初衷:一起学习、一起进步、坚持不懈
🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏
🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝

🍓 更多文章请点击
在这里插入图片描述在这里插入图片描述

一、RSA算法简介

RSA加密(Rivest-Shamir-Adleman加密)是一种非对称加密算法

  • 加密算法是目前最有影响力的 公钥加密算法,并且被普遍认为是目前 最优秀的公钥方案 之一。RSA 是第一个能同时用于 加密 和 数字签名 的算法,它能够 抵抗 到目前为止已知的 所有密码攻击,已被ISO推荐为公钥数据加密标准。
  • RSA加密算法基于一个简单的数论事实:将两个大素数相乘容易,但是将其乘积分解成原始的两个大素数却非常困难。RSA算法的核心思想就是利用这个数论事实来实现加密和解密。

  • 在RSA加密中,每个参与者拥有一对密钥:公钥和私钥。公钥可以自由分发,而私钥必须保密。发送方使用接收方的公钥对消息进行加密,接收方使用自己的私钥对加密后的消息进行解密。公钥和私钥是通过一系列数学运算生成的,并且在算法中使用了大数的运算,使得破解RSA加密变得困难。

  • RSA算法的安全性基于两个数论问题的难解性:大整数的因数分解和模取指数的离散对数问题。由于目前没有高效的算法能够在合理时间内解决这两个问题,因此RSA算法被认为是一种安全可靠的加密算法。

二、对称加密和非对称加密

加密算法分 对称加密非对称加密,其中对称加密算法的加密与解密 密钥相同,非对称加密算法的加密密钥与解密 密钥不同,此外,还有一类 不需要密钥散列算法

常见的 对称加密 算法主要有 DES3DESAES 等,常见的 非对称算法 主要有 RSADSA 等,散列算法 主要有 SHA-1MD5 等。

2.1 对称加密

对称加密算法 是应用较早的加密算法,又称为 共享密钥加密算法。在 对称加密算法 中,使用的密钥只有一个,发送接收 双方都使用这个密钥对数据进行 加密和解密。这就要求加密和解密方事先都必须知道加密的密钥。

  1. 数据加密过程:在对称加密算法中,数据发送方明文 (原始数据) 和 加密密钥 一起经过特殊 加密处理,生成复杂的 加密密文 进行发送。

  2. 数据解密过程:数据接收方 收到密文后,若想读取原数据,则需要使用 加密使用的密钥 及相同算法的 逆算法 对加密的密文进行解密,才能使其恢复成 可读明文

2.2. 非对称加密

非对称加密算法,又称为 公开密钥加密算法。它需要两个密钥,一个称为 公开密钥 (public key),即 公钥,另一个称为 私有密钥 (private key),即 私钥

因为 加密解密 使用的是两个不同的密钥,所以这种算法称为 非对称加密算法

  1. 如果使用 公钥 对数据 进行加密,只有用对应的 私钥 才能 进行解密(推荐)。

  2. 如果使用 私钥 对数据 进行加密,只有用对应的 公钥 才能 进行解密

三、代码实现

import cn.hutool.core.codec.Base64Encoder;
import com.web.exception.enums.ErrorCodeEnum;
import com.web.exception.exception.BizException;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.UUID;


public class SecureRSAUtil {
    /**
     * Base64编码
     */
    private static Base64.Encoder encoder = Base64.getEncoder();

    /**
     * Base64解码
     */
    private static Base64.Decoder decoder = Base64.getDecoder();

    private static final String ALGORITHM = "RSA";

    private static final int KEY_SIZE = 1024;


    /**
     * 生成密钥对
     *
     * @return Map对象 (private=私钥, public=公钥)
     * @throws Exception 异常
     */
    public static HashMap<String, String> rsaGenerateKeyPair() throws Exception {

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        KeyPair keyPair;

        try {
            keyPairGenerator.initialize(KEY_SIZE,
                    new SecureRandom(UUID.randomUUID().toString().replaceAll("-", "").getBytes()));
            keyPair = keyPairGenerator.generateKeyPair();
        } catch (InvalidParameterException e) {
            throw e;
        } catch (NullPointerException e) {
            throw e;
        }

        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

        HashMap<String, String> map = new HashMap<String, String>(16);
        map.put("private", Base64Encoder.encode(rsaPrivateKey.getEncoded()));
        map.put("public", Base64Encoder.encode(rsaPublicKey.getEncoded()));
        return map;
    }

    /**
     * RSA公钥加密
     *
     * @param publicKeyString 公钥
     * @param content         内容
     * @return 加密后内容
     */
    public static String rsaEncryptByPublic(String publicKeyString, String content) {
        try {
            // 获得公钥对象
            PublicKey publicKey = getPublicKeyFromString(publicKeyString);

            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 该密钥能够加密的最大字节长度
            int splitLength = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8 - 11;
            byte[][] arrays = splitBytes(content.getBytes(), splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for (byte[] array : arrays) {
                stringBuffer.append(bytesToHexString(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnum.SECURE_ERROR);
        }
    }

    /**
     * RSA私钥加密
     *
     * @param privateKeyString 私钥
     * @param content          内容
     * @return 加密后内容
     */
    public static String rsaEncryptByPrivate(String privateKeyString, String content) {
        try {
            PrivateKey privateKey = getPrivateKeyFromString(privateKeyString);

            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            // 该密钥能够加密的最大字节长度
            int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8 - 11;
            byte[][] arrays = splitBytes(content.getBytes(), splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for (byte[] array : arrays) {
                stringBuffer.append(bytesToHexString(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnum.SECURE_ERROR);
        }
    }

    /**
     * RSA公钥解密
     *
     * @param publicKeyString 公钥
     * @param content         已加密内容
     * @return 解密后内容
     */
    public static String rsaDecryptByPublic(String publicKeyString, String content) {

        try {
            PublicKey publicKey = getPublicKeyFromString(publicKeyString);

            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            // 该密钥能够加密的最大字节长度
            int splitLength = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8;
            byte[] contentBytes = hexStringToBytes(content);
            byte[][] arrays = splitBytes(contentBytes, splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for (byte[] array : arrays) {
                stringBuffer.append(new String(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnum.SECURE_ERROR);
        }
    }

    /**
     * RSA私钥解密
     *
     * @param privateKeyString 公钥
     * @param content          已加密内容
     * @return 解密后内容
     */
    public static String rsaDecryptByPrivate(String privateKeyString, String content) {
        try {
            PrivateKey privateKey = getPrivateKeyFromString(privateKeyString);

            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 该密钥能够加密的最大字节长度
            int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8;
            byte[] contentBytes = hexStringToBytes(content);
            byte[][] arrays = splitBytes(contentBytes, splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for (byte[] array : arrays) {
                stringBuffer.append(new String(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnum.SECURE_ERROR);
        }
    }


    // ---------- 获取*钥

    /**
     * 根据公钥字符串获取 公钥对象
     */
    private static PublicKey getPublicKeyFromString(String key)
            throws NoSuchAlgorithmException, InvalidKeySpecException {

        // 过滤掉\r\n
        key = key.replace("\r\n", "");

        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(decoder.decode(key));

        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);

        return publicKey;
    }

    /**
     * 根据私钥字符串获取 私钥对象
     */
    private static PrivateKey getPrivateKeyFromString(String key)
            throws NoSuchAlgorithmException, InvalidKeySpecException {

        // 过滤掉\r\n
        key = key.replace("\r\n", "");

        // 取得私钥
        PKCS8EncodedKeySpec x509KeySpec = new PKCS8EncodedKeySpec(decoder.decode(key));

        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

        PrivateKey privateKey = keyFactory.generatePrivate(x509KeySpec);

        return privateKey;
    }


    // ---------- 一些辅助方法

    /**
     * 根据限定的每组字节长度,将字节数组分组
     */
    private static byte[][] splitBytes(byte[] bytes, int splitLength) {

        // bytes与splitLength的余数
        int remainder = bytes.length % splitLength;
        // 数据拆分后的组数,余数不为0时加1
        int quotient = remainder != 0 ? bytes.length / splitLength + 1 : bytes.length / splitLength;
        byte[][] arrays = new byte[quotient][];
        byte[] array = null;
        for (int i = 0; i < quotient; i++) {
            // 如果是最后一组(quotient-1),同时余数不等于0,就将最后一组设置为remainder的长度
            if (i == quotient - 1 && remainder != 0) {
                array = new byte[remainder];
                System.arraycopy(bytes, i * splitLength, array, 0, remainder);
            } else {
                array = new byte[splitLength];
                System.arraycopy(bytes, i * splitLength, array, 0, splitLength);
            }
            arrays[i] = array;
        }
        return arrays;
    }

    /**
     * 将字节数组转换成16进制字符串
     */
    private static String bytesToHexString(byte[] bytes) {

        StringBuffer sb = new StringBuffer(bytes.length);
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(0xFF & bytes[i]);
            if (temp.length() < 2) {
                sb.append(0);
            }
            sb.append(temp);
        }
        return sb.toString();
    }

    /**
     * 将16进制字符串转换成字节数组
     */
    private static byte[] hexStringToBytes(String hex) {

        int len = (hex.length() / 2);
        hex = hex.toUpperCase();
        byte[] result = new byte[len];
        char[] chars = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(chars[pos]) << 4 | toByte(chars[pos + 1]));
        }
        return result;
    }

    /**
     * 将char转换为byte
     */
    private static byte toByte(char c) {

        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static void main(String[] args) throws Exception {
        String password = "123456789";
        System.out.println("原始密码:"+password);
        //生成秘钥对
        HashMap<String, String> stringStringHashMap = rsaGenerateKeyPair();
        // 定义私钥和公钥
        String privateKey = stringStringHashMap.get("private");
        String publicKey = stringStringHashMap.get("public");
        System.out.println("公钥:"+publicKey);
        System.out.println("私钥:"+privateKey);
        //私钥加密,公钥解密----测试
        String encryptPwd1 = rsaEncryptByPrivate(privateKey, password);
        System.out.println("私钥加密,公钥解密后" + rsaDecryptByPublic(publicKey, encryptPwd1));
        System.out.println("================================================================");
        //公钥加密,私钥解密----测试
        String encryptPwd2 = rsaEncryptByPublic(publicKey, password);
        System.out.println("公钥加密,私钥解密后" + rsaDecryptByPrivate(privateKey, encryptPwd2));

    }
}

调用上方main方法得到结果
注意

  • 双方需要使用同一个密钥对数据进行 加密和解密
    在这里插入图片描述

在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dream_sky分享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值