消息处理程序中的RAND_event()是否会导致UI中的小冻结? 有一个消息处理程序(在C++ Builder中),像这样: void __fastcall TMainForm::HandleMessages(tagMSG &Msg, bool &Handled) { RAND_event(Msg.message, Msg.wParam, Msg.lParam); //... }

消息处理程序中的RAND_event()是否会导致UI中的小冻结? 有一个消息处理程序(在C++ Builder中),像这样: void __fastcall TMainForm::HandleMessages(tagMSG &Msg, bool &Handled) { RAND_event(Msg.message, Msg.wParam, Msg.lParam); //... },c++,windows,winapi,openssl,c++builder,C++,Windows,Winapi,Openssl,C++builder,RAND\u event()会不会在UI中造成一些冻结 谢谢 编辑: RAND\u event()来自OpenSSL,下面是它的描述: RAND\u event()从Windows事件(如鼠标)收集熵 移动和其他用户交互。它应该被称为 发送到窗口的所有消息的iMsg、wParam和lParam参数 程序它将估计事件消息中包含的熵 (如有),并将其添加到PRNG中。然后程序可以处理 像往常一样发短信 当有疑问时-验证源代码 来自\crypto\rand\rand\u win.c(OpenSSL 1

RAND\u event()
会不会在UI中造成一些冻结

谢谢

编辑:

RAND\u event()
来自OpenSSL,下面是它的描述:

RAND\u event()
从Windows事件(如鼠标)收集熵 移动和其他用户交互。它应该被称为 发送到窗口的所有消息的iMsg、wParam和lParam参数 程序它将估计事件消息中包含的熵 (如有),并将其添加到PRNG中。然后程序可以处理 像往常一样发短信


当有疑问时-验证源代码

来自
\crypto\rand\rand\u win.c
(OpenSSL 1.0.2f)

正如您所看到的,这里没有循环、等待或类似的事情,只有一些基本的比较、分配和添加。您还可以自己验证
RAND_event()
中使用的一些函数,如
readtimer()
,但它们也不包含任何可能导致性能显著降低的内容(至少与使用UI相比)

编辑:
啊,我刚才看到了雷米的评论,我的错。无论如何,我将此作为一个扩展的答案(已经作为注释存在)保留在一个稍微(非常小)不同的视图中。

如果有疑问,请验证源代码

来自
\crypto\rand\rand\u win.c
(OpenSSL 1.0.2f)

正如您所看到的,这里没有循环、等待或类似的事情,只有一些基本的比较、分配和添加。您还可以自己验证
RAND_event()
中使用的一些函数,如
readtimer()
,但它们也不包含任何可能导致性能显著降低的内容(至少与使用UI相比)

编辑: 啊,我刚才看到了雷米的评论,我的错。不管怎么说,我把它作为一个扩展的答案(已经作为一个评论存在)从一个小(非常小)点不同的观点

RAND_event()是否会导致UI中的小冻结

也许吧。熵是通过
RAND_add
添加的,这意味着熵被提取然后被消化。因此,每次调用
RAND\u add
时都会调用一个哈希函数

如果您使用的是默认的RAND引擎,则使用的引擎是
\crypto\RAND\md\u RAND.c
中的引擎。这意味着
RAND\u add
调用
ssleay\u RAND\u add
。功能如下所示

如果发送了大量Windows消息,那么我可以想象桌面在消化熵的同时速度会变慢。在移动操作系统上,这个问题可能会变得更加严重。分析工具应该能够为您提供更多信息


我认为Windows上的
RAND\u事件
可能有一个优化。。。消息应累积,然后批量添加。也就是说,累积熵,然后在第8次、第16次或第32次调用时调用
RAND\u add

生成器的运行状况应该不会受到影响,因为有太多的Windows消息发送到应用程序。您可以使用来了解发送的邮件数量


如果您在某处使用
RAND\u poll
,则可以看到一个明显的块。有关这方面的详细信息,请参阅OpenSSL错误跟踪器上的


static void ssleay\u rand\u add(const void*buf,int num,double add)
{
int i,j,k,st_idx;
长md_c[2];
无符号字符local_md[md_DIGEST_LENGTH];
执行副总裁MD CTX m;
int不锁定;
如果(!num)
返回;
/*
*(基于rand(3)手册页)
*
*输入被切碎为20字节的单位(对于
*最后一个块)。这些块中的每一个都通过散列运行
*函数如下:传递给哈希函数的数据
*是当前的“md”,与“状态”中的字节数相同
*(在递增循环索引中确定的位置)为
*当前“块”、新密钥数据“块”和“计数”
*(每次使用后递增)。
*此操作的结果保存在“md”中,也被xored到
*“状态”位于用作输入的相同位置
*散列函数。
*/
/*检查一下我们是否已经有锁了*/
if(加密锁){
加密线程ID cur;
加密线程ID当前(&cur);
加密锁(CRYPTO_lock_RAND2);
do_not_lock=!CRYPTO_THREADID_cmp(&locking_THREADID,&cur);
加密锁解锁(加密锁RAND2);
}否则
不锁定=0;
如果(!不锁定)
加密锁(加密锁);
st_idx=状态指数;
/*
*使用我们自己的计数器副本,这样即使是并发线程
*种子具有完全相同的数据,并使用相同的子数组
*有些不同
*/
md_c[0]=md_计数[0];
md_c[1]=md_计数[1];
memcpy(本地医学博士、医学博士、医学博士学位);
/*状态\索引状态\数量)
state_num=state_索引;
}
/*州(索引、摘要、长度)?MD_摘要_长度:j;
MD_Init(&m);
MD_更新(&m、本地MD、MD_摘要长度);
k=(st_idx+j)-状态大小;
如果(k>0){
MD_更新(&m,&(州[st_idx]),j-k;
MD_更新(&m,&(状态[0]),k);
}否则
MD_更新(&m)和(州[st_idx]),j;
/*不要删除对MD_Update()的以下调用*/
MD_更新(&m,buf,j);
/*
*我们知道该行可能导致purify和valgrind等程序
*投诉未初始化数据的使用。问题不是,,
*是打电话的人。拆下那条线会确保你得到
*非常糟糕的随机性和其他问题,例如
*不安全的密钥。
*/
MD_Update(&m,(unsigned char*)和(MD_c[0]),sizeof(MD_c));
MD_最终和m,本地
int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    double add_entropy = 0;

    switch (iMsg) {
    case WM_KEYDOWN:
        {
            static WPARAM key;
            if (key != wParam)
                add_entropy = 0.05;
            key = wParam;
        }
        break;
    case WM_MOUSEMOVE:
        {
            static int lastx, lasty, lastdx, lastdy;
            int x, y, dx, dy;

            x = LOWORD(lParam);
            y = HIWORD(lParam);
            dx = lastx - x;
            dy = lasty - y;
            if (dx != 0 && dy != 0 && dx - lastdx != 0 && dy - lastdy != 0)
                add_entropy = .2;
            lastx = x, lasty = y;
            lastdx = dx, lastdy = dy;
        }
        break;
    }

    readtimer();
    RAND_add(&iMsg, sizeof(iMsg), add_entropy);
    RAND_add(&wParam, sizeof(wParam), 0);
    RAND_add(&lParam, sizeof(lParam), 0);

    return (RAND_status());
}
static void ssleay_rand_add(const void *buf, int num, double add)
{
    int i, j, k, st_idx;
    long md_c[2];
    unsigned char local_md[MD_DIGEST_LENGTH];
    EVP_MD_CTX m;
    int do_not_lock;

    if (!num)
        return;

    /*
     * (Based on the rand(3) manpage)
     *
     * The input is chopped up into units of 20 bytes (or less for
     * the last block).  Each of these blocks is run through the hash
     * function as follows:  The data passed to the hash function
     * is the current 'md', the same number of bytes from the 'state'
     * (the location determined by in incremented looping index) as
     * the current 'block', the new key data 'block', and 'count'
     * (which is incremented after each use).
     * The result of this is kept in 'md' and also xored into the
     * 'state' at the same locations that were used as input into the
     * hash function.
     */

    /* check if we already have the lock */
    if (crypto_lock_rand) {
        CRYPTO_THREADID cur;
        CRYPTO_THREADID_current(&cur);
        CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
        do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur);
        CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
    } else
        do_not_lock = 0;

    if (!do_not_lock)
        CRYPTO_w_lock(CRYPTO_LOCK_RAND);
    st_idx = state_index;

    /*
     * use our own copies of the counters so that even if a concurrent thread
     * seeds with exactly the same data and uses the same subarray there's
     * _some_ difference
     */
    md_c[0] = md_count[0];
    md_c[1] = md_count[1];

    memcpy(local_md, md, sizeof md);

    /* state_index <= state_num <= STATE_SIZE */
    state_index += num;
    if (state_index >= STATE_SIZE) {
        state_index %= STATE_SIZE;
        state_num = STATE_SIZE;
    } else if (state_num < STATE_SIZE) {
        if (state_index > state_num)
            state_num = state_index;
    }
    /* state_index <= state_num <= STATE_SIZE */

    /*
     * state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE] are what we
     * will use now, but other threads may use them as well
     */

    md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);

    if (!do_not_lock)
        CRYPTO_w_unlock(CRYPTO_LOCK_RAND);

    EVP_MD_CTX_init(&m);
    for (i = 0; i < num; i += MD_DIGEST_LENGTH) {
        j = (num - i);
        j = (j > MD_DIGEST_LENGTH) ? MD_DIGEST_LENGTH : j;

        MD_Init(&m);
        MD_Update(&m, local_md, MD_DIGEST_LENGTH);
        k = (st_idx + j) - STATE_SIZE;
        if (k > 0) {
            MD_Update(&m, &(state[st_idx]), j - k);
            MD_Update(&m, &(state[0]), k);
        } else
            MD_Update(&m, &(state[st_idx]), j);

        /* DO NOT REMOVE THE FOLLOWING CALL TO MD_Update()! */
        MD_Update(&m, buf, j);
        /*
         * We know that line may cause programs such as purify and valgrind
         * to complain about use of uninitialized data.  The problem is not,
         * it's with the caller.  Removing that line will make sure you get
         * really bad randomness and thereby other problems such as very
         * insecure keys.
         */

        MD_Update(&m, (unsigned char *)&(md_c[0]), sizeof(md_c));
        MD_Final(&m, local_md);
        md_c[1]++;

        buf = (const char *)buf + j;

        for (k = 0; k < j; k++) {
            /*
             * Parallel threads may interfere with this, but always each byte
             * of the new state is the XOR of some previous value of its and
             * local_md (itermediate values may be lost). Alway using locking
             * could hurt performance more than necessary given that
             * conflicts occur only when the total seeding is longer than the
             * random state.
             */
            state[st_idx++] ^= local_md[k];
            if (st_idx >= STATE_SIZE)
                st_idx = 0;
        }
    }
    EVP_MD_CTX_cleanup(&m);

    if (!do_not_lock)
        CRYPTO_w_lock(CRYPTO_LOCK_RAND);
    /*
     * Don't just copy back local_md into md -- this could mean that other
     * thread's seeding remains without effect (except for the incremented
     * counter).  By XORing it we keep at least as much entropy as fits into
     * md.
     */
    for (k = 0; k < (int)sizeof(md); k++) {
        md[k] ^= local_md[k];
    }
    if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
        entropy += add;
    if (!do_not_lock)
        CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}