【问题标题】:arduino wifi passphrase with \0arduino wifi密码与\ 0
【发布时间】:2016-09-02 15:55:41
【问题描述】:

我正在尝试将 Arduino 连接到 WiFi 网络。

const char* ssid = "ssid";
char* password = "some_hex_chars";
.
.
.
void setup(void){
  WiFi.begin(ssid, password);
.
.
.

问题是,密码短语中某处的代码为 0x00。由于 begin() 方法采用参数 char,它是以 null 结尾的字符串,所以 password 被截断。 有没有办法解决这个问题?在哪里可以找到 begin() 方法的来源来修改它?

编辑:错误。 这不是密码,是 64 个十六进制字符的 PSK,它不想连接。

更新: 我解决了这个问题。我不是PSK问题,而是WiFi路由器高级设置。当

54g™ 模式 设置为 54g 性能,它不想连接。我把它改成54g Auto后,效果很好。

【问题讨论】:

  • 为什么不把密码改成更合理的?
  • @EdCottrell 太复杂了。我不得不在很多地方改变它

标签: arduino wifi passphrase


【解决方案1】:

我对 Arduino 一无所知 - 但对 802.11 又名 Wi-Fi 了解更多。一个这样的:

不要那样做。根据 IEEE 802.11 标准,如果您的密码短语中间有 0x00,那么它在技术上是无效的。

我想,如果正确实施,您的 802.11 堆栈会将密码短语的倒数寻找未定义的行为 - 最好的情况是互操作性问题,最坏的情况是你在打赌。

怎么样?

(警告:这会很无聊,很多“网络律师”的东西)

与此相关的 IEEE 802.11 标准是 IEEE Std 802.11i-2004“修订 6:媒体访问控制 (MAC) 安全增强”[0],又名“WPA2”。

(我不会深入探讨 WEP,它显然已被弃用无用,也不会深入探讨“基本”WPA,它是等待此 WPA2 标准完成的过渡)。

相关部分可以在 802.11i 中找到,ASN MIB[1](附件 D,规范),第 136 页,将“dot11RSNAConfigPSKPassPhrase”定义为“DisplayString”。那么“DisplayString”究竟是什么类型的数据呢?

RFC 1213,“基于 TCP/IP 的互联网的网络管理的管理信息库:MIB-II”,自 1991 年起,第 3 页指出:

"DisplayString 仅限于 NVT ASCII 字符集,如 在 [6] 的第 10-11 页中定义。”

好的...

这个“[6]”是 1983 年的 RFC 854(哇!这些 IETF 和 IEEE 认真设计他们的标准,真的,真的建立在)。你还跟着我吗? :-) 看了一下,我们了解到 NVT 代表“网络虚拟终端”,在指向第 10 页和第 11 页时,我们发现:

NVT 打印机 [原文如此!记住那是 1983] [...] 可以生产 所有 95 个 USASCII 图形(代码 32 到 126)的表示形式。

好的,ASCII 码 32 到 126。 现在让我们回到 IEEE 802.11i:

在附件 H(资料性)中,“RSNA 参考实现和测试向量”,“H.4 建议的密码短语到 PSK 映射”部分(请记住,密码短语的目的,在数学上与 SSID 一起按摩,是派生一个 PSK(预共享密钥),对 802.11 操作更有用,但比“我可以用该死的键盘输入的该死的简单密码短语”更不友好)。其中,用 IEEE 的方式表述,给出了这个(第 165 页):

RSNA PSK 由 256 位或 64 个八位字节组成,以 十六进制。用户很难正确输入 64 个十六进制字符。 然而,大多数用户都熟悉密码和密码短语,并且 输入它们比输入键更舒服。一个用户更多 可能能够输入 ASCII 密码或密码短语,甚至 尽管这样做会限制可能的密钥集。这表明 可以做的最好的事情是向 PSK 引入密码短语 映射。

该子句定义了一个密码短语到 PSK 的映射,即 与 RSNA 一起使用的推荐做法。

引入此密码短语映射是为了鼓励不熟悉的用户 使用加密概念来启用其安全功能 无线局域网。

...那么密码的目的是什么。然后在第 166 页:

这里适用以下假设:

  • 密码短语是 8 到 63 个 ASCII 编码字符的序列。 63的极限来自于区分的欲望
    在密码短语和显示为 64 位十六进制的 PSK 之间
    字符。
  • 密码短语中的每个字符都必须具有 32 到 126(十进制)范围内的编码。 [强调我的]

还有,瞧!事实上,“32 到 126(十进制),包括在内”。

所以这里我们再次将密码短语作为 ASCII“在 32 到 126(十进制)的范围内”,从 IEEE 到 IETF 再到 IEEE 确认。我们还了解到它的长度应该在 8 到 63 个字节之间,我推断,这意味着如果超过 63 个字节,它将被修剪(而不是 NULL 终止,这不是问题),如果更短,将在 32-126 ASCII 码之外的第一个字符处被剪切。当然,C 字符串 NULL 终止符 0x00 更实用,更适合用于此 BTW。

因此,密码 = 仅由 32 到 126(十进制)ASCII 码组成的字符串。

查看 ASCII 表,您会看到它以空格开头,以波浪号“~”结尾。

而且绝对没有 0x00。

因此,长话短说:您的密码在标准方面在技术上是无效的,并且您正在寻找未定义的行为。

恭喜你读到这里!

附录:

当涉及到网络协议时,永远不要假设看起来像“字符串”的东西只是你可能预设的“字符串”,并始终检查确切的编码/限制。

关于 Wi-Fi 的其他示例:

另一个“字符串”是 SSID。这真的是一个字符串吗? 没有。 它是一个 32 字节的原始数组,没有 ASCII,没有 UTF-8,Unicode 等等,没有终止,只有 32 个原始字节,即使你将它“设置”为“foobar + NULL” terminator" 整个 32 字节将被堆栈使用并播出(查看 Wireshark 跟踪,然后双击剖析中的 SSID 字段:32 字节长)。因此,一个 SSID 可以只包含 ASCII 空格、制表符、CR、LF 和一些 0x00,或者只包含 0x00 顺便说一句,它将完全有效并作为一个完整的 32 字节序列进行管理。

编辑:

我想知道你设置这样一个密码的动机,我能想出的唯一想法 - 如果我错了,请纠正我 - 你的目的是玩一个巧妙的把戏,以确保普通用户使用普通键盘,永远无法输入密码。遗憾的是 - 或者实际上希望 - 正如我解释的那样,这行不通,因为 IEEE 精确地设计了密码数据类型以 100% 确保任何人使用最基本的键盘始终可以输入它。 那是他们的动机。

那么,你能做什么?

作为替代方案,您可以直接使用 PSK。那是纯原始的 32 字节(表示 64 十六进制数字 ASCII),没有可输入/可打印的考虑。例如,来自 hostapd.conf 文件(当然,示例 PSK 在这里表示为“文本”,但实际上是原始字节):

# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
# (8..63 characters) that will be converted to PSK. This conversion uses SSID
# so the PSK changes when ASCII passphrase is used and the SSID is changed.
# wpa_psk (dot11RSNAConfigPSKValue)
# wpa_passphrase (dot11RSNAConfigPSKPassPhrase)
#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
#wpa_passphrase=secret passphrase

当然,1/ 这可能不适合您的用例(部署方面),2/ Arduino Wi-Fi API 可能没有这样的功能。

希望对您有所帮助。

[0]: 你可以在这里免费下载: http://standards.ieee.org/getieee802/download/802.11i-2004.pdf

[1]: 这是“抽象语法符号”中“管理信息库”的 IEEE 行话,它是给定标准的每个数据及其名称和类型的正式分层符号。您可以将其视为“XML”,只有它的不是 XML,并且被 IETF 和 IEEE(RFC 2578、RFC 1213)使用。

【讨论】:

  • 感谢您的详细解释。现在我知道我问错了问题。问题是,我的 WiFi AP 有一个 64 个十六进制字符的 PSK。这 32 个(不是 64 个)八位字节之一是 0。似乎 Arduino API 无法区分密码短语和显示为 64 个十六进制字符的 PSK。所以我试图做的是将 PSK 八位字节作为密码传递,这显然是完全错误的。
  • @user4215456 是的,我添加了关于动机的事后想法,以及另一种方式 - 请参阅我的编辑。但确切地说,您同时发表了评论,而且... :-/ 这是标准非常重要的地方,当您遇到它时,您可以识别出不太好的实现。看起来 Arduino Wi-Fi 堆栈就是其中之一。
  • @user4215456 我的错:PSK 确实是 32 个字节(802.11i 第 137 页:dot11RSNAConfigPSKValue OBJECT-TYPE SYNTAX OCTET STRING (SIZE(32)) - 因此它的文本表示是 64 个 ASCII 字符。将修正我的答案。
  • @user4215456 再说一次,我可能会误会/误解,但快速浏览一下 Arduino 的 Wi-Fi API,似乎它根本不支持 PSK - 只有密码,而且你肯定不能将一个用于另一个,这些是不同的数据,进一步以不同的方式处理。现在 也许 theWifi.begin() 可以 区分 2(“64 char + only hex digits”与“min 8 and up to 63”)并自动适应处理两者正确的方法,但这毕竟是一个基本上是业余爱好者的平台。
  • 很好的解释。阅读本文解决了我和许多其他人的问题
猜你喜欢
  • 2017-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-12
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多