java中加解密合集

1.背景

项目过程中遇到很多需要加密和解密的数据,用于记录学习

2.对称加密和非对称加密

3.对称加密

对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥加密,这种方法在密码学中叫做对称加密算法,对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高。常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES

4.非对称加密

非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。
公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法


5.区别

1、加密和解密过程不同
对称加密的加密过程和解密过程使用的同一个密钥,加密过程相当于用原文+密钥可以传输出密文,同时解密过程用密文-密钥可以推导出原文。
但非对称加密采用了两个密钥,一般使用公钥进行加密,使用私钥进行解密。

2、加密解密速度不同
对称加密解密的速度比较快,适合数据比较长时的使用。
非对称加密和解密花费的时间长、速度相对较慢,只适合对少量数据的使用。

3、传输的安全性不同
对称加密的过程中无法确保密钥被安全传递,密文在传输过程中是可能被第三方截获的,如果密码本也被第三方截获,则传输的密码信息将被第三方破获,安全性相对较低。
非对称加密算法中私钥是基于不同的算法生成不同的随机数,私钥通过一定的加密算法推导出公钥,但私钥到公钥的推导过程是单向的,也就是说公钥无法反推导出私钥。所以安全性较高。

6、例子

6.1 DES加解密

DES 全称 Data Encryption Standard(数据加密标准),作为算法的DES称为数据加密算法(Data Encryption Algorithm, DEA),已与作为标准的DES区分开来

 

package com.cloud.user;

import java.security.Key;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;

public class DESUtil {
    public static Key setKey(String strKey) {
        Key key = null;
        try {
            KeyGenerator generator = KeyGenerator.getInstance("DES");
            generator.init(new SecureRandom(strKey.getBytes())); // 根据参数生成key
            key = generator.generateKey();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return key;
    }

    /**
     * @param source  编码内容
     * @param key     密钥
     * @param charSet 编码格式
     * @return
     */
    public static String encrypt(String source, String key, String charSet) {
        String encrypt = null;
        try {
            byte[] ret = encrypt(source.getBytes(charSet), key);
            encrypt = new String(Base64.getEncoder().encode(ret));
        } catch (Exception e) {
            e.printStackTrace();
            encrypt = null;
        }
        return encrypt;
    }

    /**
     * @param encryptedData 解码内容
     * @param key           密钥
     * @param charSet       编码格式
     * @return
     */
    public static String decrypt(String encryptedData, String key, String charSet) {
        String descryptedData = null;
        try {
            byte[] ret = descrypt(Base64.getDecoder().decode(encryptedData.getBytes()), key);
            descryptedData = new String(ret, charSet);
        } catch (Exception e) {
            e.printStackTrace();
            descryptedData = null;
        }
        return descryptedData;
    }

    private static byte[] encrypt(byte[] primaryData, String key) {
        Key desKey = setKey(key);
        try {
            Cipher cipher = Cipher.getInstance("DES"); // Cipher对象实际完成加密操作
            cipher.init(Cipher.ENCRYPT_MODE, desKey); // 用密钥初始化Cipher对象(加密)
            return cipher.doFinal(primaryData);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static byte[] descrypt(byte[] encryptedData, String key) {
        Key desKey = setKey(key);
        try {
            Cipher cipher = Cipher.getInstance("DES"); // Cipher对象实际完成解密操作
            cipher.init(Cipher.DECRYPT_MODE, desKey); // 用密钥初始化Cipher对象(解密)
            return cipher.doFinal(encryptedData);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        String code = "hello";
        String key = "thisisakey";
        String unicode = "utf-8";
        String encrypt = encrypt(code, key, unicode);
        String decrypt = decrypt(encrypt, key, unicode);
        System.out.println("原内容:" + code);
        System.out.println("加密:" + encrypt);
        System.out.println("解密:" + decrypt);
    }
}

6.2  3DES加解密

三重数据加密算法(英语:Triple Data Encryption Algorithm,缩写为TDEA,Triple DEA),或称3DES(Triple DES),是一种对称密钥加密块密码,相当于是对每个数据块应用三次DES算法。由于计算机运算能力的增强,原版DES由于密钥长度过低容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。

 

添加依赖

<dependency>
   <groupId>io.lions</groupId>
   <artifactId>LionsUtils</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <exclusions>
      <exclusion>
         <groupId>cn.ccvnc</groupId>
         <artifactId>commons-logging</artifactId>
      </exclusion>
      <exclusion>
         <groupId>cn.ccvnc</groupId>
         <artifactId>slf4j-log4j12</artifactId>
      </exclusion>
   </exclusions>
</dependency>

工具类

package com.cloud.common.util;

import io.lions.security.encryption.bidirectional.DESede;

/**
 * 常量工具类
 */
public class ConstantUtils {

    /**
     * 加密
     */
    public static final DESede DES = new DESede();

 
    /**
     * 加密盐
     */
    public static final String SALT = "@321Dr0wSsaP111";

   
}

测试

package com.cloud.user;

import com.cloud.common.util.ConstantUtils;

public class Demo3DES {


    public static void main(String[] args) throws Exception {
        System.out.println("------加密-------");
        String mingwen = "admin1";
        encrypt(mingwen);
        System.out.println("------解密-------");
        String miwen = "W6%2FfyeyMdWEI32ZCPTHLAw%3D%3D";
        decrypt(miwen);

    }

    public static void encrypt(String str) {
        String desEncrypt = ConstantUtils.DES.get3DESEncrypt(str, ConstantUtils.SALT);
        System.out.println(desEncrypt);
    }


    public static void decrypt(String str) {
        String desDecrypt = ConstantUtils.DES.get3DESDecrypt(str, ConstantUtils.SALT);
        System.out.println(desDecrypt);
    }



}

6.3 md5单向加密

MD5是一种单向加密算法,只能加密不能解密

MD5 主要用做数据一致性验证、数字签名和安全访问认证,而不是用作加密

 

package com.cloud.user;

import org.springframework.util.DigestUtils;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Util {
    /**
     * java自带jar工具 java.security.MessageDigest 实现
     *
     * @param text  要加密的字符串
     * @param rad   进制:比如 16、32
     * @param isUpp 是否转换为大写
     * @return
     */
    public static String strToMD5(String text, int rad, boolean isUpp) {
        MessageDigest messageDigest = null;
        try {
            //通过MessageDigest类来的静态方法getInstance获取MessageDigest对象
            messageDigest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // 4、获取明文字符串对应的字节数组
        byte[] input = text.getBytes();
        // 5、执行加密
        messageDigest.update(input);
        //这里也可以直接使用byte[] output = messageDigest.digest(input)方法来进行加密,就省略了上面的update方法了
        byte[] output = messageDigest.digest();
        // 6、创建BigInteger对象
        // signum为1表示正数、-1表示负数、0表示0。不写默认表示正数
        int signum = 1;
        BigInteger bigInteger = new BigInteger(signum, output);
        // 7、按照16进制(或32进制)将bigInteger转为字符串
        return isUpp ? bigInteger.toString(rad).toUpperCase() : bigInteger.toString(rad);
    }

    /**
     * spring自带的工具 org.springframework.util.DigestUtils 实现
     * @param text
     * @return 16进制
     */
    public static String _strToMD5(String text) {
        return DigestUtils.md5DigestAsHex(text.getBytes());
    }

    public static void main(String[] args) {
        String str = "hello";
        System.out.println(strToMD5(str, 16, true));
        System.out.println(_strToMD5(str));
        System.out.println(strToMD5(str, 16, false).equals(_strToMD5(str)));
    }
}

6.4 Base64加解密

Java 8 内置编码器和解码器。
static class Base64.Decoder:解码器,使用 Base64 编码来解码字节数据。
static class Base64.Encoder:编码器,使用 Base64 编码来编码字节数据。

 

package com.cloud.user;

import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.UUID;

public class Base64Util {
    public static void main(String[] args) throws Exception {
        String text = "hello";
        try {
            /**
             * static Base64.Encoder getEncoder()
             * 返回一个 Base64.Encoder ,编码使用基本型 base64 编码方案。
             */
            String base64encodedString = Base64.getEncoder().encodeToString(text.getBytes("utf-8"));
            System.out.println("Base64 编码字符串 (基本) :" + base64encodedString);

            /**
             * static Base64.Decoder getDecoder()
             * 返回一个 Base64.Decoder ,解码使用基本型 base64 编码方案。
             */
            byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);
            System.out.println("原始字符串: " + new String(base64decodedBytes, "utf-8"));

            /**
             * static Base64.Encoder getUrlEncoder()
             * 返回一个 Base64.Encoder ,编码使用 URL 和文件名安全型 base64 编码方案。
             */
            base64encodedString = Base64.getUrlEncoder().encodeToString(text.getBytes("utf-8"));
            System.out.println("Base64 编码字符串 (URL) :" + base64encodedString);

            /**
             * static Base64.Decoder getUrlDecoder()
             * 返回一个 Base64.Decoder ,解码使用 URL 和文件名安全型 base64 编码方案。
             */
            byte[] base64decodedBytes2 = Base64.getUrlDecoder().decode(base64encodedString);
            System.out.println("原始字符串: " + new String(base64decodedBytes2, "utf-8"));

            StringBuilder stringBuilder = new StringBuilder();

            for (int i = 0; i < 10; ++i) {
                stringBuilder.append(UUID.randomUUID().toString());
            }

            byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
            String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
            System.out.println("Base64 编码字符串 (MIME) :" + mimeEncodedString);

        } catch (UnsupportedEncodingException e) {
            System.out.println("Error :" + e.getMessage());
        }
    }
}

6.5  AES加解密

AES 与 DES 一样,一共有四种加密模式:电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)

 

package com.cloud.user;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESUtil {
    //指定为AES算法,不区分大小写
    private static final String KEY_ALGORITHM = "AES";
    private static final String CHARSET_NAME = "utf-8";

    /*
     * 加密 1.构造密钥生成器 2.根据ecnodeRules规则初始化密钥生成器 3.产生密钥 4.创建和初始化密码器 5.内容加密 6.返回字符串
     */
    public static String AESEncode(String encodeRules, String content) {
        try {
            // 1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance(KEY_ALGORITHM);
            // 2.根据ecnodeRules规则初始化密钥生成器
            // 生成一个128位的随机源,根据传入的字节数组
            //keygen.init(128, new SecureRandom(encodeRules.getBytes()));
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(encodeRules.getBytes());
            keygen.init(128, secureRandom);
            // 3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            // 4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            // 5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, KEY_ALGORITHM);
            // 6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            // 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key);
            // 8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byte_encode = content.getBytes(CHARSET_NAME);
            // 9.根据密码器的初始化方式--加密:将数据加密
            byte[] byte_AES = cipher.doFinal(byte_encode);
            // 10.将加密后的数据转换为字符串
            // 这里用Base64Encoder中会找不到包
            // 解决办法:
            // 在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
            String AES_encode = new String(Base64.getEncoder().encodeToString(byte_AES));
            // 11.将字符串返回
            return AES_encode;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 如果有错就返加nulll
        return null;
    }

    /*
     * 解密 解密过程: 1.同加密1-4步 2.将加密后的字符串反纺成byte[]数组 3.将加密内容解密
     */
    public static String AESDncode(String encodeRules, String content) {
        try {
            // 1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance(KEY_ALGORITHM);
            // 2.根据ecnodeRules规则初始化密钥生成器
            // 生成一个128位的随机源,根据传入的字节数组
            //keygen.init(128, new SecureRandom(encodeRules.getBytes()));
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(encodeRules.getBytes());
            keygen.init(128, secureRandom);
            // 3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            // 4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            // 5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, KEY_ALGORITHM);
            // 6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            // 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.DECRYPT_MODE, key);
            // 8.将加密并编码后的内容解码成字节数组
            byte[] byte_content = Base64.getDecoder().decode(content);
            /*
             * 解密
             */
            byte[] byte_decode = cipher.doFinal(byte_content);
            String AES_decode = new String(byte_decode, CHARSET_NAME);
            return AES_decode;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }

        // 如果有错就返加nulll
        return null;
    }

    public static void main(String[] args) {
        String encodeRules = "rule";
        String text = "hello";
        String encodeText = AESEncode(encodeRules, text);
        System.out.println("加密后的密文是:" + encodeText);
        System.out.println("解密后的内容是:" + AESDncode(encodeRules, encodeText));
    }
}

6.6 非对称加密——RSA

RSA密钥对生成:http://web.chacuo.net/netrsakeypair
在线加密解密:在线加密解密 - chahuo.com
RSA算法是一种非对称加密算法,RSA 加密主要有这么几步:生成密钥对、公开公钥、公钥加内容加密、私钥+加密公钥解密。

 

package com.cloud.user;

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

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSAUtil {
    private static final String CHARSET_NAME = "utf-8";
    private static final String TYPE = "RSA";

    /**
     * RSA公钥加密
     *
     * @param str       加密字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception 加密过程中的异常信息
     */
    public static String encrypt(String str, String publicKey) throws Exception {
        //base64编码的公钥
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(TYPE).generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance(TYPE);
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes(CHARSET_NAME)));
        return outStr;
    }

    /**
     * RSA私钥解密
     *
     * @param str        加密字符串
     * @param privateKey 私钥
     * @return 铭文
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception {
        //64位解码加密后的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes(CHARSET_NAME));
        //base64编码的私钥
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(TYPE).generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance(TYPE);
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte));
        return outStr;
    }

    public static void main(String[] args) throws Exception {
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKalqxfHXrZ0JZdLd2+BLhNS6bZxVyCOXvzFd0xCyX4oX/IbglKp9BGxQYaNl7stlHkQmMYBTAkIj0mAQzOVkqisYDevxKA5Yeitnim8R+N+a1SYaoQCfHLbCmMg4ZP0xaC30rA3DSMbEWQTD7p/g6v3sZevQUDVUcge9oaif9AQIDAQAB";
        String privateKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMpqWrF8detnQll0t3b4EuE1LptnFXII5e/MV3TELJfihf8huCUqn0EbFBho2Xuy2UeRCYxgFMCQiPSYBDM5WSqKxgN6/EoDlh6K2eKbxH435rVJhqhAJ8ctsKYyDhk/TFoLfSsDcNIxsRZBMPun+Dq/exl69BQNVRyB72hqJ/0BAgMBAAECgYEAwOZKOArcddKaMJZCoWYY1/bOy9qZXWuNddHPJsAtnzGJcXK5AvJzgqBDrl99o5z15HYcG2MVY85aNn8IwahNh8CpFF8At7O2hVz1sTER2MPeiV5324BGOCPUkT4lY2iT2Dq6hXraZDI9sovit4FnfFlWH9nMOV5ckBvm5ypcCoECQQD/YLgSqXEERuu5qjU+PBCBKqbtOq5+EBNwLb9isxTPjRPoQ98sEzWsbyeLrc73Cjql5vU1io9rsG3IiYdEvFn9AkEAyuiaK95pbILOqK096d3Gt9oz0fqc5K4c9V44anaFzkEOysZlO3o1iZxqjfHdBlJiE4j0fq52+s+L9riqFbNMVQJATL3V0tXUPoLJZ3u8kD0ggJA+pV9S/FL8ZGN69b/26v/sEYoD0IzdPjoQ2iqa3SXXxe8HlNVUj/nuo6qgWYl4SQJBAJsXsYfoh7JeRXHegV15m8O5sDRGl5efkhjmfL67e0kMpy7M+GG+5p8ZhMScYzHK1JZT73XJCr5o13Ws7qyJkMUCQQD2EaVPOG+5M0VbzGGG820NRk9omSwO3GdSf4HZ6JWmeGk0FJN4NfAHnD8nA5L/HP+muqCdYQtYD068oZrNSabP";
        String text = "hello";
        String encodeText = encrypt(text, publicKey);
        System.out.println("加密后:" + encodeText);
        System.out.println("解密后:" + decrypt(encodeText, privateKey));
    }
}

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值