DES加密算法探究【Java版本】

1、参考文章:
1.1对称加密算法;
1.2DES算法详细设计;
2、参考代码
2.1、DESUtils
2.2、Encryp-Demo
3.对称加密算法
3.1 定义

对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。

3.2 优缺点

     优点:算法公开、计算量小、加密速度快、加密效率高。

     缺点:

(1)交易双方都使用同样钥匙,安全性得不到保证。

(2)每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。

3.3 常用对称加密算法

基于“对称密钥”的加密算法主要有DES、3DES(TripleDES)、AES、RC2、RC4、RC5和Blowfish等。本文只介绍最常用的对称加密算法DES、3DES(TripleDES)和AES。
3.4、DES加密算法的几种模式:
3.4.1、参考文章 ;

    AES/CBC/NoPadding (128) 
    AES/CBC/PKCS5Padding (128) 
    AES/ECB/NoPadding (128) 
    AES/ECB/PKCS5Padding (128) 
    DES/CBC/NoPadding (56) 
    DES/CBC/PKCS5Padding (56) 
    DES/ECB/NoPadding (56) 
    DES/ECB/PKCS5Padding (56) 

    (DESede实际上是3-DES) 
    DESede/CBC/NoPadding (168) 
    DESede/CBC/PKCS5Padding (168) 
    DESede/ECB/NoPadding (168) 
    DESede/ECB/PKCS5Padding (168) 

3.4.2:需要留意的坑:

由于加密时会自动填充到8字节(64bit),那么在我们进行字节数组到字串的转化过程中,可以把它填补的不可见字符改变了,所以解密时会导致异常,用base64解决

4、代码:

package com.jm;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

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

/**
 * @Createtime 2014年12月5日 14:22:00
 * @author Lxz
 * 
 */
public class DESUtil {
    /**
     * UTF-8编码
     */
    public static final String ENCODED_UTF8 = "UTF-8";
    /**
     * GBK编码
     */
    public static final String ENCODED_GBK = "GBK";
    /**
     * GB2312编码
     */
    public static final String ENCODED_GB2312 = "GB2312";
    /**
     * ISO8859-1编码
     */
    public static final String ENCODED_ISO88591 = "ISO8859-1";
    /**
     * ASCII编码
     */
    public static final String ENCODED_ASCII = "ASCII";
    /**
     * UNICODE编码
     */
    public static final String ENCODED_UNICODE = "UNICODE";
    /**
     * CBC加密模式
     */
    public static final String CIPHER_INSTANCE_CBC = "DES/CBC/PKCS5Padding";
    /**
     * ECB加密模式
     */
    public static final String CIPHER_INSTANCE_ECB = "DES/ECB/PKCS5Padding";

    /**
     * DES加密
     * 
     * @param HexString
     *            字符串(16位16进制字符串)
     * @param keyStr
     *            密钥16个1
     * @throws Exception
     */
    public static String ENCRYPTMethod(String HexString, String keyStr)
            throws Exception {
        String jmstr = "";
        try {
            byte[] theKey = null;
            //从给定的密钥中截取生成真正的密钥来源,保证加密解密算法的唯一性,避免数据的轻易可逆;
            String jqstr = getstrByte(keyStr).substring(0,8).toUpperCase();
            theKey = jqstr.getBytes(ENCODED_ASCII);
            //Ciper[名词]:零、暗号、密码本;
            //获取CIPHER_INSTANCE_CBC模式下的密码本;
            Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE_CBC);
            //生成secrecKey;
            DESKeySpec desKeySpec = new DESKeySpec(theKey);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
            IvParameterSpec iv = new IvParameterSpec(theKey);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            byte[] theCph = cipher.doFinal(HexString.getBytes(ENCODED_GB2312));
            jmstr = toHexString(theCph).toUpperCase();
            jmstr = toHexString(theCph);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return jmstr;
    }

    public static String getstrByte(String str){
        if(null == str){
            throw new IllegalArgumentException(
            "str is null!");
        }
        MessageDigest messageDigest = getMessageDigest();
        byte[] digest;
        try {
            digest = messageDigest.digest(str.getBytes("ASCII"));
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("ASCII not supported!");
        }
        return new String(Hex.encodeHex(digest));
    }

    protected static final MessageDigest getMessageDigest() {
        String algorithm = "MD5";
        try {
            return MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("No such algorithm ["
                    + algorithm + "]");
        }
    }

    /**
     * DES加密
     * @param HexString 字符串(16位16进制字符串)
     * @param keyStr 密钥16个1
     * @param keyENCODED  Keybyte转换编码
     * @param HexStringENCODED 要加密值的转换byte编码
     * @param CipherInstanceType 需要加密类型
     * @return
     * @throws Exception
     */
    public static String ENCRYPTMethod(String HexString, String keyStr,String keyENCODED,String HexStringENCODED,String CipherInstanceType)
            throws Exception {
        String jmstr = "";
        try {
            byte[] theKey = null;
            String jqstr = getstrByte(keyStr).substring(0,8).toUpperCase();
            theKey = jqstr.getBytes(keyENCODED);
            Cipher cipher = Cipher.getInstance(CipherInstanceType);
            DESKeySpec desKeySpec = new DESKeySpec(theKey);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
            IvParameterSpec iv = new IvParameterSpec(theKey);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            byte[] theCph = cipher.doFinal(HexString.getBytes(HexStringENCODED));
            jmstr = toHexString(theCph).toUpperCase();
            jmstr = toHexString(theCph);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return jmstr;
    }

    public static String toHexString(byte b[]) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String plainText = Integer.toHexString(0xff & b[i]);
            if (plainText.length() < 2)
                plainText = "0" + plainText;
            hexString.append(plainText);
        }

        return hexString.toString();
    }

    /**
     * DES解密方法
     * @param message 需要解密字符串
     * @param key 解密需要的KEY
     * @param keyENCODED  解密KEY转换编码
     * @param HexStringENCODED  解密字符串转换编码
     * @param CipherInstanceType 解密类型
     * @return
     * @throws Exception
     */
    public static String decrypt(String message, String key,String keyENCODED,String HexStringENCODED,String CipherInstanceType) throws Exception {

        byte[] bytesrc = convertHexString(message);
        byte[] theKey = null;
        String jqstr = getstrByte(key).substring(0,
                8).toUpperCase();
        theKey = jqstr.getBytes(keyENCODED);
        Cipher cipher = Cipher.getInstance(CipherInstanceType);
        DESKeySpec desKeySpec = new DESKeySpec(theKey);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        IvParameterSpec iv = new IvParameterSpec(theKey);

        cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);

        byte[] retByte = cipher.doFinal(bytesrc);
        return new String(retByte,HexStringENCODED);
    }

    /**
     * DES解密方法,解密方法和加密方法应该是对称的;
     * @param message
     * @param key
     * @return
     * @throws Exception
     */
    public static String decrypt(String message, String key) throws Exception {

        byte[] bytesrc = convertHexString(message);
        byte[] theKey = null;
        String jqstr = getstrByte(key).substring(0,
                8).toUpperCase();
        theKey = jqstr.getBytes(ENCODED_ASCII);
        Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE_CBC);
        DESKeySpec desKeySpec = new DESKeySpec(theKey);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        IvParameterSpec iv = new IvParameterSpec(theKey);

        cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);

        byte[] retByte = cipher.doFinal(bytesrc);
        return new String(retByte,ENCODED_GB2312);
    }

    public static byte[] convertHexString(String ss) {
        byte digest[] = new byte[ss.length() / 2];
        for (int i = 0; i < digest.length; i++) {
            String byteString = ss.substring(2 * i, 2 * i + 2);
            int byteValue = Integer.parseInt(byteString, 16);
            digest[i] = (byte) byteValue;
        }

        return digest;
    }

    public static void main(String[] args) throws Exception {
        String key = "27650099-564A-4869-99B3-363F8129C0CD";
        String value = "张三内部购房百分点办法对你表白";
        String jiami = value;

        System.out.println("加密数据:" + jiami);
        String a = ENCRYPTMethod(jiami, key).toUpperCase();

        System.out.println("加密后的数据为:" + a);
        String b = decrypt(a, key);
        System.out.println("解密后的数据:" + b);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值