#include"time.h"
#include"stdlib.h"
#include"stdio.h"
#include"S_DES.h"
#include"string.h"
#include"windows.h"
#include"iostream.h"
#define STRMAX 50
const WM_GET_MSG=WM_USER+1;//搜索成功的消息類型
const WM_FINISH_MSG=WM_USER+2;//搜索完畢的消息類型
DWORD MainThreadID;//主線程ID
typedef struct threadstruct//線程參數結構體
{
int ID;
int start;
int end;
char cipher[STRMAX];
}threadstruct;
int WriteToFile(char *filename,char *char_str,int str_len)//將密文寫入文件
{
int FileLength;
FILE *SecretFile=fopen(filename,"w");
if(SecretFile==NULL)
{
printf("文件打開失敗!\n");
return -1;
}
FileLength=fwrite(char_str,sizeof(char),str_len,SecretFile);
if(FileLength<1)
{
printf("寫入文件失敗!\n");
return FileLength;
}
fclose(SecretFile);
return 1;
}
int ReadFromFile(char *filename,char *char_str,int *str_len)//從文件讀取密文
{
int FileLength;
FILE *SecretFile=fopen(filename,"r");
if(SecretFile==NULL)
{
printf("文件打開失敗!\n");
return -1;
}
FileLength=fread(char_str,sizeof(char),STRMAX,SecretFile);
if(FileLength<1)
{
printf("讀取文件失敗!\n");
return FileLength;
}
*str_len=FileLength;
fclose(SecretFile);
return 1;
}
DWORD WINAPI SerchFunc(LPVOID lpData)//線程執行函數
{
int *return_number=new int;
int i,ID,start,end;
char cipher[STRMAX],output[STRMAX];
start=((threadstruct *)lpData)->start;
end=((threadstruct *)lpData)->end;
ID=((threadstruct *)lpData)->ID;
strcpy(cipher,((threadstruct *)lpData)->cipher);
for(i=start;i<end;i++)
{
SDES A(i);
A.StringInvCipher((BYTE *)cipher,strlen(cipher),(BYTE *)output);//字符串解密
if(!strcmp(output,"this is a secret!"))
{
*return_number=i;
PostThreadMessage(MainThreadID,WM_GET_MSG,0,(LPARAM)return_number);//找到所需密鑰,此處需要傳指針類型,如果直接傳變量地址就會出錯
//PostThreadMessage(MainThreadID,WM_GET_MSG,0,(LPARAM)&i);
return 1;
}
}
*return_number=ID;
PostThreadMessage(MainThreadID,WM_FINISH_MSG,0,(LPARAM)return_number);//搜索完畢
return 0;
}
int BruteForce(int ThreadCount,char *cipherstr)//暴力破解函數
{
int i;
int by;
char output[STRMAX];
BYTE to[10];
HANDLE hThread[STRMAX];
threadstruct ts[STRMAX];
by=1024/ThreadCount;
for(i=0;i<ThreadCount;i++)
{
ts[i].start=by*i;//分派搜索字段
ts[i].end=by*(i+1);
ts[i].ID=i;
strcpy(ts[i].cipher,cipherstr);
hThread[i] = CreateThread(NULL,0,SerchFunc,(LPVOID)&ts[i],0,NULL);//啓動新的線程
CloseHandle(hThread[i]);
}
return 0;
}
int DealMessage(MSG &msg)
{
int i;
if(msg.message== WM_GET_MSG)//收到子線程的成功消息
{
i=*((int *)msg.lParam);
return i;
}
else if(msg.message== WM_FINISH_MSG)
return -1;
else
return -2;
}
int main()
{
MSG msg;
double duration;
int key,filelen,FinishCount,ThreadCount,flag;
char ch,str[STRMAX],strout[STRMAX];
clock_t start, finish;
srand((unsigned)time(NULL));
cout<<"----------------------------------------"<<endl;
cout<<" 選擇功能"<<endl;
cout<<"\n 1.加密 2.解密\n";
cout<<"----------------------------------------"<<endl;
cin>>ch;
cout<<"----------------------------------------"<<endl;
if(ch=='1')
{
cin.get();
cout<<"輸入一段明文進行加密(50個字符以內):\n";
cin.getline(str,STRMAX);
cout<<"----------------------------------------"<<endl;
key=rand()%1024;
//key=1000;
cout<<(int)key<<endl;
cout<<"開始加密。。。。。。"<<endl;
SDES A(key);
A.StringCipher((BYTE *)str,strlen(str),(BYTE *)strout);
if(WriteToFile("cipher.dat",strout,strlen(str))<1)
{
cout<<"密文寫入錯誤!"<<endl;
return 0;
}
cout<<"加密完成,密文存於cipher.dat文件中"<<endl;
cout<<"----------------------------------------"<<endl;
getchar();
}
else if(ch=='2')
{
cout<<"輸入要啓動的線程個數(2的冪1,2,4...):";
cin>>ThreadCount;
ReadFromFile("cipher.dat",str,&filelen);
str[filelen]='\0';
cout<<"----------------------------------------"<<endl;
cout<<"開始暴力破解。。。。。。"<<endl;
MainThreadID=GetCurrentThreadId();
BruteForce(ThreadCount,str);
start = clock();
FinishCount=0;
while(1)
{
if(GetMessage(&msg,NULL,0,0))//主線程循環捕獲消息
//if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
flag=DealMessage(msg);
if(flag==-1)//收到子線程的成功消息
{
FinishCount++;
if(FinishCount==ThreadCount)
{
cout<<"所有線程搜索完畢沒有找到密鑰!這TM不可能啊"<<endl;
break;
}
}
else if(flag==-2)//搜索完畢的消息
{
cout<<"消息傳遞出錯!"<<endl;
break;
}
else
{
cout<<"找到密鑰"<<flag<<endl;
break;
}
}
}
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC; //計算耗時
cout<<"----------------------------------------"<<endl;
cout<<"\n -------->耗時"<<duration<<"秒<----------\n"<<endl;
getchar();
}
else
cout<<"輸入1或者2\n";
return 1;
}
一些知識點
1.主線程創建新的線程來窮舉破譯SDES的密鑰
2.新線程利用PostThreadMessage與主線程進行通信
3.主線程向新線程傳遞結構體參數
4.主線程對MSG類型的消息的處理
運行截圖