jedisct1/c-sigma

GitHub: jedisct1/c-sigma

基于 libsodium 和 Ristretto255 的 C 语言 Sigma 协议实现,提供 Schnorr、DLEQ、Pedersen 等零知识证明原语。

Stars: 17 | Forks: 0

# C 语言 Sigma 协议实现 使用 Ristretto255 完整实现 [draft-irtf-cfrg-sigma-protocols-00](https://datatracker.ietf.org/doc/draft-irtf-cfrg-sigma-protocols/)。 ## 功能特性 ### 协议实现 - Schnorr 协议:证明离散对数知识 - DLEQ 协议:证明离散对数相等(也称为 Chaum-Pedersen) - Pedersen 承诺:证明承诺开启知识 - 通用框架:通过简化的 API 构建任意线性关系证明 ### 能力 - 非交互式证明:使用 SHAKE128 的 Fiat-Shamir 变换 - 简单和通用框架接口 - 序列化:支持完整的编码/解码及验证 - 安全:基于 libsodium 的 Ristretto255 群运算 - 规范合规:完整实现 IETF 草案规范 ## 快速开始 ``` #include #include "sigma.h" // Initialize libsodium sodium_init(); // Prove knowledge of private key uint8_t private_key[CSIGMA_SCALAR_BYTES]; uint8_t public_key[CSIGMA_POINT_BYTES]; uint8_t proof[CSIGMA_SCHNORR_PROOF_SIZE]; crypto_core_ristretto255_scalar_random(private_key); crypto_scalarmult_ristretto255_base(public_key, private_key); uint8_t message[] = "Hello"; csigma_schnorr_prove(proof, private_key, public_key, message, sizeof(message)); bool valid = csigma_schnorr_verify(proof, public_key, message, sizeof(message)); ``` ## 构建 前置条件: - C 编译器(clang 或 gcc) - libsodium 开发库 ``` # 安装 libsodium (Ubuntu/Debian) sudo apt-get install libsodium-dev # 安装 libsodium (macOS) brew install libsodium # 构建所有可执行文件 make # 运行所有测试 make check ``` ## API 参考 ### 常量 ``` #define CSIGMA_SCALAR_BYTES 32 // Scalar size #define CSIGMA_POINT_BYTES 32 // Group element size #define CSIGMA_SCHNORR_PROOF_SIZE 64 // Schnorr proof size #define CSIGMA_DLEQ_PROOF_SIZE 96 // DLEQ proof size #define CSIGMA_PEDERSEN_PROOF_SIZE 96 // Pedersen proof size ``` ### Schnorr 协议 证明知道满足 Y = x*G 的 x(G 是生成元)。 ``` // Create proof int csigma_schnorr_prove( uint8_t proof[CSIGMA_SCHNORR_PROOF_SIZE], // Output: 64-byte proof const uint8_t witness[CSIGMA_SCALAR_BYTES], // Secret x const uint8_t public_key[CSIGMA_POINT_BYTES], // Public Y = x*G const uint8_t *message, // Message to bind size_t message_len ); // Returns: 0 on success, -1 on error // Verify proof bool csigma_schnorr_verify( const uint8_t proof[CSIGMA_SCHNORR_PROOF_SIZE], const uint8_t public_key[CSIGMA_POINT_BYTES], const uint8_t *message, size_t message_len ); // Returns: true if valid, false otherwise ``` ### DLEQ 协议 在不泄露指数的情况下证明 log_g1(h1) = log_g2(h2)。 ``` // Create proof int csigma_dleq_prove( uint8_t proof[CSIGMA_DLEQ_PROOF_SIZE], // Output: 96-byte proof const uint8_t witness[CSIGMA_SCALAR_BYTES], // Secret x where h1=g1^x, h2=g2^x const uint8_t g1[CSIGMA_POINT_BYTES], const uint8_t h1[CSIGMA_POINT_BYTES], const uint8_t g2[CSIGMA_POINT_BYTES], const uint8_t h2[CSIGMA_POINT_BYTES], const uint8_t *message, size_t message_len ); // Returns: 0 on success, -1 on error // Verify proof bool csigma_dleq_verify( const uint8_t proof[CSIGMA_DLEQ_PROOF_SIZE], const uint8_t g1[CSIGMA_POINT_BYTES], const uint8_t h1[CSIGMA_POINT_BYTES], const uint8_t g2[CSIGMA_POINT_BYTES], const uint8_t h2[CSIGMA_POINT_BYTES], const uint8_t *message, size_t message_len ); // Returns: true if valid, false otherwise ``` ### Pedersen 承诺 ``` // Create commitment C = x*G + r*H int csigma_pedersen_commit( uint8_t commitment[CSIGMA_POINT_BYTES], const uint8_t value[CSIGMA_SCALAR_BYTES], const uint8_t randomness[CSIGMA_SCALAR_BYTES], const uint8_t G[CSIGMA_POINT_BYTES], const uint8_t H[CSIGMA_POINT_BYTES] ); // Prove knowledge of opening int csigma_pedersen_prove( uint8_t proof[CSIGMA_PEDERSEN_PROOF_SIZE], const uint8_t value[CSIGMA_SCALAR_BYTES], const uint8_t randomness[CSIGMA_SCALAR_BYTES], const uint8_t G[CSIGMA_POINT_BYTES], const uint8_t H[CSIGMA_POINT_BYTES], const uint8_t C[CSIGMA_POINT_BYTES], const uint8_t *message, size_t message_len ); // Verify proof bool csigma_pedersen_verify( const uint8_t proof[CSIGMA_PEDERSEN_PROOF_SIZE], const uint8_t G[CSIGMA_POINT_BYTES], const uint8_t H[CSIGMA_POINT_BYTES], const uint8_t C[CSIGMA_POINT_BYTES], const uint8_t *message, size_t message_len ); ``` ## 何时使用各个协议 ### Schnorr 协议 证明内容:在不泄露秘密值(离散对数)的情况下证明知道该值。 数学属性:证明“我知道满足 Y = x*G 的 x”,其中 G 是生成元,Y 是公开的。 用途: - 数字签名:证明你拥有与公钥对应的私钥 - 身份验证:登录服务而无需传输密码 - 加密货币钱包:在不泄露私钥的情况下证明资金所有权 - 访问控制:在不暴露凭证的情况下证明你拥有凭证 - 密码认证密钥交换 (PAKE):基于密码建立安全通道 示例场景:Alice 想要证明她拥有一个比特币地址。她使用 Schnorr 协议证明她知道与该公开地址对应的私钥,而无需泄露私钥本身。 ### DLEQ 协议 证明内容:在不泄露公共指数的情况下,证明两个离散对数相等。 数学属性:证明“log_g1(h1) = log_g2(h2)”或等价地证明存在某个秘密 x 满足“h1 = g1^x 且 h2 = g2^x”。 用途: - 可验证加密:证明密文加密了特定值而无需解密 - 匿名凭证:证明两个凭证属于同一用户而不泄露身份 - 混合网络:在隐私协议中证明正确重加密 - 跨链原子交换:证明多笔交易中使用了同一秘密 - 可验证洗牌:证明列表被正确置换而不泄露置换方式 - 盲签名:证明盲化和非盲化值之间的一致性 示例场景:投票系统需要证明在混合阶段加密的选票被正确重加密(相同选票,不同随机性),而无需泄露实际选票。 ## 协议对比 | 方面 | Schnorr | DLEQ (Chaum-Pedersen) | | ------------- | --------------------------- | ----------------------------- | | 证明大小 | 64 字节 | 96 字节 | | 证明内容 | 知道一个秘密值 | 两个离散对数相等 | | 复杂度 | 较简单 | 较复杂 | | 计算量 | 验证需 2 次指数运算 | 验证需 4 次指数运算 | | 主要用途 | 认证、签名 | 可验证加密、DLEQ | ## API 层级 ### 简单 API 用于常见协议的便捷函数(推荐大多数用户使用): - `csigma_schnorr_prove()` / `csigma_schnorr_verify()` - `csigma_dleq_prove()` / `csigma_dleq_verify()` - `csigma_pedersen_prove()` / `csigma_pedersen_verify()` ### 框架 API - 简化构建器(推荐) 使用易于使用的辅助工具构建任意线性关系证明: ``` // Add elements and scalars in one step int G = csigma_relation_add_element(&relation, generator); int X = csigma_relation_add_element(&relation, public_key); int x = csigma_relation_add_scalar(&relation); // Add equation with single term (covers 80% of use cases) csigma_relation_add_equation_simple(&relation, X, x, G); // Prove and verify csigma_prover_commit(&relation, witness, commitment, &state); csigma_prover_response(&state, challenge, response); bool valid = csigma_verify(&relation, commitment, challenge, response); ``` ### 框架 API - 通用(用于复杂多项式方程) 用于形如 C = x*G + r*H 的方程: ``` // Allocate multiple scalars/elements at once int x = csigma_relation_allocate_scalars(&relation, 1); int r = csigma_relation_allocate_scalars(&relation, 1); // Add elements int G = csigma_relation_add_element(&relation, G_value); int H = csigma_relation_add_element(&relation, H_value); // Multi-term equation int scalar_indices[] = {x, r}; int element_indices[] = {G, H}; csigma_relation_add_equation(&relation, C, scalar_indices, element_indices, 2); ``` ### 序列化 API ``` // Serialize proof int csigma_serialize_proof( uint8_t *output, const uint8_t *commitment, size_t num_commitment_elements, const uint8_t *response, size_t num_response_scalars ); // Deserialize proof (with validation) int csigma_deserialize_proof( uint8_t *commitment, size_t num_commitment_elements, uint8_t *response, size_t num_response_scalars, const uint8_t *data, size_t data_len ); // Calculate expected proof size size_t csigma_proof_size(size_t num_commitment_elements, size_t num_response_scalars); ``` 有关使用简化 API 的框架完整示例,请参见 `tests/test_framework.c`。 ## 实现细节 - 椭圆曲线群:Ristretto255(通过 libsodium) - 哈希函数:用于 Fiat-Shamir 挑战的 SHAKE128 - 证明大小: - Schnorr:64 字节(1 个承诺 + 1 个响应) - DLEQ:96 字节(2 个承诺 + 1 个响应) - Pedersen:96 字节(1 个承诺 + 2 个响应) - 安全性:128 位安全级别 - 命名空间:所有公开函数均以 `csigma_` 为前缀 - 错误处理: - Prove/create 函数成功时返回 0,错误时返回 -1 - Verify 函数有效时返回 true,否则返回 false ## 示例 请参阅以下文件以获取完整的工作示例: - `example.c` - 简单 API 演示 - `tests/test_framework.c` - 简化框架 API 用法 - `tests/test_sigma.c` - Schnorr 和 DLEQ 测试 - `tests/test_pedersen.c` - Pedersen 承诺测试
标签:DLEQ, Fiat-Shamir变换, IETF标准, libsodium, Pedersen承诺, Ristretto255, Schnorr协议, SHAKE128, Sigma协议, 加密库, 客户端加密, 密码学, 手动系统调用, 椭圆曲线, 离散对数, 网络安全, 隐私保护, 零知识证明, 非交互式证明