使用 Java 实现 RSA 加密

本文将介绍怎样使用 Java 实现 RSA 非对称加密。

废话不多说,直接上代码,不懂的看注释。代码如下:

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * RSA加密实现
 * @author hxstrive.com
 */
public class RSAEncrypt {
    /**
     * RSA算法允许最大加密数据块大小
     */
    private static final int ENCRYPT_BLOCK_SIZE = 117;
    /**
     * RSA算法允许最大解密数据块大小
     */
    private static final int DECRYPT_BLOCK_SIZE = 128;


    /**
     * 获取RSA私钥对象
     * @param privateKey 私钥
     * @return 返回 PrivateKey 对象
     */
    private static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] decoded = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 获取RSA公钥对象
     * @param publicKey 公钥
     * @return 返回 PublicKey 对象
     */
    private static PublicKey getPublicKey(String publicKey) throws Exception {
        byte[] decoded = Base64.decodeBase64(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoded);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }


    /**
     * 私钥加密
     * @param bytes 待加密字节数组
     * @param privateKey 私钥
     * @return 返回加密后的字节数组
     */
    public static byte[] encrypt(final byte[] bytes, final String privateKey) throws Exception {
        if(null == bytes || bytes.length <= 0) {
            throw new RuntimeException("待加密字节数组不能为空");
        }

        if(StringUtils.isBlank(privateKey)) {
            throw new RuntimeException("私钥不能为空");
        }
        PrivateKey privateKeyObj = getPrivateKey(privateKey);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKeyObj);

        // 开始加密
        // 暂存所有已加密字节,一起返回
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        byte[] tmpBytes = new byte[ENCRYPT_BLOCK_SIZE];
        int len;
        while((len = inputStream.read(tmpBytes)) != -1) {
            if(len != ENCRYPT_BLOCK_SIZE) { // 如果加密数据不够 117 字节
                byte[] buffer = new byte[len];
                System.arraycopy(tmpBytes, 0, buffer, 0, len);
                outputStream.write(cipher.doFinal(buffer));
            } else {
                outputStream.write(cipher.doFinal(tmpBytes));
            }
        }
        outputStream.flush();

        return outputStream.toByteArray();
    }


    /**
     * 对给定的字符串进行加密,加密成功后使用Base64返回加密结果
     * @param data 待加密字符串,使用 UTF-8 编码
     * @param privateKey 私钥
     * @return 返回使用 Base64 加密后的字符串
     */
    public static String encrypt(final String data, final String privateKey) throws Exception {
        return Base64.encodeBase64String(encrypt(data.getBytes(StandardCharsets.UTF_8), privateKey));
    }


    /**
     * 公钥解密
     * @param bytes 待解密字节数组
     * @param publicKey 公钥
     * @return 返回解密后的字节数组
     */
    public static byte[] decrypt(final byte[] bytes, final String publicKey) throws Exception {
        if(null == bytes || bytes.length <= 0) {
            throw new RuntimeException("待解密字节数组不能为空");
        }

        if(StringUtils.isBlank(publicKey)) {
            throw new RuntimeException("公钥不能为空");
        }
        PublicKey publicKeyObj = getPublicKey(publicKey);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKeyObj);

        // 开始解密
        // 暂存所有已加密字节,一起返回
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        byte[] tmpBytes = new byte[DECRYPT_BLOCK_SIZE];
        int len;
        while((len = inputStream.read(tmpBytes)) != -1) {
            if(len != DECRYPT_BLOCK_SIZE) { // 如果加密数据不够 128 字节
                byte[] buffer = new byte[len];
                System.arraycopy(tmpBytes, 0, buffer, 0, len);
                outputStream.write(cipher.doFinal(buffer));
            } else {
                outputStream.write(cipher.doFinal(tmpBytes));
            }
        }
        outputStream.flush();

        return outputStream.toByteArray();
    }


    /**
     * 对给定的字符串进行解密(该字符串采用Base64编码)
     * @param data 代码解密的Base64字符串
     * @param publicKey 公钥
     * @return 返回解密成功的字符串,默认使用UTF-8编码
     */
    public static String decrypt(final String data, final String publicKey) throws Exception {
        return new String(decrypt(Base64.decodeBase64(data), publicKey), StandardCharsets.UTF_8);
    }

}

使用方法如下:

public class Demo {
    /** 公钥 */
    private static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuOFMwnouXWEueTm2Qmua5oo8J7frN96DoSDtw11ObrfvfVKu91GcjPlF/ynUeyjwPuzmi+bkCIDs2wUn0wz3CU52o4e1drzLiDOhGGqAb+cj5//o9mUVRJGrfzZyEePW8/gaRK3Q1iqu8hkBXbWGIkGFsbc3DJdkWlkd+Y6fHGwIDAQAB";
    /** 私钥 */
    private static String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAK44UzCei5dYS55ObZCa5rmijwnt+s33oOhIO3DXU5ut+99Uq73UZyM+UX/KdR7KPA+7OaL5uQIgOzbBSfTDPcJTnajh7V2vMuIM6EYaoBv5yPn/+j2ZRVEkat/NnIR49bz+BpErdDWKq7yGQFdtYYiQYWxtzcMl2RaWR35jp8cbAgMBAAECgYA4ETJcjDl6PFUhnjXOertT9Ie591dmn5GuD0jp2LI0gLp1NgeLMOb8RZru2FX20bigi21SELHEiGDmDzBgz9B4x9lY8IIoB52FZdd+YgSVvXV/hA9Ikf1HClixC1DrixJ6/O/4e4r8uwdeTyVZvhVmf8Q37hfCRSKGCF5+plds0QJBAOltOgzTjF3iSjCjjXKprsaZZvgFaq+2/vmjzJvfDepBWU76MV+B5BB63n7C9S9jden+70qyCdATbLcezuEZCjkCQQC/EVzPNnsUre7u46bngTnkgVXcjcDler4BLBgDUCnJE06PDar48rcrEzK+0w3kCXN74ZzNFCt4A/1SKK9zh6vzAkBHfr39+bmPc+T3WtDTIue2SnwAUWBo62rTOXlM8JfJfTSGfRksQJOC/K8zMjF4z0TpY70VKszYn2p3+AazaUD5AkBNUSFVWJ6Fx7ygPs8Tb1+V8CBml5YvRnQM1WMCNDY0f/OSP92nz8//Rk2Kmq1MUebBgpKJClhswHCKBpy5C3WxAkB/prC/JNPP37P/G1+nALQpJ1kascODroWcS1x8BeLLHfCnSdYcI5uTLVzpBt/IfajEHCIDgW+yWJigqjf6DvjX";


    public static void main(String[] args) throws Exception {
        String value = "hello world";

        // 加密
        String result = RSAEncrypt.encrypt(value, PRIVATE_KEY);
        System.out.println("密文:" + result);

        // 解密
        String result2 = RSAEncrypt.decrypt(result, PUBLIC_KEY);
        System.out.println("明文:" + result2);
    }

}

运行示例,输出如下:

密文:c3Q7zAqiO8Vqp49yUBztx4FyYJub63hWm5qovDIfP9N8Zh4O4EBYC2mbdqigjO2xCaIUokFQwxuaZ/2oo6UJ6b3wxvijyfWAydiRvNKop4ewpJPfVLloZ3DAQ4aBXNJxhbas+kJa2obz3K0uYnSHEvUJr/T07GGcFbig0hx/Q7g=
明文:hello world
最困难的事情就是认识自己。——希腊
1 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号