程序与 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.exeecho 回应任何引用 指定的 ;通常 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 ..."