手把手DES加密解密详解–通俗易懂

DES介绍

DES(Data Encryption Standard)是迄今为止世界上最为广泛使用和流行的一种分组密码算法,它的分组长度为64比特,密钥长度为56比特,它是由美国IBM公司研制的,是早期的称作Lucifer密码的一种发展和修改。 每隔五年由美国国家保密局(NSA)作出评估,并重新批准它是否继续作为联邦加密标准。最后一次评估是在1994年1月,美国已决定1998年12月以后将不再使用DES。 DES是第一代公开的、完全说明细节的商业级现代算法,并被世界公认。

DES加密基于Feistel结构实现,其轮结构如下图所示:

 

 

DES的加密和解密详解

DES的加密过程:

明文二进制的加密:将明文数据转为二进制 ,再将二进制数据分组 ,每组64位,组元素不满64 则在后面补0,满64为止。再将每一组64bit数据进行初始置换 在进行轮函数。

轮函数中将右边32bit进行F运算 ,然后与左边32bit进行异或  ,得到的结果作为下一轮右边  将刚开始的右边作为下一轮左边 ,依次循环16次,最后进行逆初始置换,即可得到密文二进制 。

 

秘钥的产生:

将明文秘钥转换为二进制 ,取56bit为一组,不满56bit 补0 ,然后进行秘钥生成,将得到的秘钥组,分别拿去参与每一轮的F运算 ,即第一组秘钥对应第一轮F函数 ,生成的每组秘钥长度为:48bit

解密过程:加密和解密一样,不同的点是,最后一组秘钥对应第一轮F函数 ,即把秘钥组反过来而已。

 

 

看完大致流程,我们来看看具体的代码实现,有Java版和Python版,为了方便就以Python版来讲解,文章末尾会附上Java和Python的全部代码。

 

DES加密

实现的过程我们根据DES加密流程来一步一步的实现。(看着流程图一步一步来)

1.明文转二进制

这一步我觉得比较重要,首先你的明文可能 是 中文+字母  这样如果转二进制然后加密解密,得出的结果是不一样的,会出现一些奇怪的字符(乱码),如果只加密字母和数字就不会出现。

所以我们需要另一种字符形式来代替它,且只含有字母和数字 的组成,没错,就是转成16进制字符串 ,DES中在进制转换这块,看下图。

 

进制转换这块的流程大概就是这些,我们来实现 第一步,将明文转成16进制。

来看Python的代码

# 字符串转16进制字符串
def str2hex(self, string: str):
        return bytes.hex(string.encode('utf8'))
# 16进制字符串转字符串
def hex2str(self, hexstr):
        return bytes.fromhex(hexstr).decode()

啊这,是不是很简单,就是将明文编码为utf-8,得到字节,然后转16进制,反过来就是解码,在python中是这样,如果想明白过程实现,看我另一篇文章:字符串转16进制

结果如下

hello,世界        -->  68656c6c6f2ce4b896e7958c      &       68656c6c6f2ce4b896e7958c       -->  hello,世界 

接下来转二进制

十六进制转二进制,一个一个取出来然后转换,写了两种,选择一种即可。注意,每一个字符对应4位二进制位 如6->0110

# 十六进制转二进制

    def hex2bin(self, hex):
        hex_to_bin_table = (
            '0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100',
            '1101',
            '1110', '1111')
        bin_string = ''
        for i in hex:
            i = int(i, 16)
            bin_string = bin_string + hex_to_bin_table[i]
        return bin_string

    def hex2bin1(self, hex):
        hex_table = "0123456789ABCDEF"
        s = ""
        for i in hex:
            k = str(bin(hex_table.find(i.upper()))[2:])
            if len(k) < 4:
                k = (4 - len(k)) * "0" + k
            s += k
        return s

# 二进制转十六进制
    def bin2hex(self, bin):
        changed_str = ''
        while len(bin) > 0:
            temp = int(bin[:4], 2)
            changed_str += '%0x' % temp
            bin = bin[4:]
        return changed_str

    def bin2hex1(self, bin):
        hextable = "0123456789ABCDEF"
        binlist = re.findall(r".{4}", bin)
        s = ""
        for i in binlist:
            s += hextable[int(i, 2)].lower()
        return s

这样就得到了明文的二进制形式,接下来只要进行加密即可

我们把明文转二进制 变成一个函数,且校验是否满64位:

    def text2Bin(self, txt: str) -> str:
        """
        将明文 or 秘钥转换为二进制流 且%64=0
        :param txt: 输入的明文或秘钥
        :return: 运算的二进制流
        """
        txt = self.str2hex(txt)  # 字符串转十六进制字符串
        bintxt = self.hex2bin(txt)  # 十六进制字符串 转 二进制字符串
        k = len(bintxt) % 64
        if k != 0:
            bintxt += "0" * (64 - k)
        return bintxt

2.秘钥组生成

生成16轮的秘钥组原理图

代码中的所有置换表 都在文末的最终代码里面

生成秘钥:接受一个二进制秘钥流  64bit,进行PC1置换,取前56位,然后一分为二,每个28bit,然后进行循环移位,就是根据移位表,数字2:表示把二进制串左边2个接到右边后面,移位完将

C0和D0拼接在一起,进行PC2置换,得到子秘钥,然后再将上次循环移位的结果继续循环移位,依次生成完16组

    def generateKeyTo16(self, binKey: str):
        """
        生成16组秘钥
        :param binKey: 初始秘钥
        :return: 16组秘钥列表
        """
        keyList = []
        # 置换选择PC-1
        z1 = ""
        for i in self.PC_1:
            z1 += binKey[i - 1]
        # 28 bit key
        leftKey = z1[:28]
        rightKey = z1[28:]

        def leftShift(m, s):  # 移位函数 s:移多少
            return m[s:] + m[:s]

        for shift in self.SHIFT:
            leftKey = leftShift(leftKey, shift)
            rightKey = leftShift(rightKey, shift)
            # 置换选择PC-2
            zh = leftKey + rightKey
            ans = ""
            for i in self.PC_2:
                ans += zh[i - 1]
            keyList.append(ans)  # 添加秘钥
        return keyList

3.F函数的实现

函数的输入分析:   1.一个32bit的 二进制流       2.48bit的二进制秘钥

E表置换 :将32bit扩展成48bit(将某些位重复)

异或 :将E表结果和秘钥进行异或

S盒代换 :将异或结果(48bit)进行S盒代换

将48bit分成8份,每份6bit ,然后再让6bit变4bit  怎么变?

首先,将6bit首尾 的一个字符合并成2个 作为行号,剩下的不变,作为列号  如:010011   ->行:01   列:1001,然后 行号列号  转十进制数字,去S盒中查询行列对应的值,再把这个值转为二进制。(注意,第一组6bit 对应的是第一组S盒)

 

如将 010011 根据上图S盒表进行代换,那么 行:01  列 1001 十进制分别是 1和9 第一行 第九列  结果为6 二进制为 0110。

再将S盒所有结果拼凑起来

,进行P表置换,得到F函数的输出

   # XOR 异或操作
    def msgXorKey(self, left, right) -> str:
        xor = ""
        for i in range(len(left)):
            xor += str(int(left[i]) ^ int(right[i]))
        return xor

    # f函数
    def FFunction(self, binText: str, binKey: str) -> str:
        # 定义几个函数
        # E表扩展
        def e_Extend(bintxt) -> str:
            e = ""
            for i in self.E:
                e += bintxt[i - 1]
            return e

        # S盒处理
        def S_Box(bintxt: str) -> str:
            ans = ""
            bit6list = re.findall(r".{6}", bintxt)
            flag = 0
            for b in bit6list:
                k = int(b[0] + b[len(b) - 1], 2)  # 获取 行
                v = int(b[1:5], 2)  # 获取列
                sValue = bin(self.S[flag][k * 16 + v])[2:]  # S盒查询的结果转2进制
                if len(sValue) < 4:
                    sValue = "0" * (4 - len(sValue)) + sValue
                flag += 1
                ans += sValue
            return ans

        # P置换
        def P_Swap(bintxt: str) -> str:
            ans = ""
            for i in self.P:
                ans += bintxt[i - 1]
            return ans

        # 开始处理  E表->异或->S盒->P置换
        return P_Swap(S_Box(self.msgXorKey(e_Extend(binText), binKey)))

 

4 轮函数实现

参数 :   1.64bit的待加密二进制        2.秘钥组(秘钥组中的秘钥给F函数用的)

开始,首先先将64bit进行初始置换 ,然后分为32bit 32bit,将右边的32bit进行 F函数 ,然后在和左边32bit 异或 得到的结果作为下一轮右边,刚开始的右边32bit 作为下一轮的左边。依次进行了16次

以后,再将结果左右交换 ,然后进行逆初始置换 ,即可得到密文。

 

# ip置换和逆置换
    def ip_Swap(self, bit, reTable=False):
        n = ""
        if reTable is True:
            for i in self.IP_re_table:
                n += bit[i - 1]
        else:
            for i in self.IP_table:
                n += bit[i - 1]
        return n

    # 轮函数
    def WheelFunction(self, bitTo64: str, keyList: list):
        # 初始置换(IP置换)
        n = self.ip_Swap(bitTo64)
        leftBit = n[:32]
        rightBit = n[32:]
        # 获取16轮秘钥
        for rot in keyList:  # 16轮加密
            temp = rightBit
            k32 = self.FFunction(rightBit, rot)
            rightBit = self.msgXorKey(leftBit, k32)  # 异或
            leftBit = temp
        # 左右交换
        swapValue = rightBit + leftBit
        # 逆 初始置换
        Ciphertext = self.ip_Swap(swapValue, True)
        return Ciphertext

 

5.加密函数

整合上面实现加密

参数: 1.   明文   2. 秘钥

    def encryption(self, msg: str, key: str):
        """
        DES加密
        :param msg: 明文消息
        :param key: 明文秘钥
        :return: 密文
        """
        binMsgList = re.findall(r".{64}", self.text2Bin(msg))  # 64bit文明二进制列表
        k64 = re.findall(r".{64}", self.text2Bin(key))[0]  # 秘钥二进制流
        binKeyList = self.generateKeyTo16(k64) #生成秘钥组
        binaryCipher = ""
        for bitTo64 in binMsgList: # 依次把二进制流和秘钥 进行加密
            binaryCipher += self.WheelFunction(bitTo64, binKeyList)
        return self.bin2hex(binaryCipher) # 二进制结果转16进制

6.解密函数

接收参数:  1. 16进制密文  2. 秘钥

注意:解密的秘钥组要反过来

    def decryption(self, msg: str, key: str):
        """
        DES解密
        :param msg: 密文
        :param key: 秘钥
        :return: 明文
        """
        binMsgList = re.findall(r".{64}", self.hex2bin(msg))  # 64bit二进制列表
        k64 = re.findall(r".{64}", self.text2Bin(key))[0]  # 秘钥二进制流m
        binKeyList = self.generateKeyTo16(k64)
        binaryCipher = ""
        for bitTo64 in binMsgList:
            binaryCipher += self.WheelFunction(bitTo64, binKeyList[::-1]) # [::-1]将列表反转,即秘钥组反过来
        return self.hex2str(self.bin2hex(binaryCipher))

 

测试

des = DesUtil()
s = des.encryption("你好啊,world", "lightr.cn")
print(f"加密结果:{s}")
print(f"{s}的解密结果:{des.decryption(s, 'lightr.cn')}")
加密结果:bea987772587d33d80f57b15ec011c57
bea987772587d33d80f57b15ec011c57的解密结果:你好啊,world

 

 

全部代码

Java代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DesUtil {
    /**
     * DES加密
     * @param msg 明文消息
     * @param key 明文秘钥
     * @return 16进制密文字符串
     */
    public String encryption(String msg, String key){
        String msgbin = Check64(hex2Bin(str2Hex(msg)));
        String keybin = Check64(hex2Bin(str2Hex(key)));
        String[] msgs = regex(msgbin, ".{64}");
        String k = regex(keybin, ".{64}")[0];
        String[] keys = generateKey(k);
        StringBuilder mm = new StringBuilder();
        for (String binmsg : msgs) {
            mm.append(Wheel(binmsg, keys));
        }
        return bin2Hex(mm.toString().trim()).toLowerCase();
    }

    /**
     * DES解密
     * @param cipher 16进制密文
     * @param key 解密/加密 秘钥
     * @return 明文字符串
     */
    public String decryption(String cipher, String key){
        String msgbin = hex2Bin(cipher);
        key = Check64(hex2Bin(str2Hex(key)));
        String[] cpbin = regex(msgbin, ".{64}");
        String k = regex(key, ".{64}")[0];
        String[] keys = generateKey(k);
        Collections.reverse(Arrays.asList(keys)); //反转数组
        StringBuilder mm = new StringBuilder();
        for (String binmsg : cpbin) {
            mm.append(Wheel(binmsg, keys));
        }
        return hex2Str(bin2Hex(mm.toString().trim())).trim();

    }
    // =========进制转换===============

    /**
     * 字符串转十六进制字符串
     *
     * @param str String
     * @return HexString
     */
    public  String str2Hex(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        byte[] bytes = str.getBytes();
        int bt;
        for (byte b : bytes) {
            bt = (b & 0x0f0) >> 4;
            stringBuilder.append(chars[bt]);
            stringBuilder.append(chars[(b & 0x00f)]);
        }
        return stringBuilder.toString().trim().toLowerCase();
    }

    /**
     * 十六进制字符串转字符串
     *
     * @param hexStr
     * @return
     */
    public  String hex2Str(String hexStr) {
        String str16 = "0123456789ABCDEF";
        char[] chars = str16.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        char[] hex = hexStr.toUpperCase().toCharArray();
        int i;
        for (int j = 0; j < bytes.length; j++) {
            i = str16.indexOf(hex[j * 2]) << 4;
            i += str16.indexOf(hex[j * 2 + 1]);
            bytes[j] = (byte) i;
        }
        return new String(bytes);
    }

    public  String hex2Bin(String hexStr) {
        char[] hexchr = hexStr.toLowerCase().toCharArray();
        String binStr = "";
        for (char i : hexchr) {
            String bin = Integer.toBinaryString(Integer.parseInt(String.valueOf(i),16));
            if (bin.length() < 4) {
                bin = String.join("", Collections.nCopies(4 - bin.length(), "0")) + bin;
            }
            binStr += bin;
        }
        return binStr;
    }
    public String bin2Hex(String bin){
        char[] chars = "0123456789ABCDEF".toCharArray();
        String[] h4 = regex(bin, ".{4}");
        StringBuilder hexstr = new StringBuilder();
        for (String s : h4) {
            hexstr.append(chars[Integer.parseInt(s,2)]);
        }
        return hexstr.toString().trim();
    }

    /**
     * 检查二进制字符串是否是64位
     * @param binStr str
     * @return str64
     */
    public String Check64(String binStr) {
        int num = binStr.length() % 64;
        if (num != 0) {
            binStr += String.join("", Collections.nCopies(64 - num, "0"));
        }
        return binStr;
    }

    /**
     * 正则获取匹配的值
     * @param str 字符串
     * @param regex 正则表达式
     * @return String[]
     */
    public String[] regex(String str,String regex){
        Matcher matcher = Pattern.compile(regex).matcher(str);
        List<String> list = new ArrayList<>();
        while (matcher.find()){
            list.add(matcher.group(0));
        }
        String[] strings = new String[list.size()];
        list.toArray(strings);
        return  strings;
    }

    /**
     * 0 1 的异或
     * @param left 二进制字符串
     * @param right 二进制字符串
     * @return xor
     */
    public String xor(String left,String right){
        StringBuilder str = new StringBuilder();
        char[] leftchr = left.toCharArray();
        char[] rightchr = right.toCharArray();
        for (int i = 0; i < leftchr.length; i++) {
            str.append(leftchr[i] ^rightchr[i]);
        }
        return str.toString().trim();
    }

    /**
     * F函数的实现
     * @param bin32 64位明文的右边32位
     * @param key  当前轮的加密秘钥
     * @return
     */
    public String f_function(String bin32,String key){
        //E表置换
        bin32 = Swap(bin32,E);
        // 异或
        String xor = xor(bin32, key);
        //S盒代换
        String[] slist = regex(xor, ".{6}");
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < slist.length; i++) {
            String s = slist[i];
            int h = Integer.parseInt(s.substring(0,1) + s.substring(5),2);
            int l = Integer.parseInt(s.substring(1,5) ,2);
            String i1 = Integer.toBinaryString(S[i][h * 16 + l]);
            if (i1.length()<4){
                i1 = String.join("",Collections.nCopies(4-i1.length(),"0"))+i1;
            }
            builder.append(i1);
        }
        //P置换
        String trim = builder.toString().trim();
        return Swap(trim,P);
    }

    /**
     * 轮函数
     * @param bin64 64位明文二进制
     * @param keys 16组秘钥
     * @return
     */
    public String Wheel(String bin64,String[] keys){
        bin64 = Swap(bin64,IP_table); // 初始置换
        String leftbin = bin64.substring(0,32);
        String rightbin = bin64.substring(32);
        for (String key : keys) {
            String temp = rightbin;
            String f_function = f_function(rightbin, key);
            rightbin = xor(leftbin, f_function);
            leftbin = temp;
        }
        return Swap(rightbin+leftbin,IP_re_table);
    }

    /**
     * 生成16组秘钥
     * @param binKey 初始秘钥的二进制
     * @return keys[]
     */
    public String[] generateKey(String binKey) {
        List<String> list = new ArrayList<>();
        String leftbin, rightbin;
        binKey = Swap(binKey,PC_1);
        leftbin = binKey.substring(0,28);
        rightbin = binKey.substring(28,56);
        for (int i : SHIFT) {
            leftbin = leftbin.substring(i) + leftbin.substring(0,i);
            rightbin = rightbin.substring(i) + rightbin.substring(0,i);
            list.add(Swap(leftbin+rightbin,PC_2));
        }
        return  list.toArray(new String[list.size()]);
    }

    /**
     * 置换运算
     * @param swap 待置换的字符串
     * @param table 置换表
     * @return 置换后的字符串
     */
    public static String Swap(String swap, int[] table) {
        char[] array = swap.toCharArray();
        StringBuilder string = new StringBuilder();
        for (int i = 0; i < table.length; i++) {
            string.append(array[table[i]-1]);
        }
        return string.toString().trim();
    }


    public static final int[] PC_1 = {57, 49, 41, 33, 25, 17, 9,
            1, 58, 50, 42, 34, 26, 18,
            10, 2, 59, 51, 43, 35, 27,
            19, 11, 3, 60, 52, 44, 36,
            63, 55, 47, 39, 31, 23, 15,
            7, 62, 54, 46, 38, 30, 22,
            14, 6, 61, 53, 45, 37, 29,
            21, 13, 5, 28, 20, 12, 4};
    public static final int[] PC_2 = {14, 17, 11, 24, 1, 5, 3, 28,
            15, 6, 21, 10, 23, 19, 12, 4,
            26, 8, 16, 7, 27, 20, 13, 2,
            41, 52, 31, 37, 47, 55, 30, 40,
            51, 45, 33, 48, 44, 49, 39, 56,
            34, 53, 46, 42, 50, 36, 29, 32};
    public static final int[] SHIFT = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
    public static final int[][] S = {
            {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
                    0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
                    4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
                    15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13},

            {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
                    3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
                    0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
                    13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9},

            {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
                    13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
                    13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
                    1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12},

            {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
                    13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
                    10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
                    3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},

            {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
                    14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
                    4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
                    11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3},

            {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
                    10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
                    9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
                    4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13},

            {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
                    13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
                    1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
                    6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12},

            {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
                    1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
                    7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
                    2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}

    };
    public static final int[] P = {
            16, 7, 20, 21, 29, 12, 28, 17,
            1, 15, 23, 26, 5, 18, 31, 10,
            2, 8, 24, 14, 32, 27, 3, 9,
            19, 13, 30, 6, 22, 11, 4, 25};
    public static final int[] E = {
            32, 1, 2, 3, 4, 5, 4, 5,
            6, 7, 8, 9, 8, 9, 10, 11,
            12, 13, 12, 13, 14, 15, 16, 17,
            16, 17, 18, 19, 20, 21, 20, 21,
            22, 23, 24, 25, 24, 25, 26, 27,
            28, 29, 28, 29, 30, 31, 32, 1};
    public static final int[] IP_table = {
            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};
    public static final int[] IP_re_table = {
            40, 8, 48, 16, 56, 24, 64, 32, 39,
            7, 47, 15, 55, 23, 63, 31, 38, 6,
            46, 14, 54, 22, 62, 30, 37, 5, 45,
            13, 53, 21, 61, 29, 36, 4, 44, 12,
            52, 20, 60, 28, 35, 3, 43, 11, 51,
            19, 59, 27, 34, 2, 42, 10, 50, 18,
            58, 26, 33, 1, 41, 9, 49, 17, 57, 25};

}

Python代码

import re


class DesUtil:
    """
    使用:
    des = DesUtil()
    print(des.encryption("加密的明文", "秘钥"))
    print(des.decryption("密文", "秘钥"))
    """

    # ============== 进制转换====================

    def bin2hex(self, bin):
        hextable = "0123456789ABCDEF"
        binlist = re.findall(r".{4}", bin)
        s = ""
        for i in binlist:
            s += hextable[int(i, 2)].lower()
        return s

    def hex2bin(self, hex):
        hex_table = "0123456789ABCDEF"
        s = ""
        for i in hex:
            k = str(bin(hex_table.find(i.upper()))[2:])
            if len(k) < 4:
                k = (4 - len(k)) * "0" + k
            s += k
        return s

    def str2hex(self, string: str):
        return bytes.hex(string.encode('utf8'))

    def hex2str(self, hexstr):
        return bytes.fromhex(hexstr).decode().replace(b"\x00".decode(), "") # 去除空格

    def encryption(self, msg: str, key: str):
        """
        DES加密
        :param msg: 明文消息
        :param key: 明文秘钥
        :return: 密文
        """
        binMsgList = re.findall(r".{64}", self.text2Bin(msg))  # 64bit文明二进制列表
        k64 = re.findall(r".{64}", self.text2Bin(key))[0]  # 秘钥二进制流
        binKeyList = self.generateKeyTo16(k64)
        binaryCipher = ""
        for bitTo64 in binMsgList:
            binaryCipher += self.WheelFunction(bitTo64, binKeyList)
        return self.bin2hex(binaryCipher)

    def decryption(self, msg: str, key: str):
        """
        DES解密
        :param msg: 密文
        :param key: 秘钥
        :return: 明文
        """
        binMsgList = re.findall(r".{64}", self.hex2bin(msg))  # 64bit文明二进制列表
        k64 = re.findall(r".{64}", self.text2Bin(key))[0]  # 秘钥二进制流m
        binKeyList = self.generateKeyTo16(k64)
        binaryCipher = ""
        for bitTo64 in binMsgList:
            binaryCipher += self.WheelFunction(bitTo64, binKeyList[::-1])
        return self.hex2str(self.bin2hex(binaryCipher))

    def text2Bin(self, txt: str) -> str:
        """
        将明文 or 秘钥转换为二进制流 且%64=0
        :param txt: 输入的明文或秘钥
        :return: 运算的二进制流
        """
        txt = self.str2hex(txt)  # 字符串转十六进制字符串
        bintxt = self.hex2bin(txt)  # 十六进制字符串 转 二进制字符串
        k = len(bintxt) % 64
        if k != 0:
            bintxt += "0" * (64 - k)
        return bintxt

    def generateKeyTo16(self, binKey: str):
        """
        生成16组秘钥
        :param binKey: 初始秘钥
        :return: 16组秘钥列表
        """
        keyList = []
        # 置换选择PC-1
        z1 = ""
        for i in self.PC_1:
            z1 += binKey[i - 1]
        # 28 bit key
        leftKey = z1[:28]
        rightKey = z1[28:]

        def leftShift(m, s):  # 移位函数 s:移多少
            return m[s:] + m[:s]

        for shift in self.SHIFT:
            leftKey = leftShift(leftKey, shift)
            rightKey = leftShift(rightKey, shift)
            # 置换选择PC-2
            zh = leftKey + rightKey
            ans = ""
            for i in self.PC_2:
                ans += zh[i - 1]
            keyList.append(ans)  # 添加秘钥
        return keyList

    # XOR 异或操作
    def msgXorKey(self, left, right) -> str:
        xor = ""
        for i in range(len(left)):
            xor += str(int(left[i]) ^ int(right[i]))
        return xor

    # f函数
    def FFunction(self, binText: str, binKey: str) -> str:
        # 定义几个函数
        # E表扩展
        def e_Extend(bintxt) -> str:
            e = ""
            for i in self.E:
                e += bintxt[i - 1]
            return e

        # S盒处理
        def S_Box(bintxt: str) -> str:
            ans = ""
            bit6list = re.findall(r".{6}", bintxt)
            flag = 0
            for b in bit6list:
                k = int(b[0] + b[len(b) - 1], 2)  # 获取 行
                v = int(b[1:5], 2)  # 获取列
                sValue = bin(self.S[flag][k * 16 + v])[2:]  # S盒查询的结果转2进制
                if len(sValue) < 4:
                    sValue = "0" * (4 - len(sValue)) + sValue
                flag += 1
                ans += sValue
            return ans

        # P置换
        def P_Swap(bintxt: str) -> str:
            ans = ""
            for i in self.P:
                ans += bintxt[i - 1]
            return ans

        # 开始处理  E表->异或->S盒->P置换
        return P_Swap(S_Box(self.msgXorKey(e_Extend(binText), binKey)))

    # ip置换和逆置换
    def ip_Swap(self, bit, reTable=False):
        n = ""
        if reTable is True:
            for i in self.IP_re_table:
                n += bit[i - 1]
        else:
            for i in self.IP_table:
                n += bit[i - 1]
        return n

    # 轮函数
    def WheelFunction(self, bitTo64: str, keyList: list):
        # 初始置换(IP置换)
        n = self.ip_Swap(bitTo64)
        leftBit = n[:32]
        rightBit = n[32:]
        # 获取16轮秘钥
        for rot in keyList:  # 16轮加密
            temp = rightBit
            k32 = self.FFunction(rightBit, rot)
            rightBit = self.msgXorKey(leftBit, k32)  # 异或
            leftBit = temp
        # 左右交换
        swapValue = rightBit + leftBit
        # 逆 初始置换
        Ciphertext = self.ip_Swap(swapValue, True)
        return Ciphertext

    IP_table = [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]

    IP_re_table = [40, 8, 48, 16, 56, 24, 64, 32, 39,
                   7, 47, 15, 55, 23, 63, 31, 38, 6,
                   46, 14, 54, 22, 62, 30, 37, 5, 45,
                   13, 53, 21, 61, 29, 36, 4, 44, 12,
                   52, 20, 60, 28, 35, 3, 43, 11, 51,
                   19, 59, 27, 34, 2, 42, 10, 50, 18,
                   58, 26, 33, 1, 41, 9, 49, 17, 57, 25]

    E = [32, 1, 2, 3, 4, 5, 4, 5,
         6, 7, 8, 9, 8, 9, 10, 11,
         12, 13, 12, 13, 14, 15, 16, 17,
         16, 17, 18, 19, 20, 21, 20, 21,
         22, 23, 24, 25, 24, 25, 26, 27,
         28, 29, 28, 29, 30, 31, 32, 1]

    P = [16, 7, 20, 21, 29, 12, 28, 17,
         1, 15, 23, 26, 5, 18, 31, 10,
         2, 8, 24, 14, 32, 27, 3, 9,
         19, 13, 30, 6, 22, 11, 4, 25]

    S = [
        [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
         0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
         4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
         15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],

        [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
         3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
         0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
         13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],

        [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
         13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
         13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
         1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],

        [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
         13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
         10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
         3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],

        [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
         14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
         4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
         11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],

        [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
         10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
         9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
         4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],

        [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
         13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
         1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
         6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],

        [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
         1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
         7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
         2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],

    ]
    # key
    PC_1 = [57, 49, 41, 33, 25, 17, 9,
            1, 58, 50, 42, 34, 26, 18,
            10, 2, 59, 51, 43, 35, 27,
            19, 11, 3, 60, 52, 44, 36,
            63, 55, 47, 39, 31, 23, 15,
            7, 62, 54, 46, 38, 30, 22,
            14, 6, 61, 53, 45, 37, 29,
            21, 13, 5, 28, 20, 12, 4]

    PC_2 = [14, 17, 11, 24, 1, 5, 3, 28,
            15, 6, 21, 10, 23, 19, 12, 4,
            26, 8, 16, 7, 27, 20, 13, 2,
            41, 52, 31, 37, 47, 55, 30, 40,
            51, 45, 33, 48, 44, 49, 39, 56,
            34, 53, 46, 42, 50, 36, 29, 32]

    SHIFT = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]

版权声明:
作者:乘风归去
链接:https://www.lightr.cn/archives/1332.html
来源:乘风小栈
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
< <上一篇
下一篇>>
文章目录
关闭
目 录