这是一个高内聚低耦合可复用的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. 结构体page_cur_t

    /** Type of the index page */ typedef byte page_t; /** Index page cursor */ typedef struct page_cur_ ...

  2. 关于JQuery与AJAX验证

    AJAX验证,其实就是JS代码,他就是先利用Jquery或JS获取一个值,然后偷偷的把值传送到验证界面,然后在偷偷的把验证后的结果给传回来,利用传回来的结果在进行JS判断,从而不会刷新界面. 用图片解 ...

  3. QNX环境

    QNX开发环境和QNX虚拟机都搭建好了,开始写第一个QNX程序. 关于QNX程序开发的最好参考是QNX官网上的pdf书<10 Steps to Developing a QNX Program: ...

  4. [HDU 1561] The more, The Better

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  5. -_-#【减少 DOM 访问】“离线”更新节点,再将它们添加到树中

    Minimize DOM Access javascript 之 DOM 优化 <!DOCTYPE html> <html> <head> <meta cha ...

  6. spring--DI--3

    3.1.1  依赖和依赖注入 传统应用程序设计中所说的依赖一般指“类之间的关系”,那先让我们复习一下类之间的关系: 泛化:表示类与类之间的继承关系.接口与接口之间的继承关系: 实现:表示类对接口的实现 ...

  7. Spring概述--1

    1.1.1  Spring是什么 Spring是一个开源的轻量级Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架,其目的是用于简化企业级应用程序开发.应用程序是由 ...

  8. ssh,telnet远程AIX以及数据传输问题

    (1)telnet远程 输入:telnet 目标IP 输入用户名,密码 进入远程机器 (2)AIX默认安装ftp,使用ftp传输数据 ftp 目标IP地址 输入用户名,密码(远程服务器的) 或者输入f ...

  9. 搭建集群必备:windows如何使用Xshell远程连接(SSH)Linux

    出处about云(http://www.aboutyun.com/blog-61-22.html)欢迎访问我的博客 首先介绍一下环境: (主机)操作系统:win7 虚拟机:vmware worksta ...

  10. POJ1423 - Big Number(Stirling公式)

    题目大意 求N!有多少位 题解 用公式直接秒杀... 代码: #include<iostream> #include<cmath> using namespace std; # ...