在 bluez 5 上使用固定 PIN 进行蓝牙配对
Bluetooth pairing using fixed PIN on bluez 5
我正在尝试通过蓝牙连接 2 个或更多 Raspberry Pi 3 个开发板。我正在寻找配对时设置安全性的选项。我正在使用 Raspian-stretch(最新的可用)。 RPI-3 上可用的 Bluez 版本是 5.23(如 bluetoothd -v 命令所示)。
我使用的是无头版本。我希望配对得到保护(意思是应该有某种身份验证,我可以设置 PIN(4 位数字)或密码(6 位数字)),而无需用户登录。因此,如果我必须将 phone 连接到 RPI,则不必登录 RPI 即可进入 PIN/Passkey。
然后我想设置蓝牙 PAN 网络,以便我可以在连接到 PAN 网络的设备之间进行通信。
我想使用 PIN 配对 device/s,该 PIN 在系统文件或我可以指向的某个地方可用。例如,/temp/ 目录中的 pin.txt 文件或由 运行 代理设置 PIN。我从其他帖子中读到 bluez5.x 摆脱了早期版本的 bluez 中使用的蓝牙代理来完成我可以完成的事情。
bluetoothctl 中的代理,例如 DisplayOnly、KeyboardDisplay、NoInputNoOutput、DisplayYesNo、KeyboardOnly,要么设置必须手动输入的动态密码或确认密码,要么只允许任何设备配对和连接而无需任何身份验证,以防万一无输入无输出。
这是我在这个论坛上发现的 link,说明代理不再可用:
https://www.raspberrypi.org/forums/viewtopic.php?t=133961
我还参考了一些显示设备配对但没有解决我正在寻找的问题的示例。
联机帮助页上也没有可用信息。
https://manpages.debian.org/stretch/bluez/bluetoothctl.1.en.html
这是我找到的有关命令的信息,但仍然不是我要找的。
https://wiki.archlinux.org/index.php/Bluetooth
我也发布了这个 Raspberry Pi 论坛。这是 link:
https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=195090
任何解决此问题的帮助或建议或 link 我可以参考的 documnets 都非常感谢。
提前致谢。
我能够使用测试脚本来实现它。
任何有兴趣了解详细信息的人,请参阅我在 Raspberry Pi 论坛上的 post。下面是link.
https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=195090&p=1221455#p1221455
首先您必须配置 sspmode 0,用于 pin 请求:hciconfig hci0 sspmode 0
并使用 bt-agent 应用程序(您也可以 运行 作为守护进程):
bt-agent -c NoInputNoOutput -p /root/bluethooth.cfg
编辑文件配置,可以输入mac地址和密码:例如:XX:XX:XX:XX:XX:XX1234
或者,如果您希望所有设备都使用相同的密码,例如 1234,请像这样编辑文件:* 1234
这对我有用!
经过几天摆弄 BlueZ 5,这就是我得到的。
使用 BlueZ 5.50 & Raspbian 拉伸(Pi 零 W):
使用 --compat:
启动蓝牙
append to ExecStart line in /etc/systemd/system/dbus-org.bluez.service
或
in rc.local: sudo bluetoothd --compat &
接下来的步骤由下面发布的代码处理,但为了澄清,hciconfig 需要设置为:
sudo hciconfig hci0 sspmode 0
注 #1: 使用 'sspmode 1' 从 Android 配对时,您会收到输入 PIN 码的提示,但之后 Pi 会自动生成 6 位密码和配对失败。
注意 #2: hciconfig hci0 不能设置 auth 或 encrypt 实际上会将 agent DisplayOnly(我们将在下一步创建代理)注册为 KeyboardDisplay(sudo btmon 进行验证)并且配对不会使用预定义的 PIN。不确定 DisplayOnly 不能使用 auth、encrypt 是否有原因(可能与他们设置安全模式 3 有关)。
之后我们将使用bluetoothctl:
pi@raspberrypi:~ $ bluetoothctl
Agent registered
[bluetooth]# agent off
Agent unregistered
[bluetooth]# agent DisplayOnly
Agent registered
[bluetooth]# default-agent
Default agent request successful
[bluetooth]# discoverable on
Changing discoverable on succeeded
[CHG] Controller 11:22:33:44:55:66 Discoverable: yes
[bluetooth]# pairable on
Changing pairable on succeeded
[CHG] Controller 11:22:33:44:55:66 Pairable: yes
// Initiate pairing on remote device //
[NEW] Device AA:BB:CC:DD:EE:FF Android_phone
// Enter any PIN on Device AA:BB:CC:DD:EE:FF
Request PIN code
// retype your PIN below (on Pi)
[agent] Enter PIN code: <your PIN>
[CHG] Device AA:BB:CC:DD:EE:FF Class: 0x005a020c
...
[CHG] Device AA:BB:CC:DD:EE:FF Paired: yes
[bluetooth]# quit
注意 #3: 使用 BlueZ 5.43(Stretch 中的默认版本)使用 pexpect 注册代理(如果您尝试 运行 下面发布的代码,请注意)时好时坏
下面是 Python 2.7 代码,它设置 sspmode 并处理与预生成 PIN 的配对:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function # import print from python3: end=""
import time
import re
import pexpect # sudo apt-get install python-pexpect
import subprocess
import random
# !!! make sure bluetoothd runs in --compat mode before executing this script !!!
def pair_with_pin(start_time, pin, time_limit=60): # int(time.time()), pin - \d{4}, time_limit - approximate pairing window time in seconds, it might take up to 2x (nested timeout conditions)
"exectutes pairing with entered PIN on bluetooth adapter side"
pairing_status = False
try:
subprocess.call(['sudo','hciconfig','hci0','sspmode', '0'])
# bluetoothctl
child = pexpect.spawn('bluetoothctl')
child.expect("#")
child.sendline('agent off') # might be unnecessary
child.expect("unregistered")
child.sendline('agent DisplayOnly')
child.expect("Agent registered")
child.sendline('pairable on')
child.expect("pairable on succeeded")
child.sendline('discoverable on')
child.expect("discoverable on succeeded")
child.sendline('default-agent')
print ('Please input PIN: ' + pin)
# waiting for Phone to send a pairing request...
child.expect('Enter PIN code:', timeout = time_limit ) # timeout <= PAIRING_TIME_LIMIT to keep some kind of logic
while int(time.time()) < start_time + time_limit: # allow multiple pairing attempts during pairing window
child.sendline(pin)
i = child.expect(['Paired: yes', 'Enter PIN code:'], timeout = time_limit)
if i == 0: # found 'Paired: yes' == successful pairing
trust_mac = 'trust ' + re.search(r'(?:[0-9a-fA-F]:?){12}.+$', child.before).group(0) # extract MAC from last line, one with 'Paired: Yes'
child.sendline(trust_mac) # optionally add device to trusted
child.expect('trust succeeded', timeout = 10)
pairing_status = True
break
#else: # i == 1
# print('wrong PIN, retrying if time will allow')
except pexpect.EOF:
print ('!!!!!!!! EOF')
except pexpect.TIMEOUT:
print ('!!!!!!!! TIMEOUT')
# hide Pi's bluetooth for security reasons
child.sendline('pairable off')
child.expect("pairable off succeeded")
child.sendline('discoverable off')
child.expect("discoverable off succeeded")
child.close()
return pairing_status
#main program body
PAIRING_TIME_LIMIT = 60
BT_PIN = random.randint(1000,10000) # generate random 4-digit PIN 1000..9999
status = pair_with_pin(int(time.time()), str(BT_PIN), PAIRING_TIME_LIMIT)
if status == True:
print('Pairing successful')
最后说明:配对成功后可能可以开启加密,尝试:
hciconfig hci0 encrypt
或
hcitool enc $BDADD
我正在尝试通过蓝牙连接 2 个或更多 Raspberry Pi 3 个开发板。我正在寻找配对时设置安全性的选项。我正在使用 Raspian-stretch(最新的可用)。 RPI-3 上可用的 Bluez 版本是 5.23(如 bluetoothd -v 命令所示)。
我使用的是无头版本。我希望配对得到保护(意思是应该有某种身份验证,我可以设置 PIN(4 位数字)或密码(6 位数字)),而无需用户登录。因此,如果我必须将 phone 连接到 RPI,则不必登录 RPI 即可进入 PIN/Passkey。 然后我想设置蓝牙 PAN 网络,以便我可以在连接到 PAN 网络的设备之间进行通信。
我想使用 PIN 配对 device/s,该 PIN 在系统文件或我可以指向的某个地方可用。例如,/temp/ 目录中的 pin.txt 文件或由 运行 代理设置 PIN。我从其他帖子中读到 bluez5.x 摆脱了早期版本的 bluez 中使用的蓝牙代理来完成我可以完成的事情。
bluetoothctl 中的代理,例如 DisplayOnly、KeyboardDisplay、NoInputNoOutput、DisplayYesNo、KeyboardOnly,要么设置必须手动输入的动态密码或确认密码,要么只允许任何设备配对和连接而无需任何身份验证,以防万一无输入无输出。
这是我在这个论坛上发现的 link,说明代理不再可用: https://www.raspberrypi.org/forums/viewtopic.php?t=133961 我还参考了一些显示设备配对但没有解决我正在寻找的问题的示例。
联机帮助页上也没有可用信息。 https://manpages.debian.org/stretch/bluez/bluetoothctl.1.en.html
这是我找到的有关命令的信息,但仍然不是我要找的。 https://wiki.archlinux.org/index.php/Bluetooth
我也发布了这个 Raspberry Pi 论坛。这是 link: https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=195090
任何解决此问题的帮助或建议或 link 我可以参考的 documnets 都非常感谢。
提前致谢。
我能够使用测试脚本来实现它。
任何有兴趣了解详细信息的人,请参阅我在 Raspberry Pi 论坛上的 post。下面是link.
https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=195090&p=1221455#p1221455
首先您必须配置 sspmode 0,用于 pin 请求:hciconfig hci0 sspmode 0
并使用 bt-agent 应用程序(您也可以 运行 作为守护进程):
bt-agent -c NoInputNoOutput -p /root/bluethooth.cfg
编辑文件配置,可以输入mac地址和密码:例如:XX:XX:XX:XX:XX:XX1234
或者,如果您希望所有设备都使用相同的密码,例如 1234,请像这样编辑文件:* 1234
这对我有用!
经过几天摆弄 BlueZ 5,这就是我得到的。 使用 BlueZ 5.50 & Raspbian 拉伸(Pi 零 W):
使用 --compat:
启动蓝牙append to ExecStart line in /etc/systemd/system/dbus-org.bluez.service
或
in rc.local: sudo bluetoothd --compat &
接下来的步骤由下面发布的代码处理,但为了澄清,hciconfig 需要设置为:
sudo hciconfig hci0 sspmode 0
注 #1: 使用 'sspmode 1' 从 Android 配对时,您会收到输入 PIN 码的提示,但之后 Pi 会自动生成 6 位密码和配对失败。
注意 #2: hciconfig hci0 不能设置 auth 或 encrypt 实际上会将 agent DisplayOnly(我们将在下一步创建代理)注册为 KeyboardDisplay(sudo btmon 进行验证)并且配对不会使用预定义的 PIN。不确定 DisplayOnly 不能使用 auth、encrypt 是否有原因(可能与他们设置安全模式 3 有关)。
之后我们将使用bluetoothctl:
pi@raspberrypi:~ $ bluetoothctl
Agent registered
[bluetooth]# agent off
Agent unregistered
[bluetooth]# agent DisplayOnly
Agent registered
[bluetooth]# default-agent
Default agent request successful
[bluetooth]# discoverable on
Changing discoverable on succeeded
[CHG] Controller 11:22:33:44:55:66 Discoverable: yes
[bluetooth]# pairable on
Changing pairable on succeeded
[CHG] Controller 11:22:33:44:55:66 Pairable: yes
// Initiate pairing on remote device //
[NEW] Device AA:BB:CC:DD:EE:FF Android_phone
// Enter any PIN on Device AA:BB:CC:DD:EE:FF
Request PIN code
// retype your PIN below (on Pi)
[agent] Enter PIN code: <your PIN>
[CHG] Device AA:BB:CC:DD:EE:FF Class: 0x005a020c
...
[CHG] Device AA:BB:CC:DD:EE:FF Paired: yes
[bluetooth]# quit
注意 #3: 使用 BlueZ 5.43(Stretch 中的默认版本)使用 pexpect 注册代理(如果您尝试 运行 下面发布的代码,请注意)时好时坏
下面是 Python 2.7 代码,它设置 sspmode 并处理与预生成 PIN 的配对:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function # import print from python3: end=""
import time
import re
import pexpect # sudo apt-get install python-pexpect
import subprocess
import random
# !!! make sure bluetoothd runs in --compat mode before executing this script !!!
def pair_with_pin(start_time, pin, time_limit=60): # int(time.time()), pin - \d{4}, time_limit - approximate pairing window time in seconds, it might take up to 2x (nested timeout conditions)
"exectutes pairing with entered PIN on bluetooth adapter side"
pairing_status = False
try:
subprocess.call(['sudo','hciconfig','hci0','sspmode', '0'])
# bluetoothctl
child = pexpect.spawn('bluetoothctl')
child.expect("#")
child.sendline('agent off') # might be unnecessary
child.expect("unregistered")
child.sendline('agent DisplayOnly')
child.expect("Agent registered")
child.sendline('pairable on')
child.expect("pairable on succeeded")
child.sendline('discoverable on')
child.expect("discoverable on succeeded")
child.sendline('default-agent')
print ('Please input PIN: ' + pin)
# waiting for Phone to send a pairing request...
child.expect('Enter PIN code:', timeout = time_limit ) # timeout <= PAIRING_TIME_LIMIT to keep some kind of logic
while int(time.time()) < start_time + time_limit: # allow multiple pairing attempts during pairing window
child.sendline(pin)
i = child.expect(['Paired: yes', 'Enter PIN code:'], timeout = time_limit)
if i == 0: # found 'Paired: yes' == successful pairing
trust_mac = 'trust ' + re.search(r'(?:[0-9a-fA-F]:?){12}.+$', child.before).group(0) # extract MAC from last line, one with 'Paired: Yes'
child.sendline(trust_mac) # optionally add device to trusted
child.expect('trust succeeded', timeout = 10)
pairing_status = True
break
#else: # i == 1
# print('wrong PIN, retrying if time will allow')
except pexpect.EOF:
print ('!!!!!!!! EOF')
except pexpect.TIMEOUT:
print ('!!!!!!!! TIMEOUT')
# hide Pi's bluetooth for security reasons
child.sendline('pairable off')
child.expect("pairable off succeeded")
child.sendline('discoverable off')
child.expect("discoverable off succeeded")
child.close()
return pairing_status
#main program body
PAIRING_TIME_LIMIT = 60
BT_PIN = random.randint(1000,10000) # generate random 4-digit PIN 1000..9999
status = pair_with_pin(int(time.time()), str(BT_PIN), PAIRING_TIME_LIMIT)
if status == True:
print('Pairing successful')
最后说明:配对成功后可能可以开启加密,尝试:
hciconfig hci0 encrypt
或
hcitool enc $BDADD