【问题标题】:Inconsistent string encryption result between program and Shell程序和Shell之间的字符串加密结果不一致
【发布时间】:2020-12-14 22:36:17
【问题描述】:

我编写了下面的代码 sn-p,它通过 echo'ing 将字符串传递给 openssl,使用 popen;但是结果与我在 PowerShell 中手动传递参数不同。任何帮助表示赞赏...

void encrypt_message(const char * message_in, char * encrypted_return)
{
    char encryption_cmd[1024] = { '\0' };
    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] = { '\0' };
    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....

【问题讨论】:

  • unicode 激活了吗?
  • 不是........
  • 看起来cmdecho 正在输出包括引号。 PowerShell 不包括引号
  • 在 cmd/PowerShell 中执行不同的引号/无引号组合我仍然无法在 shell 之间获得相同的结果。
  • 所以它似乎不一致,也许关于空格也是如此。不确定您是否可以在这里依赖任何东西。

标签: c++ c powershell openssl


【解决方案1】:

echo 'this' cmd.exe 与 PowerShell 中做不同的事情

  • cmd.exe中,命令输出为逐字字符串'this' ,包括单引号和尾随空格,加上尾随换行符

    • 不幸的是,cmd.exeecho 会根据指定的方式引用任何引用;一般cmd.exe理解-引用('...');虽然它确实理解双引号("..."),虽然这种双引号对于保护诸如&之类的元字符是必要的,但echo仍然与它们相呼应(而不是 stripping 它们,您期望 syntactic 起作用的引号)。
  • 在 PowerShell 中,echo 只是 Write-Output cmdlet 的内置别名,命令输出是逐字字符串 this - 语法引号被删除,尾随空格无关 - 加上一个尾随的换行符

    • PowerShell 可以理解'...' 字符串(逐字)和"..."(可扩展,即插值),并使用语法函数正确去除引号;有关 PowerShell 中字符串文字的更多信息,请参阅this answer 的底部部分。

没有一个基于echo 的命令在两个shell 中的工作方式相同。

如果可以添加尾随换行符:

如上所述,实际上,echo 总是会导致尾随换行符被附加到正在回显的字符串中。

  • cmd.exe 中,传递字符串unquoted 并且立即 跟在| 后面:

    • echo this| openssl.exe ...

    • 如果字符串包含cmd.exe 元字符,例如&;,则^-转义它们。

  • 在 PowerShell 中,虽然 echo 'this' 有效,但您可以简单地省略 echo 并依赖 PowerShell 的 隐式 输出行为:

    • 'this' | openssl.exe ...
    • 如果字符串已嵌入 ' 字符,则将它们转义为''

如果可以在结尾添加换行符:

  • cmd.exe,你必须求助于hack

    • <NUL set /p ="this" | openssl dgst ...
    • 请参阅this answer 了解更多信息以及以这种方式可以输出哪些字符串的限制;简而言之:字符串不能以 = 开头,不能包含嵌入的 " 字符,并且不能有前导制表符和/或空格,它们总是被剥离。
  • 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 ..."

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-15
    • 2011-10-07
    • 1970-01-01
    • 2012-02-04
    • 2018-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多