我需要枚举机器密钥容器中的密钥。虽然这通常是一个可选的提供程序功能,但两者都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 倍。任何指针?
我将测试的全部来源放入 Gist。该测试在没有任何加密硬件的非常通用的 Windows 7 机器上运行。
补充:在 Server 2012 HyperV 主机上的 Server 2012 虚拟机上,减速因素甚至更大,超过 130:440 对 3.3 毫秒。确实,440ms 对我来说是一个性能问题。