尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

深入解析 luksy:Buildah 中不依赖 device mapper 的 LUKSv1/LUKSv2 离线加解密库

发布时间:2026/9/26 2:54:03

资讯中心
01
ARTICLE

深入解析 luksy:Buildah 中不依赖 device mapper 的 LUKSv1/LUKSv2 离线加解密库

深入解析 luksy:Buildah 中不依赖 device mapper 的 LUKSv1/LUKSv2 离线加解密库
云原生【免费下载链接】buildahA tool that facilitates building OCI images.项目地址https://gitcode.com/gh_mirrors/bu/buildah点击查看免费下载导读luksy 是一个以 Go 语言实现的纯用户态 LUKSLinux Unified Key Setup加解密库它能够在完全没有 Linux device mapperdm-crypt支持的环境下直接按 LUKSv1 与 LUKSv2 磁盘格式对数据流进行离线加密与解密。在 buildah 项目中luksy 被 internal/mkcw 模块深度集成用于生成机密工作负载confidential workload镜像中的加密磁盘镜像 disk.img。阅读本文后你将掌握 luksy 的核心 API、LUKSv1/LUKSv2 两种格式的磁盘布局与密钥管理机制、支持的密码学算法组合以及它在 buildah mkcw 功能中的真实调用场景。设计动机为什么需要离线加解密luksy 的设计出发点写在它的自述文件中README.md它实现基于 LUKSv1 和 LUKSv2 格式的加解密可以把它理解为gzip/bzip2/xz 的笨亲戚——输出不会比输入更小但它会加密而这正是它的价值所在。其核心目标非常明确在无法访问 Linux device mapper 的环境下完成加解密。传统上 LUKS 卷的挂载依赖 dm-crypt 内核模块与 device mapper而 luksy 把整个流程做成了纯用户态字节流处理因此可以在容器内、无特权环境、非 Linux 平台或受限内核中直接使用。不追求替代 cryptsetup。luksy 只复刻 cryptsetup 中不需要访问 device mapper 就能完成的那部分能力纯文件级加解密与密钥处理如果环境允许官方明确建议能用 cryptsetup 就用 cryptsetup原 README 原文If you can use cryptsetup instead, use cryptsetup instead。这一设计使得 luksy 天然适合作为构建期工具链的一部分buildah 在构建镜像阶段而非运行阶段就能产出符合标准 LUKS 格式的加密磁盘最终用户仍可用标准 LUKS 工具链解锁。公开 API 一览luksy 以库的形式随 buildah 一同 vendoring 在 vendor/github.com/containers/luksy 目录下核心入口分为三组函数/方法所在文件作用EncryptV1/EncryptV2encrypt.go用一至多个口令加密返回定长 LUKS 头、逐块加密函数与块大小ReadHeadersluks.go从文件中读出 LUKSv1 头或 LUKSv2 双头与 JSON 块V1Header.Decrypt/V2Header.Decryptdecrypt.go校验口令并返回逐块解密函数、块大小、payload 偏移与长度EncryptWriter/DecryptReaderencryption.go面向io.Writer/io.Reader的流式包装器ReadHeaderOptionsluks.go控制ReadHeaders行为的选项当前为空结构体为未来扩展保留加密与解密都是头 块处理函数的模式先取得定长头部含密钥材料再按固定块大小逐块调用返回的加解密函数处理 payload。块大小由格式决定LUKSv1 为 512 字节扇区LUKSv2 支持 512/1024/2048/4096 四种。LUKSv1 格式实现头结构与密钥槽LUKSv1 的实现在 v1header.go 中其常量注释标明遵循 LUKS1 On-Disk Format Specification version 1.2.3。V1Header是 592 字节的定长数组包含魔数LUKS\xba\xbe6 字节与版本号2 字节cipher name / cipher mode / hash spec 三个 32 字节的字符串字段payload offset4 字节、key bytes4 字节主密钥master key摘要 MKDigest20 字节、MKDigestSalt32 字节、MKDigestIter4 字节UUID40 字节以及8 个 48 字节的 key slot。每个V1KeySlot记录启用状态启用为0x00ac71f3禁用为0x0000dead、PBKDF2 迭代次数、密钥槽盐、密钥材料偏移与条纹数stripe。V1Stripes 4000、V1AlignKeyslots 4096、V1SectorSize 512是几个关键常量密钥材料按 4000 条 anti-forensic 条纹展开槽位与载荷均按 4096/512 字节对齐。加密流程EncryptV1EncryptV1 的完整流程校验口令数量至少 1 个、至多 8 个v1NumKeys未指定 cipher 时默认aes-xts-plain64随机生成 MKDigestSalt并确定主密钥尺寸默认 32 字节XTS 模式加倍为 64 字节随机生成 32/64 字节主密钥 mkey用 PBKDF2哈希默认 sha256计算 MKDigest 存入头中通过IterationsPBKDF2自动测定迭代次数见下文性能调优对每个口令用 PBKDF2 派生口令密钥经afSplit将主密钥拆分为 4000 条条纹再用v1encrypt以口令密钥加密这些条纹写入对应 key slot 的密钥材料区头部含全部条纹组装完毕后返回定长头head、可调用的encryptStream内部按 512 字节扇区推进 ivTweak与V1SectorSize。解密流程V1Header.DecryptV1Header.Decrypt 依次遍历 8 个 key slot跳过未启用的槽位同时记录activeKeys数量若为 0 则报volume 上没有设置口令用口令经 PBKDF2 派生密钥在KeyMaterialOffset * 512处读取条纹材料用v1decrypt解密出分裂密钥afMerge合并 4000 条条纹还原出主密钥候选用 PBKDF2 计算候选主密钥的摘要与头中的 MKDigest 比对——匹配即口令正确返回逐块解密函数、块大小、payload 偏移PayloadOffset * 512与 payload 大小全部槽位失败则返回 incorrect password。LUKSv2 格式实现双头 JSON 元数据架构LUKSv2 的实现在 v2header.go 与 v2json.go 中常量注释标明遵循 LUKS2 On-Disk Format Specification version 1.1.1。与 v1 最大的不同是两个 4096 字节的二进制头主头magicLUKS\xba\xbe即V2Magic1偏移 0与次头magicSKUL\xba\xbe即V2Magic2位于主头 HeaderSize 处每个头含版本、HeaderSize、SequenceID、Label、校验和算法sha256、64 字节盐、UUID、HeaderOffset 与 64 字节校验和可变的 JSON 区域两个头之间存放序列化后的元数据包含 keyslots、digests、segments、tokens、config 五张映射表密钥槽、摘要、段等均以 JSON 描述而非固定结构扩展性更强。V2Stripes 4000、V2AlignKeyslots 4096、V2SectorSize 4096为 v2 的关键常量。加密流程EncryptV2EncryptV2 的要点默认 cipher 同样为aes-xts-plain64payloadSectorSize缺省 4096仅接受 512/1024/2048/4096生成三个盐两个头盐 一个 mkey 盐主密钥 XTS 时 64 字节、否则 32 字节主密钥校验摘要使用 PBKDF2而每个口令密钥槽使用 Argon2 派生argon2.Key即 argon2itimeCost16、threadsCost16memoryCost 由MemoryCostArgon2自动测定口令密钥同样加密 4000 条 afSplit 条纹密钥槽元数据以 JSON 写入头部尺寸按 0x4000 起 2 倍递增的档位16KB/32KB/64KB…/4MB自动对齐并反复迭代重算 JSON 中的 JsonSize、KeyslotsSize、段偏移直到自洽后计算两个头的 sha256 校验和返回定长头部、按payloadSectorSize推进 ivTweak 的加密函数与段扇区大小。解密流程V2Header.DecryptV2Header.Decrypt 的验证链条更长遍历 JSON 中的 digests只处理类型为pbkdf2且带参数的摘要依据摘要引用的 segments 解析出 payload 偏移、大小dynamic表示延伸到文件尾、扇区大小、加密套件与 IVTweak遍历 keyslots跳过 priority 为 ignore 的槽位与摘要未引用的槽位校验 AF 类型为luks1、area 类型为raw、区域尺寸足够按 Kdf 类型分派pbkdf2/argon2i/argon2idargon2.IDKey三种口令派生解密条纹 →afMerge还原主密钥候选 → 用摘要的哈希与迭代参数计算校验值与digest.Digest比对命中即返回解密函数与 payload 信息。底层密码学算法矩阵与块处理支持的分组密码与模式v1encrypt 与v1decrypt提供了对称的加解密实现覆盖以下组合分组密码Go 实现来源支持的块模式AEScrypto/aesecb、cbc-plain、cbc-plain64、cbc-essiv:sha256、xts-plain、xts-plain64Twofishgolang.org/x/crypto/twofish同上Serpentgithub.com/aead/serpent同上CAST5golang.org/x/crypto/cast5同上哈希算法支持 sha1、sha256、sha512、ripemd160hasherByName。扇区尺寸只接受 512/1024/2048/4096缺省 512。v2 的 cipher 采用name-mode形式如aes-xts-plain64由 v2encrypt 拆分成密码与模式后复用 v1 的实现。各模式按processed/sectorSize ivTweak计算 IVcbc-plain用 32 位 IV、cbc-plain64/xts-plain64用 64 位 IV、cbc-essiv:sha256先对密钥做哈希再作为 IV 派生密钥xts-plain对扇区号取模0x100000000。bulk参数控制是否应用iv_large_sectors语义按扇区倍数缩放 IV 值头部密钥材料的加解密传falsepayload 流传true。Anti-Forensic Split 与扩散函数防取证分裂AF Split是 LUKS 的核心机制即使攻击者窃取部分密钥材料也无法直接拼出主密钥。afSplit 把主密钥拆成 4000 条条纹afMerge 反向还原中间的 diffuse 函数以计数器 哈希的方式对数据逐段扩散。分裂时只有最后一组条纹携带真实信息前 N-1 组为随机数据因此任意缺失一条条纹都会导致还原失败——这正是抗取证特性的来源。流式包装器由于加密必须按块进行luksy 提供EncryptWriter与DecryptReaderencryption.go内部缓冲区为 1 MiB 向上对齐到块大小Write侧在缓冲满块时批量加密写出Close时若残留部分块则补零填充成一个完整块后写出Read侧则缓冲、解密并成块返回。配合V1Header.Decrypt/V2Header.Decrypt返回的块函数即可完成端到端的流式加解密。性能自调优机制tune.go 实现了工作量自动测定IterationsPBKDF2从 2 次开始按 2 倍增长试跑 PBKDF2测得耗时后线性外推目标是让口令派生耗时约为 1 秒MemoryCostArgon2/MemoryCostArgon2i以 2 为起点倍增 Argon2 内存成本同样瞄准约 1 秒的耗时目标。这意味着同样的口令在不同性能的机器上会得到不同的迭代次数/内存成本从而保证解密体验的一致性每秒级别的口令校验开销这与 cryptsetup 的 benchmark 思路一致。在 buildah 中的实际应用mkcw 加密磁盘luksy 在 buildah 中的唯一消费方是 internal/mkcw机密工作负载镜像生成。其中 luks.go 提供两个辅助函数GenerateDiskEncryptionPassphrase用crypto/rand生成 32 字节随机数并编码为 hex 字符串作为磁盘加密口令CheckLUKSPassphrase调用luksy.ReadHeaders读取头再对 v1 头或 v2 双头分别调用Decrypt校验口令是否正确。在 archive.go 中可以看到完整的加密磁盘生成链路// Start encrypting and write /disk.img. header, encrypt, blockSize, err : luksy.EncryptV1([]string{diskEncryptionPassphrase}, ) ... diskHeader.Size int64(len(header)) imageSize paddingNeeded int64(footer.Len()) ... if _, err io.Copy(tw, bytes.NewReader(header)); err ! nil { ... } encryptWrapper : luksy.EncryptWriter(encrypt, tw, blockSize) if _, err io.Copy(encryptWrapper, ctxreader.NewCancelableReader(ctx, plain)); err ! nil { ... } encryptWrapper.Close()流程为先用EncryptV1默认aes-xts-plain64生成头部与加密函数 → 写出头部 → 用EncryptWriter把明文磁盘镜像流式加密成 disk.img扇区对齐、补 padding 后附加 KRUN footer。luks_test.go 的TestCheckLUKSPassphrase同时覆盖了 v1 与 v2四种扇区尺寸两条路径验证多口令两个口令均可解锁、错误口令必须失败的行为。构建与测试luksy 自带 Makefilemake构建./cmd/luksy命令行工具make test运行 Go 测试45 分钟超时含覆盖率统计与 bats 集成测试。在 buildah 仓库中它作为 vendor 依赖直接编译进项目因此使用方只需正常go build/make buildah即可无需单独安装 cryptsetup 或内核模块。限制与适用前提仅文件级加解密luksy 不提供 device mapper 映射、卷挂载、在线扩容、key slot 增删等 cryptsetup 功能它只负责头 字节流格式子集v2 的 JSON 元数据按本项目生成时的结构解析读取外部工具创建的 LUKSv2 卷时仅支持其识别到的 keyslot/digest/segment 类型luks2、pbkdf2/argon2i/argon2id、crypt建议若运行环境具备完整 LUKS 工具链应优先使用 cryptsetupluksy 的定位是构建期、无特权、跨平台等受限场景下的离线处理方案。小结luksy 用约两千行的纯 Go 代码严谨地实现了 LUKSv1/LUKSv2 两种磁盘格式的完整加解密协议从字节级头布局v1header.go、v2header.go、PBKDF2/Argon2 密钥派生、AF Split 防取证分裂到按扇区推进 IV 的流式块加解密。它在 buildah 的 mkcw 模块中承担着加密磁盘生成与口令校验的关键职责让 OCI 镜像构建流程可以在不触碰内核 device mapper 的前提下产出标准 LUKS 格式的加密卷是理解纯用户态实现磁盘加密格式的优秀范本。赞分享云原生【免费下载链接】buildahA tool that facilitates building OCI images.项目地址https://gitcode.com/gh_mirrors/bu/buildah点击查看免费下载相关推荐Podman 生态中的 luksy不依赖 device mapper 的 LUKSv1/v2 离线加解密库Podman 生态中的 luksy不依赖 device mapper 的 LUKSv1/v2 离线加解密库 luksy 是一个用 Go 实现的纯用户态加密库容器运行时云原生CLIBuildah 中的 PKCS11 接入miekg/pkcs11 依赖库解析与 OCI 镜像加解密链路Buildah 中的 PKCS 11 接入miekg/pkcs11 依赖库解析与 OCI 镜像加解密链路 本文以 Buildah 仓库中 vendor 进来的云原生ESP32-audioI2S项目在Arduino ESP核心3.1.2版本后的I2S初始化问题分析ESP32 audioI2S项目在Arduino ESP核心3.1.2版本后的I2S初始化问题分析 在ESP32音频开发中ESP32 audioI2S是一个广密码学创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。