Rust秘密共享库vsss-rs的使用:实现安全高效的阈值秘密共享方案

Rust秘密共享库vsss-rs的使用:实现安全高效的阈值秘密共享方案

可验证的秘密共享方案

这个crate提供了各种密码学可验证的秘密共享方案,当Rust标准库可用时。

  • 此实现目前正在审核中,审核完成后将发布结果。在此之前请自行承担使用风险。
  • 此实现不需要Rust标准库。
  • 除非明确注明,否则所有操作都是常数时间。

从版本2升级的注意事项

接口已重新设计以相互兼容并支持序列化。

从版本3升级的注意事项

ShareIdentifier trait已修改如下:

  • to_buffer 接收一个字节缓冲区并用标识符的字节表示填充内容
  • from_buffer 接收一个字节缓冲区并从字节表示创建标识符
  • to_vec 如果启用了features=alloc或std,则返回字节表示作为Vec

文档

可验证的秘密共享方案用于将秘密分成多个份额并在不同实体之间分发,能够验证份额是否正确并属于特定集合。这个crate包括Shamir的秘密共享方案,它不支持验证,但更多是其他方案的基础构建块。

这个crate支持Feldman和Pedersen可验证的秘密共享方案。

默认方法

分割和组合秘密的默认方法是:

  • shamir::split_secret
  • feldman::split_secret
  • pedersen::split_secret
  • combine_shares
  • combine_shares_group

完整示例代码

P-256示例

use vsss_rs::{*, shamir};
use elliptic_curve::ff::PrimeField;
use p256::{NonZeroScalar, Scalar, SecretKey};

let mut osrng = rand_core::OsRng::default();
let sk = SecretKey::random(&mut osrng);
let nzs = sk.to_nonzero_scalar();
let res = shamir::split_secret::<Scalar, u8, Vec<u8>>(2, 3, *nzs.as_ref(), &mut osrng);
assert!(res.is_ok());
let shares = res.unwrap();
let res = combine_shares(&shares);
assert!(res.is_ok());
let scalar: Scalar = res.unwrap();
let nzs_dup = NonZeroScalar::from_repr(scalar.to_repr()).unwrap();
let sk_dup = SecretKey::from(nzs_dup);
assert_eq!(sk_dup.to_bytes(), sk.to_bytes());

或者使用DefaultStdVsss结构体:

use elliptic_curve::ff::Field;

let mut osrng = rand_core::OsRng::default();
let secret = p256::Scalar::random(&mut osrng);
let res = DefaultStdVsss::<p256::ProjectivePoint>::split_secret(2, 3, secret, &mut osrng);
assert!(res.is_ok());
let shares = res.unwrap();
let res = combine_shares(&shares);
assert!(res.is_ok());
let scalar: p256::Scalar = res.unwrap();
assert_eq!(secret, scalar);

Secp256k1示例

use vsss_rs::{*, shamir};
use elliptic_curve::ff::PrimeField;
use k256::{NonZeroScalar, Scalar, ProjectivePoint, SecretKey};

let mut osrng = rand_core::OsRng::default();
let sk = SecretKey::random(&mut osrng);
let secret = *sk.to_nonzero_scalar();
let res = shamir::split_secret::<Scalar, [u8; 1], u8, Vec<u8>>(2, 3, secret, &mut osrng);
assert!(res.is_ok());
let shares = res.unwrap();
let res = combine_shares(&shares);
assert!(res.is_ok());
let scalar: Scalar = res.unwrap();
let nzs_dup = NonZeroScalar::from_repr(scalar.to_repr()).unwrap();
let sk_dup = SecretKey::from(nzs_dup);
assert_eq!( sk_dup.to_bytes(), sk.to_bytes());

Curve25519示例

use curve25519_dalek::scalar::Scalar;
use rand::Rng;
use ed25519_dalek::SecretKey;
use vsss_rs::{curve25519::WrappedScalar, *};
use x25519_dalek::StaticSecret;

let mut osrng = rand::rngs::OsRng::default();
let sc = Scalar::hash_from_bytes::<sha2::Sha512>(&osrng.gen::<[u8; 32]>());
let sk1 = StaticSecret::from(sc.to_bytes());
let ske1 = SecretKey::from_bytes(&sc.to_bytes()).unwrap();
let res = shamir::split_secret::<WrappedScalar, [u8; 1], u8, Vec<u8>>(2, 3, sc.into(), &mut osrng);
assert!(res.is_ok());
let shares = res.unwrap();
let res = combine_shares(&shares);
assert!(res.is_ok());
let scalar: WrappedScalar = res.unwrap();
assert_eq!(scalar.0, sc);
let sk2 = StaticSecret::from(scalar.0.to_bytes());
let ske2 = SecretKey::from_bytes(&scalar.0.to_bytes()).unwrap();
assert_eq!(sk2.to_bytes(), sk1.to_bytes());
assert_eq!(ske1.to_bytes(), ske2.to_bytes());

完整示例demo

以下是一个完整的示例,展示如何使用vsss-rs实现阈值秘密共享:

// 导入必要的库
use vsss_rs::{*, shamir};
use p256::{NonZeroScalar, Scalar, SecretKey};
use rand_core::OsRng;

fn main() {
    // 初始化随机数生成器
    let mut rng = OsRng::default();
    
    // 1. 创建一个秘密密钥
    let secret_key = SecretKey::random(&mut rng);
    let secret_scalar = *secret_key.to_nonzero_scalar();
    
    // 2. 使用Shamir方案分割秘密(2-3阈值方案)
    let shares_result = shamir::split_secret::<Scalar, u8, Vec<u8>>(
        2,  // 阈值
        3,  // 总份额数
        secret_scalar, 
        &mut rng
    );
    
    // 处理结果
    let shares = match shares_result {
        Ok(s) => s,
        Err(e) => {
            println!("分割秘密失败: {:?}", e);
            return;
        }
    };
    
    // 3. 验证我们可以用足够的份额恢复秘密
    let recovery_result = combine_shares(&shares[0..2]); // 使用2个份额
    
    match recovery_result {
        Ok(recovered) => {
            let recovered_scalar: Scalar = recovered;
            let recovered_key = SecretKey::from(
                NonZeroScalar::from_repr(recovered_scalar.to_repr()).unwrap()
            );
            
            // 验证恢复的密钥与原始密钥相同
            assert_eq!(recovered_key.to_bytes(), secret_key.to_bytes());
            println!("成功恢复秘密密钥!");
        }
        Err(e) => println!("恢复秘密失败: {:?}", e),
    }
}

许可证

根据以下任一许可授权:

  • Apache License, Version 2.0
  • MIT license

贡献

除非您明确声明,否则根据Apache-2.0许可证提交的任何贡献都应按照上述许可授权,不附加任何其他条款或条件。


1 回复

Rust秘密共享库vsss-rs的使用指南

介绍

vsss-rs是一个Rust实现的阈值秘密共享(Threshold Secret Sharing)库,基于Shamir的秘密共享方案。它允许你将一个秘密分割成多个份额(share),只有收集到足够数量的份额(达到阈值)才能重建原始秘密。

主要特性:

  • 安全高效的Rust实现
  • 支持任意阈值和份额数量
  • 使用有限域运算保证安全性
  • 简单易用的API

安装

在Cargo.toml中添加依赖:

[dependencies]
vsss-rs = "0.2"

基本使用方法

1. 分割秘密

use vsss_rs::{combine, split, Share};
use rand::thread_rng;

fn main() {
    // 要共享的秘密(32字节)
    let secret = b"This is a very secret message!!!".to_vec();
    
    // 设置参数:总份额数=5,阈值=3
    let n = 5;
    let k = 3;
    
    // 分割秘密
    let mut rng = thread_rng();
    let shares = split(&secret, n, k, &mut rng).unwrap();
    
    // 打印生成的份额
    for (i, share) in shares.iter().enumerate() {
        println!("Share {}: {}", i + 1, hex::encode(share));
    }
}

2. 重建秘密

use vsss_rs::{combine, Share};

fn main() {
    // 假设我们有以下3个份额(阈值=3)
    let share1 = hex::decode("0123...").unwrap(); // 替换为实际份额
    let share2 = hex::decode("4567...").unwrap();
    let share3 = hex::decode("89ab...").unwrap();
    
    // 组合份额重建秘密
    let shares: Vec<Share> = vec![share1, share2, share3];
    let secret = combine(&shares).unwrap();
    
    println!("Recovered secret: {:?}", String::from_utf8(secret).unwrap());
}

高级用法

自定义有限域

use vsss_rs::{combine, split, Share, GF256};
use rand::thread_rng;

fn main() {
    let secret = b"Custom field secret".to_vec();
    let n = 4;
    let k = 2;
    
    let mut rng = thread_rng();
    let shares = split::<GF256>(&secret, n, k, &mut rng).unwrap();
    
    // 使用任意2个份额重建
    let partial_shares = vec![shares[0].clone(), shares[2].clone()];
    let recovered = combine::<GF256>(&partial_shares).unwrap();
    
    assert_eq!(secret, recovered);
}

验证份额

use vsss_rs::{split, verify, Share, GF256};
use rand::thread_rng;

fn main() {
    let secret = b"Verifiable secret".to_vec();
    let n = 3;
    let k = 2;
    
    let mut rng = thread_rng();
    let shares = split::<GF256>(&secret, n, k, &mut rng).unwrap();
    
    // 验证份额有效性
    for share in &shares {
        assert!(verify::<GF256>(share));
    }
    
    println!("All shares are valid!");
}

完整示例demo

下面是一个完整的示例,展示了从秘密分割到重建的完整流程:

use vsss_rs::{combine, split, verify, Share, GF256};
use rand::thread_rng;
use hex;

fn main() {
    // 1. 准备要共享的秘密
    let secret = b"My top secret password".to_vec();
    println!("Original secret: {:?}", String::from_utf8_lossy(&secret));

    // 2. 设置分割参数
    let total_shares = 5;  // 总份额数
    let threshold = 3;     // 重建所需的最小份额数
    
    // 3. 分割秘密
    let mut rng = thread_rng();
    let shares = split::<GF256>(&secret, total_shares, threshold, &mut rng).unwrap();
    
    // 4. 打印并验证所有份额
    println!("\nGenerated shares:");
    for (i, share) in shares.iter().enumerate() {
        println!("Share {}: {}", i + 1, hex::encode(share));
        assert!(verify::<GF256>(share));  // 验证每个份额
    }
    
    // 5. 选择部分份额用于重建(达到阈值即可)
    let selected_shares = vec![
        shares[0].clone(),
        shares[2].clone(),
        shares[4].clone()  // 使用第1、3、5个份额
    ];
    
    // 6. 重建秘密
    let recovered = combine::<GF256>(&selected_shares).unwrap();
    println!("\nRecovered secret: {:?}", String::from_utf8_lossy(&recovered));
    
    // 7. 验证重建的秘密是否与原始秘密一致
    assert_eq!(secret, recovered);
    println!("\nSecret successfully recovered!");
}

注意事项

  1. 秘密必须是字节向量(Vec<u8>)
  2. 阈值k必须小于等于总份额数n
  3. 重建时需要至少k个有效份额
  4. 对于生产环境,请确保使用安全的随机数生成器

vsss-rs库提供了安全高效的秘密共享实现,适用于需要分布式存储敏感数据的场景,如密钥管理、安全多方计算等应用。

回到顶部