S-DES加密

2023-11-19

 

Simplified Data Encryption Standard S-DES 是一个供教学的非安全的加密算法,它与DES的特性和结构类似,但参数小,明文分组为8位,主密钥分组为10位,采用两轮迭代。

S-DES加密过程包含两个重要部分:子密码生成过程,f函数结构。

S-DES加密原理:

S-DES的子密码生成过程:

S-DES的f函数结构:

S-DES的S盒:

通过对主加密过程进行翻转来解密。

实现代码:

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <fstream>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <string>
  7 
  8 class S_DES {
  9 private:
 10     typedef unsigned int uint;
 11     typedef unsigned char uchar;
 12     typedef std::pair<unsigned int, unsigned int> PII;
 13     typedef std::pair<PII, PII> PPI;
 14     typedef std::vector<unsigned int> VI;
 15     typedef std::vector<VI> VVI;
 16     typedef std::vector<unsigned char> VC;
 17     typedef std::string String;
 18 
 19     const static VI P_10;
 20     const static VI P_8;
 21     const static VI P_4;
 22     const static VI IP;
 23     const static VI IP_1;
 24     const static VI EP;
 25     const static VVI S_1;
 26     const static VVI S_2;
 27 
 28     // MakePII
 29     inline PII MakePII(uint L, uint R) {
 30         return std::make_pair(L, R);
 31     }
 32 
 33     // MakePPI
 34     inline PPI MakePPI(uint A, uint B, uint C, uint D) {
 35         return std::make_pair(std::make_pair(A, B), std::make_pair(C, D));
 36     }
 37 
 38     // 置换,长度为X
 39     uint Permutation(uint Bit, int X, const VI &P) {
 40         uint res = 0;
 41         int n = P.size();
 42         for (int i = 0; i < n; i++) {
 43             res <<= 1;
 44             if (Bit & (1 << (X - P[i]))) res |= 1;
 45         }
 46         return res;
 47     }
 48 
 49     // 逆置换
 50     uint InversePermutation(uint Bit, int X, const VI &P) {
 51         uint res = 0;
 52         int n = P.size();
 53         for (int i = 0; i < n; i++) {
 54             if (Bit&(1 << (n - i - 1))) {
 55                 res |= 1 << (X - P[i]);
 56             }
 57         }
 58         return res;
 59     }
 60 
 61     // 以X为单位分割二进制数为两份
 62     PII Split(uint Bit, int X) {
 63         uint L = 0, R = 0;
 64         uint mask = (1 << X) - 1;
 65         R = Bit & mask;
 66         L = Bit >> X;
 67         return MakePII(L, R);
 68     }
 69     
 70     // 将四位二进制数转化为S-BOX的坐标
 71     PII GetBoxXY(uint Bit) {
 72         uint x = 0, y = 0;
 73         if (Bit&(1 << 3)) x |= 1;
 74         if (Bit&(1 << 2)) y |= 1;
 75         x <<= 1;
 76         y <<= 1;
 77         if (Bit&(1 << 0)) x |= 1;
 78         if (Bit&(1 << 1)) y |= 1;
 79         return MakePII(x, y);
 80     }
 81 
 82     // 将八位二进制数转化为S-BOX的坐标
 83     PPI GetExBox(uint Bit) {
 84         PII pii = Split(Bit,4);
 85         PII xy1 = GetBoxXY(pii.first);
 86         PII xy2 = GetBoxXY(pii.second);
 87         return MakePPI(xy1.first, xy1.second, xy2.first, xy2.second);
 88     }
 89 
 90     // 合并两个长度为X的二进制数
 91     uint Merge(uint lBit, uint rBit, int X) {
 92         return (lBit << X) | rBit;
 93     }
 94 
 95     // 将长度为L的二进制数,循环左移X次
 96     uint LS(uint Bit, int L, int X) {
 97         X %= L;
 98         uint mask = (1 << L) - 1;
 99         uint ans = ((Bit << X) & mask) | (Bit >> (L - X));
100         return ans;
101     }
102 
103     // S-DES 子密码生成过程,MasterKey是10位的主密钥。
104     PII GetSubPsw(uint MasterKey) {
105         uint K = Permutation(MasterKey, 10, P_10);// 主密钥K进行P10置换
106         PII pii = Split(K, 5);                    // 分成左5位右5位
107         uint L = pii.first;                          // 
108         uint R = pii.second;                      // 
109         L = LS(L, 5, 1);                          // 分别进行LS-1操作
110         R = LS(R, 5, 1);                          // 其结果一方面作为下一轮的初始值
111         uint K_1 = Merge(L, R, 5);                // 另一方面进行P8置换
112         K_1 = Permutation(K_1, 10, P_8);          // 得到K1
113         L = LS(L, 5, 2);                          // 再分别左循环2位
114         R = LS(R, 5, 2);                          // 
115         uint K_2 = Merge(L, R, 5);                  // 
116         K_2 = Permutation(K_2, 10, P_8);          // 经过P8置换,得到K2
117         return MakePII(K_1, K_2);
118     }
119 
120     // S-DES的f函数
121     uint Function(uint Ipt, uint K) {
122         uint ex = Permutation(Ipt, 4, EP);// E/P扩展及置换。将4位R扩展为8位
123         ex ^= K;                          // 扩展后的8位异或秘钥K
124         PPI ppi = GetExBox(ex);           // 左边4位作为S1盒输入,右边四位作为S2盒输入
125         uint x1 = ppi.first.first;          // 在S1和S2中,第一位与第四位结合形成2位代表S盒的行号
126         uint y1 = ppi.first.second;       // 第二位与第三位结合形成2位代表S盒的列号
127         uint x2 = ppi.second.first;       //
128         uint y2 = ppi.second.second;      //
129         uint s1 = S_1[x1][y1];              // 得到S盒的输出
130         uint s2 = S_2[x2][y2];            //
131         uint res = Merge(s1, s2, 2);      //
132         res = Permutation(res, 4, P_4);   // 进行P4置换,得到f函数的输出
133         return res;
134     }
135 
136     // S-DES 加密
137     uint S_DES_Main(uint Plaintext, uint K_1, uint K_2) {
138         Plaintext = Permutation(Plaintext, 8, IP);// 初始置换IP,将8位明文按照置换顺序进行位置变化。
139         PII pii = Split(Plaintext, 4);              // 置换后分
140         uint L0 = pii.first;                      // 左4位L0
141         uint R0 = pii.second;                      // 右4位R0
142         uint L1 = R0;                              // 第一轮运算,R0作为下一轮的L1
143         uint R1 = L0 ^ (Function(R0, K_1));          // R0作为f函数的输入与8位子秘钥K1参与函数运算,运算结构与L0异或,结果作为下一轮的R1
144         uint R2 = R1;                              // 第二轮运算,R1作为下一轮的R2
145         uint L2 = L1 ^ (Function(R1, K_2));       // R1作为f函数的输入与8位子密钥K2参与函数运算,运算结果与L1异或,结果作为下一轮的L2
146         uint res = Merge(L2, R2, 4);              // 
147         res = Permutation(res, 8, IP_1);          // 逆置换IP-1
148         return res;
149     }
150 
151     // S-DES 解密
152     uint Decryption(uint Cip, uint K_1, uint K_2) {
153         Cip = InversePermutation(Cip, 8, IP_1);
154         PII pii = Split(Cip, 4);
155         uint L2 = pii.first;
156         uint R2 = pii.second;
157         uint R1 = R2;
158         uint L1 = L2 ^ (Function(R1, K_2));
159         uint R0 = L1;
160         uint L0 = R1 ^ (Function(R0, K_1));
161         uint res = Merge(L0, R0, 4);
162         res = InversePermutation(res, 8, IP);
163         return res;
164     }
165 public:
166     // 将数字以二进制形式输出
167     void PrintBinary(uint b) {
168         if (b == 0) {
169             printf("0\n");
170             return;
171         }
172         VI vec;
173         vec.clear();
174         while (b > 0) {
175             if (b & 1) vec.push_back(1);
176             else vec.push_back(0);
177             b >>= 1;
178         }
179         for (auto it = vec.rbegin(); it != vec.rend(); it++) {
180             printf("%d", *it);
181         }
182         printf("\n");
183     }
184 
185     // 将二进制字符串转换为数字
186     uint StringToBinary(const std::string &Str) {
187         uint res = 0;
188         uint len = Str.length();
189         for (uint i = 0; i < len; i++) {
190             res <<= 1;
191             if (Str[i] == '1') res |= 1;
192         }
193         return res;
194     }
195 
196     // 加密一个单位的数据
197     uint EncryptInt(uint Text, uint MasterKey) {
198         auto p = GetSubPsw(MasterKey);
199         uint K_1 = p.first;
200         uint K_2 = p.second;
201         uint res = S_DES_Main(Text, K_1, K_2);
202         return res;
203     }
204     
205     // 按字符加密一个字符串
206     VI EncryptString(const String &Str, uint MasterKey) {
207         VI res;
208         auto p = GetSubPsw(MasterKey);
209         uint K_1 = p.first;
210         uint K_2 = p.second;
211         int len = Str.length();
212         for (int i = 0; i < len; i++) {
213             uint e = S_DES_Main((uint)Str[i], K_1, K_2);
214             res.push_back(e);
215         }
216         return res;
217     }
218 
219     // 加密一组vector中的数字
220     VI EncryptVector(const VI &Arr, uint MasterKey) {
221         VI res;
222         auto p = GetSubPsw(MasterKey);
223         uint K_1 = p.first;
224         uint K_2 = p.second;
225         int len = Arr.size();
226         for (int i = 0; i < len; i++) {
227             uint e = S_DES_Main(Arr[i], K_1, K_2);
228             res.push_back(e);
229         }
230         return res;
231     }
232 
233     // 加密长度为n的数组中的数字
234     VI EncryptArray(const uint Arr[], int n, uint MasterKey) {
235         VI res;
236         auto p = GetSubPsw(MasterKey);
237         uint K_1 = p.first;
238         uint K_2 = p.second;
239         for (int i = 0; i < n; i++) {
240             uint e = S_DES_Main(Arr[i], K_1, K_2);
241             res.push_back(e);
242         }
243         return res;
244     }
245 
246     // 加密长度为n的Byte数组
247     VI EncryptBytes(const uchar Arr[], int n, uint MasterKey) {
248         VI res;
249         auto p = GetSubPsw(MasterKey);
250         uint K_1 = p.first;
251         uint K_2 = p.second;
252         for (int i = 0; i < n; i++) {
253             uint e = S_DES_Main((uint)Arr[i], K_1, K_2);
254             res.push_back(e);
255         }
256         return res;
257     }
258 
259     // 加密一个文件中的数据
260     VI EncryptFile(char FileName[], uint MasterKey) {
261         VI res;
262         std::ifstream fin(FileName, std::ios::binary);
263         if (!fin.is_open()) return res;
264         int n = (int)fin.gcount(); 
265         char pc;
266         for (int i = 0; i < n; i++) {
267             fin.read(&pc, sizeof(uchar));
268             res.push_back((uint)pc);
269         }
270         return res;
271     }
272 
273     // 解密一个单位的数据
274     uint DecryptInt(uint Cip, uint MasterKey) {
275         auto p = GetSubPsw(MasterKey);
276         uint K_1 = p.first;
277         uint K_2 = p.second;
278         uint res = Decryption(Cip, K_1, K_2);
279         return res;
280     }
281 
282     // 解密vector中的数据
283     VI DecryptVector(const VI& Cips, uint MasterKey) {
284         auto p = GetSubPsw(MasterKey);
285         uint K_1 = p.first;
286         uint K_2 = p.second;
287         VI res;
288         for (auto it = Cips.begin(); it != Cips.end(); it++) {
289             uint des = Decryption(*it, K_1, K_2);
290             res.push_back(des);
291         }
292         return res;
293     }
294 
295     // 将vector中的数据转化为string类型
296     String VectorToString(const VI& vec) {
297         String res;
298         for (auto it = vec.begin(); it != vec.end(); it++) {
299             res.push_back((char)*it);
300         }
301         return res;
302     }
303 };
304 
305 const S_DES::VI S_DES::P_10{ 3, 5, 2, 7, 4, 10, 1, 9, 8, 6 };
306 const S_DES::VI S_DES::P_8{ 6, 3, 7, 4, 8, 5, 10, 9 };
307 const S_DES::VI S_DES::P_4{ 2, 4, 3, 1 };
308 const S_DES::VI S_DES::IP{ 2, 6, 3, 1, 4, 8, 5, 7 };
309 const S_DES::VI S_DES::IP_1{ 4, 1, 3, 5, 7, 2, 8, 6 };
310 const S_DES::VI S_DES::EP{ 4, 1, 2, 3, 2, 3, 4, 1 };
311 const S_DES::VVI S_DES::S_1{ { 1, 0, 3, 2 },
312                              { 3, 2, 1, 0 },
313                              { 0, 2, 1, 3 },
314                              { 3, 1, 3, 2 } };
315 const S_DES::VVI S_DES::S_2{ { 0, 1, 2, 3 },
316                              { 2, 0, 1, 3 }, 
317                              { 3, 0, 1, 0 },
318                              { 2, 1, 0, 3 } };

 

posted on 2014-09-10 19:20 cyendra 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/zinthos/p/3965024.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

S-DES加密 的相关文章

  • 信号量和自旋锁

    信号量和自旋锁 为了避免并发 防止竞争 内核提供了一组同步方法来提供对共享数据的保护 我们的重点不是介绍这些方法的详细用法 而是强调为什么使用这些方法和它们之间的差别 Linux 使用的同步机制可以说从2 0到2 6以来不断发展完善 从最初
  • python编程实验,模拟聪明版的尼姆游戏设计原理

    实验原理与内容 本实验完成一个模拟聪明版的尼姆游戏功能 尼姆游戏是个著名的游戏 有很多变种玩法 两个玩家轮流从一堆物品中拿走一部分 在每一步中 玩家可以自由选择拿走多少物品 但是必须至少拿走一个并且最多只能拿走一半物品 然后轮到下一个玩家
  • Python SQLAlchemy ( ORM )、dictalchemy、Flask-SQLAlchemy、Flask-migrate、flask-script、flask-upload

    From Python中强大的通用ORM框架 SQLAlchemy https zhuanlan zhihu com p 444930067 Python ORM之SQLAlchemy全面指南 https zhuanlan zhihu co
  • ubuntu 18.04安装wireshark及网卡接口权限问题

    1 安装 sudo apt fast install wireshark 第一次安装过程中可能会提示Should non superusers be able to capture packets 选是即可 默认是否 2 待安装成功后 你会
  • MFC 菜单栏的使用

    MFC 菜单栏的使用 主要介绍两种比较简单和常用的创建方法 一 在资源视图中添加菜单资源 通过鼠标点击添加菜单项 菜单栏设计好 以后就是添加了 介绍两种方法 1 很简单 鼠标右击想显示菜单栏的对话框属性 可以看到有一个menu的属性 点击就
  • Linux 宝塔面板的安装

    Ptw cwl 登录宝塔官网 查看宝塔的详情 www bt cn 安装 linux服务器图形化界面管理器 安装 宝塔面板 在xshell当中执行宝塔面板的安装命令 yum install y wget wget O install sh h
  • python批量处理

    python opencv图像二值化批量处理 from skimage import data dir io transform color filters import numpy as np import cv2 def convert
  • 红帽Redhat—Linux网卡聚合

    文章目录 一 实验环境设置 二 网卡聚合nmcli 配置步骤 1 创建聚合接口 2 配置网络属性 3 添加物理接口 4 激活端口 5 查看聚合接口状态 一 实验环境设置 在已经安装好的RHEL8 3添加两个新网卡 1 点击虚拟机 gt 设置
  • 机器学习笔记----Fuzzy c-means(FCM)模糊聚类详解及matlab实现

    前言 这几天一直都在研究模糊聚类 感觉网上的文档都没有一个详细而具体的讲解 正好今天有时间 就来聊一聊模糊聚类 一 模糊数学 我们大家都知道计算机其实只认识两个数字0 1 我们平时写程序其实也是这样if 1 then do 永远这种模式 在
  • C++实现String类

    C 实现String类 还没有完成 待继续 有以下注意的点 1 赋值操作符返回的是一个MyString 而重载的 返回的是一个MyString 其中的原因参看 effective c 主要是返回引用的时候 必须返回必须在此函数之前存在的引用
  • Android Studio安装教程+打包APK

    前言 这是一篇给新人的教程 如果你觉得简单啰嗦请保持冷静 同时如果本篇能给予到你帮助 是我的荣幸 Android Studio安装教程 点击链接下载Android Studio Android Studio官网下载 下载完成后双击 exe文
  • [实验三]LZW 编解码算法实现与分析

    目录 一 LZW算法 1 1 编码步骤 1 2 解码步骤 1 3 关于有可能出现当前码字CW不在词典中的情况说明 二 代码实现 2 1 程序说明 2 2 数据结构 2 3 bitio h 2 4 bitio c 2 5 lzw c 三 实验
  • VC++ FTP文件上传(断点续传)

    include
  • vue项目设置ip访问

    1 只用ip访问 打开config gt index 文件 host 172 16 1 95 新增host 改成IP地址 最后重新运行项目 2 既可以IP访问 由可以localhost访问 将config gt index 中host 该为
  • 嵌入式学习(第二周)

    目录 二 C语言基础 2 运算符和表达式 2 1 运算分类 2 2 算数运算符 2 3 关系运算符 2 4 逻辑运算符 2 5 条件运算符 2 6 位运算符 2 7 运算符的运用实例 3 程序结构和过程控制 3 1 C语言程序结构 3 2
  • 2021-03-30 maven

    1 maven父子工程 3 maven环境优化 1 修改web xml为最新的 2 将maven结构搭建完整 4 编写一个servlet Javaweb下载文件的头
  • Java日志简介及SpringBoot日志

    一 什么是日志 日志 就是介绍一个过程和经历的详细记录 项目日志 就是项目开发过程的详细记录 一般由项目经理记录 代码里的日志 就是程序员记录某个开发过程的详细情况 这是项目里每个程序员需要做的工作 日志和异常处理结合得当的话 会给项目维护
  • vue+element-ui 实现弹窗验证用户信息

  • C++零散易错点总结

    对日常做题中遇到的一些零散的易错点的总结 持续更新ing 1 string的length方法返回的是无符号数 当与负数比较时需要强制类型转换 否则会报错 1
  • appium+python自动化测试

    获取APP的包名 1 aapt即Android Asset Packaging Tool 在SDK的build tools目录下 该工具可以查看apk包名和launcherActivity 2 在android sdk里面双击SDK man

随机推荐

  • MYSQL8隐藏索引

    问题场景 我们知道 索引太多会导致UPDATE DELETE INSERT的时候 引擎需要更新索引信息 产生额外的开销 从而影响数据库性能 所以需要清理无效索引 但是表是数年前建的 索引基本都不是自己添加的 无法准确判定是否可以删除 万一删
  • shell 脚本命令太长,如何换行?

    再加ENTER
  • ElasticSearch ES 安装 常见错误 Kibana安装 设置 权限 密码

    最近在学习ES数据库 所以将一些东西记录一下 以下所有的都是基于es7 8 0版本进行的 下载安装ES数据库 安装本体 下载地址 linux mac os windows es的安装非常简单 基本都是解压然后运行就行了 这里我们就以linu
  • 如何在十天内掌握线性代数

    最近 我的朋友斯考特 杨 Scott Young 成就了一个惊人的壮举 他在一年之内 完成了传说中的MIT计算机科学课程表的全部33门课 从线性代数到计算理论 最重要的是 他是自学的 观看在线教程讲座 并用实际的考试作自我评估 到斯考特的F
  • 时序预测

    时序预测 MATLAB实现RF 随机森林 时间序列预测 目录 时序预测 MATLAB实现RF 随机森林 时间序列预测 预测效果 基本介绍 预测准备 程序设计 主程序 训练子函数 预测子函数 参考资料 致谢 预测效果 基本介绍 在机器学习中
  • Maven依赖冲突

    依赖冲突 依赖冲突是指项目依赖的某一个jar包 有多个不同的版本 因而造成类包版本冲突 依赖传递 项目依赖了A A依赖了B 项目自动依赖了B 注意 父项目中的依赖有
  • GitHub 上最火的开源项目 —— Java 篇

    很多开发者在看到自己感兴趣的项目时会使用 Star 功能 可以说 Star 的数量在一定程度上代表了开源项目的热门程度 本文整理了 Java 语言中 star 数最多的十五款开源项目 这些项目在 GitHub 上的 star 数均超过 15
  • 开发 Leader 们最该了解的软件度量指标

    无论何时 只要是要评估或对比某些东西 就需要使用度量指标 它们是可量化的衡量标准 用于判断每个行业的进展 这其中包括软件开发 在该领域 开发负责人依靠软件度量指标来跟踪性能和生产 在我们关于如何衡量和提高开发人员工作效率的博客文章中 我们讨
  • ext 6.0开发实例二

    由于Ext JS 6将原来的Ext JS和Sencha Touch合并为一个框架 因而在使用CMD来创建应用程序前 需要考虑清楚你是要创建一个通用应用程序 还是仅仅只是针对桌面或移动设备的应用程序 要做这样的考量 是因为通用应用程序和比较单
  • 关于java/android 数据序列化后SerialVersionUID的获取

    本人android 开发 遇到了一个关于数据序列化的坑 纪录下来以便以后查看 所有需要序列化本地的bean都需要继承Serializable 否则无法序列化 如果不了解序列化的知识请自行百度 我继承了Serializable 但是没有设置S
  • 2.5.14 动态内存共享AMS

    最后更新2021 08 02 这个还算是比较实用的功能 最早介绍过CPU共享 也提到过内存共享 但CPU共享是动态 实时 按需分配的 虽然有限制条件 而内存需要用DLPar功能 收工调节 至少不是实时分配 那内存可不可以实现类似CPU的实时
  • python笔记2--python 中安装package注意事项

    python笔记2 python 中安装package注意事项 使用python时候 经常需要安装相关的包 安装方法包括两种 1 直接使用easy install或者pip安装 2 下载package源码安装 1 直接使用easy inst
  • macbook上的vim怎么设置语法高亮和显示行号

    在我写这篇文章之前我的vim就很普通 没有语法高亮 无法显示行号 但是我通过在网上不断查阅一些处理方法和经验之后 我终于能将我MacBook电脑上的vim配置出语法高亮和显示行号了 作为一名乐于分享 乐于助人的新手程序员 我决定把我的解决办
  • 《Web应用安全权威指南》学习笔记

    第1章 什么是Web应用的安全隐患 第2章 搭建试验环境 邮件发送服务器Postfix POP3服务器Dovecot SSH服务器OpenSSH Web应用调试工具Fiddler 第3章 Web安全基础 HTTP回话管理 同源策略 Cook
  • k8s安全04--kube-apiserver 安全配置

    k8s安全04 kube apiserver 安全配置 1 介紹 2 安全配置 2 1 配置 insecure port 2 2 RBAC 2 3 Service Accounts 2 4 Researching Pod Security
  • Nginx 无法转发本地端口

    问题描述 本文主要分析解决 centos 下 nginx 配置端口转发后不生效 通过 nginx 配置 server 转发后 无法达到预期的转发目的 并出现502错误的问题 假设虚拟机 ip 为 192 168 0 8 并且在虚拟机内部署一
  • ISO七层模型

    物理层 O S I 模型的最低层或第一层 该层包括物理连网媒介 如电缆连线连接器 物理层的协议产生并检测电压以便发送和接收携带数据的信号 在你的桌面P C 上插入网络接口卡 你就建立了计算机连网的基础 换言之 你提供了一个物理层 尽管物理层
  • uni-app项目在微信开发者工具打开时报错[ app.json 文件内容错误] app.json: 在项目根目录未找到 app.json

    uni app项目在微信开发者工具打开时控制台报错 app json 文件内容错误 app json 在项目根目录未找到 app json env Windows mp 1 06 2303220 lib 2 32 0 解决方案 以下是一个u
  • 前端基础之ES6

    1 前后端对比 2 ES6 ECMAScript6 0 以下简称ES6 ECMAScript是一种由Ecma国际通过ECMA 262标准化的脚本 是JavaScript语言的下一代标准 2015年6月正式发布 从ES6开始的版本号采用年号
  • S-DES加密

    S DES加密 Simplified Data Encryption Standard S DES 是一个供教学的非安全的加密算法 它与DES的特性和结构类似 但参数小 明文分组为8位 主密钥分组为10位 采用两轮迭代 S DES加密过程包