程序与 Shell 之间的字符串加密结果不一致
Inconsistent string encryption result between program and Shell
我写了下面的代码片段,它使用 popen 通过回显将字符串传递给 openssl;但是结果与我在 PowerShell 中手动传递参数的结果不同。感谢任何帮助...
void encrypt_message(const char * message_in, char * encrypted_return)
{
char encryption_cmd[1024] = { '[=11=]' };
strcat(encryption_cmd, "echo '");
strcat(encryption_cmd, message_in);
strcat(encryption_cmd, "' | openssl.exe dgst -sha256 -hmac ");
strcat(encryption_cmd, SEC_KEY);
printf("CMD= %s\n",encryption_cmd);
char psBuffer[1024] = { '[=11=]' };
FILE *pPipe;
if ((pPipe = _popen(encryption_cmd, "rt")) == NULL)
return;
while (fgets(psBuffer, 1024, pPipe));
if (!feof(pPipe))
printf("Error: Failed to read the pipe to the end.\n");
sscanf(psBuffer, "(stdin)= %s", encrypted_return);
printf("RESULT= %s\n",encrypted_return);
}
这是函数的输出:
然而,当我在 PowerShell 中手动调用时,我得到了不同的结果
看起来好像 popen 在 openssl 正在解释的东西中撒了一些东西,产生了不同的结果。但我不能缩小范围到底是什么!谢谢
更新: 当我在 cmd.exe 而不是 PowerShell 中传递参数时,我得到的结果与我的程序代码相同。所以看起来它是 PowerShell做一些奇怪的事情。
echo 'this'
在 cmd.exe
和 PowerShell:
中做不同的事情
在cmd.exe
中,命令输出是逐字字符串'this'
,包括单引号和结尾的space,加一个结尾换行.
- 不幸的是,
cmd.exe
的 echo
回应任何引用 指定的 ;通常 cmd.exe
不 理解 单 -引号 ('...'
);虽然它 确实 理解 双 引号 ("..."
),但这种双引号对于保护诸如 &
, echo
仍然呼应它们(而不是 剥离 它们,你希望引用 syntactic 函数)。
在 PowerShell 中,echo
只是 Write-Output
cmdlet 的内置别名,命令输出是逐字字符串 this
- 语法引号被剥离,尾随 space 无关紧要 - 加上尾随换行符 .
- PowerShell 理解
'...'
字符串(逐字)和 "..."
(可扩展,即插值),并使用句法函数正确去除引号;有关 PowerShell 中字符串文字的更多信息,请参阅 this answer. 的底部部分
没有一个基于 echo
的命令可以在两个 shell 中发挥相同的作用。
如果可以接受尾随换行符:
如前所述,实际上,echo
总是会导致尾随换行符附加到要回显的字符串中。
在cmd.exe
中,传递字符串未加引号并且立即在其后跟|
:
echo this| openssl.exe ...
如果字符串包含 cmd.exe
个元字符,例如 &
或 ;
,^
- 转义它们。
在 PowerShell 中,虽然 echo 'this'
有效,但您可以简单地省略 echo
并依赖 PowerShell 的 implicit 输出行为:
'this' | openssl.exe ...
- 如果字符串具有 嵌入的
'
个字符,将它们转义为 ''
.
如果不可以接受追加尾随换行符:
在 cmd.exe
中,您必须 求助于 hack:
<NUL set /p ="this" | openssl dgst ...
- 查看this answer了解更多信息以及以这种方式输出字符串的限制;简而言之:字符串不能以
=
开头,不能包含嵌入的 "
字符,并且不能有前导制表符 and/or spaces,它们总是被剥离.
在 PowerShell 中,从 v7.1 开始,您目前不能通过管道将字符串发送到外部程序没有尾随换行符 - 参见GitHub issue #5974.
- 解决方法 是调用
cmd.exe
并使用其 hack:
cmd /c '<NUL set /p ="this" | openssl dgst ...'
- 同样,一定要将嵌入的
'
转义为 ''
;如果您想使用 可扩展 字符串 ("..."
) 以便您可以使用字符串插值来嵌入 PowerShell 变量,请将嵌入的 "
转义为 `"
:
$str = 'this'; cmd /c "<NUL set /p =`"$str`" | openssl dgst ..."
我写了下面的代码片段,它使用 popen 通过回显将字符串传递给 openssl;但是结果与我在 PowerShell 中手动传递参数的结果不同。感谢任何帮助...
void encrypt_message(const char * message_in, char * encrypted_return)
{
char encryption_cmd[1024] = { '[=11=]' };
strcat(encryption_cmd, "echo '");
strcat(encryption_cmd, message_in);
strcat(encryption_cmd, "' | openssl.exe dgst -sha256 -hmac ");
strcat(encryption_cmd, SEC_KEY);
printf("CMD= %s\n",encryption_cmd);
char psBuffer[1024] = { '[=11=]' };
FILE *pPipe;
if ((pPipe = _popen(encryption_cmd, "rt")) == NULL)
return;
while (fgets(psBuffer, 1024, pPipe));
if (!feof(pPipe))
printf("Error: Failed to read the pipe to the end.\n");
sscanf(psBuffer, "(stdin)= %s", encrypted_return);
printf("RESULT= %s\n",encrypted_return);
}
这是函数的输出:
然而,当我在 PowerShell 中手动调用时,我得到了不同的结果
看起来好像 popen 在 openssl 正在解释的东西中撒了一些东西,产生了不同的结果。但我不能缩小范围到底是什么!谢谢
更新: 当我在 cmd.exe 而不是 PowerShell 中传递参数时,我得到的结果与我的程序代码相同。所以看起来它是 PowerShell做一些奇怪的事情。
echo 'this'
在 cmd.exe
和 PowerShell:
在
cmd.exe
中,命令输出是逐字字符串'this'
,包括单引号和结尾的space,加一个结尾换行.- 不幸的是,
cmd.exe
的echo
回应任何引用 指定的 ;通常cmd.exe
不 理解 单 -引号 ('...'
);虽然它 确实 理解 双 引号 ("..."
),但这种双引号对于保护诸如&
,echo
仍然呼应它们(而不是 剥离 它们,你希望引用 syntactic 函数)。
- 不幸的是,
在 PowerShell 中,
echo
只是Write-Output
cmdlet 的内置别名,命令输出是逐字字符串this
- 语法引号被剥离,尾随 space 无关紧要 - 加上尾随换行符 .- PowerShell 理解
'...'
字符串(逐字)和"..."
(可扩展,即插值),并使用句法函数正确去除引号;有关 PowerShell 中字符串文字的更多信息,请参阅 this answer. 的底部部分
- PowerShell 理解
没有一个基于 echo
的命令可以在两个 shell 中发挥相同的作用。
如果可以接受尾随换行符:
如前所述,实际上,echo
总是会导致尾随换行符附加到要回显的字符串中。
在
cmd.exe
中,传递字符串未加引号并且立即在其后跟|
:echo this| openssl.exe ...
如果字符串包含
cmd.exe
个元字符,例如&
或;
,^
- 转义它们。
在 PowerShell 中,虽然
echo 'this'
有效,但您可以简单地省略echo
并依赖 PowerShell 的 implicit 输出行为:'this' | openssl.exe ...
- 如果字符串具有 嵌入的
'
个字符,将它们转义为''
.
如果不可以接受追加尾随换行符:
在
cmd.exe
中,您必须 求助于 hack:<NUL set /p ="this" | openssl dgst ...
- 查看this answer了解更多信息以及以这种方式输出字符串的限制;简而言之:字符串不能以
=
开头,不能包含嵌入的"
字符,并且不能有前导制表符 and/or spaces,它们总是被剥离.
在 PowerShell 中,从 v7.1 开始,您目前不能通过管道将字符串发送到外部程序没有尾随换行符 - 参见GitHub issue #5974.
- 解决方法 是调用
cmd.exe
并使用其 hack:cmd /c '<NUL set /p ="this" | openssl dgst ...'
- 同样,一定要将嵌入的
'
转义为''
;如果您想使用 可扩展 字符串 ("..."
) 以便您可以使用字符串插值来嵌入 PowerShell 变量,请将嵌入的"
转义为`"
:$str = 'this'; cmd /c "<NUL set /p =`"$str`" | openssl dgst ..."
- 解决方法 是调用