使用rsa对明文加密与解密

发布时间 2023-10-24 12:57:29作者: 安详的苦丁茶

公钥加密,私钥解密

/**
     * 加密
     *
     * @param plaintext    明文
     * @param publicKeyStr 公钥字符
     * @return
     * @throws Exception
     */
    public static String rsaEncrypt(String plaintext, String publicKeyStr) throws Exception {
        // 将公钥字符串和私钥字符串转换为 PublicKey 对象
        PublicKey publicKey = getPublicKey(publicKeyStr);
        // 使用公钥加密明文
        byte[] encryptedBytes = encrypt(plaintext.getBytes(StandardCharsets.UTF_8), publicKey);
        System.out.println("加密文本: " + base64Encode(encryptedBytes));
        return base64Encode(encryptedBytes);
    }

    /**
     * 加密
     *
     * @param encryptedText 加密密文
     * @param privateKeyStr 私钥字符
     * @return
     * @throws Exception
     */
    public static String rsaDecrypt(String encryptedText, String privateKeyStr) throws Exception {
        // 将公钥字符串和私钥字符串转换为 PrivateKey 对象
        PrivateKey privateKey = getPrivateKey(privateKeyStr);
        // 使用私钥解密密文
        byte[] decryptedBytes = decrypt(base64Decode(encryptedText), privateKey);
        System.out.println("解密文本: " + new String(decryptedBytes, StandardCharsets.UTF_8));
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    /**
     * 将公钥字符串转换为 PublicKey 对象
     *
     * @param publicKeyStr
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
        byte[] keyBytes = base64Decode(publicKeyStr);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

    /**
     * 将私钥字符串转换为 PrivateKey 对象
     *
     * @param privateKeyStr
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
        // 添加 Bouncy Castle 作为安全提供程序
        Security.addProvider(new BouncyCastleProvider());
        byte[] keyBytes = base64Decode(privateKeyStr);
        //pkcs1格式 转 pkcs8格式
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
    }

    /**
     * 使用公钥加密
     *
     * @param plaintext
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] plaintext, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(plaintext);
    }

    /**
     * 使用私钥解密
     *
     * @param ciphertext
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] ciphertext, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(ciphertext);
    }

    /**
     * Base64 编码
     *
     * @param data
     * @return
     */
    public static String base64Encode(byte[] data) {
        return Base64.getEncoder().encodeToString(data);
    }

    /**
     * Base64 解码
     *
     * @param data
     * @return
     */
    public static byte[] base64Decode(String data) {
        return Base64.getDecoder().decode(data);
    }

 

测试

public static void main(String[] args) throws Exception {
        // 明文
        String plaintext = "123456";
        // 使用公钥加密明文
        String s = rsaEncrypt(plaintext, publicKeyStr);
        System.out.println("加密文本: " + s);
        System.out.println("解密文本: " + rsaDecrypt(s, privateKeyStr));

        String sign = sign(plaintext);
        System.out.println("签名结果:" + sign);

        boolean verify = verify(plaintext, sign);
        System.out.println("验证签名结果:" + verify);
    }

 

秘钥格式

PKCS1的文件头格式    -----BEGIN RSA PRIVATE KEY-----
PKCS8的文件头格式    -----BEGIN PRIVATE KEY-----

 

签名

/**
     * 签名
     *
     * @param plaintext 需要签名的明文
     * @return 返回签名信息
     * @throws Exception
     */
    public static String sign(String plaintext) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // 创建Signature对象并初始化为签名模式
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);

        // 要签名的数据
        byte[] dataToSign = plaintext.getBytes(StandardCharsets.UTF_8);

        // 更新数据并签名
        signature.update(dataToSign);
        byte[] signatureBytes = signature.sign();

        // 将签名结果以Base64编码的形式输出
        String signatureBase64 = Base64.getEncoder().encodeToString(signatureBytes);
        System.out.println("RSA签名结果:" + signatureBase64);
        return signatureBase64;
    }

 

验证签名

/**
     * 验证签名
     *
     * @param plaintext 明文
     * @param decodeSrc 签名结果的Base64编码
     * @return 返回签名结果
     * @throws Exception
     */
    public static boolean verify(String plaintext, String decodeSrc) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        // 创建Signature对象并初始化为验签模式
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);

        // 原始数据和签名数据
        byte[] originalData = plaintext.getBytes(StandardCharsets.UTF_8);
        byte[] signatureBytes = Base64.getDecoder().decode(decodeSrc);

        // 更新数据并验证签名
        signature.update(originalData);
        boolean isValid = signature.verify(signatureBytes);

        if (isValid) {
            System.out.println("RSA签名验证成功");
        } else {
            System.out.println("RSA签名验证失败");
        }
        return isValid;
    }

 

注意:

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

这个是构造一个对象,并没有转换pkcs8 格式的操作

在执行转换前加上这行就可以了

Security.addProvider(new BouncyCastleProvider());

 

如果秘钥放在yml文件中需要注意以\换行