DES和RSA混合加密及解密-JAVA

DES和RSA混合加密及解密

	实际开发过程中,RSA生成的公钥应保存在加密方,私钥应保存在解密方,可使用读取文件内容方式获取密钥。

maven依赖:

 <!-- DES -->
   <dependency>
         <groupId>javax.xml.rpc</groupId>
         <artifactId>javax.xml.rpc-api</artifactId>
         <version>1.1.1</version>
     </dependency>
     <!-- RSA -->
     <dependency>
         <groupId>org.apache.axis</groupId>
         <artifactId>axis</artifactId>
         <version>1.4</version>
     </dependency>
     <!-- base64 -->
     <dependency>
         <groupId>commons-codec</groupId>
         <artifactId>commons-codec</artifactId>
         <version>1.10</version>
     </dependency>

DES工具类:

package common;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.NoSuchAlgorithmException;

/**
 * @program: Demo
 * @Date: 2019/2/20 20:59
 * @Author: LiJc
 * @Description:
 */
public class DESUtil {
    /**
     *  生成KEY
     */
    public static byte[] getKey(){
        KeyGenerator keyGenerator = null;
        try {
            keyGenerator = KeyGenerator.getInstance("DES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            System.out.println("----------------KEY生成失败!");
            return null;
        }
        keyGenerator.init(56);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] byteKey = secretKey.getEncoded();
        return byteKey;
    }

    /**
     * DES加密
     *
     * @param context
     * @return
     */
    public static byte[] desEncrypt(String context, String key) {
        try {
            // KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey conventSecretKey = secretKeyFactory.generateSecret(desKeySpec);

            // 加密
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, conventSecretKey, new IvParameterSpec(key.getBytes("UTF-8")));
            return cipher.doFinal(context.getBytes("UTF-8"));
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * DES解密
     *
     * @param context
     * @return
     */
    public static byte[] desDecrypt(byte[] context, String key) {
        try {
            // KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey conventSecretKey = secretKeyFactory.generateSecret(desKeySpec);

            // 解密
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, conventSecretKey, new IvParameterSpec(key.getBytes("UTF-8")));
            return cipher.doFinal(context);
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

RSA工具类:

package common;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import javax.crypto.Cipher;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
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;

/**
 * @program: Demo
 * @Date: 2019/2/21 22:56
 * @Author: LiJc
 * @Description:
 */
public class RSAUtil {
    /**
     * 转密钥字符串(base64编码)
     *
     * @return
     */
    public static String getKeyString(Key key) throws Exception {
        byte[] keyBytes = key.getEncoded();
        String s = new String(Base64.encodeBase64(keyBytes));
        return s;
    }

    /**
     * 得到公钥
     * @param publicKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过X509编码的Key指令获得公钥对象
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        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");
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
    }

    /**
     * 生成密钥对
     * @param pubfilePath 公钥存放的文件路径
     * @param prifilePath 私钥存放的文件路径
     */
    public static void genKeyPair(String pubfilePath, String prifilePath) {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // 初始化密钥对生成器,密钥大小为96-1024位
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        try {
            // 得到公钥字符串
            String publicKeyString = getKeyString(publicKey);
            // 得到私钥字符串
            String privateKeyString = getKeyString(privateKey);
            // 将密钥对写入到文件
            FileWriter pubfw = new FileWriter(pubfilePath);
            FileWriter prifw = new FileWriter(prifilePath);
            BufferedWriter pubbw = new BufferedWriter(pubfw);
            BufferedWriter pribw = new BufferedWriter(prifw);
            pubbw.write(publicKeyString);
            pribw.write(privateKeyString);
            pubbw.flush();
            pubbw.close();
            pubfw.close();
            pribw.flush();
            pribw.close();
            prifw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 公钥加密
     * @param data		需要加密的内容
     * @param publicKey	公钥
     * @return
     */
    public static String publicEncrypt(String data, RSAPublicKey publicKey){
        try{
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return new String(Base64.encodeBase64(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes("UTF-8"), 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");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), "UTF-8");
        }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;
    }
}

单元测试:
注意:RSA用到的密钥对为上一篇文章生成的 https://blog.csdn.net/JcMR_Li/article/details/87873079

package common;

import org.apache.commons.codec.binary.Base64;
import org.junit.Test;

import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;

/**
 * @program: Demo
 * @Date: 2019/2/22 10:18
 * @Author: LiJc
 * @Description:
 */
public class DESAndRSATest {


    /**
     * DES和RSA混合加密,先进行DES加密,将DES加密后的内容进行base64编码,再将base64编码的DES进行RSA加密
     */
    @Test
    public void test1() throws InvalidKeySpecException, NoSuchAlgorithmException {
        String deskey = "password";//des密钥//长度8位
        String content = "真香警告!"; //内容
        System.out.println("原始加密内容为:"+content);
        //DES加密
        byte[] encryptbyte =  DESUtil.desEncrypt(content, deskey); //加密后返回为字节数组
        String descontent = Base64.encodeBase64String(encryptbyte);
        System.out.println("DES加密后内容为:"+ descontent);

        //RSA部分start
        String pubkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQ1IqhPNo8M/R1pHpocNuJ6enntJoB7OAaJrVoaHbvJOI4APkheX0J1UKizOGQNRr/V6vp3B+3MrPVGJ4lfRirrgnIK86PD5K/MChSWhxslWf3jQxr7AO8rMIPre7uoGjmY3pbSY82QUGDEhgDVsWTLTjWWqFQHVTwEfBPGgaktQIDAQAB";
        //根据公钥key获取公钥
        RSAPublicKey publicKey =  RSAUtil.getPublicKey(pubkey);
        //RSA加密
        String rsacontent = RSAUtil.publicEncrypt(descontent, publicKey);
        System.out.println("RSA加密后内容为:"+rsacontent);
        String prikey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJDUiqE82jwz9HWkemhw24np6ee0mgHs4BomtWhodu8k4jgA+SF5fQnVQqLM4ZA1Gv9Xq+ncH7cys9UYniV9GKuuCcgrzo8Pkr8wKFJaHGyVZ/eNDGvsA7yswg+t7u6gaOZjeltJjzZBQYMSGANWxZMtONZaoVAdVPAR8E8aBqS1AgMBAAECgYBtteOSApPa2QyM9VyYsy1LCrvafs/PN44HoVz4S3IU9B69h9cxCWOzyC3jP0p7QA9EcDhVPh90Wl8pxK0//sRpWZrKps3ZqCQKogLSHTIaRJvvgQwN26KtIwSoXDwKqpmyhufIhXdFDmSIKb8v8rF3Sl3Mt5I+hDT83fnTjyPUPQJBAOBNObrgZQ7CvMuwtKilWhAqlNbhibfc3k4dtJ+23uixUgHq+WME6w7B0NUixT6ua7v+RKZD1RO9ANDGCEIQzfsCQQClTDPsjrkerRBsXrge6xK2drisIpEFBdYoIz9lYmCHXJctkx5nhLogxxTeAJgFWBIcOgrx5OCYOQgr5p6FikkPAkA45j470sqwCOR9w3DAy1lienrRW9tkwem+5Tg5v9kiLEFCbUogPVInpzEDsFNbCEIaKXFewBxganS3gVT89WhbAkAV90NrKyg0iGEHVar4CNsKvkoaLdnBph3oZY62JVWYh1hbqRJARWYKlwoR2lhZVXPKpnfv3y9tax7H3rSwIElHAkB7j65B6+L8Ty0RiEzHCOVXnUoUTai/BZfQ5erA9yVM/VW8p1mE/qhJOTQ5hFniO0dicl3YZyaYHW1D+Z1V4naO";
        //获取私钥
        RSAPrivateKey privateKey = RSAUtil.getPrivateKey(prikey);
        //RSA解密
        String content1 = RSAUtil.privateDecrypt(rsacontent, privateKey);
        System.out.println("RSA解密后内容为:"+content1);
        //RSA部分end

        //DES解密
        byte[] decryptbyte = DESUtil.desDecrypt(Base64.decodeBase64(content1), deskey);  //将加密后返回的字节数组进行解密
        System.out.println("DES解密后内容为:"+ new String(decryptbyte));
    }
}

测试结果:
在这里插入图片描述

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值