DES加解密

package cloud.jincheng.utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

/**
 * DES对称加密算法<br/>
 * DES现在已不被视为一种安全的加密算法,主要原因是使用的56位密钥过短
 *
 * @author jinCheng
 */
public class DesUtil {

    /**
     * 密钥长度
     */
    private static final int SECRET_KEY_SIZE = 56;

    /**
     * 算法名称
     */
    private static final String ALGORITHM_NAME = "DES";
    /**
     * 算法名称/加密模式/填充方式<br/>
     * 加密模式: ECB模式(电子密本方式,并且ECB模式不能使用IV向量),CBC模式(密文分组链接方式)<br/>
     * 填充方式: PKCS5Padding(有填充),NoPadding(无填充,测试加密数据长度必须为8字节的倍数)
     */
    private static final String TRANSFORMATION_ECB = "DES/ECB/PKCS5Padding";
    private static final String TRANSFORMATION_CBC = "DES/CBC/PKCS5Padding";

    /**
     * 初始向量key的长度:8位
     */
    private static final int IV_KEY_SIZE = 8;

    private static final Charset UTF8 = StandardCharsets.UTF_8;
    /**
     * 默认密钥
     */
    private static final String DEFAULT_KEY = "HYOK2J0=";

    /**
     * 加密
     *
     * @param plaintext      明文
     * @param charsetName    字符集
     * @param transformation 加密模式(ECB/CBC)
     * @param key            密钥
     * @param ivKey          向量key
     * @return 密文
     */
    public static String encrypt(String plaintext, String charsetName, String transformation, String key, String ivKey) {
        try {
            Cipher cipher = getCipher(Cipher.ENCRYPT_MODE, charsetName, transformation, key, ivKey);
            byte[] encrypted = cipher.doFinal(plaintext.getBytes(charsetName));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException("Encryption failed. Cause: ", e);
        }
    }

    /**
     * 加密
     *
     * @param plaintext      明文
     * @param charsetName    字符集
     * @param transformation 加密模式(ECB/CBC)
     * @param key            密钥
     * @return 密文
     */
    public static String encrypt(String plaintext, String charsetName, String transformation, String key) {
        return encrypt(plaintext, charsetName, transformation, key, key);
    }

    /**
     * 加密
     *
     * @param plaintext      明文
     * @param transformation 加密模式(ECB/CBC)
     * @param key            密钥
     * @return 密文
     */
    public static String encrypt(String plaintext, String transformation, String key) {
        return encrypt(plaintext, UTF8.name(), transformation, key);
    }

    /**
     * 加密
     *
     * @param plaintext      明文
     * @param transformation 加密模式(ECB/CBC)
     * @return 密文
     */
    public static String encrypt(String plaintext, String transformation) {
        return encrypt(plaintext, transformation, DEFAULT_KEY);
    }

    /**
     * 加密
     *
     * @param plaintext 明文
     * @return 密文
     */
    public static String encrypt(String plaintext) {
        return encrypt(plaintext, TRANSFORMATION_CBC);
    }


    /**
     * @param mode           加密/解密模式
     * @param charsetName    字符集
     * @param transformation 加密模式(ECB/CBC)
     * @param key            密钥
     * @param ivKey          向量key
     * @return Cipher
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws UnsupportedEncodingException
     * @throws InvalidKeyException
     * @throws InvalidAlgorithmParameterException
     */
    private static Cipher getCipher(int mode, String charsetName, String transformation, String key, String ivKey)
            throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance(transformation);
        if (TRANSFORMATION_CBC.equals(transformation)) {
            cipher.init(mode, getSecretKey(key, charsetName), getIvParameterSpec(ivKey, charsetName));
        } else if (TRANSFORMATION_ECB.equals(transformation)) {
            cipher.init(mode, getSecretKey(key, charsetName));
        }
        return cipher;
    }

    /**
     * 解密
     *
     * @param cipherText     密文
     * @param charsetName    字符集
     * @param transformation 加密模式(ECB/CBC)
     * @param key            密钥
     * @param ivKey          向量
     * @return 明文
     */
    public static String decrypt(String cipherText, String charsetName, String transformation, String key, String ivKey) {
        try {
            Cipher cipher = getCipher(Cipher.DECRYPT_MODE, charsetName, transformation, key, ivKey);
            byte[] decode = Base64.getDecoder().decode(cipherText);
            byte[] original = cipher.doFinal(decode);
            return new String(original, charsetName);
        } catch (Exception e) {
            throw new RuntimeException("Decryption failed. Cause: ", e);
        }
    }

    /**
     * 解密
     *
     * @param cipherText     密文
     * @param charsetName    字符集
     * @param transformation 加密模式(ECB/CBC)
     * @param key            密钥
     * @return 明文
     */
    public static String decrypt(String cipherText, String charsetName, String transformation, String key) {
        return decrypt(cipherText, charsetName, transformation, key, key);
    }

    /**
     * 解密
     *
     * @param cipherText     密文
     * @param transformation 加密模式(ECB/CBC)
     * @param key            密钥
     * @return 明文
     */
    public static String decrypt(String cipherText, String transformation, String key) {
        return decrypt(cipherText, UTF8.name(), transformation, key);
    }

    /**
     * 解密
     *
     * @param cipherText     密文
     * @param transformation 加密模式(ECB/CBC)
     * @return 明文
     */
    public static String decrypt(String cipherText, String transformation) {
        return decrypt(cipherText, transformation, DEFAULT_KEY);
    }

    /**
     * 解密
     *
     * @param cipherText 密文
     * @return 明文
     */
    public static String decrypt(String cipherText) {
        return decrypt(cipherText, TRANSFORMATION_CBC);
    }

    /**
     * 获取向量参数(IvParameterSpec),增加加密强度<br/>
     * 若key长度不足IV_KEY_SIZE,则自动补0,超过则直接截取至IV_KEY_SIZE位
     *
     * @param ivKey       向量
     * @param charsetName 字符集
     * @return 向量参数
     */
    private static IvParameterSpec getIvParameterSpec(String ivKey, String charsetName) throws UnsupportedEncodingException {
        if (ivKey == null) {
            ivKey = "";
        }
        StringBuffer stringBuffer = new StringBuffer(IV_KEY_SIZE);
        stringBuffer.append(ivKey);
        while (stringBuffer.length() < IV_KEY_SIZE) {
            stringBuffer.append("0");
        }
        if (stringBuffer.length() > IV_KEY_SIZE) {
            stringBuffer.setLength(IV_KEY_SIZE);
        }
        return new IvParameterSpec(stringBuffer.toString().getBytes(charsetName));
    }

    /**
     * 获取安全密钥
     *
     * @param key         密钥
     * @param charsetName 字符集
     * @return 安全密钥
     */
    private static Key getSecretKey(String key, String charsetName) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_NAME);
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(key.getBytes(charsetName));
            keyGenerator.init(SECRET_KEY_SIZE, secureRandom);
            return keyGenerator.generateKey();
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            throw new RuntimeException("Failed to generate key. Cause: " + e);
        }
    }

    public static void main(String[] args) {
        String plaintext = "test455644ssaasfasdfasafd";
        String encrypt = encrypt(plaintext, TRANSFORMATION_ECB);
        System.out.println(encrypt);
        System.out.println(decrypt(encrypt, TRANSFORMATION_ECB));
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值