DES加密算法及演示程序(GO-算法核心实现+Python-前端演示系统)

一. 个人感悟

该程序实现了DES加密算法的软件实现,使用Golang语言实现核心算法,使用Python实现前端展示程序,功能有字符串的加解密演示、文件的加解密演示。

1. 首先,DES是第一次写, 还是花费了一天多的时间, 包括在网上学习, 手动实现. 同样使用go语言实现, 并且封装了exe.
2. 这次遇到的bug主要是, 
 1. s盒的时候, 列索引没有初始化变量, 导致越界访问
 2. 密钥生成的移位运算没有将结果暂存, 然后进行第二次移位, 而是使用原始的C再进行第二次移位, 导致计算错误,后来修改.
3. 对于DES的这个算法, 网上很多教程, 都是使用置换表去做, 但是我细想, E置换还有一些其他的置换也可以用for来实现的, 但是无奈, 我真的时间不够了, 就先写成这样吧
4. 对于加解密演示程序的密钥生成, 这里暂时没有考虑校验位的值, 算的时候也会被抛弃掉, 后续再看情况补充吧

二. 结果验证

  1. 我的计算结果:

  1. 网站验证

  1. 多余的我就不验证了, 我已经测试好了, 都是对的.

三. 程序源码

  1. des.go

/*
************************************************************************

	> File Name: des.go
	> Author: Yu/Jinyang
	> Created Time: 2022/11/15

***********************************************************************
*/
package des

import (
	"fmt"
	"math"
	"strconv"
)

type Des struct {
	plain_text   string //明文字符串
	key          string //密钥字符串
	key_inter_v  [64]uint64
	internediate [64]uint64
	left         [32]uint64
	right        [32]uint64
	eachKey      [16][48]uint64
}

func (des *Des) SetVariable(p, k string) {
	des.plain_text = p
	des.key = k
	des.dataFormat()
}

func (des *Des) dataFormat() {

	for i := 0; i < 16; i++ {
		tem, err := strconv.ParseUint(des.plain_text[i:i+1], 16, 64)
		des.internediate[(i*4)+3] = (tem & 0x01) >> 0
		des.internediate[(i*4)+2] = (tem & 0x02) >> 1
		des.internediate[(i*4)+1] = (tem & 0x04) >> 2
		des.internediate[(i*4)+0] = (tem & 0x08) >> 3
		if err != nil {
			fmt.Println(i, "error")
		}
		tem, err = strconv.ParseUint(des.key[i:i+1], 16, 64)
		des.key_inter_v[(i*4)+3] = (tem & 0x01) >> 0
		des.key_inter_v[(i*4)+2] = (tem & 0x02) >> 1
		des.key_inter_v[(i*4)+1] = (tem & 0x04) >> 2
		des.key_inter_v[(i*4)+0] = (tem & 0x08) >> 3
		if err != nil {
			fmt.Println(i, "error")
		}
	}
	des.keyGenerate()

}

func (des *Des) initialPermutations() {
	IP := [8][8]int{{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}}

	var temp [64]uint64
	for i := 0; i < 8; i++ {
		for j := 0; j < 8; j++ {
			temp[(i*8)+j] = uint64(des.internediate[IP[i][j]-1])
		}
	}
	des.internediate = temp
}

func (des *Des) initialPermutationsInverse() {
	IP := [8][8]int{{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}}

	var temp [64]uint64
	for i := 0; i < 8; i++ {
		for j := 0; j < 8; j++ {
			temp[(i*8)+j] = uint64(des.internediate[IP[i][j]-1])
		}
	}
	des.internediate = temp
}

func (des *Des) separateLeftAndRight() {
	for i := 0; i < 32; i++ {
		des.left[i] = des.internediate[i]
		des.right[i] = des.internediate[i+32]
	}
}

func (des *Des) format() string {
	var ret string
	for j := 0; j < 16; j++ {
		tem := des.internediate[j*4] << 3
		tem += des.internediate[j*4+1] << 2
		tem += des.internediate[j*4+2] << 1
		tem += des.internediate[j*4+3]
		tem2 := fmt.Sprintf("%01x", tem)
		ret += tem2
	}
	return ret
}

func (des *Des) Encode() string {
	des.initialPermutations()
	// fmt.Println("初始置换: ", des.format())
	des.separateLeftAndRight()
	// ff
	for i := 0; i < 16; i++ {
		des.ff(i)
		for i := 0; i < 32; i++ {
			des.internediate[i+32] = des.right[i]
			des.internediate[i] = des.left[i]
		}
		// fmt.Println("key ", i, ": ", des.eachKey[i])
		// fmt.Println("Round ", i, ": ", des.format())
	}
	// ip-1
	for i := 0; i < 32; i++ {
		des.internediate[i] = des.right[i]
		des.internediate[i+32] = des.left[i]
	}
	des.initialPermutationsInverse()
	// fmt.Println("初始IP置换后:", des.internediate)
	return des.format()
}

func (des *Des) Decode() string {
	for i := 0; i < 8; i++ {
		tem := des.eachKey[i]
		des.eachKey[i] = des.eachKey[15-i]
		des.eachKey[15-i] = tem
	}
	return des.Encode()
}

func (des *Des) ff(i int) {
	tem := des.eTransform()
	tem2 := des.xorWithKey(i, tem)
	tem3 := des.ss(tem2)
	tem4 := des.pTransform(tem3)
	tem5 := des.xorWithL0(tem4)
	des.left = des.right
	des.right = tem5
}

func (des *Des) eTransform() [48]uint64 {
	var ret [48]uint64
	bitChoiceLabel := [48]uint64{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}
	for i := 0; i < 48; i++ {
		ret[i] = des.right[bitChoiceLabel[i]-1]
	}
	return ret
}

func (des *Des) xorWithKey(i int, tempv [48]uint64) [48]uint64 {
	var ret [48]uint64
	for j := 0; j < 48; j++ {
		ret[j] = tempv[j] ^ des.eachKey[i][j]
	}
	return ret
}

func (des *Des) ss(tempv [48]uint64) [32]uint64 {
	boxS := [8][4][16]uint64{ //S1
		{{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}},
		//S2
		{{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}},
		//S3
		{{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}},
		//S4
		{{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}},
		//S5
		{{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}},
		//S6
		{{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}},
		//S7
		{{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}},
		//S8
		{{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}}}
	var row uint64 = 0
	var column uint64 = 0
	var ret [32]uint64
	for i := 0; i < 8; i++ {
		column = 0
		row = tempv[i*6]*2 + tempv[(i*6)+5]
		for j := 1; j < 5; j++ {
			base := uint64(math.Pow(2, float64(4-j)))
			column += tempv[(i*6)+j] * base
		}
		tem_ret := boxS[i][row][column]
		ret[i*4] = (tem_ret & 0x08) >> 3
		ret[i*4+1] = (tem_ret & 0x04) >> 2
		ret[i*4+2] = (tem_ret & 0x02) >> 1
		ret[i*4+3] = (tem_ret & 0x01)
	}
	return ret

}

func (des *Des) pTransform(tempv [32]uint64) [32]uint64 {
	P := [32]uint64{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}
	var ret [32]uint64
	for i := 0; i < 32; i++ {
		ret[i] = tempv[P[i]-1]
	}
	return ret
}

func (des *Des) xorWithL0(tempv [32]uint64) [32]uint64 {
	var ret [32]uint64
	for i := 0; i < 32; i++ {
		ret[i] = tempv[i] ^ des.left[i]
	}
	return ret
}

func (des *Des) keyGenerate() {
	left_move := [16]int{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}
	var c [28]uint64
	var d [28]uint64
	tem_56 := des.pc1Trancform()
	// c, d
	for j := 0; j < 28; j++ {
		c[j] = tem_56[j]
		d[j] = tem_56[j+28]
	}
	for i := 0; i < 16; i++ {
		//c1, d1
		c = des.leftShift(left_move[i], c)
		d = des.leftShift(left_move[i], d)
		for j := 0; j < 28; j++ {
			tem_56[j] = c[j]
			tem_56[j+28] = d[j]
		}
		des.eachKey[i] = des.pc2Trancform(tem_56)
	}
}

func (des *Des) leftShift(i int, c [28]uint64) [28]uint64 {
	var ret [28]uint64
	for j := 0; j < i; j++ {
		tem_0 := c[0]
		for k := 0; k < 27; k++ {
			ret[k] = c[k+1]
		}
		ret[27] = tem_0
		c = ret
	}
	return ret
}

func (des *Des) pc1Trancform() [56]uint64 {
	pc_1 := [8][7]uint64{{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}}
	var temp [56]uint64
	for i := 0; i < 8; i++ {
		for j := 0; j < 7; j++ {
			temp[(i*7)+j] = uint64(des.key_inter_v[pc_1[i][j]-1])
		}
	}
	return temp
}

func (des *Des) pc2Trancform(cd [56]uint64) [48]uint64 {

	pc_2 := [8][6]uint64{{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}}
	var temp [48]uint64
	for i := 0; i < 8; i++ {
		for j := 0; j < 6; j++ {
			temp[(i*6)+j] = uint64(cd[pc_2[i][j]-1])
		}
	}
	return temp
}

2.des_core.go

/*
************************************************************************

	> File Name: main.go
	> Author: Yu/Jinyang
	> Created Time: 2022/11/15

***********************************************************************
*/
package main

import (
	"des-demo/des"
	"fmt"
)

func main() {
	var plaintext string
	// fmt.Println("请输入64位明文(16进制):")
	fmt.Scanln(&plaintext)
	// plaintext = "5469875321456045"
	var key string
	// fmt.Println("请输入64位密钥(16进制):")
	fmt.Scanln(&key)
	// key = "5987423651456987"
	des := des.Des{}
	des.SetVariable(plaintext, key)
	ciphertext := des.Encode()
	fmt.Println(ciphertext)
	plain_text_decoded := des.Decode()
	fmt.Println(plain_text_decoded)
}

3.main.py

import binascii
import os
import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMainWindow, QMessageBox
from random import *
from StaticUI.MainWindow import Ui_MainWindow
import subprocess


# 22kb 50s
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.init_ui()
        self.bind_button()
        self.plaintext = ""
        self.key = ""
        self.key2 = ""
        self.filepath = ""

    def init_ui(self):
        self.label_12.setTextInteractionFlags(Qt.TextSelectableByMouse)
        pass

    def bind_button(self):
        self.pushButton_2.clicked.connect(self.auto_gen_plaintext)
        self.pushButton_3.clicked.connect(self.auto_gen_key)
        self.pushButton_6.clicked.connect(self.auto_gen_key2)

        self.pushButton_4.clicked.connect(self.str_encode_decode)
        self.pushButton_5.clicked.connect(self.file_encode_decode)
        self.toolButton_4.clicked.connect(self.pick_file)
        pass

    def str_encode_decode(self):
        if len(self.plaintext) != 17 or len(self.key) != 17:
            QMessageBox.information(self, "警告", "明文或密钥长度不对!", QMessageBox.Yes)
        else:
            ret = subprocess.Popen(
                "des_core.exe",
                stdout=subprocess.PIPE,
                stdin=subprocess.PIPE,
                stderr=subprocess.PIPE,
            )
            ret.stdin.write(self.plaintext.encode())
            ret.stdin.flush()
            ret.stdin.write(self.key.encode())
            ret.stdin.flush()
            ans1 = ret.stdout.readline().decode()

            ans2 = ret.stdout.readline().decode()
            ret.wait()

            self.lineEdit_3.setText(ans1)
            self.lineEdit_4.setText(ans2)

        pass

    def file_encode_decode(self):
        if len(self.key2) != 17:
            QMessageBox.information(self, "警告", "明文或密钥长度不对!", QMessageBox.Yes)
        else:
            self.lineEdit_6.setText("加密中, 请等待!")
            self.lineEdit_5.setText("解密中, 请等待!")
            f = open(self.filepath, "rb")
            output_encode_file = open("des_encrypted.txt", "wb")
            output_decode_file = open("decode" + self.filepath[-4:], "wb")
            output_encode_buff = ""
            output_decode_buff = ""
            while 1:
                c = f.read(4)
                if not c:
                    break
                else:

                    cc = binascii.hexlify(c)
                    cc = str(cc, encoding="utf-8")
                    fill = 0
                    if len(cc) < 16:
                        fill = 16 - len(cc)
                        cc += (fill) * "0"
                    cc += "\n"
                    cy, m = self.encode_decode(cc, self.key2)
                    # cy = str(cy, encoding='utf-8')
                    cy = cy[:16]
                    cy = binascii.unhexlify(cy)
                    # m = str(m, encoding='utf-8')
                    m = m[:16 - fill]
                    m = binascii.unhexlify(m)
                    # output_encode_buff += cy
                    # output_decode_buff += m
                    output_encode_file.write(cy)
                    output_decode_file.write(m)

                    pass

            self.lineEdit_6.setText(os.getcwd() + "\\des_encrypted.txt")
            self.lineEdit_5.setText(os.getcwd() + "\\decode" + self.filepath[-4:])
            pass

    def auto_gen_plaintext(self):
        plaintext = "".join([choice("0123456789abcdef") for i in range(16)])
        self.plaintext = plaintext + "\n"
        self.lineEdit.setText(plaintext)
        pass

    def auto_gen_key(self):
        plaintext = "".join([choice("0123456789abcdef") for i in range(16)])
        self.key = plaintext + "\n"
        self.lineEdit_2.setText(plaintext)
        pass

    def auto_gen_key2(self):
        plaintext = "".join([choice("0123456789abcdef") for i in range(16)])
        self.key2 = plaintext + "\n"
        self.lineEdit_7.setText(plaintext)
        pass

    def pick_file(self):
        filename, filetype = QtWidgets.QFileDialog.getOpenFileName(self, "选取文件",
                                                                   os.getcwd() + '\\',
                                                                   "All Files(*);;Text Files(*.txt)")
        self.filepath = filename
        self.toolButton_4.setText(filename)

    @staticmethod
    def encode_decode(plaintext, key):
        ret = subprocess.Popen(
            "des_core.exe",
            stdout=subprocess.PIPE,
            stdin=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        ret.stdin.write(plaintext.encode())
        ret.stdin.flush()
        ret.stdin.write(key.encode())
        ret.stdin.flush()
        ans1 = ret.stdout.readline()

        ans2 = ret.stdout.readline()
        ret.wait()
        # print(ans1, ans2)
        return ans1, ans2
        pass


def main():
    app = QtWidgets.QApplication(sys.argv)  # 初始化app
    test = MainWindow()
    test.show()
    sys.exit(app.exec_())
    pass


if __name__ == '__main__':
    main()

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值