这是一个高内聚低耦合可复用的DES加密系统的实现。

Github 链接:https://github.com/cyendra/CyDES

要实现加密系统,先考虑数据的基本单位。

在DES加密中,数据是以64位为一组的(unsigned long long),我们称它为Bit。

加密过程中会对Bit做位移操作(左移、右移、循环左移、循环右移),也会做位运算(And、Or、Xor),还会做分割以及合并等操作。

我们设计一个类Bit来封装这些操作,作为数据的基本单位。

 /*
表示64位以下的数据
可以做常见的位运算
*/
class Bit {
private:
unsigned long long bit;// 表示数据,最多64位
int size;// 表示数据的位数,不超过64位
public:
// 值为0的64位数据
Bit(); // 值为_bit的64位数据
Bit(unsigned long long _bit); // 值为_bit的n位数据,当n>64位时截断
Bit(unsigned long long _bit, int n); Bit(const Bit& b);
Bit& operator=(Bit& b);
//Bit& operator=(unsigned char num); // 由byte构造8位Bit对象
void Byte(unsigned char num); // 直接左移d位
void LeftShift(int d); // 循环左移d位
void LeftRotate(int d); // 直接右移d位
void RightShift(int d); // 循环右移d位
void RightRotate(int d); // 将第pos位设置为1
// pos从左向右从0开始计数,超过size位时无效
void Set(int pos); // 将所有位都设置为1
void Set(); // 将第pos位设置为0
// pos从左向右从0开始计数,超过size位时无效
void Reset(int pos); // 将所有位都设置为0
void Reset(); // 将第pos位取反
// pos从左向右从0开始计数,超过size位时无效
void Flip(int pos); // 将所有位都取反
void Flip(); // 当所有位都为0时返回true
bool None(); // 当任意位为1时返回true
bool Any(); // 统计所有位中1的个数
int Count(); // 数据的有效位数
int Size(); // 当第pos位的值为1时返回true
// pos从左向右从0开始计数,超过size位时无效
bool operator[](int pos); // 将数据以unsigned long long的形式返回
unsigned long long ToULL(); // 将所有二进制位以二进制串形式返回
std::string ToString(); // 静态方法,将数据bit从中间分割为两份数据
static std::pair<Bit, Bit> Split(Bit bit); // 静态方法,把数据bit平分为n份,n为偶数,bit的size能被n整除
static std::vector<Bit> Split(Bit bit, int n); // 静态方法,将两份数据合并为一份数据
static Bit Merge(Bit L, Bit R); // 静态方法,将Bit数组中从L到R之间的数据合并为一份数据
static Bit Merge(Bit b[], int L, int R); // 静态方法,求两份数据的异或值
static Bit Xor(Bit x, Bit y); // 静态方法,求两份数据的OR
static Bit Or(Bit x, Bit y); // 静态方法,求两份数据的AND
static Bit And(Bit x, Bit y);
};

Bit类

DES加密过程的原理其实就是16轮迭代,而迭代过程中有两个重要的处理:子密钥生成和f函数。

所以先不考虑主加密过程,考虑子密钥和f函数的抽象。

虽然子密钥有16之多,但是我们只要有了主密钥就可以生成全部的16个子密钥。

我们把这个过程抽象出来,即输入主密钥,得到一个装有16个子密钥的动态数组:

 /*
主密钥产生子密钥的接口
单例模式
*/
class IKeyManager :public Uncopyable {
public:
// 通过主密钥产生子密钥
virtual std::vector<Bit> GetKeys(Bit MasterKey) = ;
};

IKeyManager接口

接下来考虑f函数,它接受一个32位的数据和一个48位的子密钥,返回32位的加密数据。

 /*
DES中f函数的接口
单例模式
其值通过32位的数据与48位的子密钥计算而来
*/
class IFunction :public Uncopyable {
public:
// f函数
// bit为32位的R_{i-1},Key为48位的K_i
virtual Bit ProcessKey(Bit bit, Bit Key) = ;
};

IFunction接口

有了这两个类,主加密过程就容易实现了。

考虑到主加密过程一次只能处理64位的数据,而实际应用中要多次调用主加密过程来加密长数据。

因此为了避免重复计算子密钥,要在调用主加密过程之前先设置好主秘钥。

解密操作是加密操作的逆操作,所以放在一起实现。

 /*
Data Encryption Standard 接口
继承此接口的派生类可以完成以下操作:
1-接受一个主密钥
2-对一组数据加密
3-对一组数据解密
*/
class IDes {
public:
// 将64位的key设置为主密钥
virtual void SetMasterKey(Bit key) = ; // 加密明文组dat
virtual Bit Encryption(Bit dat) = ; // 解密密文组dat
virtual Bit Decryption(Bit dat) = ;
};

IDes接口

这样一来,DES的框架就准备好了,实现的时候有两个较复杂的逻辑:置换表操作和S-Box取值操作。

因此单独把这两个操作抽象出来。设计一个类表示置换表,一个类管理置换表,一个类表示S-Box,一个类管理S-Box。

 /*
置换表接口
*/
class IPermutationTable {
public:
// 置换表中元素个数
virtual int Size() = ; // 获取表中第pos个元素
// pos从0开始计数
virtual int Get(int pos) = ;
};

IPermutationTable接口

 /*
DES中置换表的管理器接口
单例模式
它管理所有DES中要用到的置换表
*/
class IPmtTableManager :public Uncopyable {
public:
// 获取初始置换表IP
virtual IPermutationTable* GetIPTable() = ; // 获取逆初始置换表IP-1
virtual IPermutationTable* GetIPRevTable() = ; // 获取扩增排列表E
virtual IPermutationTable* GetETable() = ; // 获取缩减排列表P
virtual IPermutationTable* GetPTable() = ; // 获取密钥排列PC-1
virtual IPermutationTable* GetPC1Table() = ; // 获取密钥排列PC-2
virtual IPermutationTable* GetPC2Table() = ;
};

IPmtTableManager接口

 // S-Box的接口
class ISBox {
public:
// 通过6位数据pos获取S-Box中的值
virtual Bit Get(Bit pos) = ; // 通过指定的坐标(i,j)获取S-Box中的值
virtual Bit Get(int i, int j) = ;
};

ISBox接口

 /*
S-Box管理器的接口
单例模式
它能够返回指定编号的S-Box
*/
class ISBoxManager :public Uncopyable {
public:
// 返回指向编号为i的S-Box的指针
virtual SBox* GetSBox(int i) = ;
};

ISBoxManager接口

只有置换表还不够,置换操作也是一个较复杂的操作,应该单独抽象出来处理。

 /*
置换操作的接口
单例模式
*/
class IPermutationManager :public Uncopyable {
public:
// 用置换表table对数据bit进行置换
virtual Bit Permutation(Bit bit, IPermutationTable* table) = ;
// 用置换表table对数据bit进行逆置换
virtual Bit InversePermutation(Bit bit, IPermutationTable* table) = ;
};

IPermutationManager接口

如此一来,在添加具体实现细节以后,DES主加密过程就能顺利实现了。

为了加密长数据,我们为之前的代码套上一层外壳。

用一个类来与用户进行交互,使它可以以用户指定的分组方式来对数据分组并调用主加密过程。

/*
加密器接口
*/
class IEncryptor {
public:
// 分组操作方案
enum Type {
ECB, CBC, CFB, OFB
}; // 加密字符串
virtual std::vector<unsigned char> EncryptString(const std::string& string, Bit MasterKey, Type type) = ; // 解密字符串
virtual std::string DecryptString(const std::vector<unsigned char>& bins, Bit MasterKey, Type type) = ; // 加密二进制串
virtual std::vector<unsigned char> EncryptBinary(const std::vector<unsigned char>& bins, Bit MasterKey, Type type) = ; // 解密二进制串
virtual std::vector<unsigned char> DecryptBinary(const std::vector<unsigned char>& bins, Bit MasterKey, Type type) = ; // 加密文件
virtual std::vector<unsigned char> EncryptFile(char *filename, Bit MasterKey, Type type) = ; // 解密文件
virtual std::vector<unsigned char> DecryptFile(char *filename, Bit MasterKey, Type type) = ; // 保存二进制串到文件
virtual void SaveBinaryAsFile(const std::vector<unsigned char>& bins, char *filename) = ;
};

IEncryptor接口

最后将具体的分组过程实现即可。

 /*
区块加密法的操作模式接口
*/
class IMode :public Uncopyable {
public:
virtual std::vector<unsigned char> EncryptBinary(IDes* des, const std::vector<unsigned char>& bins, Bit MasterKey) = ;
virtual std::vector<unsigned char> DecryptBinary(IDes* des, const std::vector<unsigned char>& bins, Bit MasterKey) = ;
};

IMode接口

DES加密系统的实现的更多相关文章

  1. DES加密解密(适用Windows和Linux系统)防止linux下解密失败

    转自:http://blog.csdn.net/jerry_bj/article/details/8276552 package com.lasun.util; import java.io.File ...

  2. paip.提升安全性----Des加密 java php python的实现总结

    paip.提升安全性----Des加密 java php python的实现总结 ///////////    uapi         private static String decryptBy ...

  3. php实现和c#一致的DES加密解密

    原文:php实现和c#一致的DES加密解密 php实现和c#一致的DES加密解密,可以从网上搜到一大堆,但是测试后发现都没法用.以下正确代码是我经过苦苦才找到的.希望大家在系统整合时能用的上. 注意: ...

  4. RAS、AES、DES加密

    ---------------------------------------------------------------------------------------------------- ...

  5. BS结构中,web如何将数据进行DES加密并写道IC卡中

    在IC卡应用系统中,一般都要对IC卡数据进行DES加密,以保证数据的安全.友我科技RFID读写器云服务2.0充分考虑了这个需求,只需要软件工程师简单的配置即可实现数据的加解密并且写到数据块中.如下图所 ...

  6. DES加密模式详解

    DES加密模式详解 http://www.cnblogs.com/Lawson/archive/2012/05/20/2510781.html http://www.blogjava.net/wayn ...

  7. DES 加密解密

    [概念] 数据加密算法(Data Encryption Algorithm,DEA)是一种对称加密算法,很可能是使用最广泛的密钥系统,特别是在保护金融数据的安全中,最初开发的DEA是嵌入硬件中的.通常 ...

  8. Python Des加密与解密实现软件注册码、机器码

    原理 判断路径下是否存在识别文件,若存在就解密对比,若不存在就进入机器码注册: 获取系统C盘序列号作为识别ID,并添加随机数作为混淆,生成最终机器码. 将机器码发给软件开发者,开发者将机器码解密后,添 ...

  9. DES加密解密算法C++实现

    DES加密算法并不难,是由一些简单的变换得来的,难的是要有足够的耐心.蒟蒻并不想说自己用了多久才把代码写好的. 代码: 我真的太难了QAQ #include<iostream> using ...

随机推荐

  1. MySQL配置文件-my.ini

    下面允许我介绍一下MySQL的my.ini配置文件: my.ini是什么? my.ini是MySQL数据库中使用的配置文件,修改这个文件可以达到更新配置的目的. my.ini存放在哪里? my.ini ...

  2. addlinkedserver

    http://blog.sina.com.cn/s/blog_5321db9d0100f89g.html --创建链接服务器 exec sp_addlinkedserver  'ITSV ', ' ' ...

  3. object c小代码——日期篇

    1.判断两个日期是否是同一天,不要求小时,分钟要一样 用法 NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier: ...

  4. 关于 Lua 内存泄漏的检测

    前一阵开始和同事一起优化内存,首先是优化 Lua 内存,因为发现每次战斗完后 Lua 内存非常大,从 3M 左右在经过了10次左右的战斗后,会暴增到近 100M,很明显是有内存泄漏.      然后我 ...

  5. nyoj 84阶乘后0的个数

    描述 计算n!的十进制表示最后有多少个0 输入 第一行输入一个整数N表示测试数据的组数(1<=N<=100)每组测试数据占一行,都只有一个整数M(0<=M<=10000000) ...

  6. POJ 2251 Dungeon Master (BFS最短路)

    三维空间里BFS最短路 #include <iostream> #include <cstdio> #include <cstring> #include < ...

  7. Windows Azure 的虚拟硬盘和文件的相关概念

    虚拟硬盘和文件 在 Windows Azure 外部,虚拟硬盘可使用 VHD 或 VHDX 格式.它们还可以是固定的.动态扩展或差异的.Windows Azure 支持 VHD 格式的固定磁盘.固定格 ...

  8. 动态链接库(DLL)的使用

    2013-07-04 http://blog.csdn.net/blpluto/article/details/5715182 感觉挺好,推荐去看看.

  9. 七行jquery代码实现图片渐变切换【兼容ie6+、 Chrome、 Firefox】

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. TOR的使用

    使用步骤: 1.配置,该计算机是否需要通过代理访问互联网?选否 2.该计算机的防火墙是否仅允许特定端口的互联网连接?选否 3.互联网服务提供商(ISP)是否对Tor网络连接进行了封锁或审查?选是 4. ...