All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dxy.library.util.cipher.symmetry.BlowfishUtils Maven / Gradle / Ivy

The newest version!
package com.dxy.library.util.cipher.symmetry;

import com.dxy.library.util.cipher.constant.Algorithm;
import com.dxy.library.util.cipher.constant.AlgorithmUtils;
import com.dxy.library.util.cipher.constant.Mode;
import com.dxy.library.util.cipher.constant.Padding;
import com.dxy.library.util.common.StringUtils;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.Security;

/**
 * Blowfish工具类
 * Blowfish:密钥长(4至56)*8,块长64,速度快,在安全界尚未被充分分析、论证
 * @author duanxinyuan
 * 2019/2/15 19:16
 */
public class BlowfishUtils {

    static {
        //导入Provider,BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * Blowfish加密(最常用方式之一,使用Blowfish/ECB/PKCS5Padding方式,无偏移量)
     * @param data 密文(Base64编码)
     * @param key 密钥(Base64编码),长度必须是4~56位
     */
    public static String encrypt(String data, String key) {
        return encrypt(data, key, null, Mode.ECB, Padding.PKCS5Padding);
    }

    /**
     * Blowfish加密(最常用方式之一,使用Blowfish/ECB/PKCS5Padding方式,无偏移量)
     * @param data 密文
     * @param key 密钥,长度必须是4~56位
     */
    public static byte[] encrypt(byte[] data, byte[] key) {
        return encrypt(data, key, null, Mode.ECB, Padding.PKCS5Padding);
    }

    /**
     * Blowfish加密(最常用方式之一,使用Blowfish/CBC/PKCS7Padding方式)
     * @param data 密文(Base64编码)
     * @param key 密钥(Base64编码),长度必须是4~56位
     * @param iv 偏移量,长度必须是8位
     */
    public static String encrypt(String data, String key, String iv) {
        return encrypt(data, key, iv, Mode.CBC, Padding.PKCS7Padding);
    }

    /**
     * Blowfish加密(最常用方式之一,使用Blowfish/CBC/PKCS7Padding方式)
     * @param data 密文
     * @param key 密钥,长度必须是4~56位
     * @param iv 偏移量,长度必须是8位
     */
    public static byte[] encrypt(byte[] data, byte[] key, String iv) {
        return encrypt(data, key, iv, Mode.CBC, Padding.PKCS7Padding);
    }

    /**
     * Blowfish加密(不带偏移量)
     * @param data 密文(Base64编码)
     * @param key 密钥(Base64编码),长度必须是4~56位
     */
    public static String encrypt(String data, String key, Mode mode, Padding padding) {
        return encrypt(data, key, null, mode, padding);
    }

    /**
     * Blowfish加密(不带偏移量)
     * @param data 密文
     * @param key 密钥,长度必须是4~56位
     * @return 密文(Base64编码)
     */
    public static byte[] encrypt(byte[] data, byte[] key, Mode mode, Padding padding) {
        return encrypt(data, key, null, mode, padding);
    }

    /**
     * Blowfish加密
     * @param data 明文(Base64编码)
     * @param key 密钥(Base64编码),长度必须是4~56位
     * @param iv 偏移量,长度必须是8位
     * @param mode 密码块工作模式
     * @param padding 填充方式
     * @return 密文(Base64编码)
     */
    public static String encrypt(String data, String key, String iv, Mode mode, Padding padding) {
        if (StringUtils.isEmpty(data)) {
            return null;
        }
        byte[] encrypt = encrypt(data.getBytes(), Base64.decodeBase64(key), iv, mode, padding);
        return Base64.encodeBase64String(encrypt);
    }

    /**
     * Blowfish加密
     * @param data 明文
     * @param key 密钥,长度必须是4~56位
     * @param iv 偏移量,长度必须是8位
     * @param mode 密码块工作模式
     * @param padding 填充方式
     * @return 密文
     */
    public static byte[] encrypt(byte[] data, byte[] key, String iv, Mode mode, Padding padding) {
        check(key, iv, mode, padding);
        try {
            SecretKeySpec secretKeySpec = getSecretKeySpec(key);
            String algorithm = AlgorithmUtils.getAlgorithm(Algorithm.Blowfish, mode, padding);
            // 创建密码器
            Cipher cipher = Cipher.getInstance(algorithm);
            // 初始化
            if (StringUtils.isNotEmpty(iv)) {
                AlgorithmParameters parameters = AlgorithmParameters.getInstance(Algorithm.Blowfish.getAlgorithm());
                parameters.init(new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)));
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, parameters);
            } else {
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            }
            //加密
            return cipher.doFinal(data);
        } catch (Exception e) {
            throw new RuntimeException("Blowfish encrypt error", e);
        }
    }

    /**
     * Blowfish解密(最常用方式之一,使用Blowfish/ECB/PKCS5Padding方式,无偏移量)
     * @param data 密文(Base64编码)
     * @param key 密钥(Base64编码),长度必须是4~56位
     * @return 明文
     */
    public static String decrypt(String data, String key) {
        return decrypt(data, key, null, Mode.ECB, Padding.PKCS5Padding);
    }

    /**
     * Blowfish解密(最常用方式之一,使用Blowfish/ECB/PKCS5Padding方式,无偏移量)
     * @param data 密文
     * @param key 密钥,长度必须是4~56位
     * @return 明文
     */
    public static byte[] decrypt(byte[] data, byte[] key) {
        return decrypt(data, key, null, Mode.ECB, Padding.PKCS5Padding);
    }

    /**
     * Blowfish解密(最常用方式之一,使用Blowfish/CBC/PKCS7Padding方式)
     * @param data 密文(Base64编码)
     * @param key 密钥(Base64编码),长度必须是4~56位
     * @param iv 偏移量,长度必须是8位
     * @return 明文
     */
    public static String decrypt(String data, String key, String iv) {
        return decrypt(data, key, iv, Mode.CBC, Padding.PKCS7Padding);
    }

    /**
     * Blowfish解密(最常用方式之一,使用Blowfish/CBC/PKCS7Padding方式)
     * @param data 密文
     * @param key 密钥,长度必须是4~56位
     * @param iv 偏移量,长度必须是8位
     * @return 明文
     */
    public static byte[] decrypt(byte[] data, byte[] key, String iv) {
        return decrypt(data, key, iv, Mode.CBC, Padding.PKCS7Padding);
    }

    /**
     * Blowfish解密(不带偏移量)
     * @param data 密文(Base64编码)
     * @param key 密钥(Base64编码),长度必须是4~56位
     * @return 明文
     */
    public static String decrypt(String data, String key, Mode mode, Padding padding) {
        return decrypt(data, key, null, mode, padding);
    }

    /**
     * Blowfish解密(不带偏移量)
     * @param data 密文
     * @param key 密钥,长度必须是4~56位
     * @return 明文
     */
    public static byte[] decrypt(byte[] data, byte[] key, Mode mode, Padding padding) {
        return decrypt(data, key, null, mode, padding);
    }

    /**
     * Blowfish解密
     * @param data 密文(Base64编码)
     * @param key 密钥(Base64编码),长度必须是4~56位
     * @param iv 偏移量,长度必须是8位
     * @param mode 密码块工作模式
     * @param padding 填充方式
     * @return 明文
     */
    public static String decrypt(String data, String key, String iv, Mode mode, Padding padding) {
        if (StringUtils.isEmpty(data)) {
            return null;
        }
        byte[] decrypt = decrypt(Base64.decodeBase64(data), Base64.decodeBase64(key), iv, mode, padding);
        return new String(decrypt);
    }

    /**
     * Blowfish解密
     * @param data 密文
     * @param key 密钥,长度必须是4~56位
     * @param iv 偏移量,长度必须是8位
     * @param mode 密码块工作模式
     * @param padding 填充方式
     * @return 明文
     */
    public static byte[] decrypt(byte[] data, byte[] key, String iv, Mode mode, Padding padding) {
        check(key, iv, mode, padding);
        try {
            SecretKeySpec secretKeySpec = getSecretKeySpec(key);
            String algorithm = AlgorithmUtils.getAlgorithm(Algorithm.Blowfish, mode, padding);
            // 创建密码器
            Cipher cipher = Cipher.getInstance(algorithm);
            // 初始化
            if (StringUtils.isNotEmpty(iv)) {
                AlgorithmParameters parameters = AlgorithmParameters.getInstance(Algorithm.Blowfish.getAlgorithm());
                parameters.init(new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)));
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, parameters);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            }
            //解密
            return cipher.doFinal(data);
        } catch (Exception e) {
            throw new RuntimeException("Blowfish decrypt error", e);
        }
    }

    /**
     * 生成Blowfish的Key(128位,Base64编码)
     * @return 密钥(Base64编码)
     */
    public static String genarateKeyBase64() {
        return genarateKeyBase64(128);
    }

    /**
     * 生成Blowfish的Key(Base64编码)
     * @return 密钥(Base64编码)
     */
    public static String genarateKeyBase64(int length) {
        return Base64.encodeBase64String(genarateKey(length));
    }

    /**
     * 生成Blowfish的Key
     * @param length 密钥长度,可以选 (4至56)*8
     * @return 密钥
     */
    public static byte[] genarateKey(int length) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm.Blowfish.getAlgorithm());
            keyGenerator.init(length);
            SecretKey secretKey = keyGenerator.generateKey();
            return secretKey.getEncoded();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Blowfish key genarate error", e);
        }
    }

    private static SecretKeySpec getSecretKeySpec(byte[] key) {
        return new SecretKeySpec(key, Algorithm.Blowfish.getAlgorithm());
    }

    private static void check(byte[] key, String iv, Mode mode, Padding padding) {
        checkKey(key);
        checkModeAndPadding(mode, padding);
        if (StringUtils.isNotEmpty(iv)) {
            checkIv(iv);
            if (mode == Mode.ECB) {
                throw new RuntimeException("Blowfish ECB mode does not use an IV");
            }
        }
    }

    /**
     * 校验Blowfish密码块工作模式和填充模式
     */
    private static void checkModeAndPadding(Mode mode, Padding padding) {
        if (mode == Mode.NONE) {
            throw new RuntimeException("invalid Blowfish mode");
        }
        if (padding == Padding.SSL3Padding || padding == Padding.PKCS1Padding) {
            throw new RuntimeException("invalid Blowfish padding");
        }
        if (padding == Padding.NoPadding) {
            if (mode == Mode.ECB || mode == Mode.CBC) {
                throw new RuntimeException("invalid Blowfish algorithm");
            }
        }
    }

    /**
     * 校验Blowfish密钥,长度必须是4~56位
     */
    private static void checkKey(byte[] key) {
        if (key == null) {
            throw new RuntimeException("Blowfish key cannot be null");
        }
        if (key.length < 4 || key.length > 56) {
            throw new RuntimeException("Blowfish key not 4~56 bytes long");
        }
    }

    /**
     * 校验Blowfish偏移量,长度必须是8位
     */
    private static void checkIv(String iv) {
        if (iv.length() != 8) {
            throw new RuntimeException("Blowfish iv not 8 bytes long");
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy