Cipher 使用 RSA非对称加密算法 - 公钥加密后,只有私钥才可以解密,私钥加密后,只有公钥才可以解密 - java具体使用 非对称加密算法 - 总结心得

1.背景

有个需求,需要把加密验证数据给前端,该数据为访问对象文档库的授权加密信息,怎么办?

解决方案是使用 RSA 非对称加密算法,公钥加密后,只有私钥才可以解密,私钥加密后,只有公钥才可以解密

对象文档库自己存了一条私钥,把公钥给了用户,永久保存,用户加密授权信息后,给前端,前端就可以每次操作文档库时将这个密钥带上去即可

至于具体的使用文档库实现步骤,这里就不细说了

这里的算法是RSA,千万要与DSA区分开,两个是有区别的,对于DSA讲解请看我这篇随笔

RS256 - DSA 算法之一 - java具体使用 非对称加密算法 - 总结心得 - 岑惜 - 博客园 (cnblogs.com)

2.直接看代码,不多说了

复制代码
package cn.cenxi.common.token;

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 RSAUtil {

    //实例密钥对生成器的加密算法键名【非对称加密】
    private static final String KEY_ALGORITHM = "RSA";

    /**
     * 公钥加密
     *
     * @param input     明文
     * @param publicKey 公钥
     * @return 密文
     */
    public static String encrypt(String input, String publicKey) throws GeneralSecurityException {
        //实例加密算法的转换器
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
        //恢复公钥
        PublicKey pubKey = KeyFactory.getInstance(KEY_ALGORITHM)
                .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)));
        //设置公钥
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        //执行加密数据
        byte[] data = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
        //转字符串后返回
        return Base64.getEncoder().encodeToString(data);
    }

    /**
     * 私钥解密
     *
     * @param input      密文
     * @param privateKey 私钥
     * @return 明文
     */
    public static String decrypt(String input, String privateKey) throws GeneralSecurityException {
        //实例加密算法的转换器
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
        //恢复私钥
        PrivateKey priKey = KeyFactory.getInstance(KEY_ALGORITHM)
                .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        //设置私钥
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        //执行加密数据
        byte[] data = cipher.doFinal(Base64.getDecoder().decode(input));
        //转字符串后返回
        return new String(data, StandardCharsets.UTF_8);
    }

    /**
     * 私钥加密
     *
     * @param input      明文
     * @param privateKey 私钥
     * @return 密文
     */
    public static String encryptByPri(String input, String privateKey) throws GeneralSecurityException {
        //实例加密算法的转换器
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
        PrivateKey priKey = KeyFactory.getInstance(KEY_ALGORITHM)
                .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        cipher.init(Cipher.ENCRYPT_MODE, priKey);
        byte[] data = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(data);
    }

    /**
     * 公钥解密
     *
     * @param input     密文
     * @param publicKey 公钥
     * @return 明文
     */
    public static String decryptByPri(String input, String publicKey) throws GeneralSecurityException {
        //实例加密算法的转换器
        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
        PublicKey pubKey = KeyFactory.getInstance(KEY_ALGORITHM)
                .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)));
        cipher.init(Cipher.DECRYPT_MODE, pubKey);
        byte[] data = cipher.doFinal(Base64.getDecoder().decode(input));
        return new String(data, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) throws GeneralSecurityException {
        //密钥对生成器
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化配置,参数:密钥长度,安全随机数
        kpGen.initialize(1024, new SecureRandom());
        //生成公钥私钥键值对
        KeyPair keyPair = kpGen.generateKeyPair();
        //将公钥转为字符串【方便存储】
        String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        //将私钥转为字符串【方便存储】
        String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        System.out.println("公钥:" + publicKey);
        System.out.println("私钥:" + privateKey);

        //公钥加密,私钥解密
        String msg = "我喜欢你,可以做我女朋友吗?";
        System.out.println("加密前:" + msg);
        String pwd = RSAUtil.encrypt(msg, publicKey);
        System.out.println("公钥加密后:" + pwd);
        System.out.println("私钥解密后:" + RSAUtil.decrypt(pwd, privateKey));

        //私钥加密,公钥解密
        msg = "当然了,我的小可爱";
        System.out.println("加密前:" + msg);
        String pwd2 = RSAUtil.encryptByPri(msg, privateKey);
        System.out.println("私钥加密后:" + pwd2);
        System.out.println("公钥解密后:" + RSAUtil.decryptByPri(pwd2, publicKey));

        //使用错误的密钥来解密
        //System.out.println("私钥解密后:" + RSAUtil.decrypt(pwd, privateKey.replace("2","3")));
        //报错 javax.crypto.BadPaddingException: Decryption error

        //使用错误的公钥解密
        //System.out.println("公钥解密后:" + RSAUtil.decryptByPri(pwd2, publicKey.replace("2", "3")));
        //报错 javax.crypto.BadPaddingException: Decryption error
    }
}
View Code
复制代码

3.测试

 

 

 4.使用错误的解密密钥来解密会报错

javax.crypto.BadPaddingException: Decryption error

 

posted @   岑惜  阅读(894)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示