对称加密算法(DES、3DES、AES)

文章目录

DES

  • DES加密算法因现代的计算能力,已经被淘汰掉了,因为现在在24小时内就可以被破解
  • 特点:
    分组加密算法:明文以64位分组,64位明文输入,64位密文输出
    对称算法:加密和解密使用同一密钥
    有效密钥长度为56位:密钥通常表示为64位数,但每个第8位用于奇偶校验,可以忽略
    代替和置换:DES算法是两种加密技术的组合:混合和扩散,先替代后置换
    易于实现: DES算法只是使用了标准的算术和逻辑运算,其作用的数最多也只有64位
  • DES算法简述:
    • (1)输入64位明文数据,进行初始置换:DES算法使用64位密钥Key将64位明文输入块变为64位的密文输出块,并将输出块分为L0、R0两部分,每部分均为32位
    • (2)在密钥的控制下,进行完全相同的16轮运算f,运算过程中总数据和密钥结合,函数f由四步运算构成(ps:以下内容我已经看不懂了):密钥置换、扩展置换、S-盒代替、P-盒置换
    • (3)16轮之后,左右两部分进行交换,再连接到一起,然后再进行逆置换
    • (4)输出64位密文

java代码使用Cipher进行DES加解密


import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;

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.InvalidKeyException;
import java.security.SecureRandom;
import java.util.Locale;

public class DES {
    private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding";
    private static final String ALGORITHM = "DES";
    public static void main(String[] args) {
        try {
            //待加密字符
            String originalStr = "DES最棒了";
            System.out.println("待加密字符:" + originalStr);

            //密钥 密钥必须为8个字节的倍数,否则会报错InvalidKeyException
            String desKey = initDesKey("12345679");
            System.out.println("密钥:" + desKey);

            //进行加密
            String encrypted = encrypt(originalStr, desKey);
            System.out.println("加密结果:" + encrypted);

            //对密文解密
            String decrypted = decrypt(encrypted, desKey);
            System.out.println("密文解密后:" + decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成密钥
     * 密钥既可以通过initDesKey获取,也可以自定义生成(只要保证密钥长度是8的倍数即可)
     */
    private static String  initDesKey(String seed) throws Exception{
        //DES算法要求有一个可信任的随机数源
        SecureRandom secureRandom;
        if (null!=seed && seed.length()!=0) {
            secureRandom = new SecureRandom(HexBin.decode(seed));
        }else {
            secureRandom = new SecureRandom();
        }

        //初始化 Key生成器
        KeyGenerator key=KeyGenerator.getInstance(ALGORITHM);
        key.init(secureRandom);
        //生成一个Key
        SecretKey secretKey = key.generateKey();
        //转换为字节数组
        byte[] encoded = secretKey.getEncoded();
        //生成密钥字符串(16进制)
        return HexBin.encode(encoded);
    }

    /**
     * 加密
     */
    private static String  encrypt(String data,String key) throws Exception{
        //创建一个DESKeySpec对象
        DESKeySpec desKeySpec = createDesKeySpec(key);
        //Cipher加密器
        Cipher cipher = getCipher(desKeySpec, Cipher.ENCRYPT_MODE);
        //获取数据并加密
        return HexBin.encode(cipher.doFinal(data.getBytes())).toUpperCase(Locale.ROOT);

    }

    /**
     * 解密
     */
    private static String decrypt(final String data,String key)throws Exception {
        //创建一个DESKeySpec对象
        DESKeySpec desKeySpec = createDesKeySpec(key);
        //获得一个Cipher
        Cipher cipher = getCipher(desKeySpec, Cipher.DECRYPT_MODE);
        //解密
        return new String(cipher.doFinal(HexBin.decode(data)));
    }

    private static Cipher getCipher(DESKeySpec desKeySpec, int mode) throws Exception {
        //创建一个密钥工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        //将DESKeySpec对象转换为SecretKey对象
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        //Cipher对象实际完成加密解密操作
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        //用密钥初始化Cipher对象
        cipher.init(mode, secretKey, new IvParameterSpec(desKeySpec.getKey()));
        return cipher;
    }

    private static DESKeySpec createDesKeySpec(String key) throws InvalidKeyException {
        //创建一个DESKeySpec对象
        return new DESKeySpec(key.getBytes());
    }

}

运行结果如下:
在这里插入图片描述

3DES

  • 3DES加密算法是对DES算法的改进加强版,它相当于是对每个数据块应用三次DES加密算法
  • 加密流程,图源博主AtlanSI
    在这里插入图片描述
  • 解密流程:图源AtlanSI
    在这里插入图片描述
  • 当3DES中所有的密钥都相同时,3DES等同于普通DES
  • 特点:
    密钥长度增长,通过增加迭代次数提高了数据的安全性
    但处理速度也随之变慢,加密效率不高

java使用Cipher进行3DES加解密

import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;

import javax.crypto.*;
import javax.crypto.spec.DESedeKeySpec;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.util.Locale;

public class DES3 {
    private static final String CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";
    private static final String ALGORITHM = "DESede";
    public static void main(String[] args) {
        try {
            //待加密字符
            String originalStr = "3DES才是最棒的";
            System.out.println("待加密字符:" + originalStr);

            //获取密钥,key长度必须大于等于3*8=24
            String des3Key = initKey("4545454545AAAA");
            System.out.println("密钥长度:" + des3Key.getBytes().length);
            System.out.println("密钥:" + des3Key);

            //加密
            String encrypted = encrypt(originalStr, des3Key);
            System.out.println("加密结果:" + encrypted);

            //解密
            String decrypted = decrypt(encrypted, des3Key);
            System.out.println("解密结果:" + decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成密钥
     */
    public static String initKey(String seed) throws Exception{
        SecureRandom secureRandom;
        if (null!=seed && seed.length()!=0) {
            secureRandom = new SecureRandom(HexBin.decode(seed));
        }else {
            secureRandom = new SecureRandom();
        }

        //初始化 Key生成器
        KeyGenerator key=KeyGenerator.getInstance(ALGORITHM);
        key.init(secureRandom);
        //生成一个Key
        SecretKey secretKey = key.generateKey();
        //转换为字节数组
        byte[] encoded = secretKey.getEncoded();
        //生成密钥字符串(16进制)
        return HexBin.encode(encoded);
    }

    /**
     * 加密
     */
    private static String  encrypt(String data,String key) throws Exception{
        //创建一个DESKeySpec对象
        DESedeKeySpec desEdeKeySpec = createDesKeySpec(key);
        //Cipher加密器
        Cipher cipher = getCipher(desEdeKeySpec, Cipher.ENCRYPT_MODE);
        //获取数据并加密
        return HexBin.encode(cipher.doFinal(data.getBytes())).toUpperCase(Locale.ROOT);
    }

    /**
     * 解密
     */
    private static String decrypt(final String data,String key)throws Exception {
        //创建一个DESKeySpec对象
        DESedeKeySpec deSedeKeySpec = createDesKeySpec(key);
        //获取一个Cipher对象
        Cipher cipher = getCipher(deSedeKeySpec, Cipher.DECRYPT_MODE);
        //解密
        return new String(cipher.doFinal(HexBin.decode(data)));
    }

    private static DESedeKeySpec createDesKeySpec(String key) throws InvalidKeyException {
        //创建一个DESKeySpec对象
        return new DESedeKeySpec(key.getBytes());
    }

    private static Cipher getCipher(DESedeKeySpec deSedeKeySpec, Integer mode) throws Exception{
        // 创建一个密匙工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        // 将 DESedeKeySpec 对象转换成 SecretKey 对象
        SecretKey secureKey = keyFactory.generateSecret(deSedeKeySpec);
        // Cipher对象实际完成解密操作
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        // 用密匙初始化 Cipher对象
        cipher.init(mode, secureKey);
        return cipher;
    }
}

运行结果如下:
在这里插入图片描述

AES

  • AES加密算法被设计为支持128/192/256为密码长度
  • AES加密算法的安全性要高于3DES加密算法,所以现在已经成为了主流的对称加密算法
  • AES加密算法的五个关键词(别问我,我也不知道这五个东西具体是些啥):分组密码体制、Padding、密钥、初始向量IV和四种加密模式
    分组密码体制: 将明文切成一段一段的来加密,然后再把一段一段的密文拼起来形成最终的密文(每组数据的长度必须要求是128位,如果最后一段不够16字节,就需要Padding进行填满)
    Padding: padding就是用来把不满16个字节的分组填满为16个字节,它有三个模式PKCS5(缺几个字节就填充几个字节的5),PKCS7( 缺几个字节就填充几个字节的0),NOPADDING(不需要填充,因为懂事的数据发送方肯定会把证最后一段数据也正好是16个字节)
    初始向量IV: 初始向量IV的作用是使加密更加安全可靠,我们使用AES加密时需要主动提供初始向量,并且只需要提供一个初始向量即可,后面每段数据的加密向量都是前面一段的密文
    密钥: AES要求密钥长度可以是128/192/256位,位数越高,加密强度越大,但同时加密效率也会低一些。使用AES加密时需要主动提供一个密钥,密钥来源位随机生成(我们传入的叫做初始密钥,而后面每一轮的密钥都是由上一轮的密钥扩展而来的,密钥扩展有四个步骤:排列、置换、与轮常量异或、生成下一轮密钥的其他列)
    四种加密模式: ECB(电子密码本模式)、CBC(密码分组链接模式)、CFB、OFB,我们一般使用CBC模式,四种模式除了ECB相对不安全外,其余三种模式的区别并没有那么大

Java使用Cipher进行AES加密

import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

public class AES {
    private static final String CIPHER_MODE = "AES/ECB/PKCS5Padding";
    private static final String ALGORITHM = "AES";
    public static void main(String[] args) {
        try {
            //待加密字符
            String originalStr = "AES才是最最厉害的";
            System.out.println("待加密字符:" + originalStr);

            //获取密钥
            String aesKey = initAesKey(null);
            System.out.println("密钥:" + aesKey);

            //进行加密
            String encrypted = encrypt(originalStr, aesKey);
            System.out.println("加密结果:" + encrypted);

            //进行解密
            String decrypted = decrypt(encrypted, aesKey);
            System.out.println("解密结果:" + decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    /**
     * 生成密钥
     */
    public static String initAesKey(String seed) throws Exception {
        SecureRandom secureRandom;
        if (null!=seed && seed.length()!=0) {
            secureRandom = new SecureRandom(HexBin.decode(seed));
        } else {
            secureRandom = new SecureRandom();
        }
        // 初始化 key生成器
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
        // 要生成多少位,只需要修改这里即可 128, 192 或 256,单位 bit
        kg.init(128, secureRandom);
        // 生成一个Key
        SecretKey secretKey = kg.generateKey();
        // 转变为字节数组
        byte[] encoded = secretKey.getEncoded();
        // 生成密钥字符串
        return HexBin.encode(encoded);
    }

    /**
     * AES加密
     */
    public static String encrypt(String data, String key)throws Exception {
        Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE);
        return HexBin.encode(cipher.doFinal(data.getBytes())).toUpperCase();
    }

    /**
     * AES解密
     */
    public static String decrypt(String data, String key) throws Exception{
        Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE);
        return new String(cipher.doFinal(HexBin.decode(data)));
    }

    private static Cipher getCipher(String key, Integer mode) throws Exception {
        // 创建密匙
        SecretKey secretKey = new SecretKeySpec(HexBin.decode(key), ALGORITHM);
        // Cipher 对象实际完成解密操作
        Cipher cipher = Cipher.getInstance(CIPHER_MODE);
        // 用密匙初始化 Cipher 对象
        cipher.init(mode, secretKey);
        return cipher;
    }

}

运行结果
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值