3DES加密算法

在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明文加密成复杂的密文。目前主流加密手段大致可分为单向加密和双向加密。

  • 单向加密:通过对数据进行摘要计算生成密文,密文不可逆推还原。算法代表:Base64,MD5,SHA;
  • 双向加密:与单向加密相反,可以把密文逆推还原成明文,双向加密又分为对称加密和非对称加密。

    1. 对称加密:指数据使用者必须拥有相同的密钥才可以进行加密解密,就像彼此约定的一串暗号。算法代表:DES,3DES,AES,IDEA,RC4,RC5;

    2. 非对称加密:相对对称加密而言,无需拥有同一组密钥,非对称加密是一种“信息公开的密钥交换协议”。非对称加密需要公开密钥和私有密钥两组密钥,公开密钥和私有密钥是配对起来的,也就是说使用公开密钥进行数据加密,只有对应的私有密钥才能解密。这两个密钥是数学相关,用某用户密钥加密后的密文,只能使用该用户的加密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。因此如果公开了一对密钥中的一个,并不会危害到另外一个密钥性质。这里把公开的密钥为公钥,不公开的密钥为私钥。算法代表:RSA,DSA。

3DES是三重数据加密,且可以逆推的一种算法方案。但由于3DES的算法是公开的,所以算法本身没有密钥可言,主要依靠唯一密钥来确保数据加解密的安全。到目前为止,仍没有人能破解3DES。

package com.me.util;


import java.security.Key;

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

public class Des3 {
    // 密钥
    // private final static String secretKey = "uatspdbcccgame2014061800";

    // 向量
    private final static String iv = "01234567";

    // 加解密的编码方统一使用式
    private final static String encoding = "utf-8";

    /**
     * 3DES加密   key必须是长度大于等于 3*8 = 24 位
     *
     * @param plainText    数据源
     * @param security_key 密钥
     * @return
     * @throws Exception
     */
    public static String encode(String plainText, String security_key) throws Exception {
        //生成key,同时制定是des还是DESede,两者的key长度要求不同
        DESedeKeySpec spec = new DESedeKeySpec(security_key.getBytes());
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        Key deskey = keyfactory.generateSecret(spec);

        //通过Chipher执行加密得到的是一个byte的数组,Cipher.getInstance("DES")就是采用ECB模式,
        // cipher.init(Cipher.ENCRYPT_MODE,secretKey)就可以了.
        Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
        //加密向量
        IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);

        byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding));
        //通过base64,将加密数组转换成字符串
        return Base64.encode(encryptData);
    }


    /**
     * 3DES解密   key必须是长度大于等于 3*8 = 24 位
     *
     * @param encryptText  数据源
     * @param security_key 密钥
     * @return
     * @throws Exception
     */
    public static String decode(String encryptText, String security_key) throws Exception {
        //解密的key
        DESedeKeySpec spec = new DESedeKeySpec(security_key.getBytes());
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        Key deskey = keyfactory.generateSecret(spec);

        //Chipher对象解密Cipher.getInstance("DES")就是采用ECB模式,
        // cipher.init(Cipher.DECRYPT_MODE,secretKey)就可以了.
        Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
        //加密向量
        IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, deskey, ips);

        //通过base64,将字符串转成byte数组
        byte[] decryptData = cipher.doFinal(Base64.decode(encryptText));
        return new String(decryptData, encoding);
    }

    /**
     * DESCBC加密
     *
     * @param plainText    数据源
     * @param security_key 密钥,长度必须是8的倍数
     * @return 返回加密后的数据
     * @throws Exception
     */
    public String encryptDESCBC(final String plainText, final String security_key) throws Exception {
        // 生成key,同时制定是des还是DESede,两者的key长度要求不同
        DESKeySpec desKeySpec = new DESKeySpec(security_key.getBytes());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

        //加密向量
        final IvParameterSpec ips = new IvParameterSpec(iv.getBytes("UTF-8"));

        // 通过Chipher执行加密得到的是一个byte的数组,Cipher.getInstance("DES")就是采用ECB模式,
        // cipher.init(Cipher.ENCRYPT_MODE,secretKey)就可以了.
        final Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ips);
        final byte[] b = cipher.doFinal(plainText.getBytes("UTF-8"));
        //通过base64,将加密数组转换成字符串
        return Base64.encode(b);
    }

    /**
     * DESCBC解密
     *
     * @param encryptText  数据源
     * @param security_key 密钥,长度必须是8的倍数
     * @return 返回解密后的原始数据
     * @throws Exception
     */
    public String decryptDESCBC(final String encryptText, final String security_key) throws Exception {
        // 解密的key
        DESKeySpec desKeySpec = new DESKeySpec(security_key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

        //向量
        final IvParameterSpec ips = new IvParameterSpec(iv.getBytes("UTF-8"));

        // Chipher对象解密Cipher.getInstance("DES")就是采用ECB模式,
        // cipher.init(Cipher.DECRYPT_MODE,secretKey)就可以了.
        final Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ips);
        final byte[] retByte = cipher.doFinal(Base64.decode(encryptText));
        return new String(retByte);
    }
}

测试类

package test;

import java.net.URLEncoder;

import com.mes.util.ThreeDES;

public class ThreeDES_TEST {
    public static void main(String[] args) throws Exception {
        final String key = "cf410f84904a44cc8a7f48fc4134e8f9";
        // 加密流程
        String telePhone = "15629551180";
        ThreeDES threeDES = new ThreeDES();
        String telePhone_encrypt = "";
        telePhone_encrypt = threeDES.encryptThreeDESECB(URLEncoder.encode(telePhone, "UTF-8"), key);
        System.out.println(telePhone_encrypt);// nWRVeJuoCrs8a+Ajn/3S8g==

        // 解密流程
        String tele_decrypt = threeDES.decryptThreeDESECB(telePhone_encrypt, key);
        System.out.println("模拟代码解密:" + tele_decrypt);
    }

}

测试结果

Bu7KzIWrplmh4nVj0d2Htg==
模拟代码解密:15629551180

Base64类

package com.me.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Base64 {
    private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();


    public static String encode(byte[] data) {

        int start = 0;

        int len = data.length;

        StringBuffer buf = new StringBuffer(data.length * 3 / 2);


        int end = len - 3;

        int i = start;

        int n = 0;


        while (i <= end) {

            int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 0x0ff) << 8) | (((int) data[i + 2]) & 0x0ff);


            buf.append(legalChars[(d >> 18) & 63]);

            buf.append(legalChars[(d >> 12) & 63]);

            buf.append(legalChars[(d >> 6) & 63]);

            buf.append(legalChars[d & 63]);


            i += 3;


            if (n++ >= 14) {

                n = 0;

                buf.append(" ");

            }

        }


        if (i == start + len - 2) {

            int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 255) << 8);


            buf.append(legalChars[(d >> 18) & 63]);

            buf.append(legalChars[(d >> 12) & 63]);

            buf.append(legalChars[(d >> 6) & 63]);

            buf.append("=");

        } else if (i == start + len - 1) {

            int d = (((int) data[i]) & 0x0ff) << 16;


            buf.append(legalChars[(d >> 18) & 63]);

            buf.append(legalChars[(d >> 12) & 63]);

            buf.append("==");

        }


        return buf.toString();

    }


    private static int decode(char c) {

        if (c >= 'A' && c <= 'Z')

            return ((int) c) - 65;

        else if (c >= 'a' && c <= 'z')

            return ((int) c) - 97 + 26;

        else if (c >= '0' && c <= '9')

            return ((int) c) - 48 + 26 + 26;

        else

            switch (c) {

                case '+':

                    return 62;

                case '/':

                    return 63;

                case '=':

                    return 0;

                default:

                    throw new RuntimeException("unexpected code: " + c);

            }

    }


    /**
     * Decodes the given Base64 encoded String to a new byte array. The byte array holding the decoded data is returned.
     */


    public static byte[] decode(String s) {


        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {

            decode(s, bos);

        } catch (IOException e) {

            throw new RuntimeException();

        }

        byte[] decodedBytes = bos.toByteArray();

        try {

            bos.close();

            bos = null;

        } catch (IOException ex) {

            System.err.println("Error while decoding BASE64: " + ex.toString());

        }

        return decodedBytes;

    }


    private static void decode(String s, OutputStream os) throws IOException {

        int i = 0;


        int len = s.length();


        while (true) {

            while (i < len && s.charAt(i) <= ' ')

                i++;


            if (i == len)

                break;


            int tri = (decode(s.charAt(i)) << 18) + (decode(s.charAt(i + 1)) << 12) + (decode(s.charAt(i + 2)) << 6) + (decode(s.charAt(i + 3)));


            os.write((tri >> 16) & 255);

            if (s.charAt(i + 2) == '=')

                break;

            os.write((tri >> 8) & 255);

            if (s.charAt(i + 3) == '=')

                break;

            os.write(tri & 255);


            i += 4;

        }

    }

}

注意:

3DES密钥的长度必须是8的倍数,可取24位或32位;

加密结果的byte数组转换为字符串,一般采用两种方式:Base64处理或十六进制处理。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值