首页/新闻资讯/正文详情

Scapy CBOR 完全指南:基于 RFC 8949 的二进制数据编解码与报文构建

发布时间:2026/9/23 7:28:45 来源:云帆数科 栏目:资讯中心
Scapy CBOR 完全指南:基于 RFC 8949 的二进制数据编解码与报文构建
Scapy CBOR 完全指南基于 RFC 8949 的二进制数据编解码与报文构建【免费下载链接】scapyScapy: the Python-based interactive packet manipulation program library.项目地址: https://gitcode.com/gh_mirrors/sc/scapyCBORConcise Binary Object Representation简洁二进制对象表示是一种基于 JSON 数据模型、紧凑且自描述的二进制数据交换格式由 RFC 8949 定义。Scapy 在scapy/cbor子包中提供了一套完整、遵循 ASN.1 设计范式的 CBOR 实现不仅支持基本类型的编码/解码还通过CBOR_Packet与CBORF_*字段体系把 CBOR 数据项变成了可直接构建、解析和模糊测试的报文。阅读本文后你将掌握CBOR 头部字节与长度编码的底层原理、Scapy 中所有 CBOR 类型对象的创建与编解码方法、语义标签的使用、异常与安全解码策略以及如何用 CBOR 字段定义自己的二进制协议报文并运行官方测试验证。CBOR 是什么核心概念与 8 种主要类型从 Scapy 的视角看CBOR 是一种追求实现小巧、消息体积合理、无需版本协商即可扩展的二进制数据格式。它定义在 RFC 8949 中官方文档 也提示读者如需完整规范请参阅 RFC 8949。CBOR 的每个数据项都由一个初始字节开始高 3 位编码主要类型major type低 5 位编码附加信息additional information。这种设计让编码紧凑的同时保持了自描述特性。CBOR 提供的基本数据类型如下表主要类型名称说明Scapy 对应类0无符号整数非负整数CBOR_UNSIGNED_INTEGER1负整数负数编码为 -1-nCBOR_NEGATIVE_INTEGER2字节串原始二进制数据CBOR_BYTE_STRING3文本串UTF-8 编码字符串CBOR_TEXT_STRING4数组有序的值序列CBOR_ARRAY5映射无序键值对CBOR_MAP6语义标签带附加语义的标记值CBOR_SEMANTIC_TAG7简单值与浮点数布尔、null、undefined、浮点CBOR_FALSE/CBOR_TRUE/CBOR_NULL/CBOR_UNDEFINED/CBOR_FLOAT/CBOR_SIMPLE_VALUE这 8 种主要类型在源码中被定义为一个枚举风格的类 CBOR_MajorTypes每个元素还关联着对应的编解码器codec注册表这是 Scapy 中对象与 codec 分离设计的基础。初始字节与长度编码头部编解码的底层原理理解 CBOR 的头部编码规则是阅读后续所有字节流示例的前提。Scapy 在 cborcodec.py 中用两个函数封装了这一规则。编码端 CBOR_encode_head根据值的大小选择 5 位附加信息字段的用法——值 24直接塞进初始字节的低 5 位整个头部只有 1 字节值 256初始字节低 5 位写 240x18随后跟 1 字节值值 65536低 5 位写 250x19随后跟 2 字节大端值H值 2^32低 5 位写 260x1a随后跟 4 字节大端值I否则低 5 位写 270x1b随后跟 8 字节大端值Q。解码端 CBOR_decode_head反向解析初始字节取出major_type initial 5与additional_info initial 0x1f按上述五种情形读取长度并返回(major_type, value, remaining_bytes)。解码时会对数据不足的情况抛出CBOR_Codec_Decoding_Error例如只有0x18却没有后续字节时。官方测试 test/scapy/layers/cbor.uts 中的边界用例精确印证了这一规则CBOR_UNSIGNED_INTEGER(23)→17值塞进初始字节CBOR_UNSIGNED_INTEGER(24)→18181 字节跟随CBOR_UNSIGNED_INTEGER(1000)→1903e82 字节跟随CBOR_UNSIGNED_INTEGER(1000000)→1a000f42404 字节跟随CBOR_UNSIGNED_INTEGER(0x1234567812345678)→1b12345678123456788 字节跟随。负数同理CBOR_NEGATIVE_INTEGER(-100)编码为3863因为 CBOR 对负数采用 -1-n 的映射-100 → n99 →0x3863。在 Scapy 中创建与组合 CBOR 对象Scapy 把每个 CBOR 数据项建模为一个CBOR_Object子类的实例定义见 cbor.py所有对象都通过val属性保存其 Python 值并统一提供enc()、__bytes__()、__str__()、strshow()/show()等接口。CBOR_Object的元类会在类创建时把对象自动注册到其关联的CBORTag上保证一个类型对应一个 tag、一个 tag 对应一个 codec的注册表自洽。创建基本类型只需构造对应类 from scapy.cbor import CBOR_UNSIGNED_INTEGER, CBOR_TEXT_STRING, CBOR_BYTE_STRING, CBOR_ARRAY num CBOR_UNSIGNED_INTEGER(42) text CBOR_TEXT_STRING(Hello, CBOR!) data CBOR_BYTE_STRING(b\x01\x02\x03)组合集合类型时数组元素可以是CBOR_Object实例也可以是原始 Python 值codec 会做自动转换 arr CBOR_ARRAY([CBOR_UNSIGNED_INTEGER(1), ... CBOR_UNSIGNED_INTEGER(2), ... CBOR_TEXT_STRING(three)]) arr CBOR_ARRAY[[CBOR_UNSIGNED_INTEGER[1], CBOR_UNSIGNED_INTEGER[2], CBOR_TEXT_STRING[three]]]CBOR_ARRAY与CBOR_MAP还重写了strshow()可以按层级缩进打印数组元素与映射的键值对便于调试。创建映射时可使用CBORcodec_MAP直接接受 Python 字典键使用哈希化的原始值值则解析为 CBOR 对象 from scapy.cbor.cborcodec import CBORcodec_MAP mapping {name: Alice, age: 30, active: True}编码与解码CBOR_Codecs 与自动类型分发所有编解码器的入口统一挂在 CBOR_Codecs 这个枚举容器上默认且目前唯一的 codec 是CBOR_Codecs.CBOR。CBOR 对象的编码通过.enc()方法bytes(obj)等价于调用obj.enc() num CBOR_UNSIGNED_INTEGER(42) encoded bytes(num) encoded.hex() 182a解码使用CBOR_Codecs.CBOR.dec(encoded)返回(CBOR_Object, remainder)二元组——第一个元素是解码出的对象第二个元素是未被消费的剩余字节这使得一段字节流可以连续解码出多个 CBOR 数据项 decoded, remainder CBOR_Codecs.CBOR.dec(encoded) decoded.val 42 isinstance(decoded, CBOR_UNSIGNED_INTEGER) True解码的内部机制是 cborcodec.py 中的_decode_cbor_item读取初始字节后按major_type自动分发到对应的 codec 类0→UNSIGNED_INTEGER、1→NEGATIVE_INTEGER、……、7→SIMPLE_AND_FLOAT。这意味着dec对任意合法的 CBOR 字节流都是零配置的无需事先声明期望的类型。集合类型的便捷编码同样走 codec 类方法 from scapy.cbor import CBORcodec_ARRAY, CBORcodec_MAP encoded CBORcodec_ARRAY.enc([1, 2, 3, 4, 5]) encoded.hex() 850102030405 decoded, _ CBOR_Codecs.CBOR.dec(encoded) [item.val for item in decoded.val] [1, 2, 3, 4, 5] encoded CBORcodec_MAP.enc({x: 100, y: 200}) decoded, _ CBOR_Codecs.CBOR.dec(encoded) isinstance(decoded, CBOR_MAP) True编码端同样具备自动转换能力_encode_cbor_item见 cborcodec.py按bool → int → bytes → str → list → dict → float → None的优先级把 Python 原生值映射为 CBOR 编码特别强调先判断 bool 再判断 int因为bool是int的子类顺序颠倒会把True错编成整数 1。对于无法编码的类型如set、自定义对象会抛出CBOR_Codec_Encoding_Error。各类类型的编码细节与字节输出官方文档 cbor.rst 对主要简单类型给出了可直接验证的字节输出逐个对照如下布尔值——由 major type 7 的简单值 20/21 表示各占 1 字节 true_val CBOR_TRUE() false_val CBOR_FALSE() bytes(true_val).hex() f5 bytes(false_val).hex() f4null 与 undefined——简单值 22/23 null_val CBOR_NULL() undef_val CBOR_UNDEFINED() bytes(null_val).hex() f6 bytes(undef_val).hex() f7浮点数——Scapy 编码端固定按双精度IEEE 754 binary64输出即0xfb 8 字节大端 double float_val CBOR_FLOAT(3.14159) bytes(float_val).hex() fb400921f9f01b866e解码端则兼容半精度0xf9额外信息 25、单精度0xfa额外信息 26与双精度0xfb额外信息 27三种浮点见 CBORcodec_SIMPLE_AND_FLOAT.do_dec。其中半精度浮点binary16由实现手工转换为 Python float并正确处理了零、次正规数、无穷与 NaN 等特殊情形。测试用例还验证了float(inf)、-math.inf、math.nan与1.5e20fb442043561a882930的往返解码。负整数——按 -1-n 规则编码 neg CBOR_NEGATIVE_INTEGER(-100) bytes(neg).hex() 3863字节串 / 文本串——头部写长度后紧跟内容测试中可看到bhello→4568656c6c6f、hello→6568656c6c6f、café→65636166c3a9UTF-8 多字节字符超过 23 字节的内容自动切换到0x58/0x781 字节长度等扩展长度编码。文本串解码时会校验 UTF-8 合法性非法编码抛出解码错误。复杂结构嵌套数组与混合类型映射CBOR 天然支持任意层级的嵌套Scapy 的递归 codec 保证了嵌套结构的完整往返 nested CBORcodec_ARRAY.enc([1, [2, 3], [4, [5, 6]]]) decoded, _ CBOR_Codecs.CBOR.dec(nested) isinstance(decoded, CBOR_ARRAY) True混合类型的映射也毫无障碍——值可以是布尔、整数、文本串甚至数组 data { ... name: Bob, ... age: 25, ... active: True, ... tags: [user, admin] ... } encoded CBORcodec_MAP.enc(data) decoded, _ CBOR_Codecs.CBOR.dec(encoded) len(decoded.val) 4测试文件 test/scapy/layers/cbor.uts 还给出了手写字节流的解码验证例如8201820203array(2): [1, array(2): [2, 3]]解码后obj.val[1]仍是CBOR_ARRAYa10a33map(1): {10: -20}正确还原为带整数键的映射。此外解码器支持在一段字节流中连续解码多个顶层数据项对010203连续三次调用dec依次得到 1、2、3。语义标签Semantic Tags为数据赋予额外语义major type 6 的语义标签用于给数据项补充语义例如标签 1 表示 Unix 纪元时间戳、标签 0 表示标准日期时间字符串。Scapy 用CBOR_SEMANTIC_TAG以(tag_number, item)二元组建模 import time timestamp int(time.time()) tagged CBOR_SEMANTIC_TAG((1, CBOR_UNSIGNED_INTEGER(timestamp))) encoded bytes(tagged) decoded, _ CBOR_Codecs.CBOR.dec(encoded) decoded.val[0] # Tag number 1CBORcodec_SEMANTIC_TAG的编码实现cborcodec.py先写出 tag 号CBOR_encode_head(6, tag_num)再递归编码被标记的内容解码时校验 major type 为 6 且后面必须跟有内容。测试用例验证了 tag 0 日期时间的编码CBOR_SEMANTIC_TAG((0, CBOR_TEXT_STRING(2013-03-21T20:04:00Z)))→c074 文本串内容。安全解码与异常体系Scapy 为解码提供了安全模式避免手工处理异常。safedec在解码失败时不抛异常而是返回一个CBOR_DECODING_ERROR错误对象 invalid_data b\xff\xff\xff obj, remainder CBOR_Codecs.CBOR.safedec(invalid_data) isinstance(obj, CBOR_DECODING_ERROR) True其实现位于 CBORcodec_Object.dec非安全模式直接调用do_dec安全模式则捕获CBOR_Codec_Decoding_Error与CBOR_Error包装成携带原始字节与异常信息的CBOR_DECODING_ERROR返回。错误对象本身也实现了enc()——如果其内部包裹的是合法对象就继续编码否则原样透传字节这为部分失败 继续处理的容错流程提供了便利。配套的异常体系定义在 cbor.py层次如下CBOR_Error继承自Scapy_Exception——所有 CBOR 错误的基类CBOR_Encoding_Error——编码错误如把负数塞进无符号整数 codecCBOR_Decoding_Error——解码错误CBOR_BadTag_Decoding_Error——未知标签导致的解码错误。测试中对应验证了字节不足场景dec(b\x18)缺少 1 字节值与dec(b\x45hel)声明 5 字节却只有 3 字节都会抛出异常而safedec(b\xff\xff\xff)返回错误对象。进阶用 CBOR 字段定义二进制报文CBOR_Packet官方文档之后Scapy 把 CBOR 进一步集成进了报文模型CBOR_Packet让 CBOR 编码的载荷可以像普通 Scapy 报文一样构建与解析。核心机制在 cborpacket.py 中CBORPacket_metaclass读取类属性CBOR_root并自动展开成fields_descself_build()委托CBOR_root.build(pkt)生成字节do_dissect()委托CBOR_root.dissect(pkt, x)从字节流填充字段并返回剩余字节。字段体系定义在 cborfields.py包括标量字段CBORF_UNSIGNED_INTEGER、CBORF_NEGATIVE_INTEGER、CBORF_INTEGER自动区分正负、CBORF_BYTE_STRING、CBORF_TEXT_STRING、CBORF_BOOLEAN、CBORF_NULL、CBORF_UNDEFINED、CBORF_FLOAT结构化字段CBORF_ARRAY定长、位置对应字段序列、CBORF_ARRAY_OF变长同构数组元素可为字段或子报文、CBORF_MAP字段名即 CBOR 文本键、CBORF_SEMANTIC_TAG给内层字段打标签复杂字段CBORF_optional类型不匹配时置 None 并跳过、CBORF_PACKET内嵌子CBOR_Packet。以官方测试 test/scapy/layers/cbor.uts 中的示例为模板定义一个版本号 标题的 CBOR 报文from scapy.cborpacket import CBOR_Packet from scapy.cbor.cborfields import CBORF_ARRAY, CBORF_INTEGER, CBORF_TEXT_STRING, CBORF_MAP, CBORF_ARRAY_OF class MyCBOR(CBOR_Packet): CBOR_root CBORF_ARRAY( CBORF_INTEGER(version, 1), CBORF_TEXT_STRING(title, test), ) pkt MyCBOR() raw_data bytes(pkt) # 构建数组头 各字段编码 pkt2 MyCBOR(raw_data) # 解析从字节流还原字段 assert pkt2.version.val 1 assert pkt2.title.val test映射风格的报文把字段名作为 CBOR 文本键class MyMap(CBOR_Packet): CBOR_root CBORF_MAP( CBORF_INTEGER(version, 2), CBORF_TEXT_STRING(title, cbor), )变长数组如整数列表使用CBORF_ARRAY_OFclass ArrOfInt(CBOR_Packet): CBOR_root CBORF_ARRAY_OF(items, [], CBORF_INTEGER) pkt ArrOfInt() pkt.items [CBOR_UNSIGNED_INTEGER(1), CBOR_UNSIGNED_INTEGER(2), CBOR_UNSIGNED_INTEGER(3)]语义标签字段如 tag 1 的时间戳可写成CBORF_SEMANTIC_TAG(tag_info, None, 1, CBORF_INTEGER(ts, 0))构建出的首字节为0xc1major type 6 tag 1。字段级测试还覆盖了CBORF_PACKET嵌套Inner作为Outer的字段、CBORF_optional缺省解码、以及bytes(pkt2) raw_data的严格字节级往返一致性。随机化与模糊测试RandCBORObjectscapy/cbor/cbor.py还提供了RandCBORObject继承自RandField用于生成随机的 CBOR 对象天然支持模糊测试与报文字段随机化。其设计要点见 cbor.py默认对象列表懒加载包含 11 种类型无符号/负整数、字节串、文本串、数组、映射、真假值、null、undefined、浮点数值使用高斯分布默认均值 1000、标准差 2000字符串/数组/映射的长度使用指数分布贴近真实数据形态递归深度限制在 10 层以内超过后剔除递归类型避免无限递归且数组/映射默认较小≤3 个元素保证生成与编码性能。测试中验证了它可指定类型列表RandCBORObject(objlist[CBOR_UNSIGNED_INTEGER])、可批量生成 100 个对象、50 次编码与 50 次往返解码的成功率均不低于 90%这为把 CBOR 对象嵌入 Scapy 报文字段做变异测试提供了现成工具。互操作性与测试运行Scapy 的 CBOR 实现与业界标准库 cbor2 做了双向互操作验证覆盖全部基本类型、集合、嵌套结构与边界值2^64 边界整数、无穷/NaN、空容器、深层嵌套。注意cbor2 仅作为测试依赖出现实现本身不依赖任何第三方 CBOR 库见 test/scapy/layers/cbor.uts 文件头注释。运行官方测试套件的方式README 与测试文件头均有说明# 安装可选测试依赖仅用于互操作测试 pip install cbor2 # 运行 CBOR 测试 bash test/run_tests -t test/scapy/layers/cbor.uts -F整个 CBOR 功能模块的文件结构一目了然scapy/cbor/init.py 负责统一导出对象、codec 与字段类cbor.py 定义数据模型与异常cborcodec.py 实现编解码cborfields.py 提供报文字段cborpacket.py 提供CBOR_Packet报文基类。从 8 种主要类型、头部长度编码到语义标签、字段化报文构建与随机化模糊测试这套实现覆盖了 CBOR 从字节级到协议级的完整工作链可直接用于构建基于 CBOR 的自定义协议或处理 IoT 领域的 CBOR 载荷。【免费下载链接】scapyScapy: the Python-based interactive packet manipulation program library.项目地址: https://gitcode.com/gh_mirrors/sc/scapy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

多线程事务回滚的挑战与解决方案
多线程事务回滚的挑战与解决方案

1. 多线程事务回滚的核心挑战当面试官抛出"多线程事务怎么回滚"这个问题时,很多候选人会条件反射地回答使用Transactional注解。但真实场景下,这个回答往往暴露出对分布式事务和线程安全理解的不足。我在实际开发中处理过多次类似案例&#xf… · 2026/9/23 7:28:45

冷热微网储能电站双层优化:容量配置与定价决策
冷热微网储能电站双层优化:容量配置与定价决策

前阵子帮一个园区做冷热微网规划,聊到储能电站时被甲方问了一句:储能到底建多大、服务电价怎么定,才能让我既愿意用、又能回本?这个问题听起来简单,但它不是一个单纯的容量计算问题,而是横跨电力、制冷、供… · 2026/9/23 7:28:39

FLoRIST:破解联邦LoRA下行通信压缩难题的实战指南
FLoRIST:破解联邦LoRA下行通信压缩难题的实战指南

做联邦学习的人应该都踩过通信开销的坑。大家默认先把上行更新压缩,因为客户端多、更新碎,每轮聚集起来光传输就够呛。但如果你真的把LoRA引入联邦场景做微调,会发现真正被低估的其实是下行广播。FLoRIST是MLSys2026上讨论的一套压缩联邦LoRA… · 2026/9/23 7:28:39

基于知识蒸馏与VGG16剪枝的Faster R-CNN增量检测源码实战
基于知识蒸馏与VGG16剪枝的Faster R-CNN增量检测源码实战

简介:这份Python源码资源聚焦基于知识蒸馏的目标检测模型增量深度学习方法,面向人工智能、计算机及相关专业的学生、教师与企业研发人员,尤其适合正在做毕设、课程设计或希望进阶目标检测与模型压缩方向的学习者。项目围绕VGG16主干网络&… · 2026/9/23 13:06:06

QEMU D-Bus VMState 深入解析:让 vhost-user 等辅助进程随虚拟机一起迁移
QEMU D-Bus VMState 深入解析:让 vhost-user 等辅助进程随虚拟机一起迁移

QEMU D-Bus VMState 深入解析:让 vhost-user 等辅助进程随虚拟机一起迁移 【免费下载链接】qemu Official QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release ta… · 2026/9/23 13:05:59

RedwoodJS 框架贡献实战指南:从本地开发环境搭建到提交第一个 PR 的完整分步流程
RedwoodJS 框架贡献实战指南:从本地开发环境搭建到提交第一个 PR 的完整分步流程

后端前端Web框架开发工具 【免费下载链接】redwood RedwoodGraphQL 项目地址: https://gitcode.com/gh_mirrors/re/redwood 点击查看 免费下载 本文基于 RedwoodJS 仓库 v5.x 版本文档中的《Contributing Walkthrough》,系统讲解向 Redwood 框架&#x… · 2026/9/23 13:05:59

大吉大利晚上吃鸡:3个高频面试题让你代码不再报错
大吉大利晚上吃鸡:3个高频面试题让你代码不再报错

大吉大利晚上吃鸡:3个高频面试题让你代码不再报错 复制来的代码跑不通,报错信息看不懂,是不是让你抓狂?别慌,这其实是大多数开发者的通病。… · 2026/9/23 13:05:53

强生笔试避坑指南:3个技巧搞定性能优化难题
强生笔试避坑指南:3个技巧搞定性能优化难题

强生笔试避坑指南:3个技巧搞定性能优化难题 配置环境就卡半天?这大概是每个准备强生笔试的工程师都经历过的噩梦。依赖冲突、版本不匹配、内存溢出,光是在本地把测试跑通就得耗掉大半天时间。更让人头疼的是,强生的笔试往往涉及高并发场景下的… · 2026/9/23 13:05:46

OpenClaw(龙虾)新手篇:openclaw.json 配置文件骨架与 CLI 验证
OpenClaw(龙虾)新手篇:openclaw.json 配置文件骨架与 CLI 验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/23 13:05:40

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码