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

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

S-DES加密原理:

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

S-DES的f函数结构:

S-DES的S盒:

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

实现代码:

 #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长数据加密(117)解密(128) 和 DES 加密解密

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

  3. DES加密

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

  4. c# 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/DES加密实现) 三

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

  10. php des 加密解密实例

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

随机推荐

  1. hadoop2.2编程:MRUnit

    examples: Overview This document explains how to write unit tests for your map reduce code, and test ...

  2. 关于“javax.servlet.include.request_uri”属性值

    在springMVC的DispatcherServlet类的doService方法中有如下代码: if (WebUtils.isIncludeRequest(request)) { attribute ...

  3. Read ListViewItem content from another process z

    Normal Windows GUI applications work with messages that are sent to a window or control and the cont ...

  4. POJ 1773 Parity game 带权并查集

    分析:带权并查集,就是维护一堆关系 然后就是带权并查集的三步 1:首先确定权值数组,sum[i]代表父节点到子节点之间的1的个数(当然路径压缩后代表到根节点的个数) 1代表是奇数个,0代表偶数个 2: ...

  5. POJ 1200 Crazy Search

    思路:利用Karp-Rabin算法的思想,对每个子串进行Hash,如果Hash值相等则认为这两个子串是相同的(事实上还需要做进一步检查),Karp-Rabin算法的Hash函数有多种形式,但思想都是把 ...

  6. 多组 RadioButtonList 获取值

    <div class="row">    <table>        <thead><tr><th>操作</th ...

  7. 搭建hdfs服务器集群的搭建+trash

    完全分布式搭建需要三台机器:node1.node2和node3 搭建时间之前首先要保持时间一致:date ntpdateyum install ntpdatentpdate -u ntp.sjtu.e ...

  8. [CODEVS1216]跳马问题

    题目描述 Description 题目 输入描述 Input Description 第一行两个正整数M,N(0<M,N≤300)分别表示行和列 第二行两个正整数,表示起点的行列坐标. 第三行两 ...

  9. 【CSS3】Advanced10:Gradient

    1.background:linear-gradient(20deg/(to) bottom right,orange,red,hsl(60,100%,50%)); 2.-webkit-chrome/ ...

  10. normalization归一化

    简单的举个例子:一张表有两个变量,一个是体重kg,一个是身高cm.假设一般情况下体重这个变量均值为60(kg),身高均值为170(cm).1,这两个变量对应的单位不一样,同样是100,对于身高来说很矮 ...