我对 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)使用。