shell和脚本中的MD5输出不同



这让我疯了,我正试图基于fritzbox SPEC进行一些MD5计算来登录。基本上,你必须将挑战和密码转换为UTF-16LE,然后通过MD5进行哈希,然后连接challenge-MD5(uft-16LE(挑战密码))

为此,我在脚本中使用macOSX中的iconv和md5

echo -n "challenge-password1234" | iconv -f ISO8859-1 -t UTF-16LE | md5

哪个输出到2f42ad272c7aec4c94f0d9525080e6de

只需将其粘贴到外壳中即可完成1722e126192656712a1d352e550f1317 的输出

后一个是正确的(被fritzbox接受)第一个是错误的。

bash script.sh调用脚本会产生正确的哈希,用sh script.sh调用脚本会导致错误的哈希,这就引出了一个新的问题:为什么sh和bash的输出有什么不同?

不同版本的echo的行为方式截然不同。有些采用命令选项(如-n)来修改其行为(包括-n抑制尾随换行),有些则不采用。一些解释字符串本身中的转义序列(包括字符串末尾的c,抑制尾部换行)。。。有些人没有。有些人两者兼而有之。系统上的echo(/bin/echo)版本似乎不接受选项,因此将-n视为要打印的字符串。如果您使用bash,它的内置版本会覆盖/bin/echo,解释标志。

基本上,echo是一堆不一致性和可移植性陷阱。所以不要使用它,而是使用printf。这有点复杂,因为你必须指定一个格式字符串,然后是你想要打印的实际内容,但这可以省去很多麻烦。

$ printf "%s" "challenge-password1234" | iconv -f ISO8859-1 -t UTF-16LE | md5
1722e126192656712a1d352e550f1317

顺便说一下,以下是echo命令实际打印的内容:

$ printf "%sn" "-n challenge-password1234" | iconv -f ISO8859-1 -t UTF-16LE | md5
2f42ad272c7aec4c94f0d9525080e6de

您特别询问脚本和命令行结果之间的区别。请注意,在其他情况下,脚本结果可能无法用于Fritzbox。

AVM Fritzbox文档中的会话处理示例代码是用C#编写的,请参阅

  • https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_Technical_Note_-_Session_ID.pdf

从我得到的代码https://github.com/WolfgangFahl/fritz-csharp-api并添加了一些测试:

  • https://github.com/WolfgangFahl/fritz-csharp-api/blob/master/fritzsimpletest.cs

其灵感来源于中的测试

  • https://github.com/WolfgangFahl/fritzbox-java-api/blob/master/src/test/java/com/github/kaklakariada/fritzbox/Md5ServiceTest.java

基本上有5个例子:

  1. "->"d41d8cd98f00b204e9800998ecf8427e"
  2. "秘密","09433e1853385270b51511571e35eeca"
  3. "测试","c8059e2ec7419f590e79d7f1b774bfe6"
  4. "1234567z-äbc","9e224a41eefa284df7bb0f26c2913e2"
  5. "!\"§$%&()=?ßüäÜÖ-,;:_`´+*#'<>≤|"->"ad44a7cb10a95cb0c4d7ae90b0ff118a"现在你的例子是6:
  6. "challenge-password1234"->"1722e 126192656712a1d352e50f1317"并且这些在Java和C#实现中表现相同。现在用下面有的bash脚本来尝试这些

    echo-n"$l_s"|iconv--从代码ISO8859-1--到代码UTF-16LE|md5sum-b|gawk'{print substr($0,1,32)}'

例如在https://www.ip-phone-forum.de/threads/fritzbox-challenge-response-in-sh.264639/

因为它的getmd5函数为元音变音符的情况给出了不同的结果,例如在Mac OS Sierra上的bash中。

已经添加了一些调试输出。

为1234567z-äbc给出的编码具有字节序列2d c3 a4 62 63,而例如java实现具有2d e4 62 63。

因此,请注意密码中的元音变音符-使用此脚本解决方案,fritzbox访问可能会失败。我正在寻找一个变通方法,当我找到它时会把它发布在这里。

bash脚本

#!/bin/bash
# WF 2017-10-30
# Fritzbox handling
#
# get the property with the given name
# params
#   1: the property name e.g. fritzbox.url, fritzbox.username, fritzbox.password
#
getprop() {
  local l_prop="$1"
  cat $HOME/.fritzbox/application.properties | grep "$l_prop" | cut -f2 -d=
}
#
# get a value from the fritzbox login_sid.lua
#
getboxval() {
  local l_node="$1"
  local l_response="$2"
  if [ "$l_response" != "" ]
  then
    l_data="&response=$l_response"
  fi
  fxml=/tmp/fxml$$
  curl --insecure -s "${box_url}/login_sid.lua?username=${username}$l_response" > $fxml
  cat $fxml |
  gawk -v node=$l_node 'match($0,"<"node">([0-9a-f]+)</"node">",m) { print m[1] }'
  cat $fxml
  rm $fxml
}
#
# get the md5 for the given string
#
# see https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_Technical_Note_-_Session_ID.pdf
#
# param
#  1: s - the string
#
# return
#   md5 
#
getmd5() {
  local l_s="$1"
  echo -n "$l_s" | iconv -f ISO8859-1 -t UTF-16LE | od -x
  echo -n "$l_s" | iconv --from-code ISO8859-1 --to-code UTF-16LE | md5sum -b | gawk '{print substr($0,1,32)}'
}
# get global settings from application properties
box_url=$(getprop fritzbox.url)
username=$(getprop fritzbox.username)
password=$(getprop fritzbox.password)
# uncomment to test
getmd5 ""
#   should be d41d8cd98f00b204e9800998ecf8427e
getmd5 secret
#   should be 09433e1853385270b51511571e35eeca
getmd5 test
#   should be c8059e2ec7419f590e79d7f1b774bfe6
getmd5 1234567z-äbc
#   should be 9e224a41eeefa284df7bb0f26c2913e2
getmd5 "!"§$%&/()=?ßüäöÜÄÖ-.,;:_`´+*#'<>≤|"
#   should be ad44a7cb10a95cb0c4d7ae90b0ff118a
exit
# Login and get SID
challenge=$(getboxval Challenge "")
echo "challenge=$challenge"
md5=$(getmd5 "${challenge}-${password}")
echo "md5=$md5"
response="${challenge}-${md5}" 
echo "response=$response" 
getboxval SID "$response"

最新更新