这是一个高内聚低耦合可复用的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. Understanding Network Class Loaders

    By Qusay H. Mahmoud, October 2004     When Java was first released to the public in 1995 it came wit ...

  2. Spring的annotation用在set方法上 hibernate的annotation用get方法上

    1.Spring的annotation用在set方法上 2.hibernate的annotation用在get方法上

  3. ASP.NET 導入Excel

    常常碰到這種需求,為了避免自己每次寫Code都要東翻西找Sample,乾脆丟上來當備份 此外,也為了方便網路上的大大們Copy Paste方便,小弟已經順便標示要複製程式碼的起始結束位置 在歡樂的貼程 ...

  4. C# 线程更新UI

    最方便的用法: private void ViewMsg(string msg)        { /* control.Invoke(new SetControlTextDelegate((ct,  ...

  5. [Stephen]C#中调用C++动态链接库

    1.主程序声明引用外部方法,并完成方法调用

  6. [Raobin] Ext.net 页面由于CMB的store和对图像同时执行,所以不会触发非空验证 所以会在后台直接调Js去验证

    X.Call("valid", vm.ID_EDIT_FORM); x.Call("前台的js的方法名称"," 参数为集合");

  7. FAQ_浏览器_ChromeDriver报错

    Started ChromeDriverport=2437version=23.0.1240.0log=D:\workspace\WebdriverTest\chromedriver.log[0704 ...

  8. 浅谈PetShop之使用存储过程与PLSQL批量处理(附案例)

    1       大概思路 备注:黄色为影响参数 2       PetShop4的经典数据库连接代码回顾 PetShop4有3个函数,具体有: ExecuteReader:可以读一个表的记录,只能读不 ...

  9. tomcat 服务器全解

    ①B/S.C/S比较 ⑴C/S C/S结构即客户端/服务器(Client/Server),例如QQ: 需要编写服务器端程序,以及客户端程序,例如我们安装的就是QQ的客户端程序: 缺点:软件更新时需要同 ...

  10. POJ 2533 Longest Ordered Subsequence (LIS DP)

    最长公共自序列LIS 三种模板,但是邝斌写的好像这题过不了 N*N #include <iostream> #include <cstdio> #include <cst ...