c++;加密,c#解密=失败 < P>我有一个C++应用程序(32位),它将输入一个字符串,用一个名为RealEptrueCtrutsRetryValueRetriGrices 的代码块加密它。 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++;加密,c#解密=失败 < P>我有一个C++应用程序(32位),它将输入一个字符串,用一个名为RealEptrueCtrutsRetryValueRetriGrices 的代码块加密它。 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#,c++,C#,C++,现在-在另一个应用程序(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);

现在-在另一个应用程序(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

值字符串
“AQAAANCMnd8BFdERjHoAwE/Cl+SBAAAAEASG+C/0ymUSov+Q7G6U0RAAAAAAAAAKAATQB5ACAAABLAG8BFDERJHAAA2YAAKAAAAAAAAAHMQNYP/ECV0UWNQJNWR0DQAAEAAAEGAAAAAAAAAAAUSIZWKTWFIE25SU1NBKWAACWXUZ2LZ12ON/UOFCFCAAAAS7RYAPXO191CLFXI9M=”字符串

xx“AQAAANCMnd8BFdERjHoAwE/Cl+SBAAAA3LFKY0QLX0KEGBAY9XUOAAAAAAAAAAAAAAAZGAWAAAAAAAAAAA7Y9SESVPDSVOCO78VLQ+3AAAAAAAAAAAASAAACGAAAAAAAG1SSJ5XJVQBHCM2RK9OUTIQAA07FYOQ6VK2OHJ1YG8RQAACZCP6TMW2EBSU7KPVLF05D+jkVC7w=”字符串

这是他们的注册表内容

“用户名”=十六进制:01,00,00,00,d0,8c,9d,df,01,15,d1,11,8c,7a,00,c0,4f,c2,97,eb,01\ 00,00,00,7a,c1,be,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,00,03,66,00,00,00,a8,00,00,00,00,00,00,10,00,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,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,7a,00,c0,4f,c2,97,eb,01\ 00,00,00,de,57,ca,cb,44,0b,c7,42,9e,18,10,32,f7,1b,ae,a0,00,00,00,02,00\ 00,00,00,03,66,00,00,00,c0,00,00,00,00,00,10,00,00,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,00,a0,00,00,00,00,10,00,00,00,00,00,6d,52\ b2、3e、71、8d、5a、81、84、29、b6、ac、af、68、52、d2、10、00、00、00、d3、b1、72、ca、8a、ba、bc、\ ad、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例程,看起来应该正确读取和写入数据,但解密失败


谢谢你的帮助

乍一看,你在C++代码中使用的是8位字符字符串(“string”)而不是Unicode字符串(L“BLAH”或WCHARYT**)。C#对字符串使用Unicode。这可能就是为什么你会得到不同的结果。我的第一个检查是确保我将C++字符串作为Unicode传递。p>
祝你好运,希望这有帮助。:)

本-这正是正在发生的事情。非常感谢。