当前位置: 首页 > article >正文

DES对称加密算法

  DES(Data Encryption Standard,数据加密标准)是一种对称加密算法。

算法概述

  • 加密类型:对称加密(同一密钥用于加密和解密)。
  • 密钥长度:64位(8字节),其中有效密钥长度为56位,另外8位用于奇偶校验。
  • 数据块大小:64位(8字节),即DES将数据按64位的块进行加密。

DES加密过程

DES的加密过程主要包括以下几个步骤:初始置换(IP)、16轮Feistel结构加密、逆初始置换(IP⁻¹)。

明文处理

每次加密时,DES会将数据划分为64位的块进行处理。

  • 如果需要加密的数据超过64位,DES会将数据分成多个64位的块,然后逐块加密。
  • 如果数据长度不是64位的整数倍,则需要使用填充(padding)技术,使最后一块达到64位。

  因此,DES本身只能处理64位的数据块,但通过分块和填充,可以用于加密任意长度的数据。

填充方式

  • PKCS#5/PKCS#7 填充
    适用范围:最常用的填充方式,适用于各种分组加密算法,包括DES。
    规则:根据需要填充的字节数n,将每个填充字节都设置为n。
    • 例如,如果需要填充4个字节,每个填充字节为0x04。
      如果数据长度已经是块大小的整数倍,则在块末尾填充一个完整的块,填充值为块大小。
    • 示例:
      数据:“ABC”(3字节)
      填充后:“ABC\x05\x05\x05\x05\x05”(8字节)
      数据:“ABCDEFGH”(8字节)
      填充后:“ABCDEFGH\x08\x08\x08\x08\x08\x08\x08\x08”(16字节)
  • Zero Padding(零填充)
    适用范围:对一些特定数据可以使用,但不适用于所有情况,特别是数据中有可能包含0x00的情况。
    • 规则:使用0x00字节进行填充,直到数据达到64位的整数倍。如果原数据末尾恰好是0x00,则无法判断填充与数据的边界。
    • 示例:
      数据:“ABC”(3字节)
      填充后:“ABC\x00\x00\x00\x00\x00”(8字节)

初始置换(IP)

输入和输出

  • 输入:64位的数据块(例如,明文在加密时,密文在解密时)。
  • 输出:经过置换后的64位数据块。

置换规则

初始置换根据一个固定的置换表进行,这个表规定了每一位输入数据的位置在输出数据中的新位置。具体来说,置换表会定义64位输入中的每一位如何重新排列,排列规则是固定的。

置换表

初始置换表
在这里插入图片描述

  • 每个数字表示原始数据中位的位置。例如,第1个位置的位(最左上角的“58”)表示原始数据的第58位,现在被放置在置换后的第1位。
  • 原始数据的第2位由第50位的输入组成,依此类推。

16轮Feistel结构加密

&emps; Feistel结构是一种常见的对称加密构造方法,其基本原理是将数据分为两部分(左部分和右部分),通过多轮相似的操作,每一轮使用一个子密钥进行数据的替换和交换。最终的结果经过逆操作就能还原到原始数据。

数据分割

&emps; 在进入16轮Feistel结构之前,经过初始置换(IP)的64位数据被分成两部分:左半部分 (L0) 和 右半部分 (R0),每部分为32位。
每一轮都会输出新的左部分和右部分,记为 Ln和 Rn,其中n 是轮次编号(从1到16)。

每一轮的操作

每一轮使用一个Feistel函数F和一个子密钥Kn ,将输入的右半部分 与子密钥结合,生成一个新的右半部分。

  • 扩展置换
    32位的 Rn 通过一个固定的扩展置换表变成48位的数据。
  • 与子密钥异或(XOR)
    扩展后的48位数据与当前轮的48位子密钥Kn进行异或运算。
  • S盒替换
    将异或后的48位数据分成8组,每组6位(48位 ÷ 8 = 6位)。
    每一组6位数据通过一个固定的S盒(Substitution Box)转换为4位数据。DES总共有8个不同的S盒。
    每个S盒将6位输入映射为4位输出,从而将48位数据压缩回32位。
  • P置换(P-Permutation)
    将32位的S盒输出通过P置换表进行重新排列,得到一个的32位输出。
    在这里插入图片描述
  • Feistel函数的输出
    Feistel函数的输出是一个32位的结果,它与当前轮的左部分Ln进行异或,得到新的右部分 Rn+1。

数据交换

经过F函数处理之后,左右两部分交换位置:即Ln+1=Rn,Rn+1=Ln^F(Rn,Kn)

重复16轮

重复16轮得到最后的L16和R16

逆初始置换(IP⁻¹)

逆初始置换是初始置换的逆操作,用于在解密的最后一步将重新排列的数据恢复到原始顺序。它也有一个对应的置换表,IP⁻¹表如下:
在这里插入图片描述
这个表定义了如何将经过初始置换的数据重新排列回原来的顺序。

在第16轮完成后,不再进行左右交换,而是将R16和L16直接合并成64位的数据,然后通过逆初始置换得到最终64位的密文。

Python 实现

from Crypto.Cipher import DES
from Crypto.Util.Padding import pad,unpad
import binascii

key = b'12345678'
cipher = DES.new(key,DES.MODE_ECB)
data = "Bileton"
padded_data = pad(data.encode("utf-8"),DES.block_size)
encrypted_data = cipher.encrypt(padded_data)
print(binascii.hexlify(encrypted_data).decode('utf-8'))

>>> 66b99748acc81443

加上iv向量

from Crypto.Cipher import DES
from Crypto.Util.Padding import pad,unpad
import binascii

key = b'12345678'
iv = b'12345678'
cipher = DES.new(key,DES.MODE_CBC,iv)
data = "Bileton"
padded_data = pad(data.encode("utf-8"),DES.block_size)
encrypted_data = cipher.encrypt(padded_data)
print(binascii.hexlify(encrypted_data).decode('utf-8'))

>>> fa8669e459a42d7f

Java实现

Cipher cipher = Cipher.getInstance("DES");
byte[] keys = "12345678".getBytes("UTF-8");
Key key = new SecretKeySpec(keys, "DES");
cipher.init(Cipher.ENCRYPT_MODE,key);
String data = "Bileton";
cipher.update(data.getBytes("UTF-8"));
byte[] encryptData = cipher.doFinal();
String encodedEncryptedData = Base64.getEncoder().encodeToString(encryptData);
System.out.println(encodedEncryptedData);

>>> ZrmXSKzIFEM=

加上iv向量

Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
byte[] iv = "12345678".getBytes("UTF-8");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
byte[] keys = "12345678".getBytes("UTF-8");
Key key = new SecretKeySpec(keys, "DES");
cipher.init(Cipher.ENCRYPT_MODE,key,ivParameterSpec);
String data = "Bileton";
cipher.update(data.getBytes("UTF-8"));
byte[] encryptData = cipher.doFinal();
String encodedEncryptedData = Base64.getEncoder().encodeToString(encryptData);
System.out.println(encodedEncryptedData);

>>> +oZp5FmkLX8=

Android Studio

String data = "Bileton";
String key_string = "12345678";
Key key =new SecretKeySpec(key_string.getBytes("UTF-8"),"DES");
String iv_string = "12345678";
IvParameterSpec iv = new IvParameterSpec(iv_string.getBytes("UTF-8"));
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,key,iv);
cipher.update(data.getBytes("UTF-8"));
byte[] result = cipher.doFinal();
String encodeencrypteddata = Base64.encodeToString(result,Base64.DEFAULT);
Toast.makeText(MainActivity.this,encodeencrypteddata,Toast.LENGTH_SHORT).show();

在这里插入图片描述


http://www.kler.cn/news/353496.html

相关文章:

  • Go 语言中的静态类型和动态类型
  • 能源监控大数据界面,洞察一切生产态势
  • Vue 调用电脑摄像头拍照 返回base64格式图片 简单例子
  • Rust学习如何更有信心?
  • 【部署篇】Redis-03主从模式部署(源码方式安装)
  • 6CXX:UICC告诉终端数据长度
  • PyCharm配置Flask开发环境
  • 【数据结构-栈】【位运算优化】力扣3170. 删除星号以后字典序最小的字符串
  • SQL server 存储过程与函数
  • 【数据结构与算法】LeetCode每日一题
  • 机器学习与神经网络:开启物理学的新篇章
  • SEM推广如何进行数据分析
  • Ubuntu:用户不在sudoers文件中
  • 【Java小白图文教程】-01-Java环境安装-变量
  • 计算机是如何输入存储输出汉字、图片、音频、视频的
  • 10:00面试,10:08就出来了,问的问题有点变态。。。
  • Spring Boot框架下的知识管理策略
  • 【Python爬虫】看电影还在用VIP?一个python代码让你实现电影自由!附源码
  • C#使用PdfSharp生成PDF文件实例详解
  • find_library、pkg_check_modules、pkg_search_module的区别