用 Windows 存储密码 你好
store password with Windows Hello
我想使用 Windows Hello
存储和检索密码。用户可以在登录时选择是手动输入密码,还是使用Windows Hello
解锁(然后检索上次使用的密码,并为用户填写)。
如果 Windows Hello
设置正确,文档中有两个用例。
一个刚刚解锁:
UserConsentVerificationResult consentResult = await UserConsentVerifier.RequestVerificationAsync("userMessage");
if (consentResult.Equals(UserConsentVerificationResult.Verified))
{
// continue
}
还有一个用于签署来自服务器的消息:
var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);
if (openKeyResult.Status == KeyCredentialStatus.Success)
{
var userKey = openKeyResult.Credential;
var publicKey = userKey.RetrievePublicKey();
//the message is the challenge from the server
var signResult = await userKey.RequestSignAsync(message);
if (signResult.Status == KeyCredentialStatus.Success)
{
//the with the private key of the user signed message
return signResult.Result;
}
}
两者对我的用例都不是很有用:我想要一种对称的方式来存储和检索密码。
我的问题简而言之:
有没有办法用Windows Hello
对称存储数据?
相关文档:
https://docs.microsoft.com/en-us/windows/uwp/security/microsoft-passport
您可以按如下方式使用 PasswordVault 来设置密码:
private void SetPassword(string password, string userName)
{
PasswordVault myVault = new PasswordVault();
myVault.Add(new PasswordCredential("Your App ID", userName, password));
}
删除密码:
private void RemovePassword(string userName)
{
PasswordVault myVault = new PasswordVault();
var password = myVault.Retrieve("Your App ID", userName);
if (password != null)
myVault.Remove(password);
}
如果你想和Windows一起使用你好:
public async Task<string> SignInAsync(string userName)
{
var result = await UserConsentVerifier.RequestVerificationAsync(requestMessage);
if (result != UserConsentVerificationResult.Verified)
return null;
var vault = new PasswordVault();
var credentials = vault.Retrieve("Your App ID", userName);
return credentials?.Password;
}
这将在访问密码值之前检查Windows你好
我已经通过使用 Windows 生成的密码加密/解密我想存储的秘密来解决这个问题 你好。密码是固定消息上的签名。
一个完整的代码示例(未经测试)来说明我的观点:
const accountId = "A ID for this key";
const challenge = "sign this challenge using Windows Hello to get a secure string";
public async Task<byte[]> GetSecureEncryptionKey() {
// if first time; we first need to create a key
if (firstTime) {
if (!await this.CreateKeyAsync()) {
return null;
}
}
// get the key using Windows Hellp
return await this.GetKeyAsync();
}
private async Task<bool> CreateKeyAsync() {
if (!await KeyCredentialManager.IsSupportedAsync()) {
return false;
}
// if app opened for the first time, we need to create an account first
var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(AccountId, KeyCredentialCreationOption.ReplaceExisting);
return keyCreationResult.Status == KeyCredentialStatus.Success);
}
private async Task<byte[]> GetKeyAsync() {
var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);
if (openKeyResult.Status == KeyCredentialStatus.Success)
{
// convert our string challenge to be able to sign it
var buffer = CryptographicBuffer.ConvertStringToBinary(
challenge, BinaryStringEncoding.Utf8
);
// request a sign from the user
var signResult = await openKeyResult.Credential.RequestSignAsync(buffer);
// if successful, we can use that signature as a key
if (signResult.Status == KeyCredentialStatus.Success)
{
return signResult.Result.ToArray();
}
}
return null;
}
full source 在 github 上,展示了我如何将这些概念整合到应用程序中。
但是,这会滥用用于不同目的的密码原语,这是非常危险的。在求助于此解决方法之前,请考虑寻找更合理的方法。
具体注意事项:
- 这假设签名不是随机的。 Windows 你好,目前就是这种情况,但将来可能会改变。
- 使用签名作为密钥时,确保使用整个签名。如果 encryption/decryption 密钥需要 256 位,您可以使用 SHA-256 算法将签名映射到密钥,例如:
key = sha256(signature);
我想使用 Windows Hello
存储和检索密码。用户可以在登录时选择是手动输入密码,还是使用Windows Hello
解锁(然后检索上次使用的密码,并为用户填写)。
如果 Windows Hello
设置正确,文档中有两个用例。
一个刚刚解锁:
UserConsentVerificationResult consentResult = await UserConsentVerifier.RequestVerificationAsync("userMessage");
if (consentResult.Equals(UserConsentVerificationResult.Verified))
{
// continue
}
还有一个用于签署来自服务器的消息:
var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);
if (openKeyResult.Status == KeyCredentialStatus.Success)
{
var userKey = openKeyResult.Credential;
var publicKey = userKey.RetrievePublicKey();
//the message is the challenge from the server
var signResult = await userKey.RequestSignAsync(message);
if (signResult.Status == KeyCredentialStatus.Success)
{
//the with the private key of the user signed message
return signResult.Result;
}
}
两者对我的用例都不是很有用:我想要一种对称的方式来存储和检索密码。
我的问题简而言之:
有没有办法用Windows Hello
对称存储数据?
相关文档:
https://docs.microsoft.com/en-us/windows/uwp/security/microsoft-passport
您可以按如下方式使用 PasswordVault 来设置密码:
private void SetPassword(string password, string userName)
{
PasswordVault myVault = new PasswordVault();
myVault.Add(new PasswordCredential("Your App ID", userName, password));
}
删除密码:
private void RemovePassword(string userName)
{
PasswordVault myVault = new PasswordVault();
var password = myVault.Retrieve("Your App ID", userName);
if (password != null)
myVault.Remove(password);
}
如果你想和Windows一起使用你好:
public async Task<string> SignInAsync(string userName)
{
var result = await UserConsentVerifier.RequestVerificationAsync(requestMessage);
if (result != UserConsentVerificationResult.Verified)
return null;
var vault = new PasswordVault();
var credentials = vault.Retrieve("Your App ID", userName);
return credentials?.Password;
}
这将在访问密码值之前检查Windows你好
我已经通过使用 Windows 生成的密码加密/解密我想存储的秘密来解决这个问题 你好。密码是固定消息上的签名。
一个完整的代码示例(未经测试)来说明我的观点:
const accountId = "A ID for this key";
const challenge = "sign this challenge using Windows Hello to get a secure string";
public async Task<byte[]> GetSecureEncryptionKey() {
// if first time; we first need to create a key
if (firstTime) {
if (!await this.CreateKeyAsync()) {
return null;
}
}
// get the key using Windows Hellp
return await this.GetKeyAsync();
}
private async Task<bool> CreateKeyAsync() {
if (!await KeyCredentialManager.IsSupportedAsync()) {
return false;
}
// if app opened for the first time, we need to create an account first
var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(AccountId, KeyCredentialCreationOption.ReplaceExisting);
return keyCreationResult.Status == KeyCredentialStatus.Success);
}
private async Task<byte[]> GetKeyAsync() {
var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);
if (openKeyResult.Status == KeyCredentialStatus.Success)
{
// convert our string challenge to be able to sign it
var buffer = CryptographicBuffer.ConvertStringToBinary(
challenge, BinaryStringEncoding.Utf8
);
// request a sign from the user
var signResult = await openKeyResult.Credential.RequestSignAsync(buffer);
// if successful, we can use that signature as a key
if (signResult.Status == KeyCredentialStatus.Success)
{
return signResult.Result.ToArray();
}
}
return null;
}
full source 在 github 上,展示了我如何将这些概念整合到应用程序中。
但是,这会滥用用于不同目的的密码原语,这是非常危险的。在求助于此解决方法之前,请考虑寻找更合理的方法。
具体注意事项:
- 这假设签名不是随机的。 Windows 你好,目前就是这种情况,但将来可能会改变。
- 使用签名作为密钥时,确保使用整个签名。如果 encryption/decryption 密钥需要 256 位,您可以使用 SHA-256 算法将签名映射到密钥,例如:
key = sha256(signature);