跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

Noise-C库完整指南:从理论到实践

Noise协议框架是一套用于构建安全通信协议的加密工具包,而Noise-C则是这套框架在C语言中最具代表性的参考实现。本文将从零开始,完整介绍如何获取、编译和使用这个库,并通过一个完整的可运行示例,帮助你在理解其工作原理的同时,真正动手测试起来。

一、Noise-C是什么

Noise-C是一个纯C语言实现的Noise协议框架参考实现,由Rhys Weatherley编写,代码采用MIT许可证发布,在密码学社区中被广泛认可。它也被昵称为”Noisy”——就是把”Noise-C”说快了的效果。

作为参考实现,它的定位是正确性和完整性的示范,而不是一个开箱即用的生产级框架。它遵循”Sans-IO”原则:只负责计算加密握手消息,不处理网络收发,这给了开发者极大的灵活性。

二、仓库选择:三个主要分支

Noise-C目前有多个活跃的维护分支,你需要根据自己的场景选择:

2.1 原版仓库(rweather/noise-c)

这是Rhys Weatherley维护的原始官方仓库,是所有其他分支的上游。适合作为学习和研究的基础。

  • 地址:https://github.com/rweather/noise-c

2.2 Signal分支(signalapp/noise-c)

Signal(知名即时通讯软件)维护的公共分支,主要用于实验后量子密码学集成(如Kyber算法)。

2.3 ESPHome移植版(esphome-libs/noise-c)

这是一个针对嵌入式环境和微控制器优化的移植版本,支持PlatformIO、ESP-IDF和纯CMake三种构建系统,可以在ESP8266/ESP32等资源受限设备上运行。

本文推荐使用原版仓库,因为它是学习Noise协议最干净的起点。

三、从零开始:下载与编译

3.1 环境准备

在开始之前,确保你的系统已安装必要的构建工具:

Ubuntu/Debian:

sudo apt update
sudo apt install build-essential cmake git

macOS:

xcode-select --install
brew install cmake git

Windows(使用MSYS2或WSL2):
建议使用WSL2安装Ubuntu,然后按照Linux步骤操作。

3.2 安装依赖:libsodium

Noise-C默认使用libsodium作为加密后端,需要先安装:

Ubuntu/Debian:

sudo apt-get install libsodium-dev

macOS:

brew install libsodium

Windows(WSL2):同上Ubuntu命令。

3.3 克隆仓库并编译

# 克隆仓库
git clone https://github.com/rweather/noise-c.git
cd noise-c

# 查看所有可用分支(可选)
git branch -a

# 创建构建目录并编译
mkdir build && cd build
cmake ..
make -j$(nproc)   # 使用多核加速编译

编译完成后,核心库文件会生成在build/src/目录下(如libnoise.a)。

3.4 编译示例程序

示例程序位于examples/echo目录,单独编译它们:

cd examples/echo
mkdir build && cd build
cmake ..
make

编译完成后会生成两个可执行文件:

  • echo-server:服务端程序
  • echo-client:客户端程序

四、运行测试:完整的握手体验

4.1 启动服务端

打开一个终端,进入示例构建目录,启动服务端:

cd /path/to/noise-c/examples/echo/build
./echo-server

服务端默认监听端口2222,启动后会显示类似信息:

Listening on port 2222...

4.2 启动客户端

打开另一个终端,启动客户端连接到服务端:

cd /path/to/noise-c/examples/echo/build
./echo-client

4.3 观察输出

如果一切正常,你会看到类似下面的输出:

服务端输出:

Listening on port 2222...
Handshake complete
Received: Hello from client
Sending back: Hello from client

客户端输出:

Connected to server
Handshake complete
Sending: Hello from client
Received: Hello from client

这表明:

  1. 握手成功:双方通过Noise_XX_25519_ChaChaPoly_BLAKE2s模式完成了双向身份认证
  2. 加密传输:客户端发送的明文”Hello from client”被加密传输,服务端解密后回显

4.4 观察不同握手模式的行为

你可以修改协议名称来观察不同模式的差异。例如:

协议名称模式认证方式适用场景
Noise_XX_25519_ChaChaPoly_BLAKE2sXX双向认证客户端-服务端强认证
Noise_NN_25519_ChaChaPoly_BLAKE2sNN匿名只需加密,不需要身份验证
Noise_IK_25519_ChaChaPoly_BLAKE2sIK发起方已知响应方公钥0-RTT高性能场景

五、代码解析:为什么这是真正的”实际操作”

官方示例之所以不简单,在于它展示了 完整的生产级握手流程,而不仅仅是一个API调用演示。

核心代码骨架

// 初始化HandshakeState
noise_handshakestate_new_by_name(
    &handshake,
    "Noise_XX_25519_ChaChaPoly_BLAKE2s",
    role  // NOISE_ROLE_INITIATOR 或 NOISE_ROLE_RESPONDER
);

// 配置密钥对(XX模式需要静态密钥对)
noise_handshakestate_set_local_keypair(handshake, local_private_key);

// 握手循环——状态机驱动
while (true) {
    switch (noise_handshakestate_get_action(handshake)) {
        case NOISE_ACTION_WRITE_MESSAGE:
            noise_handshakestate_write_message(handshake, buffer, &len);
            send(sock, buffer, len, 0);  // 实际网络发送
            break;
        case NOISE_ACTION_READ_MESSAGE:
            recv(sock, buffer, sizeof(buffer), 0);  // 实际网络接收
            noise_handshakestate_read_message(handshake, buffer, len, NULL);
            break;
        case NOISE_ACTION_SPLIT:
            noise_handshakestate_split(handshake, &send_cipher, &recv_cipher);
            // 握手完成,进入加密数据传输阶段
            return true;
    }
}

关键API解读

  • noise_handshakestate_new_by_name:用一串字符串(如"Noise_XX_25519_ChaChaPoly_BLAKE2s")同时指定了握手模式、密钥交换算法、加密算法和哈希函数。
  • noise_handshakestate_get_action:返回当前状态机需要执行的动作(WRITE_MESSAGE、READ_MESSAGE、SPLIT或FAILED),驱动整个握手流程。
  • noise_handshakestate_write_message / read_message:生成加密的握手消息和解析收到的消息。
  • noise_handshakestate_split:握手完成后,将HandshakeState分裂为两个CipherState,分别用于加密发送和解密接收。

六、拓展测试:替换加密后端

Noise-C支持切换加密后端,你可以尝试使用参考实现(不依赖libsodium):

编辑include/noise/defines.h,找到并启用:

#define NOISE_USE_REFERENCE_IMPLEMENTATION

然后重新编译:

cd build
make clean
cmake -DNOISE_USE_REFERENCE_IMPLEMENTATION=ON ..
make

七、常见问题排查

7.1 找不到libsodium

CMake Error: Could NOT find Sodium

解决:确保已安装libsodium-dev,或使用参考后端编译。

7.2 端口已被占用

bind: Address already in use

解决:修改examples/echo/echo-server.c中的端口号,或杀掉占用进程。

7.3 握手失败

Handshake failed: Invalid MAC

解决:检查客户端和服务端使用的协议名称是否完全一致(包括大小写)。

八、总结

本文带你完成了从获取源码、安装依赖、编译构建到运行测试的全流程。你现在应该能够:

  1. 选择合适的Noise-C分支并根据需要编译
  2. 运行官方示例观察完整的Noise握手流程
  3. 理解状态机驱动的核心编程模型

Noise-C的价值在于:它把Noise协议框架从一个抽象规范变成了可运行的代码。通过实际运行和修改示例,你可以真正理解Noise协议的设计哲学——用状态机驱动安全通信,用协议名称定义全部安全参数。

作者

老丹

关注我
其他文章
上一个

Noise协议框架:安全通信的“可编程乐高”

下一个

Libsodium:现代密码学开发的“安全基石”

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • Ubuntu 防火墙迁移指南:从 UFW 到 firewalld 的完整实践 2026年9月12日
  • Nano 编辑器完全操作指南:从入门到熟练 2026年9月12日
  • SSCG:让自签名证书不再“危险”的生成工具 2026年9月12日
  • Ubuntu Samba 服务安装与配置完全指南 2026年9月12日
  • 从零开始:用 Docker 部署 Jellyfin 并启用英特尔核显硬件加速 2026年9月11日

文章分类

  • C/C++开发 (22)
  • Docker容器 (5)
  • Linux工具包 (17)
  • Linux服务配置 (50)
  • Linux系统 (16)
  • OpenWrt路由 (3)
  • Shell脚本 (3)
  • 代码管理 (1)
  • 安防技术 (4)
  • 数据安全 (36)
  • 未分类 (1)
  • 网络协议 (25)
  • 计算机理论 (23)
  • 音视频技术 (5)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号