使用鼠标移动和击键生成加密熵(如MEGA所示)

时间:2013-01-20 23:24:59

标签: .net encryption random entropy

我有兴趣从.NET中的鼠标移动和击键生成熵(为了加密的目的,这可以在Forms应用程序中,其中鼠标移动和击键数据通过应用程序本身或Web中的事件接收使用JavaScript记录鼠标移动和击键数据并通过Ajax发送到服务器的应用程序。

这项技术目前正在新的MEGA网站上使用。

我自己做了一些研究,并且在C ++中看到了一个很好的例子,但它有点超出我的C / C ++知识。

http://etutorials.org/Programming/secure+programming/Chapter+11.+Random+Numbers/11.21+Gathering+Entropy+from+Mouse+Events+on+Windows/

    #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很好)将是最有帮助的。

先谢谢。

克里斯

1 个答案:

答案 0 :(得分:3)

您不必这样做,Microsoft已经为您完成了这项工作。内置的.NET方法RNGCryptoServiceProvider.GetBytes()提供从Windows CryptGenRandom派生的高质量的真随机字节。引用RFC 4086:

  

Windows CryptAPI加密服务提供程序存储种子      每个用户的状态变量。当调用CryptGenRandom时,这个      与呼叫中提供的任何随机性以及各种随机性相结合      系统和用户数据,如进程ID,线程ID,系统时钟,      系统时间,系统计数器,内存状态,可用磁盘集群和      散列用户环境块。这些数据都被送到SHA-1和      输出用于为RC4密钥流设定种子。那个关键流是      用于生成请求的伪随机数据并更新      用户的种子状态变量。

     

Windows“.NET”的用户可能会发现使用它更容易      RNGCryptoServiceProvider.GetBytes方法接口。

没有必要重新发明轮子,它已经为你建造了。

相关问题