密码学之数字信封 Digital_Envelope(project完整代码)

本文档介绍了使用GIFT-128和RSA算法实现数字信封的系统安全课设实验。代码包括了_Digital_Envelope、_Digital_Envelope_GIFT-128、_Digital_Envelope_RSA和_MD5等文件的实现,详细阐述了各个部分的实现细节。虽然实验报告未展示,但提供了作者的联系方式以供交流。
摘要由CSDN通过智能技术生成

题目详见:系统安全课设实验五

 

代码框架一览(非完整Project)

_Digital_Envelope.h

#pragma once
//
//	_Digital_Envelope 类体设计,数字信封
// 2019.06.06 
// Coded By YI MENG
//
// 把十六进制、十、二进制弄到这里来

#include <string>
#include <windows.h>

class DigitalEnvelope {

public:
	//friend class GIFT_128; // GIFT_128类 需要调用进制转换函数,友元处理,,,封装性破坏太大,还是使用静态公有成员好一些

public:
	void menu();  // 根据实际情况设定选项
	static std::string Hex_TO_Bin(const std::string&);		// 十六进制转二进制流
	static std::string Bin_TO_Hex(const std::string&);		// 二进制流转十六进制

private:
	GIFT_128 gift;
	RSA rsa;

	std::string selection;		     // 菜单选择
	std::string strMD5_Send;	     // 分组秘钥的哈希数据,发送方将会同分组加密数据一起、传送给接收方,以便接收方进行解密校验
	std::string strMD5_receive;      // RSA解密所得的明文结果的哈希数据,接收方自测,用于验证解密结果是否与最初的分组秘钥一致
	std::string flag;		// 用于GIFT还是RSA的选择、以及是否查看40加密过程的校验
	std::string flagPla;	// 用于确认明文输入无误的校验
	std::string flagKey;	// 用于确认是否查看分组秘钥哈希结果的校验、询问是否对分组密钥进行RSA加解密的校验
	std::string flagCip;    // 用于确认是否查看40轮解密过程的校验、两次散列结果的数据是否一致的校验
	bool gotoRSAInAdance;   // 提前进行RSA演示的标志,若跳转了还需要回调进行GIFT-128-128加解密
};

_Digital_Envelope_GIFT-128.h

#pragma once
//
//	_Digital_Envelope_GIFT-128 类体设计
// 2019.05.28 
// Coded By YI MENG
//
#include <map>
#include <string>
#include <vector>
#include <iomanip>

//class DigitalEnvelope;

class GIFT_128 {

public:
	//friend class DigitalEnvelope;

public:
	// 内部实现

	void Initial();                          // 初始化GS表、逆表REGS 
	void AddRoundKey();                      // 轮密钥加变换
	void SetKeys();                          // 初始化40轮密钥,进行存储处理,并初始化UKey、VKey、CKey密码表
	void GSbox(std::string&);                // 在GS盒替换
	void REGSbox(std::string&);              // 在REGS盒替换
	void PermBits(std::string&);             // 在P表置换
	void REPermBits(std::string&);           // 在REP表置换
	void ENCRY();                            // 分组明文加密
    void DECRY();                            // 分组密文解密
	void InputPlaintext();                   // 输入明文
	void InputMasterkey();                   // 输入密钥
	void OutputCiphertext();                 // 输出密文
	void OutoutByByte(const std::string&);   // 数据格式化输出
	bool IsHexChar(const char&);             // 是否十六进制字符判断

public:
	// 交互设计

	std::string GetStrKey() { return strKey; }		 // 获取密钥
	std::string GetStrPla() { return strPla; }		 // 获取明文
	std::string GetStrCip() { return strCip; }		 // 获取密文
	void clearStrKey() { strKey.clear(); }			 // 清空密钥
	void DisplayENCRY();             // 40论加密中间过程数据演示
	void DisplayDECRY();             // 40论解密中间过程数据演示


private:
	// 数据封装

	std::map<char, char> GS;
	std::map<char, char> REGS;

	std::string strPla;	// 明文 Plaintext
	std::string strKey; // 秘钥 Masterkey
	std::string strCip; // 密文 Ciphertext

	//加密过程
	std::vector<std::string> VecPlaEncry; // 中间明文
	std::vector<std::string> VecKeyEncry; // 子秘钥
	std::vector<std::string> VecCipEncry; // 中间密文
	//解密过程
	std::vector<std::string> VecPlaDecry; // 中间明文(应对应加密过程的密文)
	std::vector<std::string> VecKeyDecry; // 子秘钥(应与加密过程的轮秘钥反序)
	std::vector<std::string> VecCipDecry; // 中间密文(应对应加密过程的明文)

	std::string key[8];
	std::string UKey[40];
	std::string VKey[40];

	// C++ 11版本以后,支持直接初始化
	std::string CKey[40] = {
	"01","03","07","0F","1F","3E","3D","3B","37","2F","1E","3C","39","33","27","0E",
	"1D","3A","35","2B","16","2C","18","30","21","02","05","0B","17","2E","1C","38",
	"31","23","06","0D","1B","36","2D","1A"
	};
	int P[128] = {
			 0,33,66,99,96,1,34,67,64,97,2,35,32,65,98,3,
			 4,37,70,103,100,5,38,71,68,101,6,39,36,69,102,7,
			 8,41,74,107,104,9,42,75,72,105,10,43,40,73,106,11,
			 12,45,78,111,108,13,46,79,76,109,14,47,44,77,110,15,
			 16,49,82,115,112,17,50,83,80,113,18,51,48,81,114,19,
			 20,53,86,119,116,21,54,87,84,117,22,55,52,85,118,23,
			 24,57,90,123,120,25,58,91,88,121,26,59,56,89,122,27,
			 28,61,94,127,124,29,62,95,92,125,30,63,60,93,126,31
	};
	int REP[128] = {
	0, 5, 10, 15, 16, 21, 26, 31, 32, 37, 42, 47, 48, 53, 58, 63, 64,
	69, 74, 79, 80, 85, 90, 95, 96, 101, 106, 111, 112, 117, 122, 127,
	12, 1, 6, 11, 28, 17, 22, 27, 44, 33, 38, 43, 60, 49, 54, 59, 76,
	65, 70, 75, 92, 81, 86, 91, 108, 97, 102, 107, 124, 113, 118, 123,
	8, 13, 2, 7, 24, 29, 18, 23, 40, 45, 34, 39, 56, 61, 50, 55, 72, 77,
	66, 71, 88, 93, 82, 87, 104, 109, 98, 103, 120, 125, 114, 119, 4, 9,
	14, 3, 20, 25, 30, 19, 36, 41, 46, 35, 52, 57, 62, 51, 68, 73, 78,
	67, 84, 89, 94, 83, 100, 105, 110, 99, 116, 121, 126, 115
	};
};

_Digital_Envelope_RSA.h

#pragma once
//
// _Digital_Envelope_RSA 类体设计
// 2019.05.28 
// Coded By YI MENG
// 该 RSA 加密类接口为 加解密函数参数,仅处理单个大整数,若是字符串可分割多个LL数据来进行处理
//
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <ctime>
#include <cstring>
#include <strstream>
#include <sstream>
#include <string>
#include <ctype.h>

typedef long long LL;
typedef std::vector<std::pair<char, LL>> VP;

class RSA {

public:
	RSA() { }
	RSA(const std::string & );                    // 初始化明文串
	~RSA() { delete[] isPrimeNumber; }
	void IsPrimeNumber();                         //优先初始化质数表
	
	std::string get_plainString();                // 返回明文串
	std::string get_cipherString();               // 返回密文串
	std::string get_cipherToPlain();
	void set_plainString(const std::string& str );// 重置明文串
	void clear_plainString();                     // 清空 RSA 明文
	std::string set_cipherString();               // 构造密文串,串加密
	std::string set_cipherToPlain();              // 串解密 
	

	LL gennerateRandNumber(const LL & );  // 生成随机大数
	LL mul(LL , LL , const LL & );	      // 取模大数,防止运算溢出
	LL quickpow(LL a, LL b, LL mod);      // 快速幂
	LL gcd(LL, LL);					      // gcd 求最大公约数	
	LL exgcd(LL, LL, LL &, LL &);	      // 扩展欧几里得
	void get_PrimeNumberPair(LL &, LL &); // 生成质数对 p、q
	LL get_e(LL n);						  // 生成与 欧拉函数值t 互质的 公钥e
	void get_key();						  // 生成所有秘钥
	void output_PublicKey();              // 获取加密所用的公钥
	void output_PrivateKey();             // 获取解密所用的私钥
	LL ENCRY(LL m);                       // 加密
	LL DECRY(LL c);                       // 解密
	void initial();                       // 初始化
	void computing();					  // 因地制宜,设定好属于自己的运行函数
	void STR_TO_Num(const std::string & ,LL num[]);                               // 字符串转长整型数组
	void Num_TO_STR(std::string &, const LL num[]);                               // 长整型数组转字符数组
	bool toCheckPairWasExist(const VP & , const char & ,const LL & );             // 键值对已存在的判断
	void toFindPair_GetCharToSet_CipherToPlain(const VP & , char& ,const LL & );  // 通过简直对关联恢复明文字符串
	std::string LLtoString(const LL& );  // 长整型数值转字符串
	
private:
	// 以空间换时间,预处理进行质数筛选
	 然鹅由于数组开的太大,导致编译器栈溢出,故决定自行new出堆内存,最后记得析构函数里边delete…
	const int N = 100000000;
	//short isPrimeNumber[N + 3] = new short;
	//short isPrimeNumber[100000000 + 3];
	short *isPrimeNumber = new short[N + 3];

	LL p, q;	//随机生成两个大质数
	LL n;		// p * q ,作为加密公钥对组成之一、也是解密私钥对组成之一
	LL t;		//(p - 1)*(q - 1) 欧拉函数值
	LL e, d;    // 加密用的公钥、解密用的私钥;先由t、e 互质求得e,在扩展gcd求d

	std::string plainStr;       //明文串
	std::string cipherStr;      // 密文串
	std::string cipherToPlain;  // 解密结果

	LL plainNumber[32];                // 明文,进制可自行选择,默认十进制
	std::vector<LL> cipherNumberSet;   // 密文集合,与明文保持进制一致,后边解密用得到
	LL plainNumberDecry[32];         // 解密所得结果,注意,此明文为LL数据形式
	VP vp;  // 字符串和整型数组互相转化的依据,键值对形式存储
	        // 注意,VP的pair顺序先char再LL值,使用时注意顺序,因为即使顺序反了编译器也会默认是对的,都是ASCLL数值处理。。。
};

_MD5.h

#pragma once
//
// MD5.h 哈哈,多年前收藏的散列函数,派上用场了 
//
/* MD5
 converted to C++ class by Frank Thilo (thilo@unix-ag.org)
 for bzflag (http://www.bzflag.org)

   based on:

   md5.h and md5.c
   reference implementation of RFC 1321

   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.

License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.

License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.

RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.

These notices must be retained in any copies of any part of this
documentation and/or software.

*/
#ifndef BZF_MD5_H  
#define BZF_MD5_H  

#include <string>  
#include <iostream>  

// a small class for calculating MD5 hashes of strings or byte arrays  
// it is not meant to be fast or secure  
//  
// usage: 1) feed it blocks of uchars with update()  
//      2) finalize()  
//      3) get hexdigest() string  
//      or  
//      MD5(std::string).hexdigest()  
//  
// assumes that char is 8 bit and int is 32 bit  

// Constants for MD5Transform routine.  

#define S11 7  
#define S12 12  
#define S13 17  
#define S14 22  
#define S21 5  
#define S22 9  
#define S23 14  
#define S24 20  
#define S31 4  
#define S32 11  
#define S33 16  
#define S34 23  
#define S41 6  
#define S42 10  
#define S43 15  
#define S44 21  

class MD5{
public:
	typedef unsigned int size_type; // must be 32bit  

	MD5();
	MD5(const std::string& text);
	void update(const unsigned char *buf, size_type length);
	void update(const char *buf, size_type length);
	MD5& finalize();
	std::string hexdigest() const;
	friend std::ostream& operator<<(std::ostream&, MD5 md5);
	void updateValue(const std::string& text);

private:
	void init();
	typedef unsigned char uint1; //  8bit  
	typedef unsigned int uint4;  // 32bit  
	enum { blocksize = 64 }; // VC6 won't eat a const static int here  

	void transform(const uint1 block[blocksize]);
	//void update(const unsigned char input[], size_type length);
	//void update(const char input[], size_type length);
	static void decode(uint4 output[], const uint1 input[], size_type len);
	static void encode(uint1 output[], const uint4 input[], size_type len);

	bool finalized;
	uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk  
	uint4 count[2];   // 64bit counter for number of bits (lo, hi)  
	uint4 state[4];   // digest so far  
	uint1 digest[16]; // the result  

	// low level logic operations  
	static inline uint4 F(uint4 x, uint4 y, uint4 z);
	static inline uint4 G(uint4 x, uint4 y, uint4 z);
	static inline uint4 H(uint4 x, uint4 y, uint4 z);
	static inline uint4 I(uint4 x, uint4 y, uint4 z);
	static inline uint4 rotate_left(uint4 x, int n);
	static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
	static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
	static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
	static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
};

std::string md5ForString(const std::string& str);

#endif  

pch.h

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

#ifndef PCH_H
#define PCH_H

// TODO: 添加要在此处预编译的标头


#include "_Digital_Envelope_GIFT-128.h"
#include "_Digital_Envelope_RSA.h"
#include "_Digital_Envelope.h"
#include "_MD5.h"

#endif //PCH_H

代码具体实现细节如下:

_Digital_Envelope.cpp

//
//	_Digital_Envelope 类体实现,数字信封操作平台
//
#include "pch.h"

// 菜单设计
#pragma region

void DigitalEnvelope::menu(){

	std::cout << "\n\n ========== 数字信封“飞机--航站楼”模型,现在开始演示 ==========\n";
	Sleep(700); //暂缓0.7秒后输出
	std::cout << "\n ========== 模型所使用的加密算法有 ==========\n";
	Sleep(700); //暂缓0.7秒后输出
	std::cout << "\n分组加密算法采用轻量级 GIFT-128-128 + 非对称加密采用RSA公钥加密 + MD5散列算法\n\n\n";
	Sleep(700); //暂缓0.7秒后输出

	OneMoreTime:
	std::cout &l
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值