【发布时间】:2015-09-11 05:22:15
【问题描述】:
我需要枚举机器密钥容器中的密钥。虽然这通常是一个可选的提供程序功能,但MS_STRONG_PROV 和MS_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 听起来完全可以接受。