vb.net有无类似 C语言中sizeof()函数

shihyuyao 2005-11-25 02:57:22
1.vb.net有无类似 C语言中sizeof()函数

2.vb.net字符串有无 '\0'做无结速

3."A"算是1byte还是2byte('A'+'\0')??

4."A"算是字符 还是字符串

谢谢
...全文
263 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
淡蓝色2 2005-11-26
  • 打赏
  • 举报
回复
1.vb.net有无类似 C语言中sizeof()函数
有,但只能计算结构(Structure)的占用内存大小:
System.Runtime.InteropServices.Marshal.SizeOf(YourStructure var)

2.vb.net字符串有无 '\0'做无结速
没有
.net系统的字符串是个Class,它有专门的内部属性来标识字符串的长度.不用\0
如果需要在.net framework和com之间做边界调用,则只能自己写代码检测\0 来识别从非托管传回来的字符串

3."A"算是1byte还是2byte('A'+'\0')??
是2 bytes
.net系统中的所有字符串都是两字节的Unicode字符串,无论中文还是英文还是其它的语言

4."A"算是字符 还是字符串
dim strTemp As String = "A" '字符串
Dim chrTemp As Char = "A"c '字符
hamadou 2005-11-26
  • 打赏
  • 举报
回复
1.好象没有
2.没有
3.同2
4.字符串,除非"A"C算是字符。
/ ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include #include #include #include #include #pragma comment(lib,"Shlwapi.lib") //#pragma warning(disable: 4996) // 宽字符转换为多字符(Unicode --> ASCII) #define WCHAR_TO_CHAR(lpW_Char, lpChar) \ WideCharToMultiByte(CP_ACP, NULL, lpW_Char, -1, lpChar, _countof(lpChar), NULL, FALSE); // 多字符转换为宽字符(ASCII --> Unicode) #define CHAR_TO_WCHAR(lpChar, lpW_Char) \ MultiByteToWideChar(CP_ACP, NULL, lpChar, -1, lpW_Char, _countof(lpW_Char)); //RAR命令 enum RAR_SHELL_TYPE { FIND = 1, //查找 DELLPK, //解压缩 }; #define VIR_NAME L"lpk.dll" #define NORMAL_FILE1 L"c:\\windows\\system32\\lpk.dll" #define NORMAL_FILE2 L"c:\\windows\\system\\dllcache\\lpk.dll" bool DelServer(TCHAR *szServerName); //删除服务,包含服务的EXE文件 bool ErrorPrompt();//错误信息 bool DelRegedit(HKEY szMainKey, TCHAR *szRegName); bool DelFile(TCHAR *szPath); bool TotalKillName();//全盘查杀 lpk.dll DWORD WINAPI ThreadFun(LPVOID pM); //每一个磁盘一个线程 void FindNowFile(TCHAR *szPath); //扫描查杀 bool RarShellForLpk(TCHAR *CommandLine, DWORD dwShellType);// 判断压缩包是否有lpk.exe void CmdDelShell(TCHAR *szPath); TCHAR szRarPath[MAX_PATH]; //RAR压缩软件路径 CRITICAL_SECTION g_criticalSection; // 临界区 int _tmain(int argc, _TCHAR* argv[]) { _wsetlocale(LC_ALL, L"chs"); TCHAR szServerName[] = L"Ghijkl Nopqrstu Wxy"; if (!DelServer(szServerName)) //删除服务 { // goto OVER; } TCHAR szRegName[] = L"SYSTEM\\CurrentControlSet\\services"; HKEY hKey = HKEY_LOCAL_MACHINE; if (!DelRegedit(hKey, szRegName)) //删除注册表 { // goto OVER; } TCHAR szPath[] = L"C:\\windows\\system32\\hra33.dll"; DelFile(szPath); //删除hra33.dll文件 puts("开始全盘查杀"); TotalKillName(); //全盘查杀,每一个硬盘开启一个线程,可以查杀压缩包的lpk.dll文件 OVER: system("pause"); return 0; } bool DelServer(TCHAR *szServerName) { // TODO: 在此添加命令处理程序代码 SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCM == NULL) { return ErrorPrompt(); } //TCHAR szServerName[] = L"iPod Service";//Ghijkl Nopqrstu Wxy SC_HANDLE hService = OpenService(hSCM, szServerName, SERVICE_ALL_ACCESS); if (hService == NULL) { CloseServiceHandle(hSCM); return ErrorPrompt(); } //获取服务配置信息,地址 QUERY_SERVICE_CONFIG SerInfo; DWORD dwSize = 8 * 1024; DWORD pcbBytesNeeded = 0; BOOL bQuersy = QueryServiceConfig(hService, &SerInfo;, dwSize, &pcbBytesNeeded;); SERVICE_STATUS status; ControlService(hService, SERVICE_CONTROL_STOP, &status;); BOOL bDelete = DeleteService(hService); CloseServiceHandle(hService); CloseServiceHandle(hSCM); if (bDelete && bQuersy) { CmdDelShell(SerInfo.lpBinaryPathName); puts("删除服务成功!"); return true; } else { return ErrorPrompt(); } } bool ErrorPrompt() { DWORD dwError = GetLastError(); LPTSTR lpMsgBuf = nullptr; //错误码翻译函数 FormatMessage(0x1300, NULL, dwError, 0x400, (LPTSTR)&lpMsgBuf;, 64, NULL); TCHAR szBuf[128] = { 0 }; wsprintf(szBuf, _T("出错! %s"), lpMsgBuf); LocalFree(lpMsgBuf); wprintf(L"%s\n", szBuf); return false; } bool DelRegedit(HKEY szMainKey, TCHAR *szRegName) { HKEY hResult = 0;//\\Ghijkl Nopqrstu Wxy LONG lReturn = RegOpenKeyEx(szMainKey, szRegName, NULL, KEY_ALL_ACCESS, &hResult;); if (lReturn != ERROR_SUCCESS) { return ErrorPrompt(); } lReturn = RegDeleteKey(hResult, L"Ghijkl Nopqrstu Wxy"); if (lReturn != ERROR_SUCCESS) { return ErrorPrompt(); } return true; } //删除文件 bool DelFile(TCHAR *szPath) { BOOL nRet = DeleteFile(szPath); if (nRet) return true; else return ErrorPrompt(); } bool TotalKillName() { TCHAR szDiskName[MAX_PATH] = { 0 }; GetLogicalDriveStrings(MAX_PATH, szDiskName); //获取RAR.exe执行路径 TCHAR szTmpRARPath[MAX_PATH] = { 0 }; DWORD dwSize = MAX_PATH; LONG nRet = SHRegGetValue(HKEY_CLASSES_ROOT, L"WinRAR\\shell\\open\\command", 0, 2, 0, &szTmpRARPath;, &dwSize;); PathRemoveFileSpec(szTmpRARPath); // 删除路径后面的文件名和’/’符号。该函数可以分析出一个文件的路径。 PathAppend(szTmpRARPath, L"rar.exe"); GetFileAttributes(szTmpRARPath);// 获取到压缩包rar.exe的路径 TCHAR seps[] = L"\""; TCHAR *token = NULL; TCHAR *next_token = NULL; token = _tcstok_s(szTmpRARPath, seps, &next;_token); GetShortPathName(token, szRarPath, MAX_PATH); // 初始化临界区 InitializeCriticalSection(&g_criticalSection); HANDLE phThreadArray[20]; DWORD dwDiskNum = 0; //磁盘数量 // HANDLE phThreadArray1[dwDiskNum]; for (int i = 0; i < szDiskName[i] != '\0'&&i < MAX_PATH; i++) { switch (GetDriveType(&szDiskName;[i])) { case DRIVE_REMOVABLE://移动硬盘 case DRIVE_FIXED: //硬盘 // case DRIVE_REMOTE://网络驱动器 // case DRIVE_CDROM: //CD-ROM驱动器 { /*TCHAR tmp[10] = { 0 }; _tcscpy_s(tmp, 10, &szDiskName;[i]);*/ phThreadArray[dwDiskNum] = CreateThread(NULL, 0, ThreadFun, (LPVOID)szDiskName[i], 0, NULL); dwDiskNum++; break; } default: break; } i += lstrlen(&szDiskName;[i]); } // 等待所有线程返回 WaitForMultipleObjects(dwDiskNum, phThreadArray, TRUE, -1); return true; } DWORD WINAPI ThreadFun(LPVOID lpThreadParameter) { // 进入临界区 EnterCriticalSection(&g_criticalSection); //printf("[%d] %c\n", GetThreadId(GetCurrentThread()), szDisk); TCHAR szPath[10] = { 0 }; szPath[0] = (TCHAR)lpThreadParameter; _tcscat_s(szPath, 10, L":"); wprintf(L"开始查杀 %s 盘\n", szPath); FindNowFile(szPath); // 离开临界区 LeaveCriticalSection(&g_criticalSection); return 0; } void FindNowFile(TCHAR *szPath) { WIN32_FIND_DATA stcFindData = { 0 }; TCHAR szSeach[MAX_PATH] = { 0 }; wsprintf(szSeach, L"%s\\*", szPath); HANDLE hFind = FindFirstFile(szSeach, &stcFindData;); if (hFind == INVALID_HANDLE_VALUE) { return; } do { // 判断当前找到的文件是否是当前或上层目录 if (wcscmp(stcFindData.cFileName, L".") == 0 || wcscmp(stcFindData.cFileName, L"..") == 0) { //如果是其之一,就结束本次循环 continue; } // 判断文件是否是目录,确定插入文件大小 if (stcFindData.dwFileAttributes&FILE;_ATTRIBUTE_DIRECTORY)//目录 { TCHAR path[MAX_PATH] = { 0 }; swprintf_s(path, L"%s\\%s", szPath, stcFindData.cFileName); //wprintf(L"目录\n"); FindNowFile(path); } else//文件 { // printf("%s", stcFindData.cFileName); //组合完整路径 TCHAR szFullPath[600] = { 0 }; TCHAR szShortPath[600] = { 0 }; _tcscpy_s(szFullPath, 600, szPath); _tcscat_s(szFullPath, 600, L"\\"); _tcscat_s(szFullPath, 600, stcFindData.cFileName); //转化为短路径 GetShortPathName(szFullPath, szShortPath, MAX_PATH); LPWSTR strSuffix = PathFindExtension(stcFindData.cFileName); // 获取文件的后缀名 if (_tcscmp(stcFindData.cFileName, VIR_NAME) == 0) { //正常文件判断,这二个目录下为正常文件 if (_tcscmp(szFullPath, NORMAL_FILE1) == 0 || _tcscmp(szFullPath, NORMAL_FILE2) == 0) { continue; } CmdDelShell(szShortPath); /*BOOL nRet = DeleteFile(szFullPath); if (nRet) { wprintf(L"成功删除:%s\n", szFullPath); } else { wprintf(L"删除失败:%s\n", szFullPath); }*/ } //判断rar zip else if (_tcscmp(strSuffix, L".rar") == 0 || _tcscmp(strSuffix, L".zip") == 0) { //先判断压缩包有无"lpk.dll" TCHAR CommandLine[600] = { 0 }; TCHAR Buffer[MAX_PATH] = { 0 }; // PathGetShortPath(szRarPath); GetTempPath(0x104u, Buffer); DWORD a = GetCurrentThreadId(); GetTempFileName(Buffer, L"IRAR", a, Buffer); wsprintfW(CommandLine, L"cmd /c %s vb \"%s\" lpk.dll|find /i \"lpk.dll\"", szRarPath, szShortPath, Buffer); bool nRet = RarShellForLpk(CommandLine, FIND);// 判断压缩包是否有lpk.exe if (nRet) { wsprintfW(CommandLine, L"cmd /c %s d %s lpk.dll", szRarPath, szShortPath); nRet = RarShellForLpk(CommandLine, DELLPK); if (nRet) wprintf(L"清理压缩包病毒成功:%s\n", szFullPath); else wprintf(L"清理压缩包病毒失败:%s\n", szFullPath); } } } } while (FindNextFile(hFind, &stcFindData;)); return; } bool RarShellForLpk(TCHAR *CommandLine, DWORD dwShellType) { SECURITY_ATTRIBUTES sa; HANDLE hRead, hWrite; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; if (!CreatePipe(&hRead;, &hWrite;, &sa;, 0)) { return ErrorPrompt(); } STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi; si.hStdError = hWrite; si.hStdOutput = hWrite; si.wShowWindow = SW_HIDE; si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; if (!CreateProcess(NULL, CommandLine, NULL, NULL, TRUE, NULL, NULL, NULL, &si;, π)) { return ErrorPrompt(); } CloseHandle(hWrite); char buffer[4096]; memset(buffer, 0, 4096); DWORD byteRead; while (true) { if (ReadFile(hRead, buffer, 4095, &byteRead;, NULL) == NULL) { break; } } switch (dwShellType) { case FIND: { if (strcmp(buffer, "lpk.dll\r\n") == 0) return true; else return false; }break; case DELLPK: { char seps[] = "正在删除 lpk.dll\r\n完成"; char *token = NULL; char *next_token = NULL; token = strtok_s(buffer, seps, &next;_token); if (token != NULL) return true; else return false; }break; default: break; } } void CmdDelShell(TCHAR *szPath) { TCHAR szTDelShell[300] = { 0 }; wsprintf(szTDelShell, _T("del /s /q /f /ah %s"), szPath);//地址 char szADelShell[300] = { 0 }; WCHAR_TO_CHAR(szTDelShell, szADelShell); system(szADelShell); }
主要介绍如何开发一个ActiveX控件,提供接口,与相应事件挂钩。文涉及到VARIANT,SAFEARRAY,BSTR的详细使用方法。 另外还提供了WinSock的详细开发步骤,以及如何响应网络超时,网络断开的事件方法以及在VC,VB调用该控件的方法。 一、MFC ActiveX控件开发步骤(VC 6.0): New->Projects->MFC ActiveX ControlWizard,然后输入MFCWinSock工程名。如下图: 图一 创建工程 一路狂按Next,直至Finsh出现,再按下OK,如下图:     图二 创建完成 二、架设Socket环境: 首先在StdAfx.h文件加入下面这句代码: #include // MFC socket extensions 打开MFCWinSock.cpp文件,添加代码,看起来如下: //////////////////////////////////////////////////////////////////////////// // CMFCWinSockApp::InitInstance - DLL initialization BOOL CMFCWinSockApp::InitInstance() { BOOL bInit = COleControlModule::InitInstance(); if (bInit) { // TODO: Add your own module initialization code here. if (!AfxSocketInit()) { AfxMessageBox("无法初始化Socket,请检查!"); return FALSE; } WSADATA wsaData; WORD wVersion = MAKEWORD(1, 1);//设定为Winsock 1.1版 int errCode; errCode = WSAStartup(wVersion, &wsaData);//启动Socket服务 if (errCode) { AfxMessageBox("无法找到可以使用的 WSOCK32.DLL"); return FALSE; } } return bInit; } //////////////////////////////////////////////////////////////////////////// // CMFCWinSockApp::ExitInstance - DLL termination int CMFCWinSockApp::ExitInstance() { // TODO: Add your own module termination code here. WSACleanup();//结束网络服务 return COleControlModule::ExitInstance(); } 三,提供控件接口和事件 在MFCWinSockCtl.cpp加入如下代码: #ifndef WM_MYWINSOCK #define WM_MYWINSOCK WM_USER+1888 #endif View->ClassWizard->Automation->Add Method…如下图: 图三 创建接口 这个时候,我们为这个控件添加了一个Connect()的接口,出于通用性,安全性和扩展性的考虑,我们采用了VARIANT类型的参数, 很多人可能都不太了解该类型,又或者有接触过,但被吓怕了,那么我们来看清它的本来面目: struct tagVARIANT { union { struct __tagVARIANT { VARTYPE vt; WORD wReserved1; WORD wReserved2; WORD wReserved3; union { LONG lVal; BYTE bVal; SHORT iVal; FLOAT fltVal; DOUBLE dblVal; VARIANT_BOOL boolVal; _VARIANT_BOOL bool; SCODE scode; CY cyVal; DATE date; BSTR bstrVal; IUnknown __RPC_FAR *punkVal; IDispatch __RPC_FAR *pdispVal; SAFEARRAY __RPC_FAR *parray; BYTE __RPC_FAR *pbVal; SHORT __RPC_FAR *piVal; LONG __RPC_FAR *plVal; FLOAT __RPC_FAR *pfltVal; DOUBLE __RPC_FAR *pdblVal; VARIANT_BOOL __RPC_FAR *pboolVal; _VARIANT_BOOL __RPC_FAR *pbool; SCODE __RPC_FAR *pscode; CY __RPC_FAR *pcyVal; DATE __RPC_FAR *pdate; BSTR __RPC_FAR *pbstrVal; IUnknown __RPC_FAR *__RPC_FAR *ppunkVal; IDispatch __RPC_FAR *__RPC_FAR *ppdispVal; SAFEARRAY __RPC_FAR *__RPC_FAR *pparray; VARIANT __RPC_FAR *pvarVal; PVOID byref; CHAR cVal; USHORT uiVal; ULONG ulVal; INT intVal; UINT uintVal; DECIMAL __RPC_FAR *pdecVal; CHAR __RPC_FAR *pcVal; USHORT __RPC_FAR *puiVal; ULONG __RPC_FAR *pulVal; INT __RPC_FAR *pintVal; UINT __RPC_FAR *puintVal; struct __tagBRECORD { PVOID pvRecord; IRecordInfo __RPC_FAR *pRecInfo; } __VARIANT_NAME_4; } __VARIANT_NAME_3; } __VARIANT_NAME_2; DECIMAL decVal; } __VARIANT_NAME_1; }; 它先是一个结构体,里面有一个重要成员VARTYPE vt;vt即是指明当前的数据类型,比如整型或者字符型,当指明vt后, 后面看到各种变量类型包括在一个联合体当,也就是说指明vt后,你只能使用对应的其之一变量类型。看着这众多的各种不同 类型变量集在一起,确实让人吓了一跳,但细细看来,大多数变量跟我们平时的用法相似。值得一提的是SAFEARRAY __RPC_FAR *parray; 也许有很多人还没有接触过SAFEARRAY类型的变量,SAFEARRAY实际上也是一个结构,大家可以参考MSDN,我也将在后面介绍它的具体使用方法。 用同样的方法创建DisConnect()接口 创建两个事件,FireCloseWinsock()响应网络断开事件,FireRecvSockEvent()响应网络有数据到达的事件。创建方法如下图: 图四 创建事件 重载控件消息处理函数WindowProc(),在View->ClassWizard打开类向导,在消息映射找到WindowProc,如下图: 图五 重载WindowProc() 四、编写代码 编写VariantToLong()转换函数,该函数代码如下: //类型转换,将VARIANT类型转换成Long类型 long CMFCWinSockCtrl::VariantToLong(const VARIANT &var) { long r; switch(var.vt) { case VT_UI2://USHORT r = var.uiVal; break; case VT_UI4://ULONG r = var.ulVal; break; case VT_INT://INT r = var.intVal; break; case VT_UINT://UINT r = var.uintVal; break; case VT_I4://LONG r = var.lVal; break; case VT_UI1://BYTE r = var.bVal; break; case VT_I2://SHORT r = var.iVal; break; case VT_R4://FLOAT r = (long)var.fltVal; break; case VT_R8://DOUBLE r = (long)var.dblVal; break; default: r = -1;//无法转换该值 break; } return r; } 大家可以看到,该函数将最基本的若干数据类型转换成了long类型,但VARIANT决不是个简单的谱,我将在后面继续揭开它的神秘面纱. 编写我们刚才的接口Connect(),代码代码如下: 在MFCWinSockCtrl.h加入 SOCKET OnlySock;//建立的唯一Socket,不允许重复建立多个 bool isOnlyConnect;//是否建立了连接 然后再编写Connect(),看起来如下: BOOL CMFCWinSockCtrl::Connect(const VARIANT FAR& RemoteHost, const VARIANT FAR& RemotePort) { // TODO: Add your dispatch handler code here if(isOnlyConnect)//该连接已建立,还没有断开 return FALSE; CString IPAddress; int Port;//转换成整型的端口 switch(RemoteHost.vt) { case VT_BSTR://字符串型 IPAddress = CString(RemoteHost.bstrVal); break; case VT_BYREF|VT_I1://CHAR * IPAddress.Format("%s",RemoteHost.pcVal);//RemoteHost.pbstrVal); break; default: IPAddress = ""; return FALSE; } Port = VariantToLong(RemotePort);//我们编写的一个VARIANT转换成long类型的函数 if(Port<=0) return FALSE; _TCHAR *ip = 0; struct hostent *host = 0; struct sockaddr_in addr; ULONG dotIP = inet_addr(IPAddress); OnlySock = socket(AF_INET, SOCK_STREAM, 0); // 判断是否为点IP地址格式 if (OnlySock == INVALID_SOCKET) { shutdown(OnlySock, 0x02); closesocket(OnlySock);//释放占有的SOCK资源 return FALSE; } memset(&addr, 0, sizeof(struct sockaddr_in)); // 设定 SOCKADDR_IN 结构的内容 // 如果通讯协议是选择IP Protocol,那此值固定为AF_INET // AF_INET 与 PF_INET 这两个常量值相同 addr.sin_family = AF_INET; addr.sin_port = htons(Port); addr.sin_addr.S_un.S_addr = dotIP; if (dotIP == INADDR_NONE) { host = gethostbyname(IPAddress); if (!host) { shutdown(OnlySock, 0x02); closesocket(OnlySock);//释放占有的SOCK资源 return FALSE; }; ip = inet_ntoa(*(struct in_addr*)(*host->h_addr_list)); addr.sin_addr.S_un.S_addr = inet_addr(ip); } //开始连线 if (connect(OnlySock, (LPSOCKADDR)&addr, sizeof(SOCKADDR))) { shutdown(OnlySock, 0x02); closesocket(OnlySock);//释放占有的SOCK资源 return FALSE; } int iError = WSAAsyncSelect(OnlySock, m_hWnd,WM_MYWINSOCK, FD_READ|FD_CLOSE); //只对网络断开和数据到达通知感兴趣 if(iError == SOCKET_ERROR)//无法绑定Winsock的事件通知 { shutdown(OnlySock, 0x02); closesocket(OnlySock);//释放占有的SOCK资源 return FALSE; } isOnlyConnect = true; return TRUE; } 有必要提一下WSAAsyncSelect(),这里接收网络数据到达和断开的两个消息,我们收到WM_MYWINSOCK消息时将处理该消息并作为事件传送给调用者. 第二个参数,窗口句柄,我们传送了m_hWnd,这是因为MFC ActiveX也属于一个窗口,并且是可见的,因此可以成功。 编写WindowProc(),代码看起来如下: LRESULT CMFCWinSockCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: Add your specialized code here and/or call the base class switch(message) { case WM_MYWINSOCK://响应自定义的消息 switch(WSAGETSELECTEVENT(lParam)) { case FD_READ://有新数据到达 FireRecvSockEvent(); break; case FD_CLOSE://对方已断掉当前连接 FireCloseWinsock(); break; } break; default: break; } return COleControl::WindowProc(message, wParam, lParam); } 本部分结束语: 好了,现在一个可以运行的控件已经完成,里面提供有Connect()和DisConnect()接口,和RecvSockEvent()及CloseWinsock()事件。以及WinSock的使用方法。 在下一部分(高级篇)将讲解两个重要接口SendData()和GetData(),下期内容如下: long SendData(const VARIANT FAR& Data, const VARIANT FAR& DataType,const VARIANT FAR& DataLength, const VARIANT FAR& TimeOut) long GetData(VARIANT FAR* Data, const VARIANT FAR& DataType, const VARIANT FAR& DataMaxLength, const VARIANT FAR& TimeOut) VARIANT和SAFEARRAY的复杂用法。 控件开发出来后在VC和VB环境下的使用方法。 声明: 部分资料来源于网络,本文所用的所有源代码仅供非商业用途,并请保留原版权,否则后果自负! 欢迎大家拍砖,或指正不足的地方,一起探导更好的方法。 欢迎访问www.59186618.com,感谢您的支持!
MD5加密算法(Java版) 可以运行 原理   对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。   在MD5算法,首先需要对信息进行填充,使其位长对512求余的结果等于448。因此,信息的位长(Bits Length)将被扩展至N*512+448,N为一个非负整数,N可以是零。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,现在的信息的位长=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理对信息长度的要求。   MD5有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x67452301,B=0xefcdab89,C=0x98badcfe,D=0x10325476。   当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的次数是信息512位信息分组的数目。   将上面四个链接变量复制到另外四个变量:A到a,B到b,C到c,D到d。   主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d的其三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向左环移一个不定的数,并加上a、b、c或d之一。最后用该结果取代a、b、c或d之一。   以一下是每次操作用到的四个非线性函数(每轮一个)。   F(X,Y,Z) =(X&Y)|((~X)&Z)   G(X,Y,Z) =(X&Z)|(Y&(~Z))   H(X,Y,Z) =X^Y^Z   I(X,Y,Z)=Y^(X|(~Z))   (&是与,|是或,~是非,^是异或)   这四个函数的说明:如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。   F是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。   假设Mj表示消息的第j个子分组(从0到15), 常数ti是4294967296*abs(sin(i))的整数部分,i取值从1到64,单位是弧度。(4294967296等于2的32次方)   FF(a, b, c, d, Mj, s, ti)表示 a = b + ((a + F(b, c, d) + Mj + ti) << s)   GG(a, b, c, d, Mj, s, ti)表示 a = b + ((a + G(b, c, d) + Mj + ti) << s)   HH(a, b, c, d, Mj, s, ti)表示 a = b + ((a + H(b, c, d) + Mj + ti) << s)   II(a, b, c, d, Mj, s, ti)表示 a = b + ((a + I(b, c, d) + Mj + ti) << s)   这四轮(64步)是:   第一轮   FF(a, b, c, d, M0, 7, 0xd76aa478)   FF(d, a, b, c, M1, 12, 0xe8c7b756)   FF(c, d, a, b, M2, 17, 0x242070db)   FF(b, c, d, a, M3, 22, 0xc1bdceee)   FF(a, b, c, d, M4, 7, 0xf57c0faf)   FF(d, a, b, c, M5, 12, 0x4787c62a)   FF(c, d, a, b, M6, 17, 0xa8304613)   FF(b, c, d, a, M7, 22, 0xfd469501)   FF(a, b, c, d, M8, 7, 0x698098d8)   FF(d, a, b, c, M9, 12, 0x8b44f7af)   FF(c, d, a, b, M10, 17, 0xffff5bb1)   FF(b, c, d, a, M11, 22, 0x895cd7be)   FF(a, b, c, d, M12, 7, 0x6b901122)   FF(d, a, b, c, M13, 12, 0xfd987193)   FF(c, d, a, b, M14, 17, 0xa679438e)   FF(b, c, d, a, M15, 22, 0x49b40821)   第二轮   GG(a, b, c, d, M1, 5, 0xf61e2562)   GG(d, a, b, c, M6, 9, 0xc040b340)   GG(c, d, a, b, M11, 14, 0x265e5a51)   GG(b, c, d, a, M0, 20, 0xe9b6c7aa)   GG(a, b, c, d, M5, 5, 0xd62f105d)   GG(d, a, b, c, M10, 9, 0x02441453)   GG(c, d, a, b, M15, 14, 0xd8a1e681)   GG(b, c, d, a, M4, 20, 0xe7d3fbc8)   GG(a, b, c, d, M9, 5, 0x21e1cde6)   GG(d, a, b, c, M14, 9, 0xc33707d6)   GG(c, d, a, b, M3, 14, 0xf4d50d87)   GG(b, c, d, a, M8, 20, 0x455a14ed)   GG(a, b, c, d, M13, 5, 0xa9e3e905)   GG(d, a, b, c, M2, 9, 0xfcefa3f8)   GG(c, d, a, b, M7, 14, 0x676f02d9)   GG(b, c, d, a, M12, 20, 0x8d2a4c8a)   第三轮   HH(a, b, c, d, M5, 4, 0xfffa3942)   HH(d, a, b, c, M8, 11, 0x8771f681)   HH(c, d, a, b, M11, 16, 0x6d9d6122)   HH(b, c, d, a, M14, 23, 0xfde5380c)   HH(a, b, c, d, M1, 4, 0xa4beea44)   HH(d, a, b, c, M4, 11, 0x4bdecfa9)   HH(c, d, a, b, M7, 16, 0xf6bb4b60)   HH(b, c, d, a, M10, 23, 0xbebfbc70)   HH(a, b, c, d, M13, 4, 0x289b7ec6)   HH(d, a, b, c, M0, 11, 0xeaa127fa)   HH(c, d, a, b, M3, 16, 0xd4ef3085)   HH(b, c, d, a, M6, 23, 0x04881d05)   HH(a, b, c, d, M9, 4, 0xd9d4d039)   HH(d, a, b, c, M12, 11, 0xe6db99e5)   HH(c, d, a, b, M15, 16, 0x1fa27cf8)   HH(b, c, d, a, M2, 23, 0xc4ac5665)   第四轮   II(a, b, c, d, M0, 6, 0xf4292244)   II(d, a, b, c, M7, 10, 0x432aff97)   II(c, d, a, b, M14, 15, 0xab9423a7)   II(b, c, d, a, M5, 21, 0xfc93a039)   II(a, b, c, d, M12, 6, 0x655b59c3)   II(d, a, b, c, M3, 10, 0x8f0ccc92)   II(c, d, a, b, M10, 15, 0xffeff47d)   II(b, c, d, a, M1, 21, 0x85845dd1)   II(a, b, c, d, M8, 6, 0x6fa87e4f)   II(d, a, b, c, M15, 10, 0xfe2ce6e0)   II(c, d, a, b, M6, 15, 0xa3014314)   II(b, c, d, a, M13, 21, 0x4e0811a1)   II(a, b, c, d, M4, 6, 0xf7537e82)   II(d, a, b, c, M11, 10, 0xbd3af235)   II(c, d, a, b, M2, 15, 0x2ad7d2bb)   II(b, c, d, a, M9, 21, 0xeb86d391)   所有这些完成之后,将A、B、C、D分别加上a、b、c、d。然后用下一分组数据继续运行算法,最后的输出是A、B、C和D的级联。   当你按照我上面所说的方法实现MD5算法以后,你可以用以下几个信息对你做出来的程序作一个简单的测试,看看程序有没有错误。   MD5 ("") = d41d8cd98f00b204e9800998ecf8427e   MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661   MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72   MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0   MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b   MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") =   f29939a25efabaef3b87e2cbfe641315 VB2010实现   Imports System   Imports System.Security.Cryptography   Imports System.Text   Module Example   ' 哈希输入字符串并返回一个32字符的十六进制字符串哈希。   Function getMd5Hash(ByVal input As String) As String   ' 创建新的一个MD5CryptoServiceProvider对象的实例。   Dim md5Hasher As New MD5CryptoServiceProvider()   ' 输入的字符串转换为字节数组,并计算哈希。   Dim data As Byte() = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input))   ' 创建一个新的StringBuilder收集的字节,并创建一个字符串。   Dim sBuilder As New StringBuilder()   ' 通过每个字节的哈希数据和格式为十六进制字符串的每一个循环。   Dim i As Integer   For i = 0 To data.Length - 1   sBuilder.Append(data(i).ToString("x2"))   Next i   ' 返回十六进制字符串。   Return sBuilder.ToString()   End Function   ' 验证对一个字符串的哈希值。   Function verifyMd5Hash(ByVal input As String, ByVal hash As String) As Boolean   ' 哈希的输入。   Dim hashOfInput As String = getMd5Hash(input)   ' 创建StringComparer1的哈希进行比较。   Dim comparer As StringComparer = StringComparer.OrdinalIgnoreCase   If 0 = comparer.Compare(hashOfInput, hash) Then   Return True   Else   Return False   End If   End Function   Sub Main()   Dim source As String = "Hello World!"   Dim hash As String = getMd5Hash(source)   Console.WriteLine("进行MD5加密的字符串为:" + source + " 加密的结果是:" + hash + ".")   Console.WriteLine("验证哈希...")   If verifyMd5Hash(source, hash) Then   Console.WriteLine("哈希值是相同的。")   Else   Console.WriteLine("哈希值是不相同的。")   End If   End Sub   End Module   ' 此代码示例产生下面的输出:   '   ' 进行MD5加密的字符串为:Hello World! 加密的结果是:ed076287532e86365e841e92bfc50d8c.   ' 验证哈希...   ' 哈希值是相同的。 伪代码实现   //Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating   var int[64] r, k //r specifies the per-round shift amounts   r[ 0..15]:= {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22}   r[16..31]:= {5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20}   r[32..47]:= {4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23}   r[48..63]:= {6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}   //Use binary integer part of the sines of integers as constants:   for i from 0 to 63   k[i] := floor(abs(sin(i + 1)) × 2^32)   //Initialize variables:   var int h0 := 0x67452301   var int h1 := 0xEFCDAB89   var int h2 := 0x98BADCFE   var int h3 := 0x10325476   //Pre-processing:   append "1" bit to message   append "0" bits until message length in bits ≡ 448 (mod 512)   append bit length of message as 64-bit little-endian integer to message   //Process the message in successive 512-bit chunks:   for each 512-bit chunk of message   break chunk into sixteen 32-bit little-endian words w[i], 0 ≤ i ≤ 15   //Initialize hash value for this chunk:   var int a := h0   var int b := h1   var int c := h2   var int d := h3   //Main loop:   for i from 0 to 63   if 0 ≤ i ≤ 15 then   f := (b and c) or ((not b) and d)   g := i   else if 16 ≤ i ≤ 31   f := (d and b) or ((not d) and c)   g := (5×i + 1) mod 16   else if 32 ≤ i ≤ 47   f := b xor c xor d   g := (3×i + 5) mod 16   else if 48 ≤ i ≤ 63   f := c xor (b or (not d))   g := (7×i) mod 16   temp := d   d := c   c := b   b := ((a + f + k[i] + w[g]) leftrotate r[i]) + b   a := temp   //Add this chunk's hash to result so far:   h0 := h0 + a   h1 := h1 + b   h2 := h2 + c   h3 := h3 + d   var int digest := h0 append h1 append h2 append h3   //(expressed as little-endian) 标准C语言实现   具体的一个MD5实现   /*   * md5 -- compute and check MD5 message digest.   * this version only can calculate the char string.   *   * MD5 (Message-Digest algorithm 5) is a widely used, partially   * insecure cryptographic hash function with a 128-bit hash value.   *   * Author: redraiment   * Date: Aug 27, 2008   * Version: 0.1.6   */   #include   #include   #include   #include   #define SINGLE_ONE_BIT 0x80   #define BLOCK_SIZE 512   #define MOD_SIZE 448   #define APP_SIZE 64   #define BITS 8   // MD5 Chaining Variable   #define A 0x67452301UL   #define B 0xEFCDAB89UL   #define C 0x98BADCFEUL   #define D 0x10325476UL   // Creating own types   #ifdef UINT64   # undef UINT64   #endif   #ifdef UINT32   # undef UINT32   #endif   typedef unsigned long long UINT64;   typedef unsigned long UINT32;   typedef unsigned char UINT8;   typedef struct   {   char * message;   UINT64 length;   }STRING;   const UINT32 X[4][2] = {{0, 1}, {1, 5}, {5, 3}, {0, 7}};   // Constants for MD5 transform routine.   const UINT32 S[4][4] = {   { 7, 12, 17, 22 },   { 5, 9, 14, 20 },   { 4, 11, 16, 23 },   { 6, 10, 15, 21 }   };   // F, G, H and I are basic MD5 functions.   UINT32 F( UINT32 X, UINT32 Y, UINT32 Z )   {   return ( X & Y ) | ( ~X & Z );   }   UINT32 G( UINT32 X, UINT32 Y, UINT32 Z )   {   return ( X & Z ) | ( Y & ~Z );   }   UINT32 H( UINT32 X, UINT32 Y, UINT32 Z )   {   return X ^ Y ^ Z;   }   UINT32 I( UINT32 X, UINT32 Y, UINT32 Z )   {   return Y ^ ( X | ~Z );   }   // rotates x left s bits.   UINT32 rotate_left( UINT32 x, UINT32 s )   {   return ( x << s ) | ( x >> ( 32 - s ) );   }   // Pre-processin   UINT32 count_padding_bits ( UINT32 length )   {   UINT32 div = length * BITS / BLOCK_SIZE;   UINT32 mod = length * BITS % BLOCK_SIZE;   UINT32 c_bits;   if ( mod == 0 )   c_bits = MOD_SIZE;   else   c_bits = ( MOD_SIZE + BLOCK_SIZE - mod ) % BLOCK_SIZE;   return c_bits / BITS;   }   STRING append_padding_bits ( char * argv )   {   UINT32 msg_length = strlen ( argv );   UINT32 bit_length = count_padding_bits ( msg_length );   UINT64 app_length = msg_length * BITS;   STRING string;   string.message = (char *)malloc(msg_length + bit_length + APP_SIZE / BITS);   // Save message   strncpy ( string.message, argv, msg_length );   // Pad out to mod 64.   memset ( string.message + msg_length, 0, bit_length );   string.message [ msg_length ] = SINGLE_ONE_BIT;   // Append length (before padding).   memmove ( string.message + msg_length + bit_length, (char *)&app;_length, sizeof( UINT64 ) );   string.length = msg_length + bit_length + sizeof( UINT64 );   return string;   }   int main ( int argc, char *argv[] )   {   STRING string;   UINT32 w[16];   UINT32 chain[4];   UINT32 state[4];   UINT8 r[16];   UINT32 ( *auxi[ 4 ])( UINT32, UINT32, UINT32 ) = { F, G, H, I };   int roundIdx;   int argIdx;   int sIdx;   int wIdx;   int i;   int j;   if ( argc < 2 )   {   fprintf ( stderr, "usage: %s string ...\n", argv[ 0 ] );   return EXIT_FAILURE;   }   for ( argIdx = 1; argIdx < argc; argIdx++ )   {   string = append_padding_bits ( argv[ argIdx ] );   // MD5 initialization.   chain[0] = A;   chain[1] = B;   chain[2] = C;   chain[3] = D;   for ( j = 0; j < string.length; j += BLOCK_SIZE / BITS)   {   memmove ( (char *)w, string.message + j, BLOCK_SIZE / BITS );   memmove ( state, chain, sizeof(chain) );   for ( roundIdx = 0; roundIdx < 4; roundIdx++ )   {   wIdx = X[ roundIdx ][ 0 ];   sIdx = 0;   for ( i = 0; i < 16; i++ )   {   // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.   // Rotation is separate from addition to prevent recomputation.   state[sIdx] = state [ (sIdx + 1) % 4 ] +   rotate_left ( state[sIdx] +   ( *auxi[ roundIdx ] )   ( state[(sIdx+1) % 4], state[(sIdx+2) % 4], state[(sIdx+3) % 4]) +   w[ wIdx ] +   (UINT32)floor( (1UL << 32) * fabs(sin( roundIdx * 16 + i + 1 )) ),   S[ roundIdx ][ i % 4 ]);   sIdx = ( sIdx + 3 ) % 4;   wIdx = ( wIdx + X[ roundIdx ][ 1 ] ) & 0xF;   }   }   chain[ 0 ] += state[ 0 ];   chain[ 1 ] += state[ 1 ];   chain[ 2 ] += state[ 2 ];   chain[ 3 ] += state[ 3 ];   }   memmove ( r + 0, (char *)&chain;[0], sizeof(UINT32) );   memmove ( r + 4, (char *)&chain;[1], sizeof(UINT32) );   memmove ( r + 8, (char *)&chain;[2], sizeof(UINT32) );   memmove ( r + 12, (char *)&chain;[3], sizeof(UINT32) );   for ( i = 0; i < 16; i++ )   printf ( "x", r[i] );   putchar ( '\n' );   free(string.message);    }   return EXIT_SUCCESS;   }   /* 以上程序可以在任意一款支持ANSI C的编译器上编译通过 */   /* 直接复制粘贴,请删除多余的空格,并调整格式,否则可能有编译错误 */   /* 在linux下编译,要添加链接库,命令如:gcc -o md5 md5.c -lm */

16,555

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧