DES(Data Encryption Standard)是迄今为止世界上最为广泛使用和流行的一种分组密码算法,它的分组长度为64比特,密钥长度为56比特,它是由美国IBM公司研制的,是早期的称作Lucifer密码的一种发展和修改。 每隔五年由美国国家保密局(NSA)作出评估,并重新批准它是否继续作为联邦加密标准。最后一次评估是在1994年1月,美国已决定1998年12月以后将不再使用DES。 DES是第一代公开的、完全说明细节的商业级现代算法,并被世界公认。
DES的加密过程:
明文二进制的加密:
将明文数据转为二进制
,再将二进制数据分组
,每组64位,组元素不满64 则在后面补0,满64为止。再将每一组64bit数据进行初始置换
在进行轮函数。
轮函数中将右边32bit
进行F运算
,然后与左边32bit进行异或
,得到的结果作为下一轮右边
将刚开始的右边作为下一轮左边
,依次循环16次
,最后进行逆初始置换
,即可得到密文二进制
。
将明文秘钥转换为二进制 ,取56bit
为一组,不满56bit 补0
,然后进行秘钥生成,将得到的秘钥组
,分别拿去参与每一轮的F运算
,即第一组秘钥对应第一轮F函数
,生成的每组秘钥长度为:48bit
加密和解密一样,不同的点是,最后一组秘钥对应第一轮F函数
,即把秘钥组反过来
而已。
看完大致流程,我们来看看具体的代码实现,有Java版和Python版,为了方便就以Python版来讲解,文章末尾会附上Java和Python的全部代码。
实现的过程我们根据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中是这样,原来在Java版
代码中可以详细看看怎么实现。
结果如下
:
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
生成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
函数的输入分析: 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)))
参数
: 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
整合上面实现加密
参数
: 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进制
接收参数
: 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]