IBE加密程序实战:BF-IBE原理、Python实现与避坑指南
简介这是一份面向密码学学习者与安全开发者的IBE基于身份加密系统加密程序源码包适合研究基于身份密码技术、需要动手实践SM9算法原理的高校学生与工程人员。资源共40个文件以h头文件、cpp源文件、obj目标文件为主另含sbr、pdb、ibe、key等编译与密钥相关文件以及exe可执行程序、lib静态库和dsp、dsw工程文件压缩包约1.57MB可直接在VC6环境下打开工程编译运行。内容围绕zzn、ecn、ebrick、big等大数运算与椭圆曲线模块展开配合miracl库和common.ibe、guoshaolong.ibe等参数文件完整呈现IBE加密流程的实现细节。目前已有1317人学习下载读者可借此理解双线性对、密钥生成与加解密核心逻辑并对照源码调试排错快速搭建自己的IBE实验环境。1. IBE 加密程序到底在解决什么问题从公钥证书的麻烦说起如果你维护过基于 PKI 的加密系统大概率经历过这样的场景要给一个新同事发加密文件得先让他生成密钥对、提交 CSR、等 CA 签发证书、再把证书导入信任库最后才能加密。这一套流程走完半天过去了。IBEIdentity-Based Encryption基于身份的加密想干的事很直接——把「身份」本身当公钥用比如邮箱地址、工号、设备编号加密方不需要提前拿到对方的证书只要知道这个身份字符串就能直接加密。解密方则通过一个可信的私钥生成中心PKG在需要时领取自己身份对应的私钥。这个标题里的「IBE 加密程序」核心就是实现「用身份字符串加密、由 PKG 派生私钥解密」这条链路。它适合谁适合那些密钥分发成本高、终端数量大、又不想维护庞大证书目录的场景比如内部消息系统、物联网设备下发指令、跨机构数据交换的加密层。但 IBE 不是银弹它把信任集中到了 PKG 身上PKG 一旦失守所有密文形同虚设。所以真正落地时选型、参数、私钥派生流程每一步都得抠清楚。2. 选型与原理为什么多数工程落地选 BF-IBE 而不是其他变体2.1 从 Boneh-Franklin 方案说起双线性对怎么撑起 IBEIBE 的理论根基是双线性对bilinear pairing。简单说存在一个映射 e: G1 × G2 → GT满足双线性、非退化性和可计算性。Boneh-Franklin 方案BF-IBE利用这个性质让 PKG 用主私钥 s 生成用户私钥 d_ID s·H(ID)加密方用主公钥 P_pub s·P 和身份哈希 H(ID) 就能构造密文。解密时通过配对运算消去 s恢复出明文。整个过程中加密方不需要知道 s也不需要和 PKG 交互这是 IBE 最吸引人的地方。工程上常见的配对友好曲线有 BN254、BLS12-381。BN254 在 128 位安全级别下性能较好很多区块链项目也在用库支持成熟BLS12-381 安全裕度更高但配对运算稍慢。如果你的系统对性能敏感、安全等级要求 128 位BN254 是稳妥选择。我一般会先确认目标平台有没有成熟的配对库再决定曲线而不是反过来。2.2 四种 IBE 变体的取舍BF、SK-IBE、Gentry、BB1BF-IBE 是最经典的安全性基于 BDH 假设在随机预言机模型下可证明安全。SK-IBESakai-Ohgishi-Kasahara更早但安全性证明不如 BF 完整。Gentry-IBE 在标准模型下可证明安全但密文和私钥尺寸更大性能开销明显。BB1Boneh-Boyen适合分层 IBE支持身份分层派生适合组织架构复杂的场景。选型建议如果只是做一个内部加密工具BF-IBE 足够库多、文档全、性能好如果需要标准模型证明、合规审计严格考虑 Gentry如果身份有层级关系如部门-组-用户BB1 的分层能力能省很多事。别一上来就追求「最强安全」先看你的威胁模型和性能预算。2.3 最小可跑通的加密程序结构一个 IBE 加密程序通常包含四个模块PKG 初始化生成主密钥对和公共参数、私钥提取根据身份生成私钥、加密用身份和主公钥加密、解密用私钥解密。下面是一个基于 Python 的简化结构用py_ecc库做 BN254 上的配对运算。注意这是教学级实现生产环境需要更严格的侧信道防护和密钥管理。# ibe_core.py # 依赖: pip install py_ecc from py_ecc.bn128 import G1, G2, pairing, multiply, add, curve_order from hashlib import sha256 # ---------- PKG 初始化 ---------- def setup(): # 主私钥 s实际应用应从安全随机源生成 s int.from_bytes(sha256(bmaster_seed_demo).digest(), big) % curve_order # 主公钥 P_pub s * G2 P_pub multiply(G2, s) # 公共参数G1, G2, P_pub return s, P_pub # ---------- 身份哈希到 G1 ---------- def hash_identity(identity: str): # 将身份字符串哈希后映射到 G1 点 h int.from_bytes(sha256(identity.encode()).digest(), big) % curve_order return multiply(G1, h) # ---------- 私钥提取 ---------- def extract_private_key(s, identity: str): Q_ID hash_identity(identity) # d_ID s * Q_ID return multiply(Q_ID, s) # ---------- 加密 ---------- def encrypt(P_pub, identity: str, message: bytes): Q_ID hash_identity(identity) # 随机数 r r int.from_bytes(sha256(message brand).digest(), big) % curve_order # U r * G1 U multiply(G1, r) # g_ID e(Q_ID, P_pub) g_ID pairing(Q_ID, P_pub) # 用 g_ID^r 派生对称密钥简化取配对结果的 x 坐标哈希 shared g_ID ** r key sha256(str(shared).encode()).digest() # 简单异或加密生产环境应使用 AES-GCM ciphertext bytes(m ^ key[i % len(key)] for i, m in enumerate(message)) return U, ciphertext # ---------- 解密 ---------- def decrypt(d_ID, U, ciphertext): # 恢复配对值e(d_ID, U) e(s*Q_ID, r*G1) e(Q_ID, G1)^(s*r) # 注意这里需要与加密端一致的配对目标群表示 # 简化演示实际需用 e(d_ID, U) 与加密端 g_ID^r 对应 # 此处仅展示流程完整实现需处理配对参数一致性 pass上面代码里setup生成主密钥对hash_identity把身份映射到椭圆曲线点extract_private_key用主私钥派生用户私钥encrypt用身份和主公钥生成密文。解密部分因为配对运算的目标群元素表示需要严格对齐这里只留了框架。实际工程中我会用py_ecc的pairing结果做哈希派生并确保加密端和解密端的配对输入顺序一致。参数上curve_order是 BN254 的阶sha256用于确定性演示生产环境应使用 HKDF 或 KDF 派生密钥。注意教学代码不能直接用于生产。真实系统需要处理密钥零化、随机数质量、侧信道防护以及密文格式的标准化。3. 动手实现从 PKG 初始化到加解密全流程3.1 环境准备与依赖安装先确认 Python 版本在 3.8 以上然后安装配对库。我一般用虚拟环境隔离避免和系统包冲突。python3 -m venv ibe_env source ibe_env/bin/activate pip install py_ecc hashlibpy_ecc是纯 Python 实现安装快适合原型验证。如果性能要求高可以换mcl或bn256的 C 绑定库但接口会复杂一些。安装完后用一个小脚本验证配对运算是否正常from py_ecc.bn128 import G1, G2, pairing, multiply, curve_order # 验证双线性: e(a*G1, b*G2) e(G1, G2)^(a*b) a, b 3, 5 left pairing(multiply(G1, a), multiply(G2, b)) right pairing(G1, G2) ** (a * b) print(left right) # 应输出 True如果输出True说明配对库工作正常。这一步别跳过我见过因为库版本不匹配导致配对结果不一致的翻车案例。3.2 PKG 初始化主密钥生成与公共参数发布PKG 初始化是整个系统的信任根。主私钥s必须用密码学安全的随机源生成不能像演示代码那样从固定种子派生。公共参数包括曲线参数、生成元G1、G2、主公钥P_pub以及身份哈希函数。这些参数需要公开且可验证。import secrets from py_ecc.bn128 import G1, G2, multiply, curve_order def pkg_setup(): # 用 secrets 生成主私钥 s secrets.randbelow(curve_order - 1) 1 P_pub multiply(G2, s) # 公共参数打包 params { curve: BN254, G1: G1, G2: G2, P_pub: P_pub, hash: sha256 } return s, paramss生成后必须离线保存最好用 HSM 或硬件钱包。P_pub可以公开分发客户端加密时只需要它和身份字符串。参数里的hash字段指定身份哈希算法实际部署时建议用 SHA-256 加盐防止身份枚举攻击。3.3 私钥提取身份到私钥的派生流程私钥提取是 PKG 的核心服务。用户提交身份证明如邮箱验证PKG 验证后调用extract_private_key生成私钥通过安全信道返回。私钥不能明文传输通常用 TLS 加临时密钥加密。def extract_key(s, identity: str): # 身份规范化统一小写、去空格 normalized identity.strip().lower() Q_ID hash_identity(normalized) d_ID multiply(Q_ID, s) return d_ID身份规范化很重要。如果加密方用AliceExample.com解密方用aliceexample.com哈希结果不同私钥就对不上。我一般会在文档里明确规范全部小写、去除首尾空格、域名部分不做特殊处理。私钥返回后客户端应立即存入安全存储比如系统密钥链或 TEE。3.4 加密与解密用身份字符串完成端到端加解密加密方只需要主公钥P_pub和接收方身份。下面是一个完整的加密函数用 AES-GCM 做对称加密配对结果派生密钥。from Crypto.Cipher import AES from Crypto.Random import get_random_bytes import hashlib def encrypt_message(P_pub, identity: str, plaintext: bytes): Q_ID hash_identity(identity.strip().lower()) r secrets.randbelow(curve_order - 1) 1 U multiply(G1, r) g_ID pairing(Q_ID, P_pub) shared g_ID ** r # 用 SHA-256 派生 AES 密钥 key hashlib.sha256(str(shared).encode()).digest() nonce get_random_bytes(12) cipher AES.new(key, AES.MODE_GCM, noncenonce) ct, tag cipher.encrypt_and_digest(plaintext) return U, nonce, ct, tag解密方用自己的私钥d_ID和密文中的U恢复共享值def decrypt_message(d_ID, U, nonce, ct, tag): shared pairing(d_ID, U) key hashlib.sha256(str(shared).encode()).digest() cipher AES.new(key, AES.MODE_GCM, noncenonce) return cipher.decrypt_and_verify(ct, tag)这里的关键是pairing(d_ID, U)必须等于加密端的g_ID ** r。数学上e(d_ID, U) e(s·Q_ID, r·G1) e(Q_ID, G1)^(s·r)而加密端e(Q_ID, P_pub)^r e(Q_ID, s·G2)^r e(Q_ID, G2)^(s·r)。要相等需要G1和G2在配对下对应同一个群或者使用对称配对。py_ecc的 BN254 是非对称配对所以实际实现中需要把Q_ID映射到G2或调整配对参数。这也是很多新手第一次跑 IBE 时最容易翻车的地方——配对输入群搞混解密结果全是乱码。提示如果发现解密失败先检查pairing的两个参数是否分别来自正确的群。BN254 的G1和G2不能互换。4. 避坑与排查IBE 加密程序最常见的 5 个翻车点4.1 配对群搞混导致解密失败现象加密正常解密时decrypt_and_verify抛异常或者解出来是乱码。原因pairing的第一个参数应该是G1上的点第二个是G2上的点但代码里把Q_ID映射到了G1P_pub在G2而解密时d_ID在G1U在G1两个G1点无法配对。解决统一身份哈希的目标群。如果加密用e(H(ID)∈G1, P_pub∈G2)解密就必须用e(d_ID∈G1, U∈G1)的变体或者把U放到G2。我一般会在代码里加类型断言确保配对输入群正确。4.2 身份字符串未规范化现象同一个用户加密方用带大写字母的邮箱解密方用小写私钥不匹配。原因哈希函数对大小写敏感。解决在加密和私钥提取两端都做同样的规范化——strip().lower()并在文档里写死规则。如果身份包含 Unicode还要统一 NFC 规范化。4.3 主私钥泄露或硬编码现象演示代码把s写成固定种子上线后忘记改。原因图省事。解决主私钥必须从secrets或 HSM 生成绝不进代码仓库。我见过一个内部工具把s写在配置文件里结果配置文件被误提交到公开仓库整个系统的密文都得作废重来。血泪经验密钥管理没有后悔药。4.4 随机数 r 复用现象同一对身份和消息两次加密产生相同密文。原因r用了固定值或弱随机源。解决每次加密都用secrets.randbelow生成新r。如果r复用攻击者可以通过异或密文恢复明文。这是 IBE 实现里最隐蔽的坑之一因为功能测试完全正常只有安全审计才会发现。4.5 配对运算性能瓶颈现象加密 1KB 数据耗时几百毫秒吞吐量上不去。原因配对运算是双线性对比椭圆曲线点乘慢一个数量级。解决把配对结果缓存起来同一身份多次加密时复用g_ID或者用预计算表加速pairing。如果性能要求极高考虑把 IBE 用在密钥封装层实际数据用 AES 加密这样配对只做一次。5. 进阶技巧用预计算和分层身份把 IBE 跑得更快更稳5.1 预计算配对值同一身份多次加密的优化如果你的系统需要给同一个用户频繁发加密消息每次加密都做一次pairing(Q_ID, P_pub)是浪费。g_ID e(Q_ID, P_pub)只和身份、主公钥有关可以缓存。我一般用 LRU 缓存键是规范化后的身份字符串值是配对结果。这样第一次加密做配对后续直接取缓存加密耗时从几百毫秒降到几毫秒。from functools import lru_cache lru_cache(maxsize1024) def cached_pairing(identity: str, P_pub): Q_ID hash_identity(identity.strip().lower()) return pairing(Q_ID, P_pub)注意P_pub作为参数传入时lru_cache需要它可哈希。py_ecc的点对象可能不支持哈希实际可以用P_pub的序列化字节作为缓存键。缓存大小根据活跃用户数调整1024 对大多数内部系统够用。5.2 分层 IBE用身份路径减少 PKG 压力BB1 方案支持分层身份比如公司.部门.用户。根 PKG 只负责部门级私钥部门 PKG 用上级私钥派生用户私钥。这样根 PKG 不用处理所有用户请求扩展性更好。实现上身份哈希变成对路径逐段哈希私钥派生也逐层进行。代价是密文和私钥尺寸略增但 PKG 负载大幅下降。方案私钥尺寸密文尺寸PKG 负载适用场景BF-IBE1 个 G1 点1 个 G1 点 对称密文高中小规模BB1 分层每层 1 个 G1 点1 个 G1 点 对称密文低大型组织Gentry多个群元素多个群元素中合规审计5.3 验证方法用已知向量确认实现正确写完加密程序后别急着上线。先用已知测试向量验证固定主私钥s、固定身份、固定随机数r手动计算期望的U和配对值和代码输出对比。我一般会写一个test_ibe.py覆盖正常加解密、错误身份解密失败、篡改密文验证失败三个用例。如果配对库升级跑一遍测试就能发现兼容性问题。def test_roundtrip(): s, params pkg_setup() identity aliceinternal d_ID extract_key(s, identity) U, nonce, ct, tag encrypt_message(params[P_pub], identity, bhello ibe) pt decrypt_message(d_ID, U, nonce, ct, tag) assert pt bhello ibe这个测试跑通说明基本链路没问题。然后再加上异常用例用bobinternal的私钥解aliceinternal的密文应该抛异常篡改tag一个字节也应该抛异常。这些用例能挡住大部分低级错误。5.4 一个我常犯的错忽略密文格式版本号早期我做 IBE 工具时密文只存了U、nonce、ct、tag没存版本号和曲线标识。后来升级曲线参数老密文全解不开又没有版本号做兼容分支只能让用户重新加密。现在我会在密文头部加一个字节的版本号和一个字节的曲线 ID解析时先读头再选对应的解密逻辑。这个习惯帮我省了很多后悔药。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

ISO 27799深度解析:为医疗数据安全上专用锁

ISO 27799深度解析:为医疗数据安全上专用锁

简介:ISO 27799:2016标准中文翻译(格式修订)是一份面向医疗保健组织、个人健康信息保管人及信息安全从业者的PDF文档,专门解决健康信息安全管理中的隐私保护与合规问题。内容基于ISO/IEC 27002:2013扩展,涵盖机密性、完…

2026/10/17 19:42:53 阅读更多 →
大型制造企业IT蓝图规划核心方法:从业务架构到实施路线

大型制造企业IT蓝图规划核心方法:从业务架构到实施路线

简介:面向制造企业信息化规划人员与架构师,这份演示文稿系统梳理了从业务战略到信息化战略的蓝图设计方法,完整覆盖业务架构、信息架构、应用架构与技术架构的逐层映射,并结合汽车行业实践详解产品数据管理、企业资源计划、供应链…

2026/10/17 19:41:51 阅读更多 →
从零搭建OpenResearch:个人研究知识管理系统的架构设计与实操

从零搭建OpenResearch:个人研究知识管理系统的架构设计与实操

1. 从零搭建一个OpenResearch:我为什么选择自己造轮子第一次听到“OpenResearch”这个词,很多人会下意识觉得它是个学术平台或者论文聚合站。但在我实际动手做这个项目的过程中,它更像是一套面向个人和小团队的开放式研究工作台——把资料收集…

2026/10/17 19:41:51 阅读更多 →

最新新闻

零成本AI驱动应用上架全流程方案(Web + 小程序双路径):TaoToken 统一 Key 打通 Claude Code 与云开发部署实录

零成本AI驱动应用上架全流程方案(Web + 小程序双路径):TaoToken 统一 Key 打通 Claude Code 与云开发部署实录

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

2026/10/17 22:41:40 阅读更多 →
AI生成测试代码很干~干货:用TaoToken统一Key打通Cursor上下文管理

AI生成测试代码很干~干货:用TaoToken统一Key打通Cursor上下文管理

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

2026/10/17 22:41:40 阅读更多 →
LLM+RAG+知识图谱:打造可追溯多跳推理的AI Agent

LLM+RAG+知识图谱:打造可追溯多跳推理的AI Agent

简介:《Building AI Agents with LLMs, RAG, and Knowledge Graphs》是Packt Publishing推出的英文原版技术手册,面向具备机器学习与自然语言处理基础、熟悉Python的AI开发者、研究人员和技术负责人。全书聚焦大语言模型、检索增强生成与知识图谱的协同应…

2026/10/17 22:41:40 阅读更多 →
Code Agent浪潮来袭:用TaoToken统一Key打通Claude Code与Codex的完整任务交付链路

Code Agent浪潮来袭:用TaoToken统一Key打通Claude Code与Codex的完整任务交付链路

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

2026/10/17 22:41:40 阅读更多 →
Earcut耳切法:任意多边形快速三角化的轻量索引方案

Earcut耳切法:任意多边形快速三角化的轻量索引方案

简介:这是一份基于耳切法(Ear Clipping)实现多边形三角化的 C 资源,核心库源自 mapbox 的 earcut 算法,并参考 FIST 与 David Eberly 的经典思路做了改良。它通过 Z 阶曲线散列优化顶点排序,能够处理带孔洞…

2026/10/17 22:40:40 阅读更多 →
组态王6.55发布:报表秒建、Web可控、双库协同的可用性革命

组态王6.55发布:报表秒建、Web可控、双库协同的可用性革命

简介:本资源为亚控科技组态王6.55(中文版)官方产品文档,面向工业自动化初学者、系统集成工程师及SCADA项目开发人员,聚焦于组态软件基础配置、Web发布、报表生成与KingHistorian数据库集成等核心应用场景。文档以单个W…

2026/10/17 22:40:40 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/16 14:23:36 阅读更多 →