java

java——加密、解密算法

Nick · 6月24日 · 2021年 · 本文8368字 · 阅读21分钟122

概述

在项目开发中,我们常需要用到加解密算法,加解密算法主要分为三大类:

三大类加密算法

1、对称加密算法,如:AES、DES、3DES

2、非对称加密算法,如:RSA、DSA、ECC

3、散列算法,如:MD5、SHA1、HMAC

各算法对比

  1. 对称加密算法(加解密密钥相同)
    java——加密、解密算法-左眼会陪右眼哭の博客
  2. 非对称算法(加密密钥和解密密钥不同)
    java——加密、解密算法-左眼会陪右眼哭の博客
  3. 散列算法比较
    java——加密、解密算法-左眼会陪右眼哭の博客
    对称与非对称算法比较
    java——加密、解密算法-左眼会陪右眼哭の博客

对称加密和非对称加密的区别

  • 对称加密: 加密和解密的秘钥使用的是同一个.
  • 非对称加密: 与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。

  1. 对称加密算法: 密钥较短,破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,且对计算机性能要求也没有那么高。
优点:
算法公开、计算量小、加密速度快、加密效率高
缺点:
在数据传送前,发送方和接收方必须商定好秘钥,然后 使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。
  2. 非对称加密算法: 公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。
优点:
安全
缺点:
速度较慢

项目中常用总结

对称加密: DES(56位)、AES(128位),

非对称加密: ECC(160位)或RSA(1024),

消息摘要: MD5

数字签名:DSA

其中,AES和MD5最为常用。

代码示例

添加第三方包的依赖:项目用到两个第三方包,在pom中添加这两个包的依赖:

<!-- 添加加解密算法的依赖 --> 
<dependency> 
    <groupId>org.apache.commons</groupId> 
    <artifactId>commons-lang3</artifactId> 
    <version>3.4</version> 
</dependency> 
<dependency> 
    <groupId>org.apache.directory.studio</groupId>             
    <artifactId>org.apache.commons.codec</artifactId> 
    <version>1.8</version> 
</dependency>

AES、DES加密示例

  1. 加密工具类(EncryptUtil.java)
package cn.kt.aesdemo.utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
//引入第三方包
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
/**
 * Created by tao.
 * Date: 2021/6/15 9:37
 * 描述:
 */
public class EncryptUtil {

    //--------------AES---------------
    private static final String KEY = "1234567812345678";  // 密匙,必须16位
    private static final String OFFSET = "1234567812345678"; // 偏移量
    private static final String ENCODING = "UTF-8"; // 编码
    private static final String ALGORITHM = "AES"; //算法
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; // 默认的加密算法,CBC模式

    //--------------DES---------------
    /*private static final String KEY = "12345678";  // 密匙,必须8位
    private static final String OFFSET = "12345678"; // 偏移量
    private static final String ENCODING = "UTF-8"; // 编码
    private static final String ALGORITHM = "DES"; //算法
    private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding"; // 默认的加密算法,CBC模式*/

    public static String AESencrypt(String data) throws Exception {
        //指定算法、获取Cipher对象(DES/CBC/PKCS5Padding:算法为,工作模式,填充模式)
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        //根据自定义的加密密匙和算法模式初始化密钥规范
        SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("ASCII"), ALGORITHM);
        //CBC模式偏移量IV
        IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
        //初始化加密模式
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        //单部分加密结束,重置Cipher
        byte[] encrypted = cipher.doFinal(data.getBytes(ENCODING));
        //加密后再使用BASE64做转码
        return new Base64().encodeToString(encrypted);
    }

    /**
     * AES解密
     *
     * @param data
     * @return String
     * @author tao
     * @date 2021-6-15 16:46:07
     */
    public static String AESdecrypt(String data) throws Exception {
        //指定算法、获取Cipher对象(DES/CBC/PKCS5Padding:算法为,工作模式,填充模式)
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        //根据自定义的加密密匙和算法模式初始化密钥规范
        SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("ASCII"), ALGORITHM);
        //CBC模式偏移量IV
        IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
        //初始化解密模式
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        //先用base64解码
        byte[] buffer = new Base64().decode(data);
        //单部分加密结束,重置Cipher
        byte[] encrypted = cipher.doFinal(buffer);
        return new String(encrypted, ENCODING);
    }
  1. 测试方法类
    @Test
    void AESencrypt() throws Exception {
        String str = "123456789";
        System.out.println("加密前:" + str);
        String aeSencrypt = EncryptUtil.AESencrypt(str);
        System.out.println("加密后:" + aeSencrypt);
        String aesCecrypt = EncryptUtil.AESdecrypt(aeSencrypt);
        System.out.println("解密后:" + aesCecrypt);

    }

    @Test
    void AEDencrypt() throws Exception {
        String str = "Lkkl95IF0IM";
        String aesCecrypt = EncryptUtil.AESdecrypt(str);
        System.out.println("解密后:" + aesCecrypt);
    }
  1. 测试效果
    java——加密、解密算法-左眼会陪右眼哭の博客

MD5加密示例

  1. 加密工具类(MD5Util.java)
package cn.kt.aesdemo.utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
//引入第三方包
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
/**
 * Created by tao.
 * Date: 2021/6/15 9:37
 * 描述:
 */
public class MD5Util{
    //---------------MD5-------------------
    private static final String MD5KEY = "1205529635";  // 密匙
    /**
     * MD5方法
     *
     * @param text 明文
     * @return 密文
     * @author tao
     * @date 2021-6-15 16:54:42
     */
    public static String MD5encrypt(String text) throws Exception {
        //加密后的字符串
        String encodeStr = DigestUtils.md5Hex(text + MD5KEY);
        return encodeStr;
    }

    /**
     * MD5验证方法
     *
     * @param text 明文
     * @param md5  密文
     * @return true/false
     * @author tao
     * @date 2021-6-16 15:32 :56
     */
    public static boolean verify(String text, String md5) throws Exception {
        //根据传入的密钥进行验证
        String md5Text = MD5encrypt(text);
        if (md5Text.equalsIgnoreCase(md5)) {
            return true;
        }
        return false;
    }
}
  1. 测试方法
@Test
    void MD5encrypt() throws Exception {
        System.out.println(System.currentTimeMillis());
        String str = "1205529635";
        System.out.println("加密前:" + str);
        String md5 = EncryptUtil.MD5encrypt(str);
        System.out.println("加密后:" + md5);

        //MD5校验
        boolean verify = EncryptUtil.verify(str, md5);
        System.out.println("校验结果:" + verify);  //true
    }
  1. 测试效果
    java——加密、解密算法-左眼会陪右眼哭の博客

RSA加密示例

  1. 加密工具类(RSAUtil.java)
package cn.kt.aesdemo.utils;
import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
 * Created by tao.
 * Date: 2021/6/24 14:20
 * 描述:
 */
public class RSAUtil {
    /* 指定加密算法为DESede */
    private static String ALGORITHM = "RSA";
    /* 指定key的大小 */
    private static int KEYSIZE = 1024;
    /* 指定公钥存放文件 */
    private static String PUBLIC_KEY_FILE = "1205529635";
    /* 指定私钥存放文件 */
    private static String PRIVATE_KEY_FILE = "13767661359";

    /**
     * 生成密钥对
     */
    private static void generateKeyPair() throws Exception {
        /* RSA算法要求有一个可信任的随机数源 */
        SecureRandom sr = new SecureRandom();
        /* 为RSA算法创建一个KeyPairGenerator对象 */
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
        /* 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
        kpg.initialize(KEYSIZE, sr);
        /* 生成密匙对 */
        KeyPair kp = kpg.generateKeyPair();
        /* 得到公钥 */
        Key publicKey = kp.getPublic();
        /* 得到私钥 */
        Key privateKey = kp.getPrivate();
        /* 用对象流将生成的密钥写入文件 */
        ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
        ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
        oos1.writeObject(publicKey);
        oos2.writeObject(privateKey);
        /* 清空缓存,关闭文件输出流 */
        oos1.close();
        oos2.close();
    }

    /**
     * 公钥加密方法
     * source: 源数据
     */
    public static String publicEncrypt(String source) throws Exception {
        generateKeyPair();
        /* 将文件中的公钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();
        /* 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] b = source.getBytes();
        /* 执行加密操作 */
        byte[] b1 = cipher.doFinal(b);
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b1);
    }

    /**
     * 私钥加密方法
     * source: 源数据
     */
    public static String privateEncrypts(String source) throws Exception {
        generateKeyPair();
        /* 将文件中的公钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();
        /* 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] b = source.getBytes();
        /* 执行加密操作 */
        byte[] b1 = cipher.doFinal(b);
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b1);
    }

    /**
     * 私钥解密算法
     * cryptograph:密文
     */
    public static String privateDecrypt(String cryptograph) throws Exception {
        /* 将文件中的私钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
        Key key = (Key) ois.readObject();
        /* 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] b1 = decoder.decodeBuffer(cryptograph);
        /* 执行解密操作 */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }

    /**
     * 公钥解密算法
     * cryptograph:密文
     */
    public static String publicDecrypt(String cryptograph) throws Exception {
        /* 将文件中的私钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
        Key key = (Key) ois.readObject();
        /* 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] b1 = decoder.decodeBuffer(cryptograph);
        /* 执行解密操作 */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }

     public static void main(String[] args) throws Exception {
        String source = "干嘛这么想不开,要在脸上贴个输字!";//要加密的字符串
        System.out.println("源数据:" + source);
        String cryptograph = publicEncrypt(source);//生成的密文
        System.out.println("生成的密文:" + cryptograph);
        String target = privateDecrypt(cryptograph);//解密密文
        System.out.println("解密密文:" + target);
    }
}
  1. 测试方法
    直接运行上面的main函数即可
  2. 测试效果
    java——加密、解密算法-左眼会陪右眼哭の博客
0 条回应
在线人数:1人
隐藏