My Life My Dream!

守信 求实 好学 力行
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

RSA加密算法,加解密、签名示例

Posted on 2025-09-10 20:50  江城2211  阅读(13)  评论(0)    收藏  举报

RSA加密算法,加解密、签名验签示例Demo:

package com.example.demo;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAExample {
    private static final String ALGORITHM = "RSA";
    private static final int KEY_SIZE = 2048;
    private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding";
    // 签名算法(SHA256withRSA是常用的安全组合)
    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";

    // 生成密钥对
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM);
        generator.initialize(KEY_SIZE);
        return generator.generateKeyPair();
    }

    // 私钥加密
    // 私钥加密、公钥解密  从算法上来说是可以的,但与非对称加解密设计相违背
    // 在 RSA 中,使用私钥加密在数学上是可行的,但这违背了非对称加密的设计原则和安全最佳实践。
    public static String encryptByPrivateKey(PrivateKey privateKey, String data) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, privateKey); // 用私钥初始化加密模式
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    // 公钥解密
    public static String decryptByPublicKey(PublicKey publicKey, String encryptedData) throws Exception {
        byte[] data = Base64.getDecoder().decode(encryptedData);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, publicKey); // 用公钥初始化解密模式
        byte[] decrypted = cipher.doFinal(data);
        return new String(decrypted, StandardCharsets.UTF_8);
    }


    /**
     * 使用公钥加密数据
     * @param publicKey 公钥对象
     * @param data 待加密的明文
     * @return Base64编码的密文
     * @throws Exception 加密过程中可能出现的异常
     */
    public static String encrypt(PublicKey publicKey, String data) throws Exception {
        // 获取加密实例
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);

        // 初始化加密模式
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        // 执行加密并转为Base64
        byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 使用私钥解密数据
     * @param privateKey 私钥对象
     * @param encryptedData Base64编码的密文
     * @return 解密后的明文
     * @throws Exception 解密过程中可能出现的异常
     */
    public static String decrypt(PrivateKey privateKey, String encryptedData) throws Exception {
        // 获取解密实例
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);

        // 初始化解密模式
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        // 执行解密
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    /**
     * 使用私钥对数据进行签名
     * @param privateKey 私钥对象
     * @param data 待签名的数据
     * @return Base64编码的签名结果
     * @throws Exception 签名过程中可能出现的异常
     */
    public static String sign(PrivateKey privateKey, String data) throws Exception {
        // 获取签名实例
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

        // 用私钥初始化签名器
        signature.initSign(privateKey);

        // 更新待签名的数据
        signature.update(data.getBytes(StandardCharsets.UTF_8));

        // 生成签名并转为Base64
        byte[] signBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signBytes);
    }

    /**
     * 使用公钥验证签名
     * @param publicKey 公钥对象
     * @param data 原始数据
     * @param sign 待验证的签名(Base64编码)
     * @return 验证结果:true-验证通过,false-验证失败
     * @throws Exception 验签过程中可能出现的异常
     */
    public static boolean verify(PublicKey publicKey, String data, String sign) throws Exception {
        // 获取签名实例
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

        // 用公钥初始化验签器
        signature.initVerify(publicKey);

        // 更新原始数据
        signature.update(data.getBytes(StandardCharsets.UTF_8));

        // 验证签名
        byte[] signBytes = Base64.getDecoder().decode(sign);
        return signature.verify(signBytes);
    }

    // 私钥加密、公钥解密  从算法上来说是可以的,但与非对称加解密设计相违背
    // 在 RSA 中,使用私钥加密在数学上是可行的,但这违背了非对称加密的设计原则和安全最佳实践。
    public static String encryptByKey(Key key, String data) throws Exception{
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, key); // 初始化加密模式
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }
    public static String decryptByKey(Key key, String encryptedData) throws Exception {
        byte[] data = Base64.getDecoder().decode(encryptedData);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, key); // 用公钥初始化解密模式
        byte[] decrypted = cipher.doFinal(data);
        return new String(decrypted, StandardCharsets.UTF_8);
    }
    // 密钥格式转换工具方法
    public static PublicKey getPublicKey(byte[] bytes) throws Exception {
        X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
        return KeyFactory.getInstance(ALGORITHM).generatePublic(spec);
    }

    public static PrivateKey getPrivateKey(byte[] bytes) throws Exception {
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        return KeyFactory.getInstance(ALGORITHM).generatePrivate(spec);
    }

    public static void main(String[] args) {
        try {
            // 1. 生成密钥对
            KeyPair keyPair = generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();

            System.out.println("私钥: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
            System.out.println("公钥: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));

            System.out.println();

            // 2. 原始数据
            String original = "======1111用私钥加密的数据";
            System.out.println("原始数据: " + original);

            // 3. 私钥加密
            String encrypted = encryptByPrivateKey(privateKey, original);
            System.out.println("私钥加密: " + encrypted);

            // 4. 公钥解密
            String decrypted = decryptByPublicKey(publicKey, encrypted);
            System.out.println("公钥解密: " + decrypted);


            System.out.println();
            //
            String original2 = "======2222用PublicKey加密的数据";
            System.out.println("原始数据:" +original2);
            // 5. 公钥加密
            String encrypted2 = encryptByKey(publicKey, original2);
            System.out.println("公钥加密: " + encrypted2);
            System.out.println("tkk: " + encryptByKey(publicKey, original2));

            // 6. 私钥解密
            String decrypted2 = decryptByKey(privateKey, encrypted2);
            System.out.println("私钥解密: " + decrypted2);


            String encrypted3 = encrypt(publicKey, original2);
            System.out.println("公钥加密:" + encrypted3);

            String decrypted3 = decrypt(privateKey, encrypted3);
            System.out.println("私钥解密:" + decrypted3);
            System.out.println("tkk:" + decrypt(privateKey, encrypted2));

            // 12. 待签名的数据
            String originalData = "这是需要RSA签名的数据,用于验证数据完整性和发送者身份";
            System.out.println("\n原始数据: " + originalData);

            // 13. 使用私钥签名
            String signature = sign(privateKey, originalData);
            System.out.println("签名结果(Base64): " + signature);

            // 14. 模拟传输后,使用公钥验签(正常情况)
            boolean verifySuccess = verify(publicKey, originalData, signature);
            System.out.println("正常数据验签结果: " + (verifySuccess ? "通过" : "失败"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

参考文章:https://cloud.tencent.com/developer/article/2499894