⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 help.cpp

📁 这个vc++代码实现了RSA
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Help.cpp : 实现文件
//

#include "stdafx.h"
#include "RSA.h"
#include "Help.h"
#include ".\help.h"


// CHelp 对话框

IMPLEMENT_DYNAMIC(CHelp, CDialog)
CHelp::CHelp(CWnd* pParent /*=NULL*/)
	: CDialog(CHelp::IDD, pParent)
	, m_Text(_T(""))
{
}

CHelp::~CHelp()
{
}

void CHelp::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_TREE1, m_Tree);
	DDX_Control(pDX, IDC_EDIT1, m_Edit);
}


BEGIN_MESSAGE_MAP(CHelp, CDialog)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, OnTvnSelchangedTree1)
END_MESSAGE_MAP()


// CHelp 消息处理程序

BOOL CHelp::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  在此添加额外的初始化
	 TV_INSERTSTRUCT TreeCtrlItem;

	TreeCtrlItem.hParent = TVI_ROOT;
	TreeCtrlItem.hInsertAfter = TVI_LAST;
	TreeCtrlItem.item.mask = TVIF_TEXT | TVIF_PARAM;
	TreeCtrlItem.item.pszText = _T("前言");
	TreeCtrlItem.item.lParam = 1;
	HTREEITEM hTreeItem0 = m_Tree.InsertItem(&TreeCtrlItem);

	TreeCtrlItem.hParent = TVI_ROOT;
	TreeCtrlItem.hInsertAfter = TVI_LAST;
	TreeCtrlItem.item.mask = TVIF_TEXT | TVIF_PARAM;
	TreeCtrlItem.item.pszText = _T("原理介绍");
	TreeCtrlItem.item.lParam = 0;
	HTREEITEM hTreeItem1 = m_Tree.InsertItem(&TreeCtrlItem);

	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("大数存储");
	TreeCtrlItem.item.lParam = 2;
	m_Tree.InsertItem(&TreeCtrlItem);

	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("加法");
	TreeCtrlItem.item.lParam = 3;
	m_Tree.InsertItem(&TreeCtrlItem);  
	
	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("减法");
	TreeCtrlItem.item.lParam = 4;
	m_Tree.InsertItem(&TreeCtrlItem); 

	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("乘法");
	TreeCtrlItem.item.lParam = 5;
	m_Tree.InsertItem(&TreeCtrlItem);
	
	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("除法");
	TreeCtrlItem.item.lParam = 6;
	m_Tree.InsertItem(&TreeCtrlItem);

	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("取模");
	TreeCtrlItem.item.lParam = 7;
	m_Tree.InsertItem(&TreeCtrlItem); 
	
	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("二元一次方程");
	TreeCtrlItem.item.lParam = 8;
	m_Tree.InsertItem(&TreeCtrlItem);

	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("幂模运算");
	TreeCtrlItem.item.lParam = 9;
	m_Tree.InsertItem(&TreeCtrlItem);
	
	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("素数测试");
	TreeCtrlItem.item.lParam = 10;
	m_Tree.InsertItem(&TreeCtrlItem);

	TreeCtrlItem.hParent = hTreeItem1;
	TreeCtrlItem.item.pszText = _T("输入输出");
	TreeCtrlItem.item.lParam = 11;
	m_Tree.InsertItem(&TreeCtrlItem);

	return TRUE;
}

void CHelp::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	switch(pNMTreeView->itemNew.lParam)
	{
	case 0:
		break;
	case 1:
		m_Text="";
		m_Text+="\r\n";
		m_Text+="    曾经查阅了网上找得到的各种用于实现RSA 的大数运算库,然而最终还是决定";
		m_Text+="\r\n";
		m_Text+="自己动手写一个。因为凡是效率高速度快的代码,如 crypto++、miracl、freelip、";
		m_Text+="\r\n";
		m_Text+="rsaref等,要么使用的算法过于复杂,要么编码风格杂乱无章,我的水平和耐心都实";
		m_Text+="\r\n";
		m_Text+="在是有限,以至于无法读懂这些东西。而俺读得懂的一些代码,其实现方式却又过于";
		m_Text+="\r\n";
		m_Text+="幼稚,效率极低速度一塌糊涂。我想象我这样的人不在少数,于是决心借鉴下前辈的经";
		m_Text+="\r\n";
		m_Text+="验做一个清晰易懂,效率也过得去的东西奉献给大家。";
		m_Text+="\r\n";
		m_Text+="    最后,感谢看雪论坛,在此学到了很多知识,也要感谢雪兄多次热心相助,当";
        m_Text+="\r\n";
        m_Edit.SetWindowText(m_Text);
		break;
	case 2:
		m_Text="";
		m_Text+="\r\n";
		m_Text+="    RSA 依赖大数运算,目前主流RSA 算法都建立在512 到1024位的大数运算之上。";
		m_Text+="\r\n";
		m_Text+="而大多数的编译器只能支持到64位的整数运算,即我们在运算中所使用的整数必须小";
		m_Text+="\r\n";
		m_Text+="于等于64位,即:0xffffffffffffffff,也就是18446744073709551615,这远远达不";
		m_Text+="\r\n";
		m_Text+="到RSA 的需要,于是需要专门建立大数运算库来解决这一问题。";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="    最简单的办法是将大数当作数组进行处理,也就是将大数用0—9这十个数字组成";
		m_Text+="\r\n";
		m_Text+="的数组进行表示,然后模拟人们手工进行“竖式计算”的过程编写其加减乘除函数。";
		m_Text+="\r\n";
		m_Text+="但是这样做效率很低,因为二进制为1024位的大数其十进制也有三百多位,对于任何";
		m_Text+="\r\n";
		m_Text+="一种运算,都需要在两个有数百个元素的数组空间上做多重循环,还需要许多额外的";
		m_Text+="\r\n";
		m_Text+="空间存放计算的进退位标志及中间结果。另外,对于某些特殊的运算而言,采用二进";
		m_Text+="\r\n";
		m_Text+="制会使计算过程大大简化,这种大数表示方法转化成二进制显然非常麻烦,所以在某";
		m_Text+="\r\n";
		m_Text+="些实例中则干脆采用了二进制数组的方法来记录大数,这样效率就更低了。";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="    一个有效的改进方法是将大数表示为一个n 进制数组,对于目前的32位系统而言";
		m_Text+="\r\n";
		m_Text+="n 可以取值为2 的32次方,即0x10000000,假如将一个二进制为1024位的大数转化成";
		m_Text+="\r\n";
		m_Text+="0x10000000进制,它就变成了32位,而每一位的取值范围就不是二进制的0—1或十进";
		m_Text+="\r\n";
		m_Text+="制的0—9,而是0-0xffffffff,我们正好可以用一个无符号长整数来表示这一数值。";
		m_Text+="\r\n";
		m_Text+="所以1024位的大数就是一个有32个元素的unsigned long数组,针对unsigned long数";
		m_Text+="\r\n";
		m_Text+="组进行各种运算所需的循环规模至多32次而已。而且0x100000000 进制与二进制,对";
		m_Text+="\r\n";
		m_Text+="于计算机来说,几乎是一回事,转换非常容易。";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="    例如大数18446744073709551615,等于 ffffffff ffffffff,就相当于十进制的";
		m_Text+="\r\n";
		m_Text+="99:有两位,每位都是ffffffff。而18446744073709551616 等于00000001 00000000";
		m_Text+="\r\n";
		m_Text+="00000000,就相当于十进制的100:有三位,第一位是1 ,其它两位是0,如此等等。";
		m_Text+="\r\n";
		m_Text+="在实际应用中,“数字”数组的排列顺序采用低位在前高位在后的方式,这样,大数";
		m_Text+="\r\n";
		m_Text+="A 就可以方便地用数学表达式来表示其值:A=Sum[i=0 to n](A[i]*0x100000000**i)";
		m_Text+="\r\n";
		m_Text+="(其中Sum 表示求和,A[i]表示用以记录A 的数组的第i 个元素,**表示乘方)。";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="    任何整数运算最终都能分解成数字与数字之间的运算,在0x100000000 进制下其";
		m_Text+="\r\n";
		m_Text+="“数字”最大达到0xffffffff,其数字与数字之间的运算,结果也必然超出了目前32";
		m_Text+="\r\n";
		m_Text+="系统的字长。在VC++中,存在一个__int64 类型可以处理64位的整数,所以不用担心";
		m_Text+="\r\n";
		m_Text+="这一问题,而在其它编译系统中如果不存在64位整形,就需要采用更小的进制方式来";
		m_Text+="\r\n";
		m_Text+="存储大数,例如WORD类型(16位)可以用来表示0x10000 进制,但效率更高的办法还";
		m_Text+="\r\n";
		m_Text+="是采用32位的DWORD 类型,只不过将0x100000000 进制改成0x40000000进制,这样两";
		m_Text+="\r\n";
		m_Text+="个数字进行四则运算的最大结果为 0x3fffffff * 0x3fffffff,小于0xffffffff,只";
		m_Text+="\r\n";
		m_Text+="是不能简单地用高位低位来将运算结果拆分成两个“数字”。";
		m_Text+="\r\n";
		m_Text+="\r\n";
        m_Edit.SetWindowText(m_Text);
		break;
	case 3:
        m_Text="";
		m_Text+="\r\n";
		m_Text+="设:";
		m_Text+="\r\n";
		m_Text+="  A=Sum[i=0 to p](A[i]*0x100000000**i)";
		m_Text+="\r\n";
		m_Text+="  B=Sum[i=0 to q](B[i]*0x100000000**i),p>=q";
		m_Text+="\r\n";
		m_Text+="  C=Sum[i=0 to n](C[i]*0x100000000**i)=A+B";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="显然:";
		m_Text+="\r\n";
		m_Text+="  C[i]不是简单地等于A[i]+B[i],因为如果C[i]>0xffffffff就需要进位,当然计算";
		m_Text+="\r\n";
		m_Text+="  C[i-1]时也可能产生了进位,所以计算C[i]时还要加上上次的进位值。";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="如果用carry[i]记录每次的进位则有:";
		m_Text+="\r\n";
		m_Text+="  C[i]=A[i]+B[i]+carry[i-1]-carry[i]*0x100000000";
		m_Text+="\r\n";
		m_Text+="  其中carry[-1]=0";
		m_Text+="\r\n";
		m_Text+="  若A[i]+B[i]+carry[i-1]>0xffffffff,则carry[i]=1;反之则carry[i]=0";
		m_Text+="\r\n";
		m_Text+="  若carry[p]=0,则n=p;反之则n=p+1";
		m_Text+="\r\n";
		m_Text+="\r\n";
        m_Edit.SetWindowText(m_Text);
		break;
	case 4:
        m_Text="";
		m_Text+="\r\n";
		m_Text+="设:";
		m_Text+="\r\n";
		m_Text+="  A=Sum[i=0 to p](A[i]*0x100000000**i)";
		m_Text+="\r\n";
		m_Text+="  B=Sum[i=0 to q](B[i]*0x100000000**i),p>=q";
		m_Text+="\r\n";
		m_Text+="  C=Sum[i=0 to n](C[i]*0x100000000**i)=A-B";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="显然:";
		m_Text+="\r\n";
		m_Text+="  C[i]不是简单地等于A[i]-B[i],因为如果A[i]<B[i]就需要借位,当然计算";
		m_Text+="\r\n";
		m_Text+="  C[i-1]时也可能产生了借位,所以计算C[i]时还要减去上次的借位值。";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="如果用carry[i]记录每次的借位则有:";
		m_Text+="\r\n";
		m_Text+="  C[i]=A[i]+carry[i]*0x100000000-B[i]-carry[i-1]";
		m_Text+="\r\n";
		m_Text+="  其中carry[-1]=0";
		m_Text+="\r\n";
		m_Text+="  若A[i]>B[i]则carry[i]=0;反之则carry[i]=1";
		m_Text+="\r\n";
		m_Text+="  若C[p]=0,则n=p-1;反之则n=p";
		m_Text+="\r\n";
		m_Text+="\r\n";
        m_Edit.SetWindowText(m_Text);
		break;
	case 5:
        m_Text="";
		m_Text+="\r\n";
		m_Text+="设:";
		m_Text+="\r\n";
		m_Text+="  A=Sum[i=0 to p](A[i]*0x100000000**i)";
		m_Text+="\r\n";
		m_Text+="  B=Sum[i=0 to q](B[i]*0x100000000**i),p>=q";
		m_Text+="\r\n";
		m_Text+="  C=Sum[i=0 to n](C[i]*0x100000000**i)=A*B";
		m_Text+="\r\n";
		m_Text+="";
		m_Text+="\r\n";
		m_Text+="显然:";
		m_Text+="\r\n";
		m_Text+="  C=Sum[i=0 to q](A*B[i]*0x100000000**i)";
		m_Text+="\r\n";
		m_Text+="  而(A*B[i]*100000000**i)=Sum[j=0 to p](A[j]*B[i]*0x100000000**(i+j))";
		m_Text+="\r\n";
		m_Text+="  所以C=Sum[i=0 to q](Sum[j=0 to p](A[j]*B[i]*0x100000000**(i+j)))";
		m_Text+="\r\n";
		m_Text+="";
		m_Text+="\r\n";
		m_Text+="因此:";
		m_Text+="\r\n";
		m_Text+="  C[i]=Sum[j=0 to q](A[i-j]*B[j])+carry[i-1]-carry[i]*0x100000000";
		m_Text+="\r\n";
		m_Text+="  其中carry[-1]=0";
		m_Text+="\r\n";
		m_Text+="  carry[i]=(Sum[j=0 to q](A[i-j]*B[j])+carry[i-1])/0x100000000";
		m_Text+="\r\n";
		m_Text+="  n=p+q-1,若carry[n]>0,则n=n+1,C[n]=carry";
		m_Text+="\r\n";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -