java实现非对称加密(RSA)

工具方法

package com.fhxy.utils;

import org.apache.commons.net.util.Base64;
import org.apache.tomcat.util.http.fileupload.IOUtils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;


public class RSAUtil {
    public static final String CHARSET = "UTF-8";
    public static final String RSA_ALGORITHM = "RSA";
    
    //生成密钥对,一般来说执行一次就行
    public static Map<String, String> createKeys(int keySize) {
        //为RSA算法创建一个KeyPairGenerator对象(KeyPairGenerator,密钥对生成器,用于生成公钥和私钥对)
        KeyPairGenerator kpg;
        try {
            kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
        }

        //初始化KeyPairGenerator对象,密钥长度
        kpg.initialize(keySize);
        //生成密匙对
        KeyPair keyPair = kpg.generateKeyPair();
        //得到公钥
        Key publicKey = keyPair.getPublic();
        String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded()); //返回一个publicKey经过二次加密后的字符串
        //得到私钥
        Key privateKey = keyPair.getPrivate();
        String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded()); //返回一个privateKey经过二次加密后的字符串

        Map<String, String> keyPairMap = new HashMap<String, String>();
        keyPairMap.put("publicKey", publicKeyStr);
        keyPairMap.put("privateKey", privateKeyStr);

        return keyPairMap;
    }

    /**
     * 得到公钥
     *
     * @param publicKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过X509编码的Key指令获得公钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
        return key;
    }

    /**
     * 得到私钥
     *
     * @param privateKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过PKCS#8编码的Key指令获得私钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
    }

    /**
     * 公钥加密
     *
     * @param data
     * @param publicKey
     * @return
     */
    public static String publicEncrypt(String data, RSAPublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
        } catch (Exception e) {
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 私钥解密
     *
     * @param data
     * @param privateKey
     * @return
     */

    public static String privateDecrypt(String data, RSAPrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
        } catch (Exception e) {
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 私钥加密
     *
     * @param data
     * @param privateKey
     * @return
     */

    public static String privateEncrypt(String data, RSAPrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
        } catch (Exception e) {
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 公钥解密
     *
     * @param data
     * @param publicKey
     * @return
     */

    public static String publicDecrypt(String data, RSAPublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
        } catch (Exception e) {
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
        int maxBlock = 0;
        if (opmode == Cipher.DECRYPT_MODE) {
            maxBlock = keySize / 8;
        } else {
            maxBlock = keySize / 8 - 11;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try {
            while (datas.length > offSet) {
                if (datas.length - offSet > maxBlock) {
                    buff = cipher.doFinal(datas, offSet, maxBlock);
                } else {
                    buff = cipher.doFinal(datas, offSet, datas.length - offSet);
                }
                out.write(buff, 0, buff.length);
                i++;
                offSet = i * maxBlock;
            }
        } catch (Exception e) {
            throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
        }
        byte[] resultDatas = out.toByteArray();
        IOUtils.closeQuietly(out);
        return resultDatas;
    }



//测试
    public static void main(String[] args) throws Exception {
        //生成公私钥
//        Map<String, String> keyMap = RSAUtil.createKeys(512);
        //公钥
      String publicKey = keyMap.get("publicKey");
        //私钥
    String privateKey = keyMap.get("privateKey");


        System.out.println("公钥加密——私钥解密");
        String str = "法外狂徒";
        System.out.println("明文:" + str);
        System.out.println("明文大小:" + str.getBytes().length);
        //对内容进行公钥加密
      String encodedData = RSAUtil.publicEncrypt(str, RSAUtil.getPublicKey(publicKey));
        System.out.println("公钥加密密文:" + encodedData);
        //用私钥对密文进行解密
        
        String decodedData = RSAUtil.privateDecrypt(encodedData, RSAUtil.getPrivateKey(privateKey));
        System.out.println("解密后文字: " + decodedData);
    }
}

非对称加密方式可用于多种场景,例如:
①前端加密登录信息,前端使用公钥对用户名密码进行加密,后端在登录接口时,使用私钥进行解密。
②后端对数据传输内容进行加密。
通过全局注解和切面方式,对所有有返回值的接口进行数据加密。
代码如下:

//定义一个注解,作为aop的切入方式,后面会将此注解加在所有有返回值的接口的controller层的方法上面。
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
@Documented
public @interface CompanyConditionAnno {
}
//对上面的注解进行赋能
@Aspect
@Component
public class LogAspect {
//加密用的公钥,是上面生成密钥对方法生成的
    public static final String PUBLIC_KEY = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALJi7IanVfq-gj1-vq8MZ4n1xQbMhs1iPbXWXubCviIm-nDZ6Z1O7c7GkWwaE7eZIzGSoFSHcRnQ5I59dnTF--sCAwEAAQ";

//定义切点,指向上面定义的CompanyConditionAnno注解
    @Pointcut("@annotation(com.fj.lh.dog.config.CompanyConditionAnno)")
    public void companyCodeCondition() {
    }

//采用环绕通知方式,对此切点切入的地方进行增强。简单说就是可以在方法执行前,修改方法的一系列参数,在方法执行后,对方法返回值进行修改,强的一批。
    @Around(value = " companyCodeCondition()  ")
    public String insertLog(ProceedingJoinPoint pc) throws Throwable {
        MethodSignature signature = (MethodSignature) pc.getSignature();
        //获取切入方法的对象
        Method method = signature.getMethod();
        //获取参数值
        Object[] args = pc.getArgs();
        //获取运行时参数的名称
        DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
        //获取方法中的参数名称,parameterNames[]中的值与args[]中值是key-value关系,如果有全局参数控制,可以在这里对参数值进行修改
        String[] parameterNames = discoverer.getParameterNames(method);
        //执行程序,得到程序执行结果proceed 
        Object proceed = pc.proceed(args);
        String encodedData ="";
        //将结果转成JSONString对象
        String s = JSON.toJSONString(proceed);
        if(!StringUtils.isEmpty(s)){
        //对结果进行非对称解密
             encodedData = RSAUtil.publicEncrypt(s, RSAUtil.getPublicKey(PUBLIC_KEY));
        }
        return encodedData;
    }
  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对称加密算法是一种常用的加密方式,它采用了一对密钥,即公钥和私钥。公钥是公开的,可以任意分发,而私钥则只能由密钥的所有者持有,用于解密加密数据。常见的对称加密算法包括RSA、DSA、ECC等。 下面是一个使用RSA算法实现对称加密Java示例代码: ```java import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import javax.crypto.Cipher; public class RSAEncryptionExample { public static void main(String[] args) throws Exception { String input = "Hello World!"; KeyPair keyPair = generateRSAKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); byte[] encryptedData = rsaEncrypt(input.getBytes(), publicKey); byte[] decryptedData = rsaDecrypt(encryptedData, privateKey); System.out.println("Original data: " + input); System.out.println("Encrypted data: " + new String(encryptedData)); System.out.println("Decrypted data: " + new String(decryptedData)); } public static KeyPair generateRSAKeyPair() throws Exception { KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); generator.initialize(2048); // key size KeyPair keyPair = generator.generateKeyPair(); return keyPair; } public static byte[] rsaEncrypt(byte[] data, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedData = cipher.doFinal(data); return encryptedData; } public static byte[] rsaDecrypt(byte[] data, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedData = cipher.doFinal(data); return decryptedData; } } ``` 这个示例代码中,我们首先生成了一个RSA密钥对,包括公钥和私钥。然后使用公钥对原始数据进行加密,得到加密后的数据。接着使用私钥对加密后的数据进行解密,得到原始数据。 需要注意的是,RSA算法使用的密钥长度越长,安全性就越高,但加解密的速度也越慢。在实际应用中,需要根据实际需求和环境选择合适的密钥长度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值