> 文章列表 > DES密码算法和python实现

DES密码算法和python实现

DES密码算法和python实现

1. 前言

        DES 算法是一种常见的分组加密算法,由IBM公司在1971年提出。DES 算法是分组加密算法的典型代表。其加密运算、解密运算使用相同的秘钥。

        DES 算法利用56+8奇偶校验位(第8,16,24,32,40,48,56,64)=64位的密钥对以64位为单位的块数据进行加解密。

        DES算法是以64位为一组分组加密的,所以当输入的明文长度,不满足64的整数倍时,需要涉及到数据的填充。

        DES算法将输入明文分为N个64位大小的分组,然后依次根据加密运算,生成N组加密后的密文 ,将生成的N组密文,就是我们要最终的成果——DES密文输出。

        包含DES算法在内的现代密码学知识可以查看以下博客

CISSP考试要求里的“应用密码学”内容辅助记忆趣味串讲_晓翔仔的博客-CSDN博客

2.  DES加密原理

2.1 初始置换

初始置换就是将明文M打乱重排序。并生成L0 , R0

2.2 生成子秘钥

DES加密的过程,明文M共经历了16次运算迭代,每次迭代的数据长度是48 ,因此我们需要16组48位的加密秘钥来进行加密。

        PC-1置换

        PC-2置换

2.3  迭代的过程

f函数

         f函数就是不断计算Li,Ri的过程,此过程包括四个部分:E盒置换、S盒置换、P盒置换、左右校验

2.4 逆置换

2.5 解密

        解密过程同加密过程,只不过是按照反向的次序。

2.6 数据填充

        当明文长度不为分组长度的整数倍时,需要在最后一个分组中填充一些数据使其凑满一个分组长度。

NoPadding
API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充\\0或者空格,然后trim

PKCS5Padding
加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8
解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文。
加密字符串为为AAA,则补位为AAA55555;加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。

PKCS7Padding
PKCS7Padding 的填充方式和PKCS5Padding 填充方式一样。只是加密块的字节数不同。PKCS5Padding明确定义了加密块是8字节,PKCS7Padding加密快可以是1-255之间。

2.7 加密模式

电子代码本(Electronic CodeBook, ECB)模式

        一般用途:加密少量数据,如秘钥和PIN值

密码分组链接(Cipher Block Chaini吨, CBC)模式

         一般用途:加密大型数据

密码回馈(Cipher FeedBack, CFB)模式

        一般用途:加密较小数据,单独加密每个位

输出回馈(Output FeedBack, OFB)模式

        特点:比OFB发生扩展错误的可能性小

计数(CounTeR, CTR)模式。

        特点:IV计数器,并行

参考

这篇博客将DES加密原理讲的通俗易懂,值得阅读。

DES加密算法原理及代码实现_des加密算法代码_better_hui的博客-CSDN博客

3. 代码实现

3.1 ECB和CBC模式的加解密代码

from pyDes import des, CBC, PAD_PKCS5
import binasciidef bytesToHexString(data):temp = []for i in data:temp.append('0x%02X' % i)return temp"""DES-ECB 加密:param s: 原始字符串,密钥:return: 加密后字符串,16进制"""def des_encrypt(s, key):secret_key = keyiv = secret_keyk = des(secret_key)en = k.encrypt(s)return binascii.b2a_hex(en)"""DES-ECB 解密:param s: 原始字符串,密钥:return: 解密后字符串,16进制"""def des_decrypt(s, key):secret_key = keyiv = secret_keyk = des(secret_key)en = k.decrypt(s)return binascii.b2a_hex(en)"""DES-CBC 加密:param s: 原始字符串,密钥:return: 加密后字符串,16进制"""def des_cbc__encrypt(s, key, iv):secret_key = keyk = des(secret_key, mode=CBC, IV=iv)en = k.encrypt(s)return binascii.b2a_hex(en)"""DES-CBC 加密:param s: 原始字符串,密钥:return: 加密后字符串,16进制"""def des_cbc__decrypt(s, key, iv):secret_key = keyk = des(secret_key, mode=CBC, IV=iv)en = k.decrypt(s)return binascii.b2a_hex(en)if __name__ == '__main__':data = '1111111111111111'key = '1111111111111111'iv = '1111111111111111'  # iv 仅仅用于cbc模式,若iv设置为全0,则CBC模式的计算结果和ECB模式是一样的print("data:", data, "key:", key, "iv:", iv)print("des ecb encrypt result:", des_encrypt(bytes.fromhex(data), bytes.fromhex(key)))print("des ecb decrypt result:", des_decrypt(bytes.fromhex(data), bytes.fromhex(key)))print("des cbc encrypt result:",des_cbc__encrypt(bytes.fromhex(data), bytes.fromhex(key), bytes.fromhex(iv)))print("des cbc decrypt result:",des_cbc__decrypt(bytes.fromhex(data), bytes.fromhex(key), bytes.fromhex(iv)))

自测结果

data: 1111111111111111 key: 1111111111111111 iv: 1111111111111111
des ecb encrypt result: b'f40379ab9e0ec533'
des ecb decrypt result: b'237b2304c393d3ac'
des cbc encrypt result: b'82e13665b4624df5'
des cbc decrypt result: b'326a3215d282c2bd'Process finished with exit code 0

3.2 一种应用场景下的DES解码编码python代码

已知:

1.使用DES ECB密码算法,秘钥已经获取到。

2. 获取到"明文前缀“+密文",都是十六进制表示,密文由"固定长度的固定位 + 时间戳+ crc"组成。crc 使用ccitt_false模式。

需要:

明文前缀不变,密文DES解码后,更新时间戳为最新,并重新计算crc,再加密生成转发数据。

python程序:

import pyDes
from pyDes import des, CBC, PAD_PKCS5, ECB
import binascii
import datetime
from time import time
from binascii import unhexlify
from crcmod import mkCrcFun# CRC16/CCITT
def crc16_ccitt(s):crc16 = mkCrcFun(0x11021, rev=True, initCrc=0x0000, xorOut=0x0000)return get_crc_value(s, crc16)# CRC16/CCITT-FALSE
def crc16_ccitt_false(s):crc16 = mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000)return get_crc_value(s, crc16)# CRC16/MODBUS
def crc16_modbus(s):crc16 = mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)return get_crc_value(s, crc16)# CRC16/XMODEM
def crc16_xmodem(s):crc16 = mkCrcFun(0x11021, rev=False, initCrc=0x0000, xorOut=0x0000)return get_crc_value(s, crc16)# common func
def get_crc_value(s, crc16):data = s.replace(' ', '')crc_out = hex(crc16(unhexlify(data))).upper()str_list = list(crc_out)if len(str_list) == 5:str_list.insert(2, '0')  # 位数不足补0crc_data = ''.join(str_list[2:])# return crc_data[:2] + ' ' + crc_data[2:]return crc_data[:2] + crc_data[2:]def bytesToHexString(data):temp = []for i in data:temp.append('0x%02X' % i)return temp"""DES-ECB 加密:param s: 原始字符串,密钥:return: 加密后字符串,16进制"""def des_encrypt(s, key):secret_key = keyiv = secret_keyk = des(secret_key, pyDes.ECB, IV=iv, padmode=pyDes.PAD_PKCS5)en = k.encrypt(s)return binascii.b2a_hex(en)"""DES-ECB 解密:param s: 原始字符串,密钥:return: 解密后字符串,16进制"""def des_decrypt(s, key):secret_key = keyiv = secret_keyk = des(secret_key, pyDes.ECB, IV=iv, padmode=pyDes.PAD_PKCS5)en = k.decrypt(s)return binascii.b2a_hex(en)if __name__ == '__main__':key = '1111111111111111'input_data = '0101e1618051991f4520329c8dec711dd986f7ebf5dcdf7aeec6'print("输入报文:", input_data)fix_mingwen = input_data[:4]print("输入数据的明文部分是", fix_mingwen)input_data_miwen = input_data[4:]print("输入数据的密文部分是:", input_data_miwen)data_body = repr(des_decrypt(bytes.fromhex(input_data_miwen), bytes.fromhex(key)))[2:-1]print("解密后的明文:", data_body)# 计算此刻的时间戳timestamp = hex(int(time())).strip("0x")print("此时的时间戳:", timestamp)# 计算明文data_body = repr(data_body)[1:29] + timestamp#crc16 计算有多种模式,这里用crc16_ccitt_falsecrc16_result = crc16_ccitt_false(data_body)data_body = data_body + crc16_resultprint("更新的时间戳的明文:", data_body)data_body_secrect = des_encrypt(bytes.fromhex(data_body), bytes.fromhex(key))data_body_secrect = repr(data_body_secrect)[2:-1]print("加密后的密文: ", data_body_secrect)data_body_secrect_all = fix_mingwen + data_body_secrectprint("输出加密后的完整报文:", data_body_secrect_all)data_body_length = len(data_body_secrect_all) // 2dataList = []for i in range(0, data_body_length):dataList.append(data_body_secrect_all[2 * i] + data_body_secrect_all[2 * i + 1])  # 每个字节由相邻两个16机制字符组成data_body_kongge = " ".join(dataList)print("含有空格的报文表示:", data_body_kongge)

自测结果:

输入报文: 0101e1618051991f4520329c8dec711dd986f7ebf5dcdf7aeec6
输入数据的明文部分是 0101
输入数据的密文部分是: e1618051991f4520329c8dec711dd986f7ebf5dcdf7aeec6
解密后的明文: 7072656668313233343536373839644335d2ff0b
此时的时间戳: 64433e0f
更新的时间戳的明文: 707265666831323334353637383964433e0f3921
加密后的密文:  e1618051991f4520329c8dec711dd986d35c06166403b220
输出加密后的完整报文: 0101e1618051991f4520329c8dec711dd986d35c06166403b220
含有空格的报文表示: 01 01 e1 61 80 51 99 1f 45 20 32 9c 8d ec 71 1d d9 86 d3 5c 06 16 64 03 b2 20Process finished with exit code 0

5. 最后

        DES由于密钥过短,并不认识是安全的密码学算法。一般推荐更新为3DES算法。