DES/3DES加密,解密

〇、前言

        最近在项目中,涉及到与第三方厂家系统进行对接时,在参数传递过程中考虑到了数据的安全性,故双方采用3DES进行对传递参数的加解密,因此,进一步了解了下3DES的加解密算法,再次进行梳理。
一、DES算法

     DES,Data Encryption Standard,即:数据加密标准,是一种使用密钥加密的块算法。

      DES算法在POS、ATM、磁卡及IC卡、加油站、高速公路收费站等领域被广泛应用,以此来实现关键数据的保密,如信用卡持卡人的PIN的加密传输,IC卡与POS间的双向认证、金融交易数据包的MAC校验等,均用到DES算法。

      1、DES算法的入口参数有三个: Key、Data、Mode。

      其中Key为8个字节共64位,是DES算法的工作密钥;

        Data也为8个字节64位,是要被加密或被解密的数据;

        Mode为DES的工作方式,有两种:加密或解密。
      2、DES算法过程:

  如果mode为加密,则用Key 去把数据Data进行加密, 生成Data的密码形式(64位)作为DES的输出结果;

  如果mode为解密,则用Key去把密码形式的数据Data解密,还原为Data的明码形式(64位)作为DES的输出结果。

  在通信网络的两端,双方约定一致的Key,在通信的源点用Key对核心数据进行DES加密,然后以密码形式在公共通信网(如电话网)中传输到通信网络的终点,数据到达目的地后,用同样的Key对密码数据进行解密,便再现了明码形式的核心数据。这样,便保证了核心数据(如PIN、MAC等)在公共通信网中传输的安全性和可靠性。

  通过定期在通信网络的源端和目的端同时改用新的Key,便能更进一步提高数据的保密性,这正是现在金融交易网络的流行做法。

        (PS:不过在当今为了数据的更安全,一般采用加密平台进行数据的硬加密,实现数据明文不落地,尤其是在金融行业尤为运用广泛。)

       3、DES算法步骤

       DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位(实际用到了56位,第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1),其算法主要分为两步:
   ①初始置换
       其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则为将输入的第58位换到第一位,第50位换到第2位……依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位,例:设置换前的输入值为D1D2D3……D64,则经过初始置换后的结果为: L0=D58D50……D8;R0=D57D49……D7。
    其置换规则见下表:
    58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,
    62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
    57,49,41,33,25,17,9, 1,59,51,43,35,27,19,11,3,
    61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,  7
   ②逆置换
     经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出。
     此算法是对称加密算法体系中的代表,在计算机网络系统中广泛使用。

4、DES算法实现
    见 "三、算法实现"

二、3DES算法

       3DES(又称Triple DES),是进行了三重数据加密,即:每个数据块进行了三次DES加密算法,使用3条64位的密钥对数据进行三次加密,故比DES加密更为安全,更难破解。

   1、加密算法,其具体实现如下:

      设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,M代表明文,C代表密文:
        3DES加密过程为:C=Ek3(Dk2(Ek1(M)))
        3DES解密过程为:M=Dk1(EK2(Dk3(C)))

      注:K1、K2、K3决定了算法的安全性,若三个密钥互不相同,本质上就相当于用一个长为168位的密钥进行加密。多年来,它在对付强力攻击时是比较安全的。若数据对安全性要求不那么高,K1可以等于K3。在这种情况下,密钥的有效长度为112位。

     2、3DES算法实现

      (见 "三、算法实现")
三、算法实现

1、Java实现

<span style="font-size:12px;">package com.xcbeyond.security;
     
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
     
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    /**
     * 加解密工具类
     * @author xcbeyond
     * 2016-8-6下午11:16:46
     */
    public class ScrtUtil {
        private static final Log log = LogFactory.getLog(ScrtUtil.class);
        private static final String DES3 = "DESede";
        private static final String DES = "DES";
     
            /**
          * 测试方法
          * @param args
          */
         public static void main(String[] args) {
            //密钥
            String key = "0123456789asdfghjklzxcvbnmqwertyuiop";
            //待加密数据
            String data = "1000000";
            
            System.out.println("加密前的数据为:" + data);
            System.out.println();
            
            //DES加解密
            String encoded = encryptDES(getDesKey(key), data.getBytes());
            System.out.println("DES加密后的数据为:" + encoded);
            String decoded = decryptDES(getDesKey(key), hexStringToBytes(encoded));
            System.out.println("DES解密后的数据为:" + new String(decoded));
            System.out.println();
            
            encoded = encrypt3DES(get3DesKey(key), data.getBytes());
            System.out.println("3DES加密后的数据为:" + encoded);
            decoded = decrypt3DES(get3DesKey(key), hexStringToBytes(encoded));
            System.out.println("3DES解密后的数据为:" + new String(decoded));
            
            
            
          }
     
           /**
         * 生成24字节的3DES密钥。
         * (不够24字节,则补0;超过24字节,则取前24字节。)
         * @param key 密钥字符串
         * @return
         */
        public static byte[] get3DesKey(String key) {
            byte[] keyBytes = new byte[24];
            if(key.getBytes().length > 24) {
                for(int i = 0;i<24;i++) {
                    keyBytes[i] = key.getBytes()[i];
                }
            } else {
                for(int i = 0;i<24;i++) {
                    if(i < key.getBytes().length) {
                        keyBytes[i] = key.getBytes()[i];
                    } else {
                        keyBytes[i] = 0x00;
                    }
                }
            }
            return keyBytes;
        }
     
        /**
         * 生成8字节的DES密钥。
         * (不够8字节,则补0;超过8字节,则取前8字节。)
         * @param key 密钥字符串
         * @return
         */
        public static byte[] getDesKey(String key) {
            byte[] keyBytes = new byte[8];
            if(key.getBytes().length > 8) {
                for(int i = 0;i<8;i++) {
                    keyBytes[i] = key.getBytes()[i];
                }
            } else {
                for(int i = 0;i<8;i++) {
                    if(i < key.getBytes().length) {
                        keyBytes[i] = key.getBytes()[i];
                    } else {
                        keyBytes[i] = 0x00;
                    }
                }
            }
            return keyBytes;
        }
     
        /**
         * 3DES加密
         * @param
         *         key    :加密密钥
         *         value    :被加密的数据
         * @return
         *         加密后的数据
         */
        public static String encrypt3DES(byte[] key, byte[] value) {
            byte[] retValue = null;
            try {
                SecretKey deskey = new SecretKeySpec(key, DES3);
                Cipher c1 = Cipher.getInstance(DES3);
                c1.init(1, deskey);
                retValue = c1.doFinal(value);
            } catch (Exception ex) {
                if(log.isErrorEnabled()) {
                    log.error("3DES加密错误" + ex);
                }
            }
           
            //转换为16进制数返回
            return getHexString(retValue);
        }
     
        /**
         * 3DES解密
         * @param
         *         key    :解密密钥
         *         value    :被解密的数据
         * @return
         *         解密后的明文数据
         */
        public static String decrypt3DES(byte[] key, byte[] value) {
            byte[] retValue = null;
            try {
                SecretKey deskey = new SecretKeySpec(key, DES3);
                Cipher c1 = Cipher.getInstance(DES3);
                c1.init(2, deskey);
                retValue = c1.doFinal(value);
            } catch (Exception ex) {
                if(log.isErrorEnabled()) {
                    log.error("3DES解密错误" + ex);
                }
            }
            return new String(retValue);
        }
     
        /**
         * DES加密
         * @param
         *         key    :加密密钥
         *         value    :被加密的数据
         * @return
         *         加密后的数据
         */
        public static String encryptDES(byte[] key, byte[] value) {
            byte[] retValue = null;
            try {
                SecretKey deskey = new SecretKeySpec(key, DES);
                Cipher c1 = Cipher.getInstance(DES);
                c1.init(1, deskey);
                retValue = c1.doFinal(value);
            } catch (Exception ex) {
                if(log.isErrorEnabled()) {
                    log.error("DES加密错误" + ex);
                }
            }
           
            //转换为16进制数返回
            return getHexString(retValue);
        }
     
        /**
         * DES解密
         * @param
         *         key    :解密密钥
         *         value    :被加密的数据
         * @return
         *         加解密后的明文数据
         */
        public static String decryptDES(byte[] key, byte[] value) {
            byte[] retValue = null;
            try {
                SecretKey deskey = new SecretKeySpec(key, DES);
                Cipher c1 = Cipher.getInstance(DES);
                c1.init(2, deskey);
                retValue = c1.doFinal(value);
            } catch (Exception ex) {
                if(log.isErrorEnabled()) {
                    log.error("DES解密错误" + ex);
                }
            }
            return new String(retValue);
        }
       
        /*
         * 转换为16进制数
         * @param data
         * @return   
         *         16进制数
         */
        public static String getHexString(byte[] data) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.length; ++i) {
                String ch = Integer.toHexString(data[i] & 0xFF).toUpperCase();
                if (ch.length() == 2)
                    sb.append(ch);
                else
                    sb.append("0").append(ch);
            }
            return sb.toString();
        }
       
         /**
         * 将16进制的字符串转换为byte数组
         * @param hexString
         * @return
         */
        public static byte[] hexStringToBytes(String hexString) {  
            if (hexString == null || hexString.equals("")) {  
                return null;  
            }
            hexString = hexString.toUpperCase();  
            int length = hexString.length() / 2;  
            char[] hexChars = hexString.toCharArray();  
            byte[] d = new byte[length];  
            for (int i = 0; i < length; i++) {  
                int pos = i * 2;  
                d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));  
            }  
            return d;  
        }
        
        public static byte charToByte(char c) {  
            return (byte) "0123456789ABCDEF".indexOf(c);  
        }
    }</span>


温馨注意:

        Java与其它语言进行相互加密、解密时,应在java中需要待加密或解密数据后追加字符串结束符“\0”,否则造成相互加解密存在数据差异。


2、Delphi实现
 

<span style="font-size:12px;">//---------------------------------------------------------------------------
    //包含DES加/解密和3DES加/解密
    //---------------------------------------------------------------------------
    unit DesCipher;
    //---------------------------------------------------------------------------
    interface
    //---------------------------------------------------------------------------
    uses
        SysUtils, StrUtils;
    //---------------------------------------------------------------------------
    type
        TKeyByte=array[0..5] of Byte;
        TDesMode=(dmEncry, dmDecry);
        function DesEncryStrHex(Str, Key: string): string;

更多请见:http://www.mark-to-win.com/tutorial/50542.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。 最早的定义了该算法的标准(ANS X9.52,1998年发布)将其描述为“三重数据加密算法(TDEA)”— 即为ANSI X3.92中定义的数据加密算法(DEA)的三次重复操作— 而完全没有使用术语“3DES”或“DES”。FIPS PUB 46-3(1999)定义了“三重数据加密算法”(TDEA),也使用了术语“Triple DES”和“DES”。该标准中互换的使用“数据加密算法”(DEA)和“DES”的概念,其中以此开始DES的定义: 数据加密标准(DES)应当包括下文中的数据加密算法DES[4])与三重数据加密算法(TDEA,如ANSI X9.52中所描述的) NIST SP 800-67(2004,2008[5])主要使用术语TDEA,但也提到了“Triple DES(TDEA)”。ISO/IEC 18033-3(2005)使用“TDEA”,但其中提到: TDEA通称Triple DES(数据加密标准)。 没有一个定义了本算法的标准使用术语“3DES”。 3DESughhhg34465345556555678==算法== 3DES使用“密钥包”,其包含3个DES密钥,K1,K2和K3,均为56位(除去奇偶校验位)。加密算法为: 密文 = EK3(DK2(EK1(平文))) 也就是说,使用K1为密钥进行DES加密,再用K2为密钥进行DES解密”,最后以K3进行DES加密。 而解密则为其反过程: 平文 = DK1(EK2(DK3(密文))) 即以K3解密,以K2“加密”,最后以K1解密。 每次加密操作都只处理64位数据,称为一块。 无论是加密还是解密,中间一步都是前后两步的逆。这种做法提高了使用密钥选项2时的算法强度,并在使用密钥选项3时与DES兼容。 密钥选项[编辑] 标准定义了三种密钥选项: 密钥选项1:三个密钥是独立的。 密钥选项2:K1和K2是独立的,而K3=K1 密钥选项3:三个密钥均相等,即K1=K2=K3 密钥选项1的强度最高,拥有3 x 56 = 168个独立的密钥位。 密钥选项2的安全性稍低,拥有2 x 56 = 112个独立的密钥位。该选项比简单的应用DES两次的强度较高,即使用K1和K2,因为它可以防御中途相遇攻击。 密钥选项3等同与DES,只有56个密钥位。这个选项提供了与DES的兼容性,因为第1和第2次DES操作相互抵消了。该选项不再为国家标准科技协会(NIST)所建议[6],亦不为ISO/IEC 18033-3所支持。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值