DES encryption algorithm and python implementation

1 Introduction

        The DES algorithm is a common block encryption algorithm proposed by IBM in 1971. DES algorithm is a typical representative of block encryption algorithm. Its encryption operation and decryption operation use the same secret key.

        The DES algorithm uses 56+8 parity bits (8th, 16th, 24th, 32nd, 40th, 48th, 56th, 64th) = 64-bit key to encrypt and decrypt block data in units of 64 bits.

        The DES algorithm uses 64 bits as a group of block encryption, so when the length of the input plaintext does not satisfy the integer multiple of 64, it needs to involve data padding.

        The DES algorithm divides the input plaintext into N 64-bit groups, and then generates N groups of encrypted ciphertexts according to the encryption operation. The generated N groups of ciphertexts are the final result we want - DES ciphertext output .

        For modern cryptography knowledge including DES algorithm, you can check the following blog

The "Applied Cryptography" content in the CISSP exam requirements assists memory and interesting lectures_Xiaoxiangzai's Blog-CSDN Blog

2. DES encryption principle

2.1 Initial replacement

The initial permutation is to scramble and reorder the plaintext M. and generate L0 , R0

2.2 Generate subkey

During the DES encryption process, the plaintext M has undergone 16 operation iterations, and the data length of each iteration is 48, so we need 16 sets of 48-bit encryption keys for encryption.

        PC-1 replacement

        PC-2 replacement

2.3 Iterative process

f function

         The f function is the process of continuously calculating Li and Ri. This process includes four parts: E box replacement, S box replacement, P box replacement, left and right check

2.4 Inverse permutation

2.5 Decryption

        The decryption process is the same as the encryption process, but in reverse order.

2.6 Data filling

        When the length of the plaintext is not an integer multiple of the packet length, some data needs to be filled in the last packet to make up a packet length.

The NoPadding
API or the algorithm itself does not process the data, and the encrypted data is filled with the algorithm agreed upon by the encryption parties. For example, if you want to encrypt and decrypt string data, you can add \0 or spaces, and then trim

Before PKCS5Padding
encryption: the data byte length is 8, and the remainder is m. If m>0, then make up 8-m bytes, and the byte value is 8-m. section, the byte value is the number of bytes to be added, if it is 0, then 8 bytes will be added
after decryption: take the last byte, the value is m, then delete m bytes from the end of the data, and the remaining data is is the original text before encryption.
If the encrypted string is AAA, the padding is AAA55555; if the encrypted string is BBBBBB, the padding is BBBBBB22; if the encrypted string is CCCCCCCC, the padding is CCCCCCCC88888888.

PKCS7Padding
The filling method of PKCS7Padding is the same as that of PKCS5Padding. Only the number of bytes of the encrypted block is different. PKCS5Padding clearly defines that the encryption block is 8 bytes, and the encryption block of PKCS7Padding can be between 1-255.

2.7 Encryption mode

Electronic CodeBook (ECB) mode

        General purpose: Encrypt small amounts of data, such as secret keys and PIN values

Cipher Block Chaining (Cipher Block Chaining, CBC) mode

         General Purpose: Encrypting Large Data

Cipher FeedBack (CFB) mode

        General Purpose: Encrypting smaller data, encrypting each bit individually

Output FeedBack (OFB) mode

        Features: less likely to have expansion errors than OFB

Count (CounTeR, CTR) mode.

        Features: IV counter, parallel

reference

This blog explains the principles of DES encryption in an easy-to-understand way, and it is worth reading.

DES encryption algorithm principle and code implementation_des encryption algorithm code_better_hui's blog-CSDN blog

3. Code implementation

3.1 Encryption and decryption codes in ECB and CBC modes

from pyDes import des, CBC, PAD_PKCS5
import binascii


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 = key
    iv = secret_key
    k = 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 = key
    iv = secret_key
    k = 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 = key

    k = 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 = key

    k = 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)))

self test results

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 decoding and encoding python code in an application scenario

A known:

1. Using the DES ECB encryption algorithm, the secret key has been obtained.

2. Obtained "plaintext prefix" + ciphertext", which are all represented in hexadecimal. The ciphertext is composed of "fixed length fixed bits + timestamp + crc". crc uses ccitt_false mode.

need:

The prefix of the plaintext remains unchanged. After the ciphertext is decoded by DES, the timestamp is updated to the latest, and the crc is recalculated, and then encrypted to generate forwarded data.

python program:

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')  # 位数不足补0
    crc_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 = key
    iv = secret_key
    k = 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 = key
    iv = secret_key
    k = 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_false
    crc16_result = crc16_ccitt_false(data_body)
    data_body = data_body + crc16_result
    print("更新的时间戳的明文:", 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_secrect
    print("输出加密后的完整报文:", data_body_secrect_all)

    data_body_length = len(data_body_secrect_all) // 2
    dataList = []
    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)

Self-test results:

输入报文: 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 20

Process finished with exit code 0

4. Finally

        DES is not considered a secure cryptographic algorithm because the key is too short. It is generally recommended to update to the 3DES algorithm.

Guess you like

Origin blog.csdn.net/qq_33163046/article/details/130300157