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

📄 helpdlg.cpp

📁 这个程序是网络信息安全概论课的课程实践,自己动手编写一个具于1024位大数 运算的ELGamal加密系统。 ELGamal 依赖大数运算
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// HELPDlg.cpp : implementation file
//

#include "stdafx.h"
#include "elgamaltool.h"
#include "HELPDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CHELPDlg dialog


CHELPDlg::CHELPDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHELPDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CHELPDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CHELPDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHELPDlg)
	DDX_Control(pDX, IDC_HELPEDIT, m_Edit);
	DDX_Control(pDX, IDC_TREE1, m_Tree);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CHELPDlg, CDialog)
	//{{AFX_MSG_MAP(CHELPDlg)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, OnSelchangedTree1)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHELPDlg message handlers

BOOL CHELPDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
    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;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CHELPDlg::OnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	switch(pNMTreeView->itemNew.lParam)
	{

       case 0:
		break;
	case 1:
		m_Text="";
		m_Text+="\r\n";
		m_Text+="        这个程序是网络信息安全概论课的课程实践,自己动手编写一个具于1024位大数";
		m_Text+="\r\n";
		m_Text+="运算的ELGamal加密系统。为此我查找了一些效率高的著名大数运算库如 crypto++, ";
		m_Text+="\r\n";
		m_Text+="miracl,freelip,rsaref等,要么使用的算法过于复杂,要么编码风格杂乱无章,我的";
		m_Text+="\r\n";
		m_Text+="水平有限,以至于无法读懂这些东西。而我读得懂的一些代码,其实现方式却又过于";
		m_Text+="\r\n";
		m_Text+="幼稚,效率极低速度一塌糊涂。";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="        真是“踏破铁谢无觅处”,在网上看到一篇由afanty写的文章“关于RSA运算的计"; 
		m_Text+="\r\n";
		m_Text+="算机计算讨论”,眼前霍然开朗,这篇文章用了最简单的结构和最容易理解的算法实现";
		m_Text+="\r\n";
		m_Text+="了大数运算,而且速度还不慢.我的大数运算就是基于afanty的算法,现在生成ELGamal";
		m_Text+="\r\n";
		m_Text+="算法所需的公钥大概一般在14秒左右。这里对afanty表示谢意。";
		m_Text+="\r\n";
		m_Text+="\r\n";
		m_Text+="     最后,感谢看雪论坛,我在此学到了很多知识.";
        m_Text+="\r\n";
        m_Text+="\r\n";
		m_Text+="   A0617230@pub.ss.pku.edu.cn";
        m_Edit.SetWindowText(m_Text);
		break;
       case 2:
		m_Text="";
		m_Text+="\r\n";
		m_Text+="   ELGamal 依赖大数运算,目前主流ELGamal算法都建立在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+="C=A*B,首先我们需要观察日常做乘法所用的“竖式计算”过程:";
		m_Text+="\r\n";
		m_Text+="A3 A2 A1 A0";
		m_Text+="\r\n";
		m_Text+=" * B2 B1 B0";
		m_Text+="\r\n";
		m_Text+="-------------------------------";
		m_Text+="\r\n";
		m_Text+="=                  A3B0 A2B0 A1B0 A0B0";
		m_Text+="\r\n";
		m_Text+="+        A3B1 A2B1 A1B1 A0B1:";
		m_Text+="\r\n";
		m_Text+="A3B2 A2B2 A1B2 A0B2";
		m_Text+="\r\n";
		m_Text+=" -------------------------------";
		m_Text+="\r\n";
		m_Text+="= C5     C4     C3      C2     C1     C0 ";
		m_Text+="\r\n";
		m_Text+="可以归纳出:C=Sum[j=0 to q](A[i-j]*B[j]),其中i-j必须>=0且<=p。当然这";

⌨️ 快捷键说明

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