一、对称加密 (Symmetric Key Encryption) 

对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。对称加密有很多种算法,由于它效率很高,所以被广泛使用在很多加密协议的核心当中。自1977年美国颁布DES(Data Encryption Standard)密码算法作为美国数据加密标准以来,对称密码体制迅速发展,得到了世界各国的关注和普遍应用。对称密码体制从工作方式上可以分为分组加密和序列密码两大类。

对称加密算法的优点:算法公开、计算量小、加密速度快、加密效率高。

对称加密算法的缺点:交易双方都使用同样钥匙,安全性得不到保证。此外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。而与公开密钥加密算法比起来,对称加密算法能够提供加密和认证却缺乏了签名功能,使得使用范围有所缩小。

对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。

分组密码:也叫块加密(block cyphers),一次加密明文中的一个块。是将明文按一定的位长分组,明文组经过加密运算得到密文组,密文组经过解密运算(加密运算的逆运算),还原成明文组,有 ECB、CBC、CFB、OFB 四种工作模式。

序列密码:也叫流加密(stream cyphers),一次加密明文中的一个位。是指利用少量的密钥(制乱元素)通过某种复杂的运算(密码算法)产生大量的伪随机位流,用于对明文位流的加密。解密是指用同样的密钥和密码算法及与加密相同的伪随机位流,用以还原明文位流。

常用对称加密算法包括 DES、3DES、AES

1. DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合。
2. 3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。
3. AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密。

算法特征
1. 加密方和解密方使用同一个密钥。
2. 加密解密的速度比较快,适合数据比较长时的使用。
3. 密钥传输的过程不安全,且容易被破解,密钥管理也比较麻烦。

二、简介对称加密算法 Des

1、数据加密标准 Des

(1)Des 设计理念

Des 设计中使用了分组密码设计的两个原则:混淆(confusion)和扩散(diffusion),其目的是抗击敌手对密码系统的统计分析。混淆是使密文的统计特性与密钥的取值之间的关系 尽可能复杂化,以使密钥和明文以及密文之间的依赖性对密码分析者来说是无法利用的。扩散的作用就是将每一位明文的影响尽可能迅速地作用到较多的输出密文位中,以便在大量的 密文中消除明文的统计结构,并且使每一位密钥的影响尽可能迅速地扩展到较多的密文位中,以防对密钥进行逐段破译。

2、Des 加密算法结构流程

3、Des 加密算法电子编码本 ECB (Electronic Code Book,电子编码本) 模式流程 

(1)ECB 模式 & 性能

ECB 模式是最简单的加密模式,明文消息被分成固定大小的块(分组),并且每个块被单独加密。每个块的加密和解密都是独立的,且使用相同的方法进行加密,所以可以进行并行计算,但是这种方法一旦有一个块被破解,使用相同的方法可以解密所有的明文数据,安全性比较差。适用于数据较少的情形,加密前需要把明文数据填充到块大小的整倍数。

ECB算法优点:
简单、孤立,每个块单独运算。适合并行运算。传输错误一般只影响当前块。
ECB算法缺点:
同明文输出同密文,可能导致明文攻击。

(2)ECB 加密 & 解密流程

Encryption:

Decryption:

4、Des 分组加密所需参数 

(1)Key:64位主密钥

(2)明文:64位的倍数

(3)密文:64位的倍数

(4)分组模式填充方式:PKCS5

(5)分组密码工作模式:EBC模式

5、Des 加密过程

(1)初始置换(IP)

根据初始置换表,对相应明文位置上的二进制进行置换操作,即把64  位的数据块的原第  58  位换到第一位,原第 50 位换到第二位.依此类推。目的在于打乱明文中各位的次序。

(2)子密钥生成

从用户处取得一个 64 位长的密钥key  ,去除 64 位密钥中作为奇偶校验位的第 8、16、24、32、40、48、56、64 位,剩下的 56 位作为有效输入密钥。把生成的 56 位输入密钥分成均等的 A,B 两部分,每部分为 28 位,使用置换选择 1 对剩下的 58 位打乱,输出左 28 位 C 和右 28 位 D。两个部分都进行向左移位,移位后的两部分数据有两个作用。第一输出子密钥,每 i 轮两部分合在一起进行进行置换选择 2 得到迭代运算的第 i 个子密钥,第二作为下一轮子密钥运算。总共 16 轮运算(i=1,2,9,6 左移 1 位,其余 2 位)。

(3)16 轮迭代运算 (Des 核心)

首先将二进制分为两个 32 位的部分:left 和 right。保持 left 不变,根据扩展置换表把 right 由 32 位扩展成 48 位。把扩展后的 48 位 right 与第 i 次迭代生成的 48 位子密钥按位异或运算,形成一个新的 48 位的 right。然后与主密钥生成的 48 位子密钥异或操作,然后进行 S 盒代换,得到一个 32 位的二进制数据,将数据进行 P 盒置换后,与 left 进行异或操作,结果作为下一轮迭代运算的 right 部分。上一轮 right 部分作为下一轮运算的 left 部分。第 16 次迭代不交换两者的数值。

(4)初始逆置换

16轮迭代运算后,依据初始逆置换表,对相应位置的二进制数进行置换操作。最后得到密文。

6、Des 解密过程

Des 算法是对称的,既可用加密又可用于解密,只不过在16次迭代中使用的密钥次序正好相反。解密时,第一次迭代使用子密钥K16,依次类推。

7、分组密码工作方式

ECB,将明文消息分成 n 个 m  bit 组(m 通常为 64),如果长度不是 m 整数倍,则在明文末尾进行填充 (本次实验采用PKCS5)

三、实现对称加密算法 Des

1、语言 & 环境

(1)语言

Python

(2)环境

Python版本:python 3.7

Python工具:PyCharm Professional

2、操作流程

(1)在 < text.txt > 文件中读取需要加密的文本
(2)在 < key.txt > 文件中写入随机产生固定长度的Key
(3)在 < ciphertext.txt > 文件中写入DES加密、Base64编码后的数据
(4)在 < plaintext.txt > 文件中写入Base64解码、DES解密后的数据

3、主要代码

(1)Main 函数

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 if __name__ == '__main__':
2 key = getRandomString()
3 with open('text.txt', 'r+') as fr:
4 text = (fr.read()) # 从 'text.txt' 文件中读取加密文本
5 D = Des()
6 C = (base64.b64encode((D.encrypt(key, text, True)).encode("utf8"))).decode() # 加密
7 C1 = (base64.b64decode(C)).decode()
8 P = D.decrypt(key, C1, True) # 解密
9 with open('key.txt', 'w+') as fwk: # 存储密钥
10 fwk.write(key)
11 with open('ciphertext.txt', 'w+') as fwc: # 存储密文
12 fwc.write(C)
13 with open('plaintext.txt', 'w+') as fwp: # 存储明文
14 fwp.writelines(P)
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(2)Encryption

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def encrypt(self, key, text, padding): # DES 加密函数
2 return self.run(key, text, ENCRYPT, padding)
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(3)Decryption

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def decrypt(self, key, text, padding): # DES 解密函数
2 return self.run(key, text, DECRYPT, padding)
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(4)字符串和比特数组之间相互转换

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def string_to_bit_array(text): # 字符串-->bit数组
2 array = list()
3 for char in text:
4 binval = binvalue(char, 8) # 获得每个字符的二进制
5 array.extend([int(x) for x in list(binval)])
6 return array
7
8 def bit_array_to_string(array): # bit数组-->字符串
9 res = ''.join([chr(int(y, 2)) for y in [''.join([str(x) for x in bytes]) for bytes in nsplit(array, 8)]])
10 return res
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(5)二进制处理

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def binvalue(val, bitsize): # 以给定大小的字符返回二进制值
2 binval = bin(val)[2:] if isinstance(val, int) else bin(ord(val))[2:]
3 if len(binval) > bitsize:
4 raise Exception("binary value larger than the expected size")
5 while len(binval) < bitsize:
6 binval = "" + binval
7 return binval
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(6)列表划分

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def nsplit(s, n): # 将列表拆分为大小为'n'的子列表
2 return [s[k:k + n] for k in range(0, len(s), n)]
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(7)获取随机固定长度序列 Key

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def getRandomString(slen=8): # 获得key的随机序列
2 return ''.join(random.sample(string.ascii_letters + string.digits, slen))
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(8)初始化 Des 类

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def __init__(self):
2 self.password = None # 存放初始key
3 self.text = None # 存放明文
4 self.keys = list() # 存放key值列表集合
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(9)PKCS5 模式 数据填充

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def addPadding(self): # PKCS5 进行数据填充,不管是否是BlockSize的整数倍都需要进行填充
2 pad_len = 8 - (len(self.text) % 8)
3 self.text += pad_len * chr(pad_len)
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(10)数据填充移除

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def removePadding(self, data): # 删除纯文本的填充
2 pad_len = ord(data[-1])
3 return data[:-pad_len]
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(11)获取 Key 值集合列表

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def generatekeys(self): # 统计计算所有key值的算法
2 self.keys = []
3 key = string_to_bit_array(self.password)
4 key = self.permut(key, CP_1) # 置换选择1 初始化key 64bit-->56bit
5 g, d = nsplit(key, 28) # 分片 (g->LEFT),(d->RIGHT)
6 for i in range(16): # 16轮循环
7 g, d = self.shift(g, d, SHIFT[i]) # (g->LEFT),(d->RIGHT)分别进行移位操作
8 tmp = g + d # 合并 28bit+28bit-->56bit
9 self.keys.append(self.permut(tmp, CP_2)) # 置换选择2 56bit-->48bit
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(12)Key 值移位函数

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def shift(self, g, d, n): # 每轮key值产生所需的函数
2 return g[n:] + g[:n], d[n:] + d[:n]
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(13)基本置换 扩展置换 压缩置换

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def permut(self, block, table): # 置换(本程序中充当基本置换、压缩置换的角色)
2 return [block[x - 1] for x in table]
3
4 def expand(self, block, table): # 扩展置换
5 return [block[x - 1] for x in table]
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(14)自定义 XOR 函数

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def xor(self, t1, t2): # 应用xor并返回结果列表
2 return [x ^ y for x, y in zip(t1, t2)]
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(15)S 盒代换

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 def substitute(self, d_e): # S盒代换
2 subblocks = nsplit(d_e, 6) # 将位数组分割为6位的子列表
3 result = list()
4 for i in range(len(subblocks)): # 遍历子列表
5 block = subblocks[i]
6 row = int(str(block[0]) + str(block[5]), 2) # 得到第一位和最后一个位表示的行
7 column = int(''.join([str(x) for x in block[1:][:-1]]), 2) #得到第二、三、四、五位表示的列
8 val = S_BOX[i][row][column] # 取为本轮分配的SBOX[i]中的值
9 bin = binvalue(val, 4) # 将值转换为二进制
10 result += [int(x) for x in bin] # 将二进制值添加到结果列表中
11 return result
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

(16)16轮运算核心

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
1 for block in text_blocks: # 遍历所有数据块
2 block = string_to_bit_array(block)
3 block = self.permut(block, IP) # 数据块的初始置换
4 g, d = nsplit(block, 32) # 数据块分片 g(LEFT), d(RIGHT)
5 tmp = None
6 for i in range(16): # 16轮循环
7 d_e = self.expand(d, E) # d(RIGHT)的扩展 32bit-->48bit
8 if action == ENCRYPT:
9 tmp = self.xor(self.keys[i], d_e)
10 else:
11 tmp = self.xor(self.keys[15 - i], d_e) # 如果是解密的话先使用最后的key
12 tmp = self.substitute(tmp) # S盒代换 48bit-->32bit
13 tmp = self.permut(tmp, P) # P盒置换
14 tmp = self.xor(g, tmp)
15 g = d
16 d = tmp
17 result += self.permut(d + g, IP_1) # 数据块的初始逆置换
18 final_res = bit_array_to_string(result)
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <

4、数据测试

(1)测试结果

(2)在 < text.txt > 文件中读取需要加密的文本

(3)在 < key.txt > 文件中写入随机产生固定长度的Key

(4)在 < ciphertext.txt > 文件中写入DES加密、Base64编码后的数据

(5)在 < plaintext.txt > 文件中写入Base64解码、DES解密后的数据

5、该项目所有代码文件上传至 Github 

(1)GitHub 主页

https://github.com/Qftm

(2)Des 项目地址

https://github.com/Qftm/My-Des

对称加密算法 ~ Des的更多相关文章

  1. [转] 对称加密算法DES、3DES

    转自:http://www.blogjava.net/amigoxie/archive/2014/07/06/415503.html 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法, ...

  2. 常用加密算法的Java实现总结(二) ——对称加密算法DES、3DES和AES

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

  3. 对称加密算法DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES。

    对称加密算法:DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES. 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文 ...

  4. 对称加密算法DES、3DES和AES 原理总结(转载)

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

  5. java-信息安全(二)-对称加密算法DES,3DES,AES,Blowfish,RC2,RC4

    概述 信息安全基本概念: DES(Data Encryption Standard,数据加密标准) 3DES(Triple DES,三重数据加密算法(TDEA,Triple Data Encrypti ...

  6. 第七章 对称加密算法--DES

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第7章“初等加密算法--对称加密算法” 7.1.对称加密算法 特点: 加密与解密使用同一个密钥 是使用最广的算法 常见对称加密 ...

  7. 对称加密算法-DES以及DESede算法

    一.简述 对称加密算法就是能将数据加解密.加密的时候用密钥对数据进行加密,解密的时候使用同样的密钥对数据进行解密. DES是美国国家标准研究所提出的算法.因为加解密的数据安全性和密钥长度成正比.des ...

  8. 计算机网络安全 —— 对称加密算法 DES

    一.对称加密算法概念 我们通过计算机网络传输数据时,如果无法防止他人窃听, 可以利用密码学技术将发送的数据变换成对任何不知道如何做逆变换人都不可理解的形式, 从而保证了数据的机密性.这种变换被称为加密 ...

  9. DES、3DES、AES、PBE对称加密算法实现及应用

    1.对称加密算法概述 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去.收信方收到密文后,若想解读原文 ...

随机推荐

  1. cannot import name '_imaging' 与No module named PIL解决方法

    今天学习廖雪峰的python 第三方模块pillow一章. 直接使用from PIL import Image 会报"No module named PIL",显然这是没有安装pi ...

  2. Retrofit 2.0 超能实践,完美支持Https传输

    http://blog.csdn.NET/sk719887916/article/details/51597816 前阵子看到圈子里Retrofit 2.0,RxJava(Android), OkHt ...

  3. Maven编译中的一些坑

    错误1: invalid LOC header 这个错误比较好解决,jar下载不完全,去到相应的Maven包目录,把东西删掉重新编译就行. 错误2: java.lang.TypeNotPresentE ...

  4. 解决Select标签的Option在IE浏览中display:none不生效的问题

    页面的Select标签,需要控制Select的Option不需要显示,根据条件来隐藏某些Option选项. 正常情况下使用hide()就能实现,hide()方法实际是给Option加上display属 ...

  5. Python flask中的配置

    当你开始学习Flask时,配置看上去是小菜一碟.你仅仅需要在config.py定义几个变量,然后万事大吉. 然而当你不得不管理一个生产上的应用的配置时,这一切将变得棘手万分. 你不得不设法保护API密 ...

  6. XGBoost算法--学习笔记

    学习背景 最近想要学习和实现一下XGBoost算法,原因是最近对项目有些想法,准备做个回归预测.作为当下比较火的回归预测算法,准备直接套用试试效果. 一.基础知识 (1)泰勒公式 泰勒公式是一个用函数 ...

  7. C#高级编程笔记之第三章:对象和类型

    类和结构的区别 类成员 匿名类型 结构 弱引用 部分类 Object类,其他类都从该类派生而来 扩展方法 3.2 类和结构 类与结构的区别是它们在内存中的存储方式.访问方式(类似存储在堆上的引用类型, ...

  8. 用Laravel Sms实现 laravel短信验证码的发送

    使用Laravel Sms这个扩展包实现短信验证码的发送,这里以阿里云的短信服务为例: 首先,要创建短信签名和短信模板,具体申请详情如下, 接下来,需要创建AccessKey,由于AccessKey是 ...

  9. JavaScript设计模式 Item 5 --链式调用

    1.什么是链式调用 这个很容易理解,例如: $(this).setStyle('color', 'red').show(); 一般的函数调用和链式调用的区别:调用完方法后,return this返回当 ...

  10. springMVC简单的一些操作

    SpringMVC的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器进行处理,由DispatcherServlet来统一 ...