我有兴趣从.NET中的鼠标移动和击键生成熵(为了加密的目的,这可以在Forms应用程序中,其中鼠标移动和击键数据通过应用程序本身或Web中的事件接收使用JavaScript记录鼠标移动和击键数据并通过Ajax发送到服务器的应用程序。
这项技术目前正在新的MEGA网站上使用。
我自己做了一些研究,并且在C ++中看到了一个很好的例子,但它有点超出我的C / C ++知识。
#include <windows.h>
#include <wincrypt.h>
#include <commctrl.h>
#define SPC_ENTROPY_PER_SAMPLE 0.5
#define SPC_MOUSE_DLGID 102
#define SPC_PROGRESS_BARID 1000
#define SPC_MOUSE_COLLECTID 1003
#define SPC_MOUSE_STATIC 1002
typedef struct {
double dEntropy;
DWORD cbRequested;
POINT ptLastPos;
DWORD dwLastTime;
HCRYPTHASH hHash;
} SPC_DIALOGDATA;
typedef struct {
POINT ptMousePos;
DWORD dwTickCount;
} SPC_MOUSEPOS;
static BOOL CALLBACK MouseEntropyProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
SPC_MOUSEPOS MousePos;
SPC_DIALOGDATA *pDlgData;
switch (uMsg) {
case WM_INITDIALOG:
pDlgData = (SPC_DIALOGDATA *)lParam;
SetWindowLong(hwndDlg, DWL_USER, lParam);
SendDlgItemMessage(hwndDlg, SPC_PROGRESS_BARID, PBM_SETRANGE32, 0,
pDlgData->cbRequested);
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) = = IDOK && HIWORD(wParam) = = BN_CLICKED) {
EndDialog(hwndDlg, TRUE);
return TRUE;
}
break;
case WM_MOUSEMOVE:
pDlgData = (SPC_DIALOGDATA *)GetWindowLong(hwndDlg, DWL_USER);
if (pDlgData->dEntropy < pDlgData->cbRequested) {
MousePos.ptMousePos.x = LOWORD(lParam);
MousePos.ptMousePos.y = HIWORD(lParam);
MousePos.dwTickCount = GetTickCount( );
ClientToScreen(hwndDlg, &(MousePos.ptMousePos));
CryptHashData(pDlgData->hHash, (BYTE *)&MousePos, sizeof(MousePos), 0);
if ((MousePos.ptMousePos.x != pDlgData->ptLastPos.x ||
MousePos.ptMousePos.y != pDlgData->ptLastPos.y) &&
MousePos.dwTickCount - pDlgData->dwLastTime > 100) {
pDlgData->ptLastPos = MousePos.ptMousePos;
pDlgData->dwLastTime = MousePos.dwTickCount;
pDlgData->dEntropy += SPC_ENTROPY_PER_SAMPLE;
SendDlgItemMessage(hwndDlg, SPC_PROGRESS_BARID, PBM_SETPOS,
(WPARAM)pDlgData->dEntropy, 0);
if (pDlgData->dEntropy >= pDlgData->cbRequested) {
EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE);
SetFocus(GetDlgItem(hwndDlg, IDOK));
MessageBeep(0xFFFFFFFF);
}
}
}
return TRUE;
}
return FALSE;
}
BOOL SpcGatherMouseEntropy(HINSTANCE hInstance, HWND hWndParent,
BYTE *pbOutput, DWORD cbOutput) {
BOOL bResult = FALSE;
BYTE *pbHashData = 0;
DWORD cbHashData, dwByteCount = sizeof(DWORD);
HCRYPTHASH hHash = 0;
HCRYPTPROV hProvider = 0;
SPC_DIALOGDATA DialogData;
if (!CryptAcquireContext(&hProvider, 0, MS_DEF_PROV, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) goto done;
if (!CryptCreateHash(hProvider, CALG_SHA1, 0, 0, &hHash)) goto done;
if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashData, &dwByteCount,
0)) goto done;
if (cbOutput > cbHashData) goto done;
if (!(pbHashData = (BYTE *)LocalAlloc(LMEM_FIXED, cbHashData))) goto done;
DialogData.dEntropy = 0.0;
DialogData.cbRequested = cbOutput * 8;
DialogData.hHash = hHash;
DialogData.dwLastTime = 0;
GetCursorPos(&(DialogData.ptLastPos));
bResult = DialogBoxParam(hInstance, MAKEINTRESOURCE(SPC_MOUSE_DLGID),
hWndParent, MouseEntropyProc, (LPARAM)&DialogData);
if (bResult) {
if (!CryptGetHashParam(hHash, HP_HASHVAL, pbHashData, &cbHashData, 0))
bResult = FALSE;
else
CopyMemory(pbOutput, pbHashData, cbOutput);
}
done:
if (pbHashData) LocalFree(pbHashData);
if (hHash) CryptDestroyHash(hHash);
if (hProvider) CryptReleaseContext(hProvider, 0);
return bResult;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nShowCmd) {
BYTE pbEntropy[20];
INITCOMMONCONTROLSEX CommonControls;
CommonControls.dwSize = sizeof(CommonControls);
CommonControls.dwICC = ICC_PROGRESS_CLASS;
InitCommonControlsEx(&CommonControls);
SpcGatherMouseEntropy(hInstance, 0, pbEntropy, sizeof(pbEntropy));
return 0;
}
如果有人能够了解如何通过.NET实现这一目标(C#或VB.Net很好)将是最有帮助的。
先谢谢。
克里斯
答案 0 :(得分:3)
您不必这样做,Microsoft已经为您完成了这项工作。内置的.NET方法RNGCryptoServiceProvider.GetBytes()提供从Windows CryptGenRandom派生的高质量的真随机字节。引用RFC 4086:
Windows CryptAPI加密服务提供程序存储种子 每个用户的状态变量。当调用CryptGenRandom时,这个 与呼叫中提供的任何随机性以及各种随机性相结合 系统和用户数据,如进程ID,线程ID,系统时钟, 系统时间,系统计数器,内存状态,可用磁盘集群和 散列用户环境块。这些数据都被送到SHA-1和 输出用于为RC4密钥流设定种子。那个关键流是 用于生成请求的伪随机数据并更新 用户的种子状态变量。
Windows“.NET”的用户可能会发现使用它更容易 RNGCryptoServiceProvider.GetBytes方法接口。
没有必要重新发明轮子,它已经为你建造了。