在 win 7 下使用命名密钥容器更改密码混乱
在某些运行 Windows 7 的系统上,我们在其中生成了密钥 名称密钥容器,如果我们更改用户的密码,当我们调用 CryptAcquireCertificatePrivateKey() 我们得到一个错误 CRYPT_E_NO_KEY_PROPERTY (0x8009200B)。
并非所有盒子都会出现这种情况。我们最初认为这是与不在网络上的域计算机有关的东西,并且它无法刷新它域的东西,但我们让它在一些独立的计算机上重现。
我在这里读取密钥的代码
if((StoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, QWARQ_CERT_STORE_NAME)) != NULL)
{
/* Look for certificate with matching user guid. */
if((CertContext = CertFindCertificateInStore(StoreHandle,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR,DataBuffer, NULL)) != NULL)
{
if(CryptAcquireCertificatePrivateKey(CertContext, 0,NULL, &CryptProvHandle, &KeySpec, &FreeHandle))
{
}
else
{
DWORD dwError=GetLastError(); //CRYPT_E_NO_KEY_PROPERTY
}
}
}
是生成密钥/密钥容器的代码
if(CryptAcquireContext(&hCryptProv,KEY_CONTAINER_NAME, NULL,PROV_RSA_FULL, 0) == FALSE) //CRYPT_NEWKEYSET
{
DWORD result = GetLastError();
if (NTE_BAD_KEY_STATE == result)
{
DebugLogging::DbgPrintF(TEXT("[CertInitialization] NTE_BAD_KEY_STATE - user has changed his password \n"), result);
return false;
}
else if (NTE_BAD_KEYSET != result)
{
DebugLogging::DbgPrintF(TEXT("[CertInitialization] could not acquire CSP[0x%x]\n"), result);
return false;
}
if(CryptAcquireContext(&hCryptProv, KEY_CONTAINER_NAME, NULL,PROV_RSA_FULL, CRYPT_NEWKEYSET) == FALSE) //CRYPT_NEWKEYSET
{
DWORD result = GetLastError();
DebugLogging::DbgPrintF(TEXT("[CertInitialization] could not acquire CSP from new keyset[0x%x]\n"), result);
return false;
}
}
if(CryptGenKey(hCryptProv, AT_KEYEXCHANGE, RSA2048BIT_KEY |CRYPT_EXPORTABLE, &hKey)== FALSE)
{
DebugLogging::DbgPrintF(TEXT("CertGeneration() could not generate key[%d]\n"),GetLastError());
return false;
}
On some systems running Windows 7 where we've generated a key in a
name key container, if we change the user's password, when we call
CryptAcquireCertificatePrivateKey() we get an error
CRYPT_E_NO_KEY_PROPERTY (0x8009200B).
This doesn't happen on all boxes. We orginally thought it was something to w/ a domain machine not on the network and there it couldn't refresh it domain stuff, but we got it to reproduce on some standalone machines.
My code for reading the key
if((StoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, QWARQ_CERT_STORE_NAME)) != NULL)
{
/* Look for certificate with matching user guid. */
if((CertContext = CertFindCertificateInStore(StoreHandle,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR,DataBuffer, NULL)) != NULL)
{
if(CryptAcquireCertificatePrivateKey(CertContext, 0,NULL, &CryptProvHandle, &KeySpec, &FreeHandle))
{
}
else
{
DWORD dwError=GetLastError(); //CRYPT_E_NO_KEY_PROPERTY
}
}
}
here is code that generates the key/key container
if(CryptAcquireContext(&hCryptProv,KEY_CONTAINER_NAME, NULL,PROV_RSA_FULL, 0) == FALSE) //CRYPT_NEWKEYSET
{
DWORD result = GetLastError();
if (NTE_BAD_KEY_STATE == result)
{
DebugLogging::DbgPrintF(TEXT("[CertInitialization] NTE_BAD_KEY_STATE - user has changed his password \n"), result);
return false;
}
else if (NTE_BAD_KEYSET != result)
{
DebugLogging::DbgPrintF(TEXT("[CertInitialization] could not acquire CSP[0x%x]\n"), result);
return false;
}
if(CryptAcquireContext(&hCryptProv, KEY_CONTAINER_NAME, NULL,PROV_RSA_FULL, CRYPT_NEWKEYSET) == FALSE) //CRYPT_NEWKEYSET
{
DWORD result = GetLastError();
DebugLogging::DbgPrintF(TEXT("[CertInitialization] could not acquire CSP from new keyset[0x%x]\n"), result);
return false;
}
}
if(CryptGenKey(hCryptProv, AT_KEYEXCHANGE, RSA2048BIT_KEY |CRYPT_EXPORTABLE, &hKey)== FALSE)
{
DebugLogging::DbgPrintF(TEXT("CertGeneration() could not generate key[%d]\n"),GetLastError());
return false;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
了解有关 DPAPI 的更多信息后
密码更改
在此方法中,在密码更改期间可以连续访问用户的主密钥。在 Active Directory 域中进行密码更改操作期间,Winlogon 组件会调用 DPAPI:
密码重置(设置)
在该方法中,管理员强制重置用户密码。密码重置比更改密码更复杂。由于管理员未以用户身份登录,并且无权访问用户的旧密码,因此旧密码无法用于解密旧主密钥并使用新密码重新加密。
After learning more about DPAPI
Password Change
In this method, there is continuity of access to the user's master keys during a password change. The DPAPI is invoked by the Winlogon component during password change operations in an Active Directory domain:
Password Reset (Set)
In this method, an administrator forcibly resets a user password. A password reset is more complex than a password change. Because the administrator is not logged on as the user and does not have access to the user's old password, that old password cannot be used to decrypt the old master key and re-encrypt it with the new password.