我有一个本机程序,它接受在命令行中传递的密码。该密码显示在服务器日志中,因此我想通过在输入命令行之前对其进行加密来混淆它。然后我会在程序中解密它并像以前一样使用它。我的想法是我使用 powershell 创建一个带有密码的 SecureString,然后使用 ConvertFrom-SecureString 将其设为可打印的文本字符串。然后将该字符串在命令行上传递给本机 c++ 程序。从那里,我将其解码回二进制加密形式,然后将其解密回原始纯文本密码。容易吧?
从很少的文档来看,我认为 ConvertFrom-SecureString 进行 Base64 编码以使二进制 SecureString 无法打印文本。谁能证实这一点?我使用 ATL::Base64Decode() 恢复二进制字节。在比较原始和解码的前 20 个字节时,这似乎有效。
之后,我试图解密 SecureString 字节。再次,一些文档似乎暗示 SecureString 加密是使用机器密钥(或用户会话密钥)完成的。基于此,我正在尝试使用 DPAPI CryptUnprotectData 方法进行解密。在这里,虽然我得到了一个“(0x8007000d)数据无效”的decrupt失败。这听起来会奏效吗?如果是这样,知道我在哪里偏离路线吗?
这是解密方法...
// Decrypts an encoded and encrypted string with DPAPI and Machine Key, returns the decrypted string
static HRESULT Decrypt(CStringW wsEncryptedBase64, OUT CStringW& wsPlainText)
{
HRESULT hr = S_OK;
DATA_BLOB dbIn = { 0 };
DATA_BLOB dbOut = { 0 };
const wchar_t *pos = wsEncryptedBase64.GetBuffer(wsEncryptedBase64.GetLength());
dbIn.cbData = wsEncryptedBase64.GetLength() / 2;
dbIn.pbData = (byte*)malloc(dbIn.cbData * sizeof(byte));
int num = 0;
for (size_t i = 0; i < dbIn.cbData; i += 1)
{
swscanf_s(pos, L"%2hhx", &num);
dbIn.pbData[i] = num;
pos += sizeof(wchar_t);
}
if (::CryptUnprotectData(&dbIn, NULL, NULL, NULL, NULL,
CRYPTPROTECT_UI_FORBIDDEN, &dbOut))
{
wsPlainText = CStringW(reinterpret_cast< wchar_t const* >(dbOut.pbData), dbOut.cbData / 2);
}
else
{
hr = HRESULT_FROM_WIN32(::GetLastError());
if (hr == S_OK)
{
hr = SEC_E_DECRYPT_FAILURE;
}
}
return hr;
}