C++ 将Powershell SecureString传递给C++;节目?

C++ 将Powershell SecureString传递给C++;节目?,c++,powershell,encryption,securestring,dpapi,C++,Powershell,Encryption,Securestring,Dpapi,我有一个本机程序,它接受在命令行中传递的密码。该密码显示在服务器日志中,因此我希望在将其放入命令行之前对其进行加密,以使其混淆。然后我会在程序中解密它,并像以前一样使用它。我的想法是使用powershell创建带有密码的SecureString,然后使用ConvertFrom SecureString将其设置为可打印的文本字符串。然后,该字符串在命令行中传递到本机C++程序。从那里,我将其解码回二进制例外形式,然后将其解密回原始的纯文本密码。简单,对吗 从有限的文档来看,我认为ConvertFr

我有一个本机程序,它接受在命令行中传递的密码。该密码显示在服务器日志中,因此我希望在将其放入命令行之前对其进行加密,以使其混淆。然后我会在程序中解密它,并像以前一样使用它。我的想法是使用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;
}
//使用DPAPI和机器密钥对编码和加密的字符串进行解密,返回解密后的字符串
静态HRESULT解密(CStringW wsEncryptedBase64,OUT CStringW&wsPlainText)
{
HRESULT hr=S_正常;
DATA_BLOB dbIn={0};
DATA_BLOB dbOut={0};
const wchar_t*pos=wsEncryptedBase64.GetBuffer(wsEncryptedBase64.GetLength());
dbIn.cbData=wsEncryptedBase64.GetLength()/2;
dbIn.pbData=(字节*)malloc(dbIn.cbData*sizeof(字节));
int num=0;
对于(大小i=0;i(dbOut.pbData),dbOut.cbData/2);
}
其他的
{
hr=HRESULT_FROM_WIN32(::GetLastError());
如果(hr==S_正常)
{
hr=密码解密失败;
}
}
返回人力资源;
}

通过查看dotPeek中的二进制文件可以看出,ConvertFrom String使用SecureStringToCoTaskMemUnicode将安全字符串负载转换为字节数组。该字节数组以十六进制形式返回,例如
byte.ToString(“x2)

这假设您正在使用您所说的DPAPI,而不是在ConvertFrom SecureString上使用Key或SecureKey参数


所以,在C++程序中,不要使用Base64解码,只要将每两个字符作为十六进制字节解析,然后调用生成的字节数组上的CurtTurnPcExcDATA(填充到DATAAB BROB)中。.

您可能也想共享powershell加密代码。完美答案!一旦我转到简单的inpur字符串解码,它就可以完美地工作。以下是解决方案(仍然需要一些CLESNUP和错误处理。。。