3. 设备注册与认证机制

设备注册与认证机制 学习卡片

任务目标

为OTA升级系统设计设备接入安全机制,确保只有完成注册且通过认证的合法设备才能连接OTA服务器并获取升级包。本案例实现设备唯一标识生成、注册请求签名、服务器端注册校验与设备认证令牌签发,形成完整的设备接入闭环。

核心设计

  • 设备唯一标识:使用设备出厂时烧录的硬件序列号(32位十六进制字符串)作为不可篡改的设备身份,结合随机生成的设备密钥作为注册凭证。
  • 注册流程:设备携带序列号+密钥向服务器发起注册,服务器校验序列号格式与密钥强度后,生成设备ID(UUID)并签发认证令牌。
  • 认证机制:设备后续每次连接OTA服务器时,需携带令牌;服务器验证令牌有效性与过期时间,拒绝未注册或令牌失效的请求。

完整实现

import hashlib
import hmac
import uuid
import time
import re

# ---------- 设备端 ----------
class OTA_Device:
    def __init__(self, serial_no, secret_key):
        self.serial_no = serial_no          # 出厂烧录的硬件序列号
        self.secret_key = secret_key        # 设备密钥(仅设备与服务器知晓)
        self.device_id = None
        self. = None
        self._expire = 0

    def register_payload(self):
        """生成注册请求:序列号 + 时间戳 + HMAC签名"""
        timestamp = str(int(time.time()))
        message = f"{self.serial_no}|{timestamp}"
        signature = hmac.new(
            self.secret_key.encode(),
            message.encode(),
            hashlib.sha256
        ).hexdigest()
        return {
            "serial_no": self.serial_no,
            "timestamp": timestamp,
            "signature": signature
        }

    def authenticate_header(self):
        """生成认证请求头:设备ID + 令牌"""
        return {
            "X-Device-ID": self.device_id,
            "X-Auth-": self.
        }

# ---------- 服务器端 ----------
class OTA_Server:
    def __init__(self):
        # 模拟数据库:序列号 -> 密钥(出厂预置)
        self.registered_devices = {}
        # 已注册设备:device_id -> {serial_no, , _expire}
        self.active_sessions = {}

    def add_factory_device(self, serial_no, secret_key):
        """出厂时预置设备信息到服务器数据库"""
        self.registered_devices[serial_no] = secret_key

    def _verify_signature(self, payload):
        """校验注册请求签名"""
        if payload["serial_no"] not in self.registered_devices:
            return False
        expected_key = self.registered_devices[payload["serial_no"]]
        message = f"{payload['serial_no']}|{payload['timestamp']}"
        expected_sig = hmac.new(
            expected_key.encode(),
            message.encode(),
            hashlib.sha256
        ).hexdigest()
        # 防重放:时间戳在5分钟内有效
        if abs(int(time.time()) - int(payload["timestamp"])) > 300:
            return False
        return hmac.compare_digest(expected_sig, payload["signature"])

    def register_device(self, payload):
        """处理设备注册请求,返回设备ID与令牌"""
        if not self._verify_signature(payload):
            return None
        serial_no = payload["serial_no"]
        device_id = str(uuid.uuid4())
         = hashlib.sha256(
            f"{serial_no}|{uuid.uuid4()}|{time.time()}".encode()
        ).hexdigest()
        expire = int(time.time()) + 3600  # 令牌1小时有效
        self.active_sessions[device_id] = {
            "serial_no": serial_no,
            "": ,
            "_expire": expire
        }
        return {"device_id": device_id, "": , "expire": expire}

    def authenticate(self, device_id, ):
        """验证设备认证信息是否有效"""
        session = self.active_sessions.get(device_id)
        if not session:
            return False
        if session[""] != :
            return False
        if int(time.time()) > session["_expire"]:
            return False
        return True

# ---------- 验证流程 ----------
def demo_flow():
    # 1. 出厂预置
    server = OTA_Server()
    serial = "A1B2C3D4E5F60718293A4B5C6D7E8F90"
    secret = "k9x2m7q4z8p1v5t3"
    server.add_factory_device(serial, secret)

    # 2. 设备注册
    device = OTA_Device(serial, secret)
    reg_payload = device.register_payload()
    reg_result = server.register_device(reg_payload)
    assert reg_result is not None, "注册失败"
    device.device_id = reg_result["device_id"]
    device. = reg_result[""]
    device._expire = reg_result["expire"]
    print("注册成功,设备ID:", device.device_id[:8], "...")

    # 3. 设备认证(模拟OTA连接)
    auth_header = device.authenticate_header()
    is_valid = server.authenticate(
        auth_header["X-Device-ID"],
        auth_header["X-Auth-"]
    )
    assert is_valid, "认证失败"
    print("认证通过,允许接入OTA服务器")

    # 4. 非法设备测试
    fake_device = OTA_Device("FFFFFFFFFF0000000000000000000000", "wrong_key")
    fake_payload = fake_device.register_payload()
    fake_result = server.register_device(fake_payload)
    assert fake_result is None, "非法设备不应注册成功"
    print("非法设备注册被拒绝(预期行为)")

    # 5. 过期令牌测试
    server.active_sessions[device.device_id]["_expire"] = int(time.time()) - 10
    expired_valid = server.authenticate(device.device_id, device.)
    assert not expired_valid, "过期令牌不应通过"
    print("过期令牌认证被拒绝(预期行为)")

    print("\n全部验证通过:注册与认证机制工作正常")

if __name__ == "__main__":
    demo_flow()

运行方式

python3 ota_auth_demo.py

验证方法与通过标准

  • 注册成功路径:合法设备携带正确签名注册,返回设备ID与令牌,控制台输出“注册成功”。
  • 认证通过路径:使用注册返回的令牌请求认证,输出“认证通过,允许接入OTA服务器”。
  • 非法设备拒绝:伪造序列号或密钥的设备注册返回None,输出“非法设备注册被拒绝”。
  • 过期令牌拒绝:将令牌有效期改为过去时间后认证失败,输出“过期令牌认证被拒绝”。
  • 最终判定:程序无异常退出且打印“全部验证通过”,说明注册与认证闭环正确。

关键说明

  • HMAC-SHA256签名确保注册请求来自持有正确密钥的设备,时间戳窗口防止重放攻击。
  • 认证令牌有效期1小时,过期后设备需重新注册或刷新令牌(本案例聚焦核心机制,刷新流程可基于同一签名方案扩展)。
  • 实际生产环境中,设备密钥应安全存储在安全元件或TEE中,服务器端密钥应使用KMS管理,本案例用内存字典模拟数据库存储。