📄 advance.cpp
字号:
// Advance.cpp : implementation file
//
#include "stdafx.h"
#include "RSA Tool.h"
#include "Advance.h"
#include "BigNumber.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
const char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAdvance property page
IMPLEMENT_DYNCREATE(CAdvance, CPropertyPage)
CAdvance::CAdvance() : CPropertyPage(CAdvance::IDD)
{
//{{AFX_DATA_INIT(CAdvance)
m_keylen = 0;
KeyEmpty = 1;
//}}AFX_DATA_INIT
}
CAdvance::~CAdvance()
{
}
void CAdvance::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAdvance)
DDX_Control(pDX, IDC_CLEAR, m_CLEAR);
DDX_Control(pDX, IDC_TIME, m_Showtime);
DDX_Control(pDX, IDC_Q, m_Q);
DDX_Control(pDX, IDC_P, m_P);
DDX_Control(pDX, IDC_N, m_N);
DDX_Control(pDX, IDC_E, m_E);
DDX_Control(pDX, IDC_D, m_D);
DDX_Control(pDX, IDC_KEYLEN, m_KEYLEN);
DDX_CBIndex(pDX, IDC_KEYLEN, m_keylen);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAdvance, CPropertyPage)
//{{AFX_MSG_MAP(CAdvance)
ON_BN_CLICKED(IDC_GENERATEKEYS, OnGeneratekeys)
ON_BN_CLICKED(IDC_DECRYPT, OnDecrypt)
ON_BN_CLICKED(IDC_ENCRYPT, OnEncrypt)
ON_BN_CLICKED(IDC_SAVEKEYS, OnSavekeys)
ON_BN_CLICKED(IDC_SAVECLT, OnSaveclt)
ON_BN_CLICKED(IDC_SAVECIT, OnSavecit)
ON_BN_CLICKED(IDC_OPENKEYS, OnOpenkeys)
ON_BN_CLICKED(IDC_OPENCLT, OnOpenclt)
ON_BN_CLICKED(IDC_OPENCIT, OnOpencit)
ON_BN_CLICKED(IDC_CLEAR, OnClear)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAdvance message handlers
void CAdvance::OnGeneratekeys()
{
CBigNumber bnP, bnQ, bnE, bnN, bnD, bnCMP;
SYSTEMTIME before, after;
char elapsed[10];
char strP[MAX_PATH], strQ[MAX_PATH], strE[MAX_PATH], strN[350], strD[350];//N, D有可能超过300字节但是不会超过350字节
int len=2;
for(int i = 0; i < m_KEYLEN.GetCurSel(); i++)
{
len *= 2;
}
//初始化
GetLocalTime(&before);
P.Init(0);
Q.Init(0);
N.Init(0);
EUL.Init(0);
E.Init(0);
D.Init(0);
bnP.Init(0);
bnQ.Init(0);
bnE.Init(0);
// 生成指定bit的大数
P.GetPrime(len);
Q.GetPrime(len);
bnP.Init(P);
bnQ.Init(Q);
bnP.BigNumberToString(strP); // 把数组形式的大数转化成字符串
bnQ.BigNumberToString(strQ);
N.Init(bnP.Mul(bnQ)); // 计算 N = P * Q
bnN.Init(N);
bnN.BigNumberToString(strN);
bnP.Init(P);
bnQ.Init(Q);
bnP.m_ulValue[0]--; // P - 1
bnQ.m_ulValue[0]--; // Q - 1
EUL.Init(bnP.Mul(bnQ)); // EUL = (P-1) * (Q-1)
do{
bnE.GetPrime(len); // 产生指定位数的公钥,这里以素数作为公钥,可以节省时间,但公钥的范围小了
bnCMP.Init(0);
}while(((N.Mod(bnE)).Cmp(bnCMP)) == 0); // 产生的数与欧拉函数值除1外还有其他公因子
E.Init(bnE);
bnE.BigNumberToString(strE);
D.Init(E.SolEqu(EUL)); // 计算私钥
bnD.Init(D);
bnD.BigNumberToString(strD);
GetLocalTime(&after); // 计算花费时间
memset(elapsed, 0, 10);
bnP.GetElapsedTime(elapsed, before, after);
m_Showtime.SetWindowText(elapsed);
m_P.SetWindowText(strP); // 在对话框中输出大数
m_Q.SetWindowText(strQ);
m_N.SetWindowText(strN);
m_E.SetWindowText(strE);
m_D.SetWindowText(strD);
AfxMessageBox("密钥生成成功");
}
void CAdvance::OnDecrypt()
{
unsigned i = 0;
char szPlain[MAX_PATH], szBuf[MAX_PATH];
CString strTemp, strResult, strReplace;
CBigNumber bnCIT, bnCLT, bnD, bnN;
unsigned nIndex = 0;
SYSTEMTIME before, after;
char elapsed[10];
if ( m_cit.GetLength() == 0 ){
AfxMessageBox("请导入密文");
return ;
}
bnD.Init(0);
bnN.Init(0);
if ( KeyEmpty == 1 ){
AfxMessageBox("密钥为空,请导入密钥");
return ;
}
GetLocalTime(&before);
bnCIT.Init(0);
bnCLT.Init(0);
m_clt = "";
while(i < iCount){
strTemp = m_cit.Mid(nIndex, iLength[i]); // 获取每次加密后对应的密文
nIndex += iLength[i];
// iLength[i]里面是保存的每次读取的字节数
bnCIT.Init(0);
bnCIT.StringToBigNumber(strTemp); // 把密文转换成大数形式
bnCLT.Init(bnCIT.RsaEn(D, N)); // 解密
memset(szPlain, 0, MAX_PATH);
memset(szBuf, 0, MAX_PATH);
bnCLT.BigNumberToString(szPlain); // 把大数形式的明文转换成字符串
bnCLT.NumberToChars(szBuf, szPlain);
strReplace = szBuf;
m_clt += strReplace; // 连接明文
i++;
}
GetLocalTime(&after); // 计算花费时间
bnCIT.GetElapsedTime(elapsed, before, after);
m_Showtime.SetWindowText(elapsed);
D.Init(0);
N.Init(0);
AfxMessageBox("解密完毕");
}
void CAdvance::OnEncrypt()
{
CString strCipher;
CBigNumber bnCipher, bnE, bnResult;
CString strBlock, strResult, strReplace;
unsigned BlockSize = 12; // 分组长度12字节,96比特
unsigned long PlainSize; // 明文转化成数字后的长度
unsigned long Blocks = 0; // 分组数
BOOL finished = TRUE;
unsigned long i = 0, j = 0, nIndex = 0, nBytes;
SYSTEMTIME before, after;
char szLength[6];
char elapsed[10];
char temp1[MAX_PATH], temp2[MAX_PATH], szCipher[350];;
GetLocalTime(&before);
if ( m_clt.GetLength() == 0 ){
AfxMessageBox("请导入明文");
return ;
}
PlainSize = m_clt.GetLength();
bnE.Init(0);
if (E.Cmp(bnE) == 0){ // 公钥为0
AfxMessageBox("请先生成或导入密钥");
return ;
}
if (PlainSize % 12 != 0) // 计算分组数
Blocks = PlainSize / (unsigned long)BlockSize + 1;
else
Blocks = PlainSize / (unsigned long)BlockSize;
bnCipher.Init(0);
iCount = 0;
while(finished){
if (PlainSize - i < BlockSize)
BlockSize = PlainSize - i;
strBlock = m_clt.Mid(i, BlockSize);
memset(temp1, 0, MAX_PATH);
memset(temp2, 0, MAX_PATH);
CLT.StringToChars(temp1, strBlock);
CLT.CharsToNumber(temp2, temp1);
strResult = temp2;
bnResult.Init(0);
bnResult.StringToBigNumber(strResult);
bnCipher.Init(bnResult.RsaEn(E, N));
memset(szCipher, 0, MAX_PATH);
bnCipher.BigNumberToString(szCipher); // 加密后的数字转化成字符串
strReplace = szCipher;
iLength[iCount++] = strlen(szCipher); // 记录一次加密后密文的长度
itoa(strlen(szCipher), szLength, 10);
nBytes = strlen(szLength); // 把密文长度装换成字符串
for (j = 0; j < 5; j++){ // 密文的前四个字节保存一个分组被加密后的长度,
if ( j >= nBytes ) // 如果有剩,则用空格填充
m_cit += ' ';
else
m_cit += szLength[j];
}
m_cit += strReplace; // 一个分组的前面的数字是该分组的字节数,便于解密
i += BlockSize;
if ((unsigned long)i >= PlainSize)
finished = FALSE;
}
GetLocalTime(&after);
CLT.GetElapsedTime(elapsed, before, after);
m_Showtime.SetWindowText(elapsed);
AfxMessageBox("加密成功");
}
void CAdvance::OnSavekeys()
{
char strN[350], strE[MAX_PATH], strD[350];
CBigNumber bnD, bnE, bnN;
CString buf, FilePath;
char *szbuf;
const char szFilter[] = "文本文件(*.txt)|*.txt";
int dlen, elen, nlen, i, pos;
bnD.Init(0);
bnE.Init(0);
bnN.Init(0);
if (D.Cmp(bnD) == 0 || N.Cmp(bnN) == 0){
AfxMessageBox("密钥为空,请先生成密钥");
return ;
}
D.BigNumberToString(strD); // 把大数形式密钥转换成字符串形式
E.BigNumberToString(strE);
N.BigNumberToString(strN);
dlen = strlen(strD); // 获取密钥长度
elen = strlen(strE);
nlen = strlen(strN);
szbuf = new char[dlen + nlen + elen + 6];
memset(szbuf, 0, dlen + nlen + elen + 6);
for (i = 0; i < dlen; i++) // 首先保存D
*(szbuf + i) = strD[i];
*(szbuf + i++) = '\r'; // 加入回车换行符
*(szbuf + i++) = '\n';
pos = i;
for (i = pos; i < pos + elen; i++) // 然后爆出E
*(szbuf + i) = strE[i - pos];
*(szbuf + i++) = '\r'; // 加入回车换行符
*(szbuf + i++) = '\n';
pos = i;
for (i = pos; i < pos + nlen; i++) // 最后保存N
*(szbuf + i) = strN[i - pos];
*(szbuf + i) = '\0';
CFileDialog dlg(FALSE, NULL, NULL, NULL, szFilter);
if (dlg.DoModal() == IDOK){
FilePath = dlg.GetPathName(); // 获取目录名
if (FilePath.Right(4) != ".txt") // 只给出文件名,则加上扩展名,否则不用加
FilePath += ".txt";
CFile mFile(FilePath, CFile::modeCreate | CFile::modeWrite); // 读写方式打开
mFile.Write(szbuf, strlen(szbuf)); // 写文件
AfxMessageBox("密钥保存成功");
delete []szbuf;
}
}
void CAdvance::OnSaveclt()
{
char *buf;
int ilen;
const char szFilter[] = "文本文件(*.txt)|*.txt";
CString FilePath, str_CLT;
CBigNumber bn;
ilen = m_clt.GetLength();
if (ilen == 0){
AfxMessageBox("明文为空");
return ;
}
CFileDialog dlg(FALSE, NULL, NULL, NULL,szFilter);
if (dlg.DoModal() == IDOK){
FilePath = dlg.GetPathName();
if (FilePath.Right(4) != ".txt") // 只给出文件名,则加上扩展名,否则不用加
FilePath += ".txt";
CFile mFile(FilePath, CFile::modeCreate | CFile::modeWrite);
ilen = m_clt.GetLength();
buf = new char[ilen + 1];
memset(buf, 0, ilen+1);
bn.StringToChars(buf, m_clt);
buf[ilen] = '\0';
mFile.WriteHuge(buf, ilen);
AfxMessageBox("明文保存成功");
delete []buf;
}
D.Init(0);
E.Init(0);
N.Init(0);
}
void CAdvance::OnSavecit()
{
char *buf;
int iLen;
const char szFilter[] = "文本文件(*.txt)|*.txt";
CString FilePath, str_CIT;
CFileDialog dlg(FALSE, NULL, NULL, NULL,szFilter);
iLen = m_cit.GetLength();
if (iLen == 0){
AfxMessageBox("密文为空");
return ;
}
if (dlg.DoModal() == IDOK){
FilePath = dlg.GetPathName();
if (FilePath.Right(4) != ".txt") // 只给出文件名,则加上扩展名,否则不用加
FilePath += ".txt";
CFile mFile(FilePath, CFile::modeCreate | CFile::modeWrite);
buf = new char[iLen + 1];
memset(buf, 0, iLen+1);
CIT.StringToChars(buf, m_cit);
buf[iLen] = '\0';
mFile.WriteHuge(buf, iLen);
AfxMessageBox("密文保存成功");
delete []buf;
}
}
void CAdvance::OnOpenkeys() // 密钥读取后,D, N即被赋值,以便进行解密
{
CString strN, strE, strD;
const char szFilter[] = "文本文件(*.txt)|*.txt";
CString FilePath;
char *buf;
int i, pos;
int FileSize;
CFileDialog dlg(TRUE, NULL, NULL, NULL,szFilter);
if (dlg.DoModal() == IDOK){
FilePath = dlg.GetPathName(); // 获取目录名
CFile mFile(FilePath, CFile::modeRead); // 以读方式打开文件
FileSize = mFile.GetLength() + 1;
if (FileSize == 1){
AfxMessageBox("密钥为空");
return ;
}
buf = new char[FileSize];
memset(buf, 0, FileSize);
mFile.Read(buf, FileSize); // 读取文件
// 首先读入D,遇到回车换行符D结束
for (i = 0; i < FileSize; i++){
strD += *(buf + i);
if ( *(buf + i) == '\r' )
break;
}
// 然后读入E,遇到回车换行符E结束
pos = i + 2;
for (i = pos; i < FileSize; i++){
strE += *(buf + i);
if ( *(buf + i) == '\r' )
break;
}
// 最后读入N,遇到回车换行符节结束
pos = i + 2;
for (i = pos; i < FileSize; i++){
strN += *(buf + i);
if ( *(buf + i) == '\r' )
break;
}
/////////////////////////////////////////
//////去掉最后的'\0',否则前功尽弃,//////
strD.Delete(strD.GetLength()-1, 1);
strE.Delete(strE.GetLength()-1, 1);
strN.Delete(strN.GetLength()-1, 1);
/////////////////////////////////////////
/////////////////////////////////////////
if (strD.GetLength() > 350) {
AfxMessageBox("打开的不是密钥文件");// 如果打开错误文件,可能引起越界出错!
return;
}
D.Init(0);
E.Init(0);
N.Init(0);
D.StringToBigNumber(strD); // 把读取的密钥转换成大数形式
E.StringToBigNumber(strE);
N.StringToBigNumber(strN);
m_D.SetWindowText(strD); // 在对话框中显示密钥
m_E.SetWindowText(strE);
m_N.SetWindowText(strN);
AfxMessageBox("密钥读取成功");
KeyEmpty = 0;
delete []buf;
}
}
void CAdvance::OnOpenclt() // 读取明文后,全局变量m_clt(CString)保存明文的值
{
const char szFilter[] = "文本文件(*.txt)|*.txt";
CString FilePath;
char *buf;
unsigned long FileSize;
CFileDialog dlg(TRUE, NULL, NULL, NULL,szFilter);
if ( dlg.DoModal() == IDOK ){
FilePath = dlg.GetPathName();
CFile mFile(FilePath, CFile::modeRead);
FileSize = mFile.GetLength() + 1;
if ( FileSize == 1 ){
AfxMessageBox("明文为空");
return ;
}
buf = new char[FileSize];
memset(buf, 0, FileSize);
mFile.ReadHuge(buf, FileSize);
m_clt = buf;
AfxMessageBox("明文读取成功");
delete []buf;
}
}
void CAdvance::OnOpencit() // 读取密文后,全局变量m_cit(CStirng)保存密文的值,以便进行加密
{
const char szFilter[] = "文本文件(*.txt)|*.txt";
CString FilePath, strTemp;
char *buf, bloSize[4]; //因为1024bit最多128字节,128在文件上占3个字节,剩下一个结束符
unsigned long FileSize, nIndex = 0;
int citlen;
unsigned i, j, k = 0;
CFileDialog dlg(TRUE, NULL, NULL, NULL,szFilter);
if ( dlg.DoModal() == IDOK ){
FilePath = dlg.GetPathName(); // 得到文件的路径
CFile mFile(FilePath, CFile::modeRead); // 以读方式打开文件
FileSize = mFile.GetLength() + 1; // 得到文件大小
if (FileSize == 1){
AfxMessageBox("密文为空");
return ;
}
buf = new char[FileSize];
memset(buf , 0, FileSize);
mFile.ReadHuge(buf, FileSize); // 读取密文
if (buf[3] != ' ') { // 因为文件格式为每组密文开头共四个字节,前三字节组合的数字为改组的字节数,第四字节为空格
// 因为这样对1024bit的密钥最多是个三位数,所以4字节够用了。如果不检测,如果密文被破坏,解密会失败,甚至引起程
// 序崩溃
AfxMessageBox("密文文件格式错误");
delete []buf;
return ;
}
iCount = 0;
m_cit = "";
while(1){
memset(bloSize, 0, 4);
strTemp = "";
for (i = 0; i < 3; i++)
bloSize[i] = buf[nIndex + i];
bloSize[3] = '\0';
nIndex += 5;
citlen = atoi(bloSize);
for (j = nIndex; j < nIndex + citlen; j++)
strTemp += buf[j];
m_cit += strTemp;
iLength[iCount++] = citlen;
nIndex += citlen;
if (buf[nIndex] == '\0')
break;
}
delete []buf;
AfxMessageBox("密文读取成功");
}
}
void CAdvance::OnClear()
{
P.Init(0);
Q.Init(0);
D.Init(0);
E.Init(0);
N.Init(0);
EUL.Init(0);
m_clt = "";
m_cit = "";
m_P.SetWindowText("");
m_Q.SetWindowText("");
m_E.SetWindowText("");
m_D.SetWindowText("");
m_N.SetWindowText("");
m_Showtime.SetWindowText("");
KeyEmpty = 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -