www.gusucode.com > 轻松实现DES算法查看器C++源码程序 > 轻松实现DES算法查看器/deschecker/DESChecker/DESDlg.cpp

    // DESDlg.cpp : implementation file
//

#include "stdafx.h"
#include "DES.h"
#include "DESDlg.h"
#include "table.h"

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

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();
	
	// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA
	
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL
	
	// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDESDlg dialog

CDESDlg::CDESDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDESDlg::IDD, pParent)
{
	item=0;
	//{{AFX_DATA_INIT(CDESDlg)
	m_key = _T("");
	m_old = _T("");
	m_new = _T("");
	m_Last = _T("");
	m_oldbin = _T("");
	m_keybin = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDESDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDESDlg)
	DDX_Control(pDX, IDC_STATIC13, m_static13);
	DDX_Control(pDX, IDC_STATIC1, m_static1);
	DDX_Control(pDX, IDC_STATIC2, m_static2);
	DDX_Control(pDX, IDC_STATIC3, m_static3);
	DDX_Control(pDX, IDC_STATIC4, m_static4);
	DDX_Control(pDX, IDC_STATIC5, m_static5);
	DDX_Control(pDX, IDC_STATIC6, m_static6);
	DDX_Control(pDX, IDC_STATIC7, m_static7);
	DDX_Control(pDX, IDC_STATIC8, m_static8);
	DDX_Control(pDX, IDC_STATIC9, m_static9);
	DDX_Control(pDX, IDC_STATIC10, m_static10);
	DDX_Control(pDX, IDC_STATIC11, m_static11);
	DDX_Control(pDX, IDC_STATIC12, m_static12);
	DDX_Control(pDX, IDC_LIST1, m_listdata);
	DDX_Text(pDX, IDC_EDIT2, m_key);
	DDV_MaxChars(pDX, m_key, 8);
	DDX_Text(pDX, IDC_EDIT1, m_old);
	DDV_MaxChars(pDX, m_old, 8);
	DDX_Text(pDX, IDC_EDIT3, m_new);
	DDX_Text(pDX, IDC_EDIT4, m_Last);
	DDX_Text(pDX, IDC_EDIT5, m_oldbin);
	DDX_Text(pDX, IDC_EDIT6, m_keybin);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDESDlg, CDialog)
//{{AFX_MSG_MAP(CDESDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_ERASEBKGND()
ON_BN_CLICKED(IDC_ENCRYPT, OnEncrypt)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, OnItemchangedList1)
	ON_BN_CLICKED(IDC_DECRYPT, OnDecrypt)
	ON_BN_CLICKED(IDS_ABOUTBOX, OnAboutbox)
	ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)
	ON_EN_CHANGE(IDC_EDIT2, OnChangeEdit2)
	ON_BN_CLICKED(IDC_HELPDES, OnHelpdes)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDESDlg message handlers

BOOL CDESDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	
	m_old="learning";
	m_key="computer";
	GetDlgItem(IDC_DECRYPT)->EnableWindow(false);
	UpdateData(false);
	// Add "About..." menu item to system menu.
	
	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);
	
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}
	
	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	CenterWindow(GetDesktopWindow());
	::SendMessage(m_listdata.m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE,
		LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES,
		LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
	m_listdata.InsertColumn(0,"NO.",LVCFMT_LEFT,30);
	m_listdata.InsertColumn(1,"L0",LVCFMT_LEFT,40);
	m_listdata.InsertColumn(2,"R0",LVCFMT_LEFT,40);
	m_listdata.InsertColumn(3,"F函数值",LVCFMT_LEFT,60);
	m_listdata.InsertColumn(4,"密钥Ki",LVCFMT_LEFT,50);
	m_listdata.InsertColumn(5,"S盒",LVCFMT_LEFT,45);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CDESDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDESDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting
		
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
		
		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;
		
		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
		CClientDC dc(this);
		SetBkMode(dc.m_hDC, TRANSPARENT);
		//dc.TextOut(10, 10,  "请在此处输入明文:");
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDESDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CDESDlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	int m_nCurrentSel = pNMListView->iItem;
	CString info;
	info.Format("%s", m_listdata.GetItemText(m_nCurrentSel,1));
	GetDlgItem(IDC_EDIT7)->SetWindowText(info);
	info.Format("%s", m_listdata.GetItemText(m_nCurrentSel,2));
	GetDlgItem(IDC_EDIT8)->SetWindowText(info);
	info.Format("%s", m_listdata.GetItemText(m_nCurrentSel,3));
	GetDlgItem(IDC_EDIT9)->SetWindowText(info);
	info.Format("%s", m_listdata.GetItemText(m_nCurrentSel,4));
	GetDlgItem(IDC_EDIT10)->SetWindowText(info);
	info.Format("%s", m_listdata.GetItemText(m_nCurrentSel,5));
	GetDlgItem(IDC_EDIT11)->SetWindowText(info);
	*pResult = 0;
}

void CDESDlg::SaveToList()
{
	//////////////////////////////////////////////////////////////////////////
	// 测试数据,将L, R, K, F, S数据存入列表
	CString str, strl, strr, strs, strf, strk;
	str="", strl="", strr="", 
	strk="", strs="", strf="";
	item=m_listdata.InsertItem(0xffff, "N", 1);
	str.Format("%d", item+1);
	m_listdata.SetItem(item, 0, 1, str, NULL, 0, 0, 0);
	// 上面将第第一列的值插入,显示为迭代次数
	for(int k=0; k<32; k++)	
	{
		str.Format("%d", L0[k]);
		strl+=str;
		str.Format("%d", R0[k]);
		strr+=str;
	}
	for( k=0; k<32; k++)	
	{
		str.Format("%d", frk[k]);
		strf+=str;
	}
	for( k=0; k<48; k++)
	{
		str.Format("%d", k1[k]);
		strk+=str;
	}
	for( k=0; k<8; k++)	
	{
		str.Format("%d_", stmp[k]);
		strs+=str;
	}
	m_listdata.SetItem(item, 1, 1, strl, NULL, 0, 0, 0);
	m_listdata.SetItem(item, 2, 1, strr, NULL, 0, 0, 0);
	m_listdata.SetItem(item, 3, 1, strf, NULL, 0, 0, 0);
	m_listdata.SetItem(item, 4, 1, strk, NULL, 0, 0, 0);
	m_listdata.SetItem(item, 5, 1, strs, NULL, 0, 0, 0);
}

void CDESDlg::OnAboutbox() 
{
	// TODO: Add your control notification handler code here
	//SendMessage(WM_SYSCOMMAND, (WPARAM) IDM_ABOUTBOX, (LPARAM)0);
	OnSysCommand(IDM_ABOUTBOX, 0);
}

void CDESDlg::OnChangeEdit1() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	PlaySound("KEYCLICK",  AfxGetResourceHandle(),
		SND_RESOURCE|SND_ASYNC|SND_NODEFAULT);	
}

void CDESDlg::OnChangeEdit2() 
{
	PlaySound("KEYCLICK",  AfxGetResourceHandle(),
		SND_RESOURCE|SND_ASYNC|SND_NODEFAULT);		
}

BOOL CDESDlg::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	
	CRect rc;
	GetClientRect(&rc);
	CBrush brush, *pOldbrush;
	brush.CreateSolidBrush(RGB(236, 246, 255));
	pOldbrush=pDC->SelectObject(&brush);
	pDC->FillRect(&rc, &brush);
	pDC->SelectObject(pOldbrush);
	return true;
}


void CDESDlg::OnHelpdes() 
{
	// TODO: Add your control notification handler code here
	
	CFile f; 
	char* pFileName = "des.chm";
	if( !f.Open( pFileName, CFile::modeCreate | CFile::modeWrite, NULL ) )
	{
		AfxMessageBox("Can not create file!");
		return ;
	}
	CString path = f.GetFilePath();
	HGLOBAL hRes;
	HRSRC hResInfo;
	//获取应用实例 
	HINSTANCE insApp = AfxGetInstanceHandle();
	//寻找EXE资源名
	hResInfo = FindResource(insApp,"des.chm","CHM");
	hRes = LoadResource(insApp,hResInfo );   // Load it
	DWORD dFileLength = SizeofResource( insApp, hResInfo );  //计算EXE文件大小
	f.WriteHuge((LPSTR)hRes,dFileLength);  //写入临时文件
	f.Close();
	HINSTANCE HINSsd = ShellExecute(NULL, "open",path, NULL, NULL, SW_SHOWNORMAL); //运行它.  
	//WinExec(path, SW_SHOW);
}

void CDESDlg::OnEncrypt() 
{
	m_listdata.DeleteAllItems();				//清空列表项目
	// TODO: Add your control notification handler code here
	UpdateData(true);
	//////////////////////////////////////////////////////////////////////////
	// 对输入的数据进行验证
	if(m_old.GetLength()!=8)
	{
		MessageBox("请输入8位明文", "友情提示");
		return;
	}
	if(m_key.GetLength()!=8)
	{
		MessageBox("请输入8位密文", "友情提示");
		return;
	}
	PlaySound("BEGIN",  AfxGetResourceHandle(),
		SND_RESOURCE|SND_ASYNC|SND_NODEFAULT);
	// char plaintext[8];
	// strcpy(plaintext,m_old);

	// 让解密按钮有效;
	GetDlgItem(IDC_DECRYPT)->EnableWindow(true);
	CString str;			// 该字符串存储ASCII码
	//////////////////////////////////////////////////////////////////////////
	// 初始化数组元素清0
	memset(L0, 0, 32);		
	memset(R0, 0, 32);
	
	memset(k1, 0, 48);
	memset(Kc0, 0, 28);	
	memset(Kd0, 0, 28);
	
	memset(re, 0, 48);
	memset(old, 0, 64);
	
	memset(s, 0, 48);
	//////////////////////////////////////////////////////////////////////////
	// 此处开始加密
	m_new="";		//先将密文清空	
	
	//////////////////////////////////////////////////////////////////////////
	/// 此处对明文处理,将对应的ASCII码转化为二进制	
	int flag=true;
	for(int i=0; i<8; i++)
	{
		char ch=m_old.GetAt(i);
		if(ch&0x80&&flag)
		{
			MessageBox("含有中文字符,加密错误不负责任!", "友情提示");
			flag=false;
			//return;
		}
		memset(tmp, 0, 8);
		for(int j=0; j<8; j++)
		{
			tmp[j]=(ch%2+2)%2;
			ch/=2;
		}
		for(j=7; j>=0; j--)
		{
			old[i*8+7-j]=tmp[j];
		}	
	}
	
	// 此处显示明文二进制
	m_oldbin="";
	for(i=0; i<64; i++)	
	{
		str.Format("%d", old[i]);
		m_oldbin+=str;
	}
	GetDlgItem(IDC_EDIT5)->SetWindowText(m_oldbin);
	
	for(i=0; i<32; i++)
	{	
		L0[i]=old[IP_Table[i]-1];			/// 获得L0共32位
		R0[i]=old[IP_Table[i+32]-1];		/// 获得R0共32位
	}
	
	//////////////////////////////////////////////////////////////////////////
	/// 此处开始对C0,D0处理
	for(i=0; i<8; i++)
	{
		memset(tmp, 0, 8);
		char ch=m_key.GetAt(i);
		if(ch&0x80)
		{
			MessageBox("含有中文字符,加密失败", "友情提示");
			return;
		}
		for(int j=0; j<8; j++)
		{
			tmp[j]=ch%2;
			ch/=2;
		}
		for(j=7; j>=0; j--)
		{
			k[i*8+7-j]=tmp[j];
		}
	}
	
	for(i=0; i<28; i++)
	{
		Kc0[i]=k[PC1_Table[i]-1];			/// 获得c0共28位
		Kd0[i]=k[PC1_Table[i+28]-1];		/// 获得d0共28位
	}
	
	//////////////////////////////////////////////////////////////////////////
	/// 此处开始16迭代算法
	isDecrypt=false;
	for(i=1; i<=16; i++)
	{
		CDESDlg::Iterate(i);
	}

	//////////////////////////////////////////////////////////////////////////
	// 最后一次生成的L16与R16调换位置装入密文字符串里
	int miwen[64];
	memset(miwen, 0, 64);
	// 逆初始置换,真它MOTHER的麻烦!
	int mitmp[64];
	memset(mitmp, 0, 64);
	for(i=0; i<32; i++)	
	{
		mitmp[i]=R0[i];
		mitmp[32+i]=L0[i];
		//交换L0,R0的值
		L0[i]=mitmp[i];
		R0[i]=mitmp[i+32];
	}

	for(i=0; i<64; i++)	
	{
		miwen[i]=mitmp[IPR_Table[i]-1];
	}
	
	//////////////////////////////////////////////////////////////////////////
	// 将密文2进制存入m_keybin
	str="";
	m_keybin="";
	for(i=0; i<64; i++)	
	{
		str.Format("%d", miwen[i]);
		m_keybin+=str;
	}
	GetDlgItem(IDC_EDIT6)->SetWindowText(m_keybin);

	//////////////////////////////////////////////////////////////////////////
	// 将密文ASCII码放入编辑框里面去
	m_new="";
	for(i=0; i<8; i++)
	{
		int tmp=0;
		tmp+=miwen[8*i];
		for(int j=1; j<8; j++)
		{
			tmp*=2;
			tmp+=miwen[i*8+j];
		}
		str.Format("%c", tmp);
		m_new+=str;
	}
	GetDlgItem(IDC_EDIT3)->SetWindowText(m_new);
}

void CDESDlg::OnDecrypt() 
{
	PlaySound("BEGIN",  AfxGetResourceHandle(),
		SND_RESOURCE|SND_ASYNC|SND_NODEFAULT);
	m_listdata.DeleteAllItems();		//清空列表项目
	//////////////////////////////////////////////////////////////////////////
	///  重新开始16次迭代算法
	isDecrypt=true;
	int i;
	for(i=16; i>=1; i--)
	{
		CDESDlg::Iterate(i);
	}

	//////////////////////////////////////////////////////////////////////////
	// 最后一次生成的L16<->R16调换位置
	int minwen[64];
	memset(minwen, 0, 64);
	// 逆初始置换,真它MOTHER的麻烦!
	int mintmp[64];
	memset(mintmp, 0, 64);

	for(i=0; i<32; i++)	
	{
		mintmp[i]=R0[i];
		mintmp[32+i]=L0[i];
	}
	
	for(i=0; i<64; i++)	
	{
		minwen[i]=mintmp[IPR_Table[i]-1];
	}

	//////////////////////////////////////////////////////////////////////////
	// 将密文ASCII码放入编辑框里面去
	CString str;
	m_Last="";
	for(i=0; i<8; i++)
	{
		int tmp=0;
		tmp+=minwen[8*i];
		for(int j=1; j<8; j++)
		{
			tmp*=2;
			tmp+=minwen[i*8+j];
		}
		str.Format("%c", tmp);
		m_Last+=str;
	}
	UpdateData(false);
	// 让解密按钮无效;
	GetDlgItem(IDC_DECRYPT)->EnableWindow(false);
}

void CDESDlg::Iterate(int numOfIteration)
{
	//////////////////////////////////////////////////////////////////////////
	/// 此处迭代生成子密钥ki
	int j=2;					// 移位次数
	if(	numOfIteration==1||numOfIteration==2||
		numOfIteration==9||numOfIteration==16)
	{
		j=1;
	}
	//////////////////////////////////////////////////////////////////////////
	//如果为解密,迭代移位的次序变换相反方向
	if(isDecrypt)
	{
		if(numOfIteration==16)
		{
			j=0;
		}
		else if(numOfIteration==15||numOfIteration==8||numOfIteration==1)
		{
			j=-1;
		}
		else
		{
			j=-2;
		}
	}
	
	int Kctmp[28], Kdtmp[28];	//  C0, D0中间传递数据
	memset(Kctmp, 0, 28);
	memset(Kdtmp, 0, 28);
	for(int i=0; i<28; i++)
	{
		Kctmp[i]=Kc0[(i+j+28)%28];
		Kdtmp[i]=Kd0[(i+j+28)%28];
	}
	
	//////////////////////////////////////////////////////////////////////////
	// 将KCTMP, KDTMP的数据存入KC,KD中去
	for(i=0; i<28; i++)
	{
		Kc0[i]=Kctmp[i];
		Kd0[i]=Kdtmp[i];
	}
	
	//////////////////////////////////////////////////////////////////////////
	// 生成子密钥Ki,存储到数组k1[48]中去
	int ktmp[56];
	memset(ktmp, 0, 56);
	for(i=0; i<28; i++)
	{
		ktmp[i]=Kc0[i];
		ktmp[i+28]=Kd0[i];
	}
	
	memset(k1, 0, 48);
	for(i=0; i<48; i++)
	{
		k1[i]=ktmp[PC2_Table[i]-1];
	}
	
	//////////////////////////////////////////////////////////////////////////
	// 将Ri-1扩充成48位并与Ki相加并模2
	memset(re, 0, 48);
	for(i=0; i<48; i++)
	{	
		re[i]=(R0[E_Table[i]-1]+k1[i])%2;
	}
	
	//////////////////////////////////////////////////////////////////////////
	// 	分成8组, 每组6位,有一个二维数组s[8][6]存储
	for(i=0; i<6; i++)
	{
		for(int j=0; j<8; j++)
		{
			s[j][i]=re[6*j+i];
		}
	}
	
	//////////////////////////////////////////////////////////////////////////
	// 以下通过8个S盒得到8个S数并存到S[8]中S_Box[8][4][16] 
	memset(s0, 0, 8);
	for(i=0; i<8; i++)
	{
		s0[i]=S_Box[i][s[i][5]+s[i][0]*2][s[i][1]*8+s[i][2]*4+s[i][3]*2+s[i][4]];
	}
	
	memset(stmp, 0, 8);
	memcpy(stmp, s0, sizeof(s0));
	//////////////////////////////////////////////////////////////////////////
	// 将8个数分别转换成2进制,再存入到frk[32]
	int f[32];
	memset(f, 0, 32);
	for(i=0; i<8; i++)
	{
		int tmp[4];
		memset(tmp, 0, 4);
		for(int j=0; j<4; j++)
		{
			tmp[j]=s0[i]%2;
			s0[i]/=2;
		}
		for(j=0; j<4; j++)
		{
			f[4*i+j]=tmp[3-j];
		}
	}
	
	// 经过P变换存入frk[32]
	for(i=0; i<32; i++)
	{
		frk[i]=f[P_Table[i]-1];
	}
	
	int Ltmp[32], Rtmp[32];
	memset(Ltmp, 0, 32);
	memset(Rtmp, 0, 32);
	
	for(i=0; i<32; i++)
	{
		Ltmp[i]=R0[i];
		Rtmp[i]=(L0[i]+frk[i])%2;
	}
	
	// 最后将数据存入L0,RO里面去
	for(i=0; i<32; i++)
	{
		L0[i]=Ltmp[i];
		R0[i]=Rtmp[i];
	}
	
	CDESDlg::SaveToList();
	//////////////////////////////////////////////////////////////////////////
	// 16次迭代算法结束,真累呀^_^
}