コマンドラインで渡されるパスワードを受け取るネイティブプログラムがあります。そのパスワードはサーバー ログに表示されるため、コマンド ラインに入力する前に暗号化して難読化したいと考えています。次に、プログラムでそれを復号化し、以前と同じように使用します。アイデアは、powershell を使用してパスワードで SecureString を作成し、ConvertFrom-SecureString を使用して印刷可能なテキスト文字列にすることです。その文字列は、コマンド ラインでネイティブの C++ プログラムに渡されます。そこから、バイナリの暗号化された形式にデコードし、元のプレーン テキストのパスワードに復号化します。簡単でしょ?
わずかなドキュメントから、ConvertFrom-SecureString は Base64 エンコーディングを実行して、バイナリの SecureString を印刷可能なテキストにしないと思います。誰でもそれを確認できますか?ATL::Base64Decode() を使用してバイナリ バイトを復元します。これは、元の信号とデコードされた信号の最初の 20 バイトを比較するとうまくいくようです。
その後、SecureString バイトを復号化しようとしています。ここでも、SecureString 暗号化がマシン キー (またはユーザー セッション キー) を使用して行われていることを示唆するドキュメントがいくつかあります。これに基づいて、DPAPI CryptUnprotectData メソッドを使用して復号化しようとしています。ここでは、「(0x8007000d)データが無効です」というエラーが発生します。これはうまくいくように聞こえますか?もしそうなら、私がコースから外れている場所はありますか?
これが復号化方法です...
// 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;
}