【问题标题】:Slow key enumeration in a machine RSA key container机器 RSA 密钥容器中的慢速密钥枚举
【发布时间】:2015-09-11 05:22:15
【问题描述】:

我需要枚举机器密钥容器中的密钥。虽然这通常是一个可选的提供程序功能,但MS_STRONG_PROVMS_ENH_RSA_AES_PROV 都支持它。我不认为我做错了什么或异常:首先,使用CryptAcquireContext(... CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT ...) 获取上下文句柄,然后反复调用CryptGetProvParam(... PP_ENUMCONTAINERS ...),直到枚举耗尽:

void enum_keys(HCRYPTPROV hprov) {
  BYTE buf[1024];  // Max key name length we support.
  for (DWORD first_next = CRYPT_FIRST; 1; first_next = CRYPT_NEXT) {
    DWORD buf_len = sizeof buf;
    if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, buf, &buf_len, first_next)) {
      if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
      else exit(1);
    }
  }
}

void do_benchmark(DWORD enum_flags) {
  enum_flags |= CRYPT_VERIFYCONTEXT;
  HCRYPTPROV hprov;
  if (!CryptAcquireContext(&hprov, NULL, MS_ENH_RSA_AES_PROV_A,
                           PROV_RSA_AES, enum_flags))
    exit(1);

  int K = 100;
  ClockIn();  // Pseudocode
  for (int i = 0; i < K; ++i)
    enum_keys (hprov);
  ClockOut();  // Pseudocode.
  printf(" %f ms per pass\n", TimeElapsed() / K);

  CryptReleaseContext(hprov, 0);
}

void main() {
  printf("--- User key store access performance test... ");
  do_benchmark(0);
  printf("--- Machine key store access performance test... ");
  do_benchmark(CRYPT_MACHINE_KEYSET);
}

为了对枚举进行基准测试,我将上下文获取和释放排除在循环之外,只对枚举进行计时,并重复枚举 100 次。我注意到的是,普通用户的枚举速度比管理员慢得多。当我以自己(启用 UAC 的管理员成员)身份运行测试时,我得到了

--- User key store access performance test...  3.317211 ms per pass
--- Machine key store access performance test...  78.051593 ms per pass

但是,当我从提升的提示符下运行相同的测试时,结果却大不相同:

--- User key store access performance test...  3.279580 ms per pass
--- Machine key store access performance test...  1.499939 ms per pass

在后台,向管理员报告的密钥比向非管理员用户报告的多,但这是意料之中且正常的。我不明白为什么非管理员用户的枚举速度要慢 40 倍。有什么指点吗?

我正在输入完整的source of my test into a Gist。该测试在没有任何加密硬件的非常通用的 Windows 7 机器上运行。

添加:在 Server 2012 HyperV 主机上的 Server 2012 虚拟机上,减速因素甚至更大,超过 130:440 对 3.3 毫秒。确实,440 毫秒对我来说是一个性能问题。

【问题讨论】:

  • 请不要链接到站外内容。如果代码对您的问题很重要(通常很重要),请将其放在您的问题中。
  • @IInspectable:谢谢,我不知道问题中不允许链接。事实上,SO 在询问时甚至会出现一个“插入链接”按钮。如果您能给我一个指向规则的指针,我将不胜感激。但主要是,我被撕裂了。事实上,这是一个大约 60 行的程序,你可以说其中没有什么是必要的:说“我正在以一种应该的方式枚举键”就足够了,但应该引出一个“至少向我展示一些你的代码”跟进);另一方面,一切对于快速复制都是必不可少的。您是否建议将完整的来源发布到问题中?
  • 不严格禁止链接到非现场内容。然而,关于 stackoverflow 的问题应该是独立的。如果异地资源暂时不可用或永久消失,则问题可能不再有用。可以在How do I ask a good question? 找到指南我建议在您现在链接到它的地方添加整个源代码。您观察到的效果可能是由您的代码引起的,也可能不是。不看代码就很难提供好的答案。
  • @IInspectable:啊,现在我想我明白了规则的精神。 “自给自足”是试金石。我希望我当时做对了(但如果我弄错了请告诉我):我认为我的问题 is 是独立的,没有代码,因为第一段简要描述了我所做的事情,并且代码类似于 M&M 披露,这将有助于那些想要(我希望!)深入挖掘的人。在重现有趣的问题时,我经常希望拥有完整的源代码,而不仅仅是 MCVE!总而言之,我非常感谢您的反馈。我将添加一个 MCVE,但保留指向 Gist 的链接。非常感谢!
  • 枚举了多少键?如果只有 1,可能有问题,如果有 1000 万,那么 400ms 听起来完全可以接受。

标签: winapi cryptoapi mscapi


【解决方案1】:

可能与微软的这个问题有关:

You experience poor performance when you call the CryptAcquireContext function in Windows Server 2008 R2 or in Windows 7

从问题: "出现此问题是因为 Windows Server 2008 R2 和 Windows 7 中的 CryptAcquireContext 函数发生了变化。

此更改检查函数是否在域环境中运行。但是,该过程非常耗时,并导致 CryptAcquireContext 函数的运行时间增加。”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-17
    • 2012-09-13
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    相关资源
    最近更新 更多