I have a native program that takes a password that is passed in on command line. That password is showing up in server logs so I want to obfuscate it by encrypting it before putting on the command line. I would then decrypt it in the program and use it as before. The idea is I use powershell to create a SecureString with the password, then make it a printable text string using ConvertFrom-SecureString. That string is then passed in on the command line to the native c++ program. From there, I decode it back to a binary excrypted form, and then decrypt it back to the original plain text password. Easy right?
From scant documentation, I think the ConvertFrom-SecureString does a Base64 encoding to make the binary SecureString inot printable text. Can anyone confirm that? I recover the binary bytes using ATL::Base64Decode(). This appears to work when comparing the first 20 bytes from orignal and decoded.
After that I'm trying to decrypt the SecureString bytes. Again some documentation appears to imply that the SecureString Encryption is done using Machine Key (or User Session Key). Based on this, I'm trying to decrypt using the DPAPI CryptUnprotectData method. Here, though I get an decrupt failure with "(0x8007000d) The data is invalid". Does this sound like it will work? If so any idea where I'm off course?
Heres the decrypt method ...
// 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;
}