daksh7011/Nyx

GitHub: daksh7011/Nyx

Nyx 是一款基于 Compose Multiplatform 的跨平台图像隐写应用,使用 AES-256-GCM 加密并将密文嵌入 PNG 像素的最低有效位中,让用户用密码加解密隐藏在图片里的文本信息。

Stars: 1 | Forks: 1

![Nyx logo](https://raw.githubusercontent.com/daksh7011/Nyx/develop/images/nyx-logo.png) # Nyx **你有想要分享的秘密吗?把它藏进一张图片里,并用密码锁起来。** [![License: MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/39/39faa54be350a1dab8afd3b2fb8c1c83e4d9cff84abfef2374d19a18053687c4.svg)](https://github.com/daksh7011/Nyx/actions/workflows/ci.yml) ## 概述 Nyx 将加密的文本信息隐藏在普通图片的像素中。 信息使用从你的密码派生出的密钥通过 AES-256-GCM 进行封装, 写入图像 RGB 通道的最低有效位中,并 导出为无损的 PNG 格式。对其他人来说,它只是一张图片;有了 密码,Nyx 就能准确还原原始信息。 Nyx 是一款 Compose Multiplatform 应用:只需一个 Kotlin 代码库即可运行在 Android、 桌面端 (Linux/macOS/Windows)、Web 端 (Kotlin/Wasm) 以及 iOS 上。 ## 工作原理 ``` message ──(AES-256-GCM)──> encrypted blob ──(LSB embed, 2 bits per R/G/B channel)──> stego PNG key = PBKDF2-HMAC-SHA256(password, 600,000 iterations, random 16-byte salt) ``` 1. **Encrypt** — 明文通过 AES-256-GCM 封装。每条信息都会获得一个 全新的随机 salt 和 nonce,因此加密相同的文本两次会生成 不同的数据块。GCM 是经过认证的:错误的密码或被篡改的图像 会彻底失效——你绝不会得到乱码输出。 2. **Embed** — 加密的数据块会被加上标记帧,并分散到每个像素的红色、绿色和蓝色通道的 两个最低有效位中。写入位置通过带密钥的置换进行打散,因此 payload 不会留下 任何聚集区域。对于单张图片来说过大的 payload 可以跨越多张图片。 3. **Export** — 结果始终为 PNG 格式(无损——这是让 payload 得以保留的必要条件)。解密则反转该流程:提取、认证、解密。 ## 功能 - **加密向导** — 选择一张载体图像(各平台均支持文件选择器, Android/iOS 支持相机拍照),输入信息和密码,即可获得一张保存到你的 vault 中并随时准备分享的隐写 PNG 图片。 - **Vault** — 以网格形式展示你的隐写图像,支持详情查看、分享/导出、 归档和删除。元数据存储在 SQLDelight 中;图像字节以 PNG 文件形式存储在磁盘上。 - **解密** — 打开 vault 中的图像或选择任何图像,输入密码, 即可显示并复制隐藏的信息。对于密码错误和未包含隐藏信息的情况, 会给出明确且截然不同的如实反馈。 - **主题** — 五种调色板(Midnight、Espresso、Nardo、Cream、Mist),支持 系统/浅色/深色模式覆盖,并在多次启动时保持设置。 - **设置** — 关于、开源许可证、擦除 vault、应用版本。 - **无广告、无账号、无网络** — Nyx 不会发起任何网络请求。 你的图像和秘密永远不会离开你的设备。 ## 平台 | 平台 | Vault 持久化 | 相机捕获 | 备注 | |---|---|---|---| | Android 12+ (API 31) | 是 | 是 | 主要目标平台 | | Desktop JVM (Linux / macOS / Windows) | 是 | 否 | Compose for Desktop | | Web (Kotlin/Wasm) | 仅限会话 | 否 | 加密 / 解密 / 导出功能完全可用;vault 列表目前仅存储在内存中 | | iOS (设备 + 模拟器) | 是 | 是 | 仅在 macOS 环境下构建 | ## 架构 ``` flowchart TD subgraph Entry["Entry apps"] android[":androidApp"] desktop[":desktopApp"] web[":webApp"] ios["client/iosApp (Xcode project, macOS-only)"] end subgraph ClientLayer["Client"] clientMod[":client — initKoin, App(), NyxDb (SqlDelight) + VaultSource, iOS source impls"] end subgraph Features["Features — each split :feature:*:client:{api, basic}"] feat["navigation · splash · theme · vault · encrypt · decrypt · settings"] common[":feature:common:client:{api, koin}"] end subgraph Shared["Engines and shared"] crypto[":crypto (AES-256-GCM, PBKDF2)"] steg[":steganography (pure-Kotlin LSB codec)"] data[":shared:data (results, source interfaces, events, clock, ids)"] pres[":shared:presentation (BaseViewModel, ViewState/UiState)"] design[":shared:design-library (Nx* + tokens) incl. :snapshot goldens"] end subgraph TestInfra["Test infra"] ts[":shared:test-support"] cts[":shared:compose-test-support"] end android --> clientMod desktop --> clientMod web --> clientMod ios --> clientMod clientMod --> Features feat --> common Features --> Shared TestInfra -.-> ClientLayer TestInfra -.-> Features TestInfra -.-> Shared ``` - **功能模块** (`:feature:X:client:{api,basic}`):`api` 暴露 `Feature` 接口以及类型安全的 `@Serializable` 路由;`basic` 在隔离的 Koin 容器中实现 该接口。`basic` 模块从不依赖于另一个功能的 `basic`——它只能依赖于另一个功能的 `api` 以便访问其 路由(例如 vault → 加密/解密)。跨功能的运行时信号传递通过 `DomainEventBus` 进行。 - **Engines**:`:crypto` (cryptography-kotlin,AES-256-GCM + PBKDF2) 和 `:steganography` (基于 `PixelImage` 的纯 Kotlin LSB 编解码器) 不依赖于任何其他 项目模块,并通过用例被调用。 - **`:client`** 拥有全局 DI、SqlDelight 数据库 (`NyxDb`) 及其基于 SqlDelight 的 `VaultSource`,以及 iOS 平台源实现 (iOS 没有独立的应用模块)。Android、桌面端和 Web 端的实现 位于各自的入口应用模块中。 - **设计系统**:`Nx*` 原子组件包含主题 token,为 每种视觉状态提供预览,并在 `:shared:design-library:snapshot` 中进行 Paparazzi 黄金测试。 - `build-logic/` 中的 **约定插件** 保持了模块构建脚本的 声明式特性;`gradle/libs.versions.toml` 是唯一的版本来源。 ## 构建 前置条件:JDK 21 和带有 API 37 的 Android SDK。iOS 另外需要 配备 Xcode 的 macOS。 ``` ./gradlew build # everything: assemble + tests + detekt ./gradlew :androidApp:assembleDebug # Android APK ./gradlew :androidApp:installDebug # install on a connected device ./gradlew :desktopApp:run # run the desktop app ./gradlew :webApp:wasmJsBrowserDevelopmentRun # dev server for the web app ./gradlew :shared:design-library:snapshot:verifyPaparazziDebug # design-system goldens ``` **Linux / Windows 注意事项:** iOS 目标会被自动跳过 (`kotlin.native.ignoreDisabledTargets=true`);其他所有内容均可在 本地构建和测试。iOS 编译和 `client/iosApp/` Xcode 项目会在 macOS 环境下进行验证。 ## 安全模型(请务必阅读) - **安全层在于密码学,而不是隐写术。** 信息 使用 AES-256-GCM 加密;密钥通过 PBKDF2-HMAC-SHA256 从你的密码派生而来,包含 60 万次迭代和一个随机的 16 字节 salt,并且每条信息都有一个 全新的随机 nonce。GCM 是一种认证加密——错误的 密码或被修改的图像都会被检测到并拒绝,绝不会悄无声息地被 解密成噪音。 - **LSB 隐写术是一个混淆层。** 编解码器通过带密钥的置换将嵌入的 比特分散到整个图像中,以防止 RS / 样本对隐写分析发现聚集区域——但请假设强大的对手仍然能够 检测出*某些东西*被隐藏了。然而没有你的密码,他们无法 读取它。 - **PNG 只能在无损通道中存活。** 会对图像进行重新压缩(通常压缩为 JPEG)的通讯应用和社交网络 会破坏 payload。请将隐写 图像作为文件分享,而不是作为内联照片发送。 - **你的密码决定了一切。** 无论迭代次数多少,弱密码都会被离线 破解。没有任何恢复机制:失去 密码,就失去了信息。 - **与重写前的 Nyx 彻底脱节。** 旧版(2026 年之前)的 Android 应用生成的图像使用的是已废弃的格式,无法被当前版本解密。 Nyx 是一个实验性的开源项目,基于 MIT 许可证发布,不提供任何形式的担保。它通过 [cryptography-kotlin](https://github.com/whyoleg/cryptography-kotlin) 构建于经过严格审查的加密原语之上,但它 尚未经过独立审计。请勿将其作为保护高风险秘密的 唯一手段。 ## 邮件赞助软件 Nyx 是一款邮件赞助软件 (emailware)。如果你喜欢使用这款应用,或者它在任何方面帮助到了你,请发邮件给 [daksh@technowolf.in](mailto:daksh@technowolf.in) 告诉我——任何你想 说的内容都可以。如果能听到这个项目对某些人 有所帮助,我会真心感激。 :) ## 许可证 [MIT 许可证](LICENSE) — 版权所有 (c) 2020 TechnoWolf FOSS
标签:AES加密, Kotlin, 信息隐藏, 后台面板检测, 图像隐写, 密码学, 手动系统调用, 跨平台应用