对称加密算法DES、DESede、AES

192 阅读3分钟

对称密码体制中大部分加密算法属于分组密码,而分组密码是每次只能处理特定长度的一块数据的一类密码算法,这里的“一块”就称为分组。此外,一个分组的比特数就称为分组长度。
对称密码中的DES和DESede算法的分组长度都是64比特,因此它们一次只能加密64比特的明文并生成64比特的密文。AES算法的分组长度为128比特,因此AES一次可加密128比特的明文并生成128比特的密文。
分组密码算法只能加密固定长度的分组,但是我们需要加密的明文长度可能会超过分组密码的分组长度,这时就需要对分组密码算法进行迭代,以便将一段很长的明文全部加密。而迭代的方法就称为分组密码的模式
大家可能会有疑问:"如果明文很长,将明文分割成若干个分组再逐个加密不就好了吗?”事实上可没有那么简单。将明文分割成多个分组并逐个加密的方法称为ECB模式,这种模式具有极大的安全隐患。因此要记住千万不能使用ECB模式。
模式有很多种类,分组密码的主要模式有以下5种:

  • ECB模式:Electronic CodeBook mode
  • CBC模式:Cipher Block Chaining mode
  • CFB模式:Cipher FeedBack mode
  • OFB模式:Output FeedBack mode
  • CTR模式:CounTeR mode

1973年NIST征求国家密码标准方案,IBM公司提交了自己研制的算法(Luciffer算法),1977年该算法被正式采纳,成为事实标准,即数据加密标准(Data Encryption Standard,DES),DES算法由此诞生。DES算法密钥偏短仅有56位,迭代次数偏少,后来又能被暴力破解,因此现在已经不再使用。
作为DES算法的一种改良,DESede算法针对其密钥长度偏短和迭代次数偏少等问题作了相应改进,提高了安全强度。DESede算法处理速度较慢,密钥计算时间较长,加密效率不高等问题使得也不鼓励使用。
1997年NIST发起了征集DES替代算法---AES(Advanced Encryption Standard,AES)算法的活动,最终,比利时人Daemen和Rijmen提出的Rijndael算法以其密钥设置快、存储要求低,在硬件实现和限制存储的条件下性能优异当选AES算法。
AES算法的密钥长度可为128、192、256,默认为128位。

package com.fulcrum.encrypt;

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

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

public class AESDemo {

    private static final String KEY_ALGORITHM = "AES";
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";

    private static final byte[] iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    private static final IvParameterSpec ivSpec = new IvParameterSpec(iv);

    public static void main(String[] args) throws Exception {
        String str = "开放自由包容";
        byte[] sk = initKey();
        System.out.println("--原文:"+str);
        byte[] input = encrypt(str.getBytes(StandardCharsets.UTF_8), sk);
        System.out.println("加密后:"+ Base64.encodeBase64String(input));
        byte[] output = decrypt(input, sk);
        System.out.println("解密后:"+new String(output));
    }

    public static byte[] decrypt(byte[] data,byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
        Key k = toKey(key);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, k, ivSpec);
        return cipher.doFinal(data);
    }

    public static byte[] encrypt(byte[] data, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
        Key k = toKey(key);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, k, ivSpec);
        return cipher.doFinal(data);
    }

    public static byte[] initKey() throws NoSuchAlgorithmException {
        KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
        kg.init(256);//设置密钥长度,128、192或256皆可
        SecretKey secretKey = kg.generateKey();
        return secretKey.getEncoded();
    }

    public static Key toKey(byte[] key){
        SecretKey secretKey = new SecretKeySpec(key, KEY_ALGORITHM);
        return secretKey;
    }
}

截屏2024-03-12 13.40.23.png