?? rsahelpdlg.cpp
字號:
// RsahelpDlg.cpp : implementation file
//
#include "stdafx.h"
#include "ASYMMETRIC KEY CRYPTOSYSTEM.h"
#include "RsahelpDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CRsahelpDlg dialog
CRsahelpDlg::CRsahelpDlg(CWnd* pParent /*=NULL*/)
: CDialog(CRsahelpDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CRsahelpDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CRsahelpDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CRsahelpDlg)
DDX_Control(pDX, IDC_TREERsa, m_TREERsa);
DDX_Control(pDX, IDC_HelpRsa, m_HelpRsa);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CRsahelpDlg, CDialog)
//{{AFX_MSG_MAP(CRsahelpDlg)
ON_NOTIFY(TVN_SELCHANGED, IDC_TREERsa, OnSelchangedTree)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRsahelpDlg message handlers
BOOL CRsahelpDlg::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_TREERsa.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_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("大數(shù)存儲");
TreeCtrlItem.item.lParam = 2;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("加法");
TreeCtrlItem.item.lParam = 3;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("減法");
TreeCtrlItem.item.lParam = 4;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("乘法");
TreeCtrlItem.item.lParam = 5;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("除法");
TreeCtrlItem.item.lParam = 6;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("取模");
TreeCtrlItem.item.lParam = 7;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("二元一次方程");
TreeCtrlItem.item.lParam = 8;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("冪模運算");
TreeCtrlItem.item.lParam = 9;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("素數(shù)測試");
TreeCtrlItem.item.lParam = 10;
m_TREERsa.InsertItem(&TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = _T("輸入輸出");
TreeCtrlItem.item.lParam = 11;
m_TREERsa.InsertItem(&TreeCtrlItem);
return TRUE;
}
void CRsahelpDlg::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
switch(pNMTreeView->itemNew.lParam)
{
case 0:
break;
case 1:
m_Text="";
m_Text+="\r\n";
m_Text+=" 俺曾經(jīng)查閱了網(wǎng)上找得到的各種用于實現(xiàn)RSA 的大數(shù)運算庫,然而最終還是決定";
m_Text+="\r\n";
m_Text+="自己動手寫一個。因為凡是效率高速度快的代碼,如 crypto++、miracl、freelip、";
m_Text+="\r\n";
m_Text+="rsaref等,要么使用的算法過于復(fù)雜,要么編碼風(fēng)格雜亂無章,俺的水平和耐心都實";
m_Text+="\r\n";
m_Text+="在是有限,以至于無法讀懂這些東西。而俺讀得懂的一些代碼,其實現(xiàn)方式卻又過于";
m_Text+="\r\n";
m_Text+="幼稚,效率極低速度一塌糊涂。俺想象俺這樣的人不在少數(shù),于是決心做一個清晰易";
m_Text+="\r\n";
m_Text+="懂,效率也過得去的東西奉獻給大家。";
m_Text+="\r\n";
m_Text+="\r\n";
m_Text+=" 這個函數(shù)庫剛做好的時候,生成1024位的隨機密鑰耗時大約5 分鐘,俺認(rèn)為是可";
m_Text+="\r\n";
m_Text+="以接受的。但后來找到一個叫tE! 的老外用miracl庫寫的RsaTools,發(fā)現(xiàn)其生成1024";
m_Text+="\r\n";
m_Text+="位的密鑰耗時不超過三秒鐘!于是俺針對俺的代碼開始了艱苦的優(yōu)化工作,希望能達";
m_Text+="\r\n";
m_Text+="到甚至超過這一水平。一周之后1024位密鑰的平均生成時間已經(jīng)降至5 秒以內(nèi),但是";
m_Text+="\r\n";
m_Text+="單單依靠優(yōu)化代碼來進一步提高速度也非常困難了。于是俺開始借助金山詞霸來查閱";
m_Text+="\r\n";
m_Text+="能夠通過google找到的一切與Rsa 算法相關(guān)的論文,直到今天俺決定放棄,因為俺發(fā)";
m_Text+="\r\n";
m_Text+="現(xiàn)在改用越來越復(fù)雜的數(shù)學(xué)算法的同時俺離自己的初衷也越來越遠(yuǎn):俺的代碼也不再";
m_Text+="\r\n";
m_Text+="清晰易懂了。";
m_Text+="\r\n";
m_Text+="\r\n";
m_Text+=" 現(xiàn)在這個版本的函數(shù)庫采用了最簡單的結(jié)構(gòu)和最容易理解的算法,速度也不算太";
m_Text+="\r\n";
m_Text+="慢,用C++ 語言,可在VC6.0 下直接編譯通過,希望大家喜歡。如果發(fā)現(xiàn)Bug 或者有";
m_Text+="\r\n";
m_Text+="好的修改建議,俺將非常感謝您能夠給俺一個Mail。";
m_Text+="\r\n";
m_Text+="\r\n";
m_Text+=" 最后,感謝看雪論壇,俺在此學(xué)到了很多知識,也要感謝雪兄多次熱心相助,當(dāng)";
m_Text+="\r\n";
m_Text+="然還要乘機拍拍馬屁,感謝俺家甜甜的支持!";
m_Text+="\r\n";
m_Text+="\r\n";
m_Text+=" afanty@vip.sina.com";
m_HelpRsa.SetWindowText(m_Text);
break;
case 2:
m_Text="";
m_Text+="\r\n";
m_Text+=" RSA 依賴大數(shù)運算,目前主流RSA 算法都建立在512 到1024位的大數(shù)運算之上。";
m_Text+="\r\n";
m_Text+="而大多數(shù)的編譯器只能支持到64位的整數(shù)運算,即我們在運算中所使用的整數(shù)必須小";
m_Text+="\r\n";
m_Text+="于等于64位,即:0xffffffffffffffff,也就是18446744073709551615,這遠(yuǎn)遠(yuǎn)達不";
m_Text+="\r\n";
m_Text+="到RSA 的需要,于是需要專門建立大數(shù)運算庫來解決這一問題。";
m_Text+="\r\n";
m_Text+="\r\n";
m_Text+=" 最簡單的辦法是將大數(shù)當(dāng)作數(shù)組進行處理,也就是將大數(shù)用0—9這十個數(shù)字組成";
m_Text+="\r\n";
m_Text+="的數(shù)組進行表示,然后模擬人們手工進行“豎式計算”的過程編寫其加減乘除函數(shù)。";
m_Text+="\r\n";
m_Text+="但是這樣做效率很低,因為二進制為1024位的大數(shù)其十進制也有三百多位,對于任何";
m_Text+="\r\n";
m_Text+="一種運算,都需要在兩個有數(shù)百個元素的數(shù)組空間上做多重循環(huán),還需要許多額外的";
m_Text+="\r\n";
m_Text+="空間存放計算的進退位標(biāo)志及中間結(jié)果。另外,對于某些特殊的運算而言,采用二進";
m_Text+="\r\n";
m_Text+="制會使計算過程大大簡化,這種大數(shù)表示方法轉(zhuǎn)化成二進制顯然非常麻煩,所以在某";
m_Text+="\r\n";
m_Text+="些實例中則干脆采用了二進制數(shù)組的方法來記錄大數(shù),這樣效率就更低了。";
m_Text+="\r\n";
m_Text+="\r\n";
m_Text+=" 一個有效的改進方法是將大數(shù)表示為一個n 進制數(shù)組,對于目前的32位系統(tǒng)而言";
m_Text+="\r\n";
m_Text+="n 可以取值為2 的32次方,即0x10000000,假如將一個二進制為1024位的大數(shù)轉(zhuǎn)化成";
m_Text+="\r\n";
m_Text+="0x10000000進制,它就變成了32位,而每一位的取值范圍就不是二進制的0—1或十進";
m_Text+="\r\n";
m_Text+="制的0—9,而是0-0xffffffff,我們正好可以用一個無符號長整數(shù)來表示這一數(shù)值。";
m_Text+="\r\n";
m_Text+="所以1024位的大數(shù)就是一個有32個元素的unsigned long數(shù)組,針對unsigned long數(shù)";
m_Text+="\r\n";
m_Text+="組進行各種運算所需的循環(huán)規(guī)模至多32次而已。而且0x100000000 進制與二進制,對";
m_Text+="\r\n";
m_Text+="于計算機來說,幾乎是一回事,轉(zhuǎn)換非常容易。";
m_Text+="\r\n";
m_Text+="\r\n";
m_Text+=" 例如大數(shù)18446744073709551615,等于 ffffffff ffffffff,就相當(dāng)于十進制的";
m_Text+="\r\n";
m_Text+="99:有兩位,每位都是ffffffff。而18446744073709551616 等于00000001 00000000";
m_Text+="\r\n";
m_Text+="00000000,就相當(dāng)于十進制的100:有三位,第一位是1 ,其它兩位是0,如此等等。";
m_Text+="\r\n";
m_Text+="在實際應(yīng)用中,“數(shù)字”數(shù)組的排列順序采用低位在前高位在后的方式,這樣,大數(shù)";
m_Text+="\r\n";
m_Text+="A 就可以方便地用數(shù)學(xué)表達式來表示其值:A=Sum[i=0 to n](A[i]*0x100000000**i)";
m_Text+="\r\n";
m_Text+="(其中Sum 表示求和,A[i]表示用以記錄A 的數(shù)組的第i 個元素,**表示乘方)。";
m_Text+="\r\n";
m_Text+="\r\n";
m_Text+=" 任何整數(shù)運算最終都能分解成數(shù)字與數(shù)字之間的運算,在0x100000000 進制下其";
m_Text+="\r\n";
m_Text+="“數(shù)字”最大達到0xffffffff,其數(shù)字與數(shù)字之間的運算,結(jié)果也必然超出了目前32";
m_Text+="\r\n";
m_Text+="系統(tǒng)的字長。在VC++中,存在一個__int64 類型可以處理64位的整數(shù),所以不用擔(dān)心";
m_Text+="\r\n";
m_Text+="這一問題,而在其它編譯系統(tǒng)中如果不存在64位整形,就需要采用更小的進制方式來";
m_Text+="\r\n";
m_Text+="存儲大數(shù),例如WORD類型(16位)可以用來表示0x10000 進制,但效率更高的辦法還";
m_Text+="\r\n";
m_Text+="是采用32位的DWORD 類型,只不過將0x100000000 進制改成0x40000000進制,這樣兩";
m_Text+="\r\n";
m_Text+="個數(shù)字進行四則運算的最大結(jié)果為 0x3fffffff * 0x3fffffff,小于0xffffffff,只";
m_Text+="\r\n";
m_Text+="是不能簡單地用高位低位來將運算結(jié)果拆分成兩個“數(shù)字”。";
m_Text+="\r\n";
m_Text+="\r\n";
m_HelpRsa.SetWindowText(m_Text);
break;
case 3:
m_Text="";
m_Text+="\r\n";
m_Text+="設(shè):";
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就需要進位,當(dāng)然計算";
m_Text+="\r\n";
m_Text+=" C[i-1]時也可能產(chǎn)生了進位,所以計算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_HelpRsa.SetWindowText(m_Text);
break;
case 4:
m_Text="";
m_Text+="\r\n";
m_Text+="設(shè):";
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]就需要借位,當(dāng)然計算";
m_Text+="\r\n";
m_Text+=" C[i-1]時也可能產(chǎn)生了借位,所以計算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_HelpRsa.SetWindowText(m_Text);
break;
case 5:
m_Text="";
m_Text+="\r\n";
m_Text+="設(shè):";
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";
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -