S-DES加密

时间:2021-12-06 09:34:56

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

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

S-DES加密原理:

S-DES加密

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

S-DES加密

S-DES的f函数结构:

S-DES加密

S-DES的S盒:

S-DES加密

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

实现代码:

 #include <cstdio>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <string> class S_DES {
private:
typedef unsigned int uint;
typedef unsigned char uchar;
typedef std::pair<unsigned int, unsigned int> PII;
typedef std::pair<PII, PII> PPI;
typedef std::vector<unsigned int> VI;
typedef std::vector<VI> VVI;
typedef std::vector<unsigned char> VC;
typedef std::string String; const static VI P_10;
const static VI P_8;
const static VI P_4;
const static VI IP;
const static VI IP_1;
const static VI EP;
const static VVI S_1;
const static VVI S_2; // MakePII
inline PII MakePII(uint L, uint R) {
return std::make_pair(L, R);
} // MakePPI
inline PPI MakePPI(uint A, uint B, uint C, uint D) {
return std::make_pair(std::make_pair(A, B), std::make_pair(C, D));
} // 置换,长度为X
uint Permutation(uint Bit, int X, const VI &P) {
uint res = ;
int n = P.size();
for (int i = ; i < n; i++) {
res <<= ;
if (Bit & ( << (X - P[i]))) res |= ;
}
return res;
} // 逆置换
uint InversePermutation(uint Bit, int X, const VI &P) {
uint res = ;
int n = P.size();
for (int i = ; i < n; i++) {
if (Bit&( << (n - i - ))) {
res |= << (X - P[i]);
}
}
return res;
} // 以X为单位分割二进制数为两份
PII Split(uint Bit, int X) {
uint L = , R = ;
uint mask = ( << X) - ;
R = Bit & mask;
L = Bit >> X;
return MakePII(L, R);
} // 将四位二进制数转化为S-BOX的坐标
PII GetBoxXY(uint Bit) {
uint x = , y = ;
if (Bit&( << )) x |= ;
if (Bit&( << )) y |= ;
x <<= ;
y <<= ;
if (Bit&( << )) x |= ;
if (Bit&( << )) y |= ;
return MakePII(x, y);
} // 将八位二进制数转化为S-BOX的坐标
PPI GetExBox(uint Bit) {
PII pii = Split(Bit,);
PII xy1 = GetBoxXY(pii.first);
PII xy2 = GetBoxXY(pii.second);
return MakePPI(xy1.first, xy1.second, xy2.first, xy2.second);
} // 合并两个长度为X的二进制数
uint Merge(uint lBit, uint rBit, int X) {
return (lBit << X) | rBit;
} // 将长度为L的二进制数,循环左移X次
uint LS(uint Bit, int L, int X) {
X %= L;
uint mask = ( << L) - ;
uint ans = ((Bit << X) & mask) | (Bit >> (L - X));
return ans;
} // S-DES 子密码生成过程,MasterKey是10位的主密钥。
PII GetSubPsw(uint MasterKey) {
uint K = Permutation(MasterKey, , P_10);// 主密钥K进行P10置换
PII pii = Split(K, ); // 分成左5位右5位
uint L = pii.first; //
uint R = pii.second; //
L = LS(L, , ); // 分别进行LS-1操作
R = LS(R, , ); // 其结果一方面作为下一轮的初始值
uint K_1 = Merge(L, R, ); // 另一方面进行P8置换
K_1 = Permutation(K_1, , P_8); // 得到K1
L = LS(L, , ); // 再分别左循环2位
R = LS(R, , ); //
uint K_2 = Merge(L, R, ); //
K_2 = Permutation(K_2, , P_8); // 经过P8置换,得到K2
return MakePII(K_1, K_2);
} // S-DES的f函数
uint Function(uint Ipt, uint K) {
uint ex = Permutation(Ipt, , EP);// E/P扩展及置换。将4位R扩展为8位
ex ^= K; // 扩展后的8位异或秘钥K
PPI ppi = GetExBox(ex); // 左边4位作为S1盒输入,右边四位作为S2盒输入
uint x1 = ppi.first.first; // 在S1和S2中,第一位与第四位结合形成2位代表S盒的行号
uint y1 = ppi.first.second; // 第二位与第三位结合形成2位代表S盒的列号
uint x2 = ppi.second.first; //
uint y2 = ppi.second.second; //
uint s1 = S_1[x1][y1]; // 得到S盒的输出
uint s2 = S_2[x2][y2]; //
uint res = Merge(s1, s2, ); //
res = Permutation(res, , P_4); // 进行P4置换,得到f函数的输出
return res;
} // S-DES 加密
uint S_DES_Main(uint Plaintext, uint K_1, uint K_2) {
Plaintext = Permutation(Plaintext, , IP);// 初始置换IP,将8位明文按照置换顺序进行位置变化。
PII pii = Split(Plaintext, ); // 置换后分
uint L0 = pii.first; // 左4位L0
uint R0 = pii.second; // 右4位R0
uint L1 = R0; // 第一轮运算,R0作为下一轮的L1
uint R1 = L0 ^ (Function(R0, K_1)); // R0作为f函数的输入与8位子秘钥K1参与函数运算,运算结构与L0异或,结果作为下一轮的R1
uint R2 = R1; // 第二轮运算,R1作为下一轮的R2
uint L2 = L1 ^ (Function(R1, K_2)); // R1作为f函数的输入与8位子密钥K2参与函数运算,运算结果与L1异或,结果作为下一轮的L2
uint res = Merge(L2, R2, ); //
res = Permutation(res, , IP_1); // 逆置换IP-1
return res;
} // S-DES 解密
uint Decryption(uint Cip, uint K_1, uint K_2) {
Cip = InversePermutation(Cip, , IP_1);
PII pii = Split(Cip, );
uint L2 = pii.first;
uint R2 = pii.second;
uint R1 = R2;
uint L1 = L2 ^ (Function(R1, K_2));
uint R0 = L1;
uint L0 = R1 ^ (Function(R0, K_1));
uint res = Merge(L0, R0, );
res = InversePermutation(res, , IP);
return res;
}
public:
// 将数字以二进制形式输出
void PrintBinary(uint b) {
if (b == ) {
printf("0\n");
return;
}
VI vec;
vec.clear();
while (b > ) {
if (b & ) vec.push_back();
else vec.push_back();
b >>= ;
}
for (auto it = vec.rbegin(); it != vec.rend(); it++) {
printf("%d", *it);
}
printf("\n");
} // 将二进制字符串转换为数字
uint StringToBinary(const std::string &Str) {
uint res = ;
uint len = Str.length();
for (uint i = ; i < len; i++) {
res <<= ;
if (Str[i] == '') res |= ;
}
return res;
} // 加密一个单位的数据
uint EncryptInt(uint Text, uint MasterKey) {
auto p = GetSubPsw(MasterKey);
uint K_1 = p.first;
uint K_2 = p.second;
uint res = S_DES_Main(Text, K_1, K_2);
return res;
} // 按字符加密一个字符串
VI EncryptString(const String &Str, uint MasterKey) {
VI res;
auto p = GetSubPsw(MasterKey);
uint K_1 = p.first;
uint K_2 = p.second;
int len = Str.length();
for (int i = ; i < len; i++) {
uint e = S_DES_Main((uint)Str[i], K_1, K_2);
res.push_back(e);
}
return res;
} // 加密一组vector中的数字
VI EncryptVector(const VI &Arr, uint MasterKey) {
VI res;
auto p = GetSubPsw(MasterKey);
uint K_1 = p.first;
uint K_2 = p.second;
int len = Arr.size();
for (int i = ; i < len; i++) {
uint e = S_DES_Main(Arr[i], K_1, K_2);
res.push_back(e);
}
return res;
} // 加密长度为n的数组中的数字
VI EncryptArray(const uint Arr[], int n, uint MasterKey) {
VI res;
auto p = GetSubPsw(MasterKey);
uint K_1 = p.first;
uint K_2 = p.second;
for (int i = ; i < n; i++) {
uint e = S_DES_Main(Arr[i], K_1, K_2);
res.push_back(e);
}
return res;
} // 加密长度为n的Byte数组
VI EncryptBytes(const uchar Arr[], int n, uint MasterKey) {
VI res;
auto p = GetSubPsw(MasterKey);
uint K_1 = p.first;
uint K_2 = p.second;
for (int i = ; i < n; i++) {
uint e = S_DES_Main((uint)Arr[i], K_1, K_2);
res.push_back(e);
}
return res;
} // 加密一个文件中的数据
VI EncryptFile(char FileName[], uint MasterKey) {
VI res;
std::ifstream fin(FileName, std::ios::binary);
if (!fin.is_open()) return res;
int n = (int)fin.gcount();
char pc;
for (int i = ; i < n; i++) {
fin.read(&pc, sizeof(uchar));
res.push_back((uint)pc);
}
return res;
} // 解密一个单位的数据
uint DecryptInt(uint Cip, uint MasterKey) {
auto p = GetSubPsw(MasterKey);
uint K_1 = p.first;
uint K_2 = p.second;
uint res = Decryption(Cip, K_1, K_2);
return res;
} // 解密vector中的数据
VI DecryptVector(const VI& Cips, uint MasterKey) {
auto p = GetSubPsw(MasterKey);
uint K_1 = p.first;
uint K_2 = p.second;
VI res;
for (auto it = Cips.begin(); it != Cips.end(); it++) {
uint des = Decryption(*it, K_1, K_2);
res.push_back(des);
}
return res;
} // 将vector中的数据转化为string类型
String VectorToString(const VI& vec) {
String res;
for (auto it = vec.begin(); it != vec.end(); it++) {
res.push_back((char)*it);
}
return res;
}
}; const S_DES::VI S_DES::P_10{ , , , , , , , , , };
const S_DES::VI S_DES::P_8{ , , , , , , , };
const S_DES::VI S_DES::P_4{ , , , };
const S_DES::VI S_DES::IP{ , , , , , , , };
const S_DES::VI S_DES::IP_1{ , , , , , , , };
const S_DES::VI S_DES::EP{ , , , , , , , };
const S_DES::VVI S_DES::S_1{ { , , , },
{ , , , },
{ , , , },
{ , , , } };
const S_DES::VVI S_DES::S_2{ { , , , },
{ , , , },
{ , , , },
{ , , , } };

S-DES加密的更多相关文章

  1. Android数据加密之Des加密

    前言: 端午节前有个同事咨询我有关Android DES加密的相关实现,简单的实现了一下,今天来总结一下. 其他几种加密方式: Android数据加密之Rsa加密 Android数据加密之Aes加密 ...

  2. php使用openssl进行Rsa长数据加密&lpar;117&rpar;解密&lpar;128&rpar; 和 DES 加密解密

    PHP使用openssl进行Rsa加密,如果要加密的明文太长则会出错,解决方法:加密的时候117个字符加密一次,然后把所有的密文拼接成一个密文:解密的时候需要128个字符解密一下,然后拼接成数据. 加 ...

  3. DES加密

    接口等加密字段 import java.security.SecureRandom; import javax.crypto.Cipher;import javax.crypto.SecretKey; ...

  4. c&num; DES加密解密

    class DESHelper { string _iv = "9AUP"; string _key = "9d"; /// <summary> / ...

  5. (iOS)Base64加密和DES加密、以及JAVA和iOS中DES加密统一性问题

    我们在项目中为了安全方面的考虑,通常情况下会选择一种加密方式对需要安全性的文本进行加密,而Base64加密和DES64加密是常用的加密算法.我记得我在前一个项目中使用的就是这两种加密算法的结合:Bas ...

  6. PYTHON实现DES加密及base64源码

    要求是实现DES加密,解密,我是用python实现的,还是有挺多坑的,改bug就改了挺久,加密实现后,解密过程就比较轻松. 另外,附加base64编码源码 要求:输入秘钥为64位二进制数(有效位为56 ...

  7. des加密解密——java加密,php解密

    最近在做项目中,遇到des加密解密的问题. 场景是安卓app端用des加密,php这边需要解密.之前没有接触过des这种加密解密算法,但想着肯定会有demo.因此百度,搜了代码来用.网上代码也是鱼龙混 ...

  8. DES加密解密

    加密后生成Base64字符串,并去除'='字符. 加密后替换掉'+',这样加密后的字符串可以作为url参数传递. using System; using System.IO; using System ...

  9. iOS 开发之路(AES&sol;DES加密实现) 三

    最近接触的这个项目由于以前服务器上用的是DES/CBC/PKCS5Padding加密方式,为了让在iOS上的加密结果与服务器端保持一致,我做了很多尝试,现在分享给大家.PS:现在不推荐用DES了,只是 ...

  10. php des 加密解密实例

    des加密是对称加密中在互联网应用的比较多的一种加密方式,php 通过mcrypt扩展库来支持des加密,要在Php中使用des加密,需要先安装mcrypt扩展库 $iv_size = mcrypt_ ...

随机推荐

  1. Spring Bean详细讲解

    什么是Bean? Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象. Spring 容器会自动完成@bean对象的实例化. 创建应用对象之间的协作关系的行为称为:装配( ...

  2. java正则表达式

    java正则表达式 1.Java正则表达式的语法与示例:  http://baike.xsoftlab.net/view/207.html 2.Java 正则表达式:  http://www.runo ...

  3. Comware 架构理解

    网络操作系统 首先什么是网络操作系统: 一种说法是:运行在路由器,网络交换机,防火墙上的特别的操作系统 另一种说法是:部署在局域网或者私有网络,允许网络中的多个计算机共享文件和打印机,因为现在的单机系 ...

  4. ASP&period;Net 验证控件 RegularExpressionValidator

    定义和用法 RegularExpressionValidator 控件用于验证输入值是否匹配指定的模式. 注释:除非浏览器不支持客户端验证或 EnableClientScript 属性被设置为 fal ...

  5. jsp中文件下载的实现

    jsp中实现文件下载的最简单的方式是在网页上做超级链接,如:<a href="music/abc.mp3">点击下载</a>.但是这样服务器上的目录资源会直 ...

  6. 使用PHP导出Word文档的原理和实例

    PHP操作Word文档的方法有很多,这里再为大家提供一种方法. 原理   一般,有2种方法可以导出doc文档,一种是使用com,并且作为php的一个扩展库安装到服务器上,然后创建一个com,调用它的方 ...

  7. Gleb And Pizza CodeForces - 842B

    CodeForces - 842B #include<bits/stdc++.h> using namespace std; int main() { int r,d,t; double ...

  8. JSP判断移动设备

    日期: 2014年3月6日 人员::铁锚 看到了一篇很好的文章, <在天猫,前端做什么?>,里面有天猫php判断移动设备的正则(个人猜测),觉得很好用,于是就决定移植到JSP里面. jsp ...

  9. nginx做负载均衡&plus;keepalived&lpar;做主备&rpar;

    部署Nginx 一,安装nginx依赖: 查看是否已经安装 rpm -qa |grep gcc rpm -qa |grep openssl-devel rpm -qa |grep pcre-devel ...

  10. drf2 FBV和CBV

    FBV 基于函数的视图 CBV 基于类的视图 也就是说我们是用函数编写视图~还是类编写视图 urlpatterns = [ path('admin/', admin.site.urls), path( ...