我有一个c ++应用程序(32位),它将输入一个字符串,使用名为WriteProtectedStringValueToRegistry的代码块加密它
LONG WriteProtectedStringValueToRegistry(LPCTSTR subKey, LPCTSTR valueName, LPCTSTR value)
{size_t len = strlen( value );
if (!subKey || !valueName)
return ERROR_INVALID_DATA;
LONG result = 0;
DWORD keyCreationResult = 0;
HKEY newKey;
// Create a new key or open existing key.
result = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
subKey,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&newKey,
&keyCreationResult);
if (ERROR_SUCCESS != result)
{
return result;
}
if (keyCreationResult == REG_OPENED_EXISTING_KEY)
{
WriteLog("Opened existing key '%s'\n", subKey);
}
else
{
WriteLog("Created new key '%s'\n", subKey);
}
DATA_BLOB unencryptedData, encryptedData;
unencryptedData.pbData = (BYTE *)value;
// Save the NULL character in the data
// We need to multiply the length of the string by the
// size of the data contained therein to support multi-
// byte character sets.
unencryptedData.cbData = (len + 1) * sizeof(*value);
if (!CryptProtectData(
&unencryptedData,
L"My Encrypted Data",
NULL,
NULL,
NULL,
0,
&encryptedData))
{
RegCloseKey(newKey);
return GetLastError();
}
// OK, so now we can save the data to the registry.
result = RegSetValueEx(
newKey,
valueName,
0,
REG_BINARY,
encryptedData.pbData,
encryptedData.cbData);
// Free the encrypted data buffer
LocalFree(encryptedData.pbData);
RegCloseKey(newKey);
return result;
}
现在 - 在另一个应用程序(c#,为任何CPU构建)中,我使用Microsoft的DPAPI类来解密从注册表中读取的二进制字符串。
private void btnRead_Click(object sender, EventArgs e)
{
try
{
RegistryKey rKey1 = Registry.LocalMachine;
rKey1 = rKey1.OpenSubKey(@"SOFTWARE\XXX\XXX\Credentials", true);
var value = (byte[])rKey1.GetValue("UserName");
var valueAsString = BitConverter.ToString(value);
string decrypted = DPAPI.Decrypt(EncodeTo64(valueAsString));
}
catch (Exception ex)
{
while (ex != null)
{
Console.WriteLine(ex.Message);
ex = ex.InnerException;
}
}
}
使用测试装置,我可以确认写入注册表的数据可以在c ++程序中加密和未加密,并且使用不同的测试装置,我可以确认加密和解密在c#应用程序中有效。
string xx = DPAPI.Encrypt("Administrator");
string yy = DPAPI.Decrypt(xx);
// works encrypt and decrypt
byte[] data;
data = Convert.FromBase64String(xx);
rKey2.SetValue("UserNamecsharp", data, RegistryValueKind.Binary);
byte[] value = (byte[])rKey1.GetValue("UserName");
var valueAsString = Convert.ToBase64String(value);
string decrypted = DPAPI.Decrypt(valueAsString);
看起来注册表中的起始值是相同的,并且在调试器中运行时,它们看起来非常接近 - 直到四个A的
valueAsString
“AQAAANCMnd8BFdERjHoAwE / CL + sBAAAAesG + C / 0ymUSov + q7G6U0rAAAAAAkAAAATQB5ACAARQBuAGMAcgB5AHAAdABlAGQAIABEAGEAdABhAAAAA2YAAKgAAAAQAAAAhMQNYP / ECV0uWNQJNwR0DQAAAAAEgAAAoAAAABAAAAAusIzWvKtWfIE25su1nBkWEAAAACWxuZ2lz12ON / uOafeqdfcUAAAAs7rYAvpeXoSH191clwcFXxmIA9M =” 字符串
XX “AQAAANCMnd8BFdERjHoAwE / CL + sBAAAA3lfKy0QLx0KeGBAy9xuuoAAAAAACAAAAAAADZgAAwAAAABAAAAA7y9SEsVpdsVoCO78Vlq + 3AAAAAASAAACgAAAAEAAAAG1Ssj5xjVqBhCm2rK9oUtIQAAAA07Fyyoq6vK2OHJ1ygG4t8RQAAACZp6TmW2EBsu7kPVlf05D + jkVC7w ==” 串
以下是他们的注册表内容......
“用户名”=己烷:01,00,00,00,d0,8c,9D,DF,01,15,d1,11,8c,7α,00,c0,4f,c2,97,EB,01 \ 00,00,00,7a,C1,是,0B,FD,32,99,44,A8,BF,EA,BB,1B,a5,34,AC,00,00,00,00,24,00, \ 00,00,4d,00,79,00,20,00,45,00,6e,00,63,00,72,00,79,00,70,00,74,00,65,00,64, \ 00,20,00,44,00,61,00,74,00,61,00,00,00,03,66,00,00,a8,00,00,00,10,00,00,00, \ 84,c4,0d,60,FF,c4,09,5d,2E,58,d4,09,37,04,74,0d,00,00,00,00,04,80,00,00,A0, \ 00,00,00,10,00,00,00,2e,b0,8c,D6,BC,AB,56,7c,81,36,E6,CB,b5,9c,19,16,10,00, \ 00,00,25,B1,b9,9d,A5,CF,图5d,图8e,37,FB,8E,69,F7,AA,75%,f7,14,00,00,00,B3,BA,D8, \ 02,FA,5E,5E,84,87,D7,DD,5C,97,07,05,5f,19,88,03,D3
“UserNamecsharp”=己烷:01,00,00,00,d0,8c,9D,DF,01,15,d1,11,8c,7α,00,c0,4f,c2,97,EB,01 \ 00,00,00,德,57,CA,CB,44,0b,c7,42,9e,18,10,32,f7,1b,AE,a0,00,00,00,00,02,00, \ 00,00,00,00,03,66,00,00,c0,00,00,00,10,00,00,00,3b,CB,d4,84,b1,5a,5D,b1,5a, \ 02,3b,BF,15,96,AF,b7,00,00,00,00,04,80,00,00,a0,00,00,00,10,00,00,00,6d,52, \ b2,3e,71,8d,5A,81,84,29,B6,交流,自动对焦,68,52,d2,10,00,00,00,D3,b1,72,CA,8A,BA,BC, \ 广告,8E,1C,图9D,72,80,6e,2D,f1,14,00,00,00,99,A7,A4,e6,5b,61,01,B2,EE,e4,3d,59, \ 图5f,d3,90,FE,8E,45,42,EF
我必须遗漏一些东西,使用相同的cypt32.dll例程,看起来应该正确读取和写入数据,但解密失败。
感谢您的帮助
答案 0 :(得分:2)
乍一看,您的C ++代码中似乎使用的是8位字符串(“string”)而不是unicode字符串(L“blah”或wchar_t *)。 C#对字符串使用Unicode。这可能就是为什么你会得到不同的结果。我的第一个检查是确保我将C ++字符串作为unicode传递。
祝你好运,希望这会有所帮助。 :)