Java 实现 RSA 非对称加密算法

  • 前言
  • 一、非对称加密算法简介
  • 二、RSA 加解密代码实例
  • 1.生成 RSA 密钥
  • 2.RSA 加解密
  • 3.测试代码
  • 三、RSA 签名验签代码实例
  • 2.RSA 签名验签
  • 3.测试代码


前言

文章字数比较多,可直接查看代码:源码地址,文中描述有误的地方欢迎各位大神指导。

一、非对称加密算法简介

非对称加密算法又称现代加密算法,是计算机通信安全的基石,保证了加密数据不会被破解。与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密(privatekey),因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。公钥和私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。常见算法:RSA、ECC。

加解密和签名验签区别:

既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。

注意: 公钥加密、私钥解密,私钥签名、公钥验签。

二、RSA 加解密代码实例

1.生成 RSA 密钥

代码如下:

public static KeyPair generateKeyPair(int keysize) {
        try {
            // 获取指定算法的密钥对生成器(RSA)
            KeyPairGenerator generator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
            // 初始化密钥对生成器(指定密钥长度, 使用默认的安全随机数源)
            generator.initialize(keysize);
            // 随机生成一对密钥(包含公钥和私钥)
            return generator.generateKeyPair();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2.RSA 加解密

代码如下:

/**
     * RSA 加密
     *
     * @param publicKeyBytes 公钥
     * @param plain          原文
     * @return 密文
     */
    public static byte[] rsaEncrypt(byte[] publicKeyBytes, byte[] plain) {
        try {
        	// RSA
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(publicKeyBytes);
            PublicKey publicKey = keyFactory.generatePublic(pubX509);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(plain);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA 解密
     *
     * @param privateKeyBytes  私钥
     * @param encrypted        密文
     * @return 原文
     */
    public static byte[] rsaDecrypt(byte[] privateKeyBytes, byte[] encrypted) {
        try {
			// RSA
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

3.测试代码

代码如下:

public static void main(String[] args) {
        String plain = "123";
        KeyPair keyPair = generateKeyPair(2048);
        byte[] encrypt = rsaEncrypt(keyPair.getPublic().getEncoded(), plain.getBytes());
        byte[] decrypt = rsaDecrypt(keyPair.getPrivate().getEncoded(), encrypt);
        System.err.println(new String(decrypt));
    }

三、RSA 签名验签代码实例

2.RSA 签名验签

代码如下:

/**
     * rsaSign.
     *
     * @param privateKeyBytes 私钥
     * @param plain 明文
     * @return String 签名
     */
    public static String rsaSign(byte[] privateKeyBytes, String plain) throws Exception {
        final KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        final PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        final PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        final Signature signature = Signature.getInstance(RSA_SIGN_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(plain.getBytes(StandardCharsets.UTF_8));
        final byte[] signed = signature.sign();
        return new String(Base64.encodeBase64URLSafe(signed), StandardCharsets.UTF_8);
    }

    /**
     * rsaVerify.
     *
     * @param publicKeyBytes 公钥
     * @param plain 原文
     * @param sign 签名
     * @return boolean
     */
    public static boolean rsaVerify(byte[] publicKeyBytes, String plain, String sign)
        throws Exception {
        final KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        final X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(publicKeyBytes);
        final PublicKey publicKey = keyFactory.generatePublic(pubX509);
        final Signature signature = Signature.getInstance(RSA_SIGN_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(plain.getBytes(StandardCharsets.UTF_8));
        return signature.verify(Base64.decodeBase64URLSafe(sign));
    }

3.测试代码

代码如下:

public static void main(String[] args) throws Exception {
        final String sign = rsaSign(privateKey, plain);
        System.err.println(sign);
        final boolean verify = rsaVerify(publicKey, plain, sign);
        System.err.println(verify);
    }