对称加密算法-详解测试DEMO

一,概述

        前面讲解了大体通用的对称,非对称,MD系列等加密算法。

       见前面 我的博客文:  https://blog.csdn.net/Mynah886/article/details/82787683

但感觉还是不能直观的让开发者来直接爽起来。最近又看到了其他人分享的,自己项目正好又要涉及使用了。故此重新细化下。供使用时候直接拿来!

         对称加密算法就是传统的用一个密码进行加密和解密。就像我们常用的WinZIP && WinRAR 对压缩包的加密和解密,就是使用对称加密算法。

        代表算法/实现方式:

              1) DES(Data Encryption standard)数据加密标准   3DES, 密钥长度一般 56/64.  DES算法由于密钥过短,可以在短时间内被暴力破解,所以现在已经不安全了

              2) AES高级DES替代者(工作模式:ECB, CBC, PCBC, CTR, CFB8~128... 填充方式:NoPadding, PKCS5Padding, ISO10126Padding...), 密钥长度一般 128/192/256.

              3) RC4/5/6算法: 是参数可变的分组密码算法,三个可变的参数是:分组大小、密钥大小和加密轮数; 加密时使用了2r+2个密钥相关的的32位字: 这里r表示加密的轮数。

               4) Blowfish算法: 每次加密一个64位分组,使用32位~448位的可变长度密钥,应用于内部加密,输入64位明文,输出64位密文。加密过程分为两个阶段:密钥预处理和信息加密。 自从32位处理器诞生后,blowfish加密算法在加密速度上就超越了DES加密算法,引起了人们的关注。blowfish加密算法没有注册专利,不需要授权,可以免费使用

               5) PBE(Password Based Encryption)基于口令加密 = 口令+盐

               6)IDEA,早于AES替代出来取代DES. 密钥长度128 . 工作模式:ECB, 填充方式:PKCS5Padding/PKCS7Padding/... 。实现方式有Bouncy Castle

              注意: 密钥长度直接决定加密强度,而工作模式和填充模式可以看成是对称加密算法的参数和格式选择。Java标准库提供的算法实现并不包括所有的工作模式和所有填充模式,但是通常我们只需要挑选常用的使用就可以了。

 

          从程序的角度看,所谓加密,就是这样一个函数,它接收密码和明文,然后输出密文:

secret = encrypt(key, message);

          而解密则相反,它接收密码和密文,然后输出明文:

plain = decrypt(key, secret);

 

二, 开发DEMO

2.1 我们先用AES加密算法 && ECB模式加密并解密。

    Java标准库提供的对称加密接口非常简单,使用时按以下步骤编写代码:

  1. 根据算法名称/工作模式/填充模式获取Cipher实例;

  2. 根据算法名称初始化一个SecretKey实例,密钥必须是指定长度;

  3. 使用SerectKey初始化Cipher实例,并设置加密或解密模式;

  4. 传入明文或密文,获得密文或明文。

/**
 * desc- 对称加密,ECB模式加密并解密
 * 加密算法  AES, 填充方式 ECB
 * auth  xupengfei
 *
 * @param key 加密key
 * @param input 需要加密的字节数组
 * @return 加密后的字节数组
 */
public static byte[] encrypt( byte[] key,  byte[] input) {
        byte[] result = null;
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            SecretKey keySpec = new SecretKeySpec(key, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);
            result = cipher.doFinal(input);
        }catch (Exception ex){
            log.error("EX-------- {}", ex);
        }
        return result;
}
/**
 * desc 对称 解密,ECB模式加密并解密
 * 加密算法  AES, 填充方式 ECB
 * auth  xupengfei
 *
 * @param key 加密key
 * @param input 需要解密的字节数组
 * @return 解密后的字节数组
 * @throws GeneralSecurityException
 */
public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return cipher.doFinal(input);
}
/**
 *  测试类
 * @param args
 * @throws Exception
 */
@Test
public void testAesECB() throws Exception {
    // 原文:
    String message = "Hello world,I am DCONE member, please call me mynah!";
    log.debug("Message: " + message);
    // 128位密钥 = 16 bytes Key:
    byte[] key = "xupengfei1234567".getBytes("UTF-8");
    // 加密:
    byte[] data = message.getBytes("UTF-8");
    byte[] encrypted = encrypt(key, data);
    log.debug("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));
    // 解密:
    byte[] decrypted = decrypt(key, encrypted);
    log.debug("Decrypted: " + new String(decrypted, "UTF-8"));
}

2.1  测试结果如下:

 

2.2  ECB模式是最简单的AES加密模式,它只需要一个固定长度的密钥,固定的明文会生成固定的密文,这种一对一的加密方式会导致安全性降低,更好的方式是通过CBC模式,它需要一个随机数作为IV参数,这样对于同一份明文,每次生成的密文都不同。        

        在CBC模式下,需要一个随机生成的16字节IV参数,必须使用 SecureRandom 生成。因为多了一个IvParameterSpec实例,因此,初始化方法需要调用Cipher的一个重载方法并传入IvParameterSpec。 可以发现每次生成的IV不同,密文也不同。

/**
 * desc 对称加密, CBC 模式加密并解密
 * 加密算法  AES, 填充方式 CBC
 * auth  xupengfei
 *
 * @param key
 * @param input
 * @return
 * @throws GeneralSecurityException
 */
public static byte[] encrypt2(byte[] key, byte[] input) throws GeneralSecurityException {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
    // CBC模式 要生成一个 16bytes 的initialization vector
    SecureRandom sr = SecureRandom.getInstanceStrong();
    byte[] iv = sr.generateSeed(16);
    IvParameterSpec ivps = new IvParameterSpec(iv);
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
    byte[] data = cipher.doFinal(input);
    // IV不需要保密,把 IV && 密文一起返回
    return join(iv, data);
}
/**
 * desc 对称 解密,CBC模式加密并解密
 * 加密算法  AES, 填充方式 CBC
 * auth  xupengfei
 *
 * @param key
 * @param input
 * @return
 * @throws GeneralSecurityException
 */
public static byte[] decrypt2(byte[] key, byte[] input) throws GeneralSecurityException {
    // 把 入参input 分割成:  IV && 密文
    byte[] iv = new byte[16];
    byte[] data = new byte[input.length - 16];
    System.arraycopy(input, 0, iv, 0, 16);
    System.arraycopy(input, 16, data, 0, data.length);
    // 解密
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
    IvParameterSpec ivps = new IvParameterSpec(iv);
    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
    return cipher.doFinal(data);
}
/**
 *
 *
 * @param bs1
 * @param bs2
 * @return
 */
public static byte[] join(byte[] bs1, byte[] bs2) {
    byte[] r = new byte[bs1.length + bs2.length];
    System.arraycopy(bs1, 0, r, 0, bs1.length);
    System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
    return r;
}
/**
 * 测试类 CBC 模式
 *
 * @param args
 * @throws Exception
 */
@Test
public void testAesCBC() throws Exception {
    // 明文
    String message = "Hello world,I am DCONE member, please call me mynah, ouye!";
    log.debug("Message: " + message);
    // 256位密钥 = 32 bytes Key:
    byte[] key = "0123456789abcdef0123456789abcdef".getBytes("UTF-8");
    // 加密
    byte[] data = message.getBytes("UTF-8");
    byte[] encrypted = encrypt(key, data);
    log.debug("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));
    // 解密
    byte[] decrypted = decrypt(key, encrypted);
    log.debug("Decrypted: " + new String(decrypted, "UTF-8"));
}

2.2  测试结果如下:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值