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. String对象不可改变的特性

    1. 声明String对象 String s = "abcd"; 图1 2. 将一个字符串变量赋值给另一个String变量 String s2 = s; 图2 3. 字符串连接 s ...

  2. Reflector+Reflexil 相结合实现对DLL文件修改

    在工作过程中,我们有可能遇到这样的问题:公司发给客户的软件包突然报错了,但是你知道哪里报错了,而这个代码已经编译成DLL文件了,源代码不在自己这里.怎么办呢?还好现在有Reflexil插件,这个插件只 ...

  3. [swustoj 191] 迷宫逃离

    迷宫逃离(0191) 描述 江鸟突然想到了一个迷宫逃离的游戏,话说有三个人被困于一个n*m的迷宫里,他们三人都可以向上.向下.向左.向右四个方向进行走动,当然他们所在的初始位置没有障碍物,同时只能走到 ...

  4. 【 D3.js 进阶系列 — 6.2 】 饼状图的拖拽

    本文讲解稍微复杂一些的拖拽应用,即拖拽饼图的各部分. 在[入门 - 第 9.1 章]讲解了如何制作饼状图.饼状图的各部分是用具有宽度的弧线来表示的.在与用户进行交互的时候,如果每一部分都能拖拽,是很有 ...

  5. Bootstrap插件的使用

    昨天,我偶然间发现了它——BootStrap插件,它是一一套功能强大的前端组件.说起来,我跟这插件还真算得上有缘,我本来并不是去找这个插件的,我本来是找BootStarp Paginator这个分页插 ...

  6. Sharepoint的网页(Page),网页解析(Parsing)与解析安全处理(Security)

    转:http://www.chawenti.com/articles/8592.html Microsoft SharePoint Foundation 中主要有两种类型的页面,分别是应用程序页(Ap ...

  7. JAVA与.NET的相互调用——利用JNBridge桥接模式实现远程通讯

    分布式开发的历史 利用Remote方式调用远程对象实现服务器与客户端之间通讯是一种常用的网络开发方式,在.NET与JAVA开发当中,对Remote远程对象早已有着足够的支持(对Remote远程对象调用 ...

  8. [TOP]疯狂的投资

    [TOP]疯狂的投资 这是罗辑思维一期<疯狂的投资>的节目笔记,这期主要是通过菲尔德铺设横跨大西洋的电缆的故事讲了创业者需要的特质和<二十一世纪资本论>的一个观念:随着自由市场 ...

  9. Linux入门1

    在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器).它类似于DOS下的command和后来的cmd.exe.它接收用户命令,然后调用相应的应用程序. Li ...

  10. Phonegap3.4 环境搭建及新建项目

    一.环境准备 1.到这里安装Node.js. 2.到这里下载Adroid ADT Bundle for Windows,下载后解压,我的放在:F:\MobileDev\adt-bundle-windo ...