我在C++中使用DPAPI来加密我需要存储在文件中的一些数据.问题是我需要从C#读取该文件,所以我需要能够:
C++加密,C++解密(工作正常)
C#encrypt,C#decrypt(工作正常)
C++加密,C#解密,反之亦然(不工作)
在C#中我使用DllImport来调用方法CryptProtectData和CryptUnprotectData,我按照这里的解释实现它们.我知道在C#中我可以使用ProtectedData类中包含的方法,但我是这样做的(使用DllImport)来确保两个代码(c ++和c#)的外观和工作方式基本相同.
现在奇怪的是,即使两个代码看起来都相同,我也会得到不同的输出,例如对于这个文本:
"纯文本"
在C++中,我得到:
01 00 00 00 D0 8C 9D DF 01 15 D1 11 8C 7A 00 C0 4F C2 97 EB 01 00 00 00 2E 6F 88 86 E6 16 9B 4F 9B BF 35 DA 9F C6 EC 12 00 00 00 00 02 00 00 00 00 00 03 66 00 00 A8 00 00 00 10 00 00 00 93 06 68 39 DB 58 FE …
CryptProtectMemory
DPAPI中的API允许您传递该CRYPTPROTECTMEMORY_SAME_PROCESS
标志,从而防止其他进程解密内存。解决此问题的一种方法是使用OpenProcess
,WriteProcessMemory
和CreateRemoteThread
将代码注入目标进程并进行调用CryptUnprotectMemory
,从而解密内存并将其泄漏给另一个进程。
假设两个进程都在Windows Vista或更高版本上的同一受限特权用户(即非管理员)的上下文中运行,这是否仍然可能?我给人的印象是,无论进程ACL是什么,进程内存写操作都被限制的用户拒绝,但我可能是错的。
对于密码加密,我想使用ProtectedData
。
据我了解,这是的包装CryptProtectData
。
MSDN仅声明基于用户凭据的加密含糊之处,并且如果用户没有漫游配置文件,则解密通常必须在同一台计算机上完成。
它使用哪种加密算法?
是否有分析指出这种加密是否适合密码存储?
还应该如何实现本地密码存储?
在我的应用程序中,我需要加密各种设置和密码。\n到目前为止,我一直在使用 RijndaelManaged 类等执行此操作,如下所示:
\n\n/// <summary>\n/// Encrypts the string defined by parameter "data" and returns the encrypted data as string\n/// </summary>\n/// <param name="data">Data to be encrypted</param>\n/// <returns>The encrypted data</returns>\npublic static string Encrypt(string data)\n {\n if (data == "")\n return "";\n\n byte[] bytes = Encoding.ASCII.GetBytes(initVector);\n byte[] rgbSalt = Encoding.ASCII.GetBytes(saltValue);\n byte[] buffer = Encoding.UTF8.GetBytes(data);\n byte[] rgbKey = new PasswordDeriveBytes(passPhrase, rgbSalt, hashAlgorithm, passwordIterations).GetBytes(keySize / 8);\n RijndaelManaged managed = new RijndaelManaged();\n managed.Mode = CipherMode.CBC;\n ICryptoTransform transform = managed.CreateEncryptor(rgbKey, bytes);\n MemoryStream memStream = new MemoryStream();\n …
Run Code Online (Sandbox Code Playgroud) 在阅读Microsoft 关于 DPAPI 的文档时,我发现了以下文本:
DPAPI专注于为用户提供数据保护。由于 DPAPI 需要密码来提供保护,因此 DPAPI 的逻辑步骤是使用用户的登录密码,在某种程度上,它确实这样做了。DPAPI 实际上使用用户的登录凭据。在用户使用密码登录的典型系统中,登录凭据只是用户密码的哈希值。
这让我开始思考 - 那些不需要密码的帐户又如何呢?
我指的是Windows和IIS安装的默认帐户,例如NETWORK SERVICE、LOCAL SERVICE、LOCAL SYSTEM、ASPNET。
如果我在这些帐户之一下运行的 Web 应用程序中使用 DPAPI,则 DPAPI MasterKey 将使用什么凭据?
我目前正在编写ac#mvc web应用程序,其中从用户获取密码并存储在数据库中 - sql server.我需要一种散列密码的方法.
建议使用Data Protection API(DPAPI).我不喜欢它和互联网上的研究,很少有信息存在.
任何人都可以指出有关它的进一步信息的方向吗?或者给我一个如何设置和使用它的概述等.
我们有一个加密/解密数据的应用程序DataProtectionScope.LocalMachine
.我们现在必须将范围更改为DataProtectionScope.CurrentUser
.
LocalMachine
当范围更改为时,在范围内加密的现有字符串是否仍然可读CurrentUser
,假设用户当然登录到同一台计算机?
编辑:我写了一个非常快速和肮脏的测试应用程序.奇怪的是,在同一台计算机上,我可以通过LocalMachine和CurrentUser范围解密在LocalMachine或CurrentUser范围内加密的字符串.这听起来不像是正确的行为,帮忙!
private void btnUserEncrypt_Click(object sender, EventArgs e)
{
//encrypt data
var data = Encoding.Unicode.GetBytes(txtUserEncrypt.Text);
byte[] encrypted = ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser);
txtUserEncrypt.Text = Convert.ToBase64String(encrypted);
}
private void btnUserDecrypt_Click(object sender, EventArgs e)
{
byte[] data = Convert.FromBase64String(txtUserDecrypt.Text);
//decrypt data
byte[] decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.CurrentUser);
txtUserDecrypt.Text = Encoding.Unicode.GetString(decrypted);
}
private void btnMachineEncrypt_Click(object sender, EventArgs e)
{
//encrypt data
var data = Encoding.Unicode.GetBytes(txtMachineEncrypt.Text);
byte[] encrypted = ProtectedData.Protect(data, null, DataProtectionScope.LocalMachine);
txtMachineEncrypt.Text = Convert.ToBase64String(encrypted);
}
private …
Run Code Online (Sandbox Code Playgroud) 我想知道是否有人在Web场环境中成功使用DPAPI和用户存储?
因为我们的应用程序是最近从1.1转换为2.0的ASP.NET应用程序,所以我们使用直接调用CryptUnprotect
方法的自定义包装器.但这应该ProtectedData
与2.0框架中可用的方法相同.
因为我们在Web场环境中运行,所以我们无法保证执行加密的计算机将是解密它的计算机.(也因为机器故障不应该破坏我们的加密数据).
所以我们拥有的是一个服务组件,它在我们每个Web框上的特定用户帐户下运行.根据推荐,此用户设置为具有漫游配置文件.
我们遇到的问题是在一台机器上加密的信息无法在另一台机器上解密,这会因win32错误而失败:
'密钥无法在指定状态下使用'.
我怀疑这是因为我在多台机器上将加密服务作为用户运行时犯了一个错误,因此保持用户同时登录多台计算机.
如果这是问题,那么在Web场环境中如何使用DPAPI和User Store?
SignalR使用Azure Web角色大量扩展.但是,当我在Azure辅助角色中使用自托管OWIN项目时,SignalR将在添加多个实例时开始出现问题.为了记录,我的项目使用Redis作为背板.
将Azure辅助角色实例增加到一个以上时,客户端连接将随机失败,并显示错误"ConnectionId格式不正确".我相信这是由于负载均衡导致单个客户端的协商跨越多个服务器时引起的; 我不相信参与协商的多台服务器可以解密数据(DPAPI在封面下?).
我尝试在app.config中设置<machineKey /> validationKey和decryptionKey,但这似乎没有什么区别; 问题依然存在.同样,该项目将作为Web角色(IIS)正常工作,但不能作为工作者角色(OWIN自托管).
假设这是DpapiDataProtectionProvider的问题,我如何确保提供程序在多个服务器/实例之间呈现相同的加密/解密结果?
解
SignalR(DpapiDataProtectionProvider)使用的默认保护提供程序似乎不支持Azure Worker Role scaleout.通过滚动我自己的示例提供程序,我能够扩展SignalR/OWIN/Azure Worker并且不会收到随机400 HTTP /"ConnectionId的格式不正确".请记住,以下示例不会保护/保护令牌.
public class ExampleDataProvider : IDataProtector
{
public byte[] Protect(byte[] userData)
{
Trace.TraceInformation("Protect called: " + Convert.ToBase64String(userData));
return userData;
}
public byte[] Unprotect(byte[] protectedData)
{
Trace.TraceInformation("Unprotect called: " + Convert.ToBase64String(protectedData));
return protectedData;
}
}
public class ExampleProtectionProvider : IDataProtectionProvider
{
public IDataProtector Create(params string[] purposes)
{
Trace.TraceInformation("Example Protection Provider Created");
return new ExampleDataProvider();
}
}
Run Code Online (Sandbox Code Playgroud)
在Owin启动期间注入自定义提供程序:
public class Startup
{
public void …
Run Code Online (Sandbox Code Playgroud) 我有这个代码来存储和恢复授权令牌(字母数字):
public static void Store (string token)
{
byte[] buffer = Encoding.UTF8.GetBytes (token.PadRight (32));
ProtectedMemory.Protect (buffer, MemoryProtectionScope.SameLogon);
Settings.Default.UserToken = buffer.ToHexString ();
Settings.Default.Save ();
}
public static string Retrieve ()
{
byte[] buffer = Settings.Default.UserToken.FromHexString ();
if (buffer.Length == 0)
return String.Empty;
ProtectedMemory.Unprotect (buffer, MemoryProtectionScope.SameLogon);
return Encoding.UTF8.GetString (buffer).Trim ();
}
Run Code Online (Sandbox Code Playgroud)
它大部分工作正常,尽管有时我会得到垃圾(很多FD
字节,和一些可读的字节)。我怀疑只有当我重新启动时才会发生这种情况,但我在重现它时遇到了一些困难。
这是预期的行为吗?也就是说,是否MemoryProtectionScope.SameLogon
意味着重启后数据将始终无法读取?难道我做错了什么?
和FromHexString
方法ToHexString
完全符合您的期望。
我尝试过使用UTF8算法和SHA256进行密码加密,但建议不要使用它们.相反,我被建议使用DPAPI.我浏览了一些谷歌的示例代码并不清楚.你能帮我解决DPAPI算法吗?
我知道ProtectedData类最终会调用 Windows 的数据保护 API (DPAPI)。DPAPI 函数的文档提供了诸如密钥存储位置、谁可以解密数据等详细信息。但是,我无法找到任何有关实际底层加密算法是什么的文档。(我需要了解安全文档保护方法的详细信息,以供即将进行的审核)。这只是使用 AES 还是类似的东西?这有多安全?
我正在尝试从我的 Chrome 浏览器获取会话。我可以在开发人员工具中看到 2 个 cookie 文件。但这对于用户从浏览器获取 cookie 值来说很不方便,我想用代码来做。所以我使用此代码来获取 Chrome 默认配置文件 cookie sqlite DB:
string local = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string path = @"Google\Chrome\User Data\Default\Cookies";
path = Path.Combine(local, path);
Run Code Online (Sandbox Code Playgroud)
接下来我创建 SQLite 连接和请求
var cmd = new SQLiteCommand("SELECT encrypted_value, name FROM cookies WHERE host_key = 'my_host_ip'", con);
Run Code Online (Sandbox Code Playgroud)
然后我读了结果
byte[] encryptedCookie = (byte[])r.GetValue(r.GetOrdinal("encrypted_value"));
Run Code Online (Sandbox Code Playgroud)
并尝试解密它:
var decodedData = ProtectedData.Unprotect(encryptedCookie, null, DataProtectionScope.CurrentUser);
var plainText = Encoding.ASCII.GetString(decodedData);
Run Code Online (Sandbox Code Playgroud)
在这里我有例外
System.Security.Cryptography.CryptographicException
我知道我必须在启动浏览器的同一用户帐户下(在同一台机器上)解密 cookie 内容,并且参数DataProtectionScope.CurrentUser
用于
我在调试器中看到 63 个字节(在encryptedCookie
数组中),我也在 SQLite DB BLOB 字段中看到了这个字节。但Unprotect
方法抛出System.Security.Cryptography.CryptographicException: Invalid …