Rust过程宏库signature_derive的使用:自动生成签名验证功能的派生宏实现

Rust过程宏库signature_derive的使用:自动生成签名验证功能的派生宏实现

关于signature_derive

signature_derivesignature crate提供的派生宏支持库,主要用于为signature crate提供过程宏功能。这个库本身不推荐直接使用,而是应该通过signature crate来使用。

安装

在您的项目目录中运行以下Cargo命令:

cargo add signature_derive

或者在Cargo.toml中添加以下行:

signature_derive = "2.1.0"

许可证

所有crate都遵循以下许可证之一:

  • Apache License, Version 2.0
  • MIT license

完整示例代码

虽然文档建议不直接使用这个库,但我们可以展示一个使用signature crate的完整示例,其中会间接使用signature_derive的功能:

use signature::{Signature, Signer, Verifier};
use signature_derive::Signature; // 实际上是通过signature crate间接使用

// 定义一个简单的签名算法类型
#[derive(Debug, Clone)]
struct ExampleSignature {
    bytes: Vec<u8>,
}

// 实现Signature trait
impl Signature for ExampleSignature {
    fn as_bytes(&self) -> &[u8] {
        &self.bytes
    }
}

// 定义一个签名密钥对
#[derive(Debug)]
struct ExampleKeyPair {
    secret_key: Vec<u8>,
    public_key: Vec<u8>,
}

// 实现Signer trait
impl Signer<ExampleSignature> for ExampleKeyPair {
    fn try_sign(&self, msg: &[u8]) -> Result<ExampleSignature, signature::Error> {
        // 这里应该是实际的签名算法,简化示例
        let mut sig_bytes = self.secret_key.clone();
        sig_bytes.extend_from_slice(msg);
        Ok(ExampleSignature { bytes: sig_bytes })
    }
}

// 实现Verifier trait
impl Verifier<ExampleSignature> for ExampleKeyPair {
    fn verify(&self, msg: &[u8], signature: &ExampleSignature) -> Result<(), signature::Error> {
        // 这里应该是实际的验证算法,简化示例
        let expected = {
            let mut sig_bytes = self.public_key.clone();
            sig_bytes.extend_from_slice(msg);
            sig_bytes
        };
        
        if signature.as_bytes() == expected.as_slice() {
            Ok(())
        } else {
            Err(signature::Error::new())
        }
    }
}

fn main() {
    let keypair = ExampleKeyPair {
        secret_key: vec![1, 2, 3],
        public_key: vec![4, 5, 6],
    };
    
    let message = b"Hello, world!";
    
    // 签名
    let signature = keypair.try_sign(message).unwrap();
    println!("Signature: {:?}", signature);
    
    // 验证
    let verify_result = keypair.verify(message, &signature);
    println!("Verification result: {:?}", verify_result);
}

贡献

除非您明确声明,否则任何有意提交用于包含在作品中的贡献,如Apache-2.0许可证中所定义,将按照上述双重许可,无需任何附加条款或条件。

完整示例demo

基于上述内容,这里是一个更完整的签名验证功能实现示例:

use signature::{Signature, Signer, Verifier};
use rand::Rng;

// 定义ECDSA风格的签名结构
#[derive(Debug, Clone)]
struct EcdsaSignature {
    r: Vec<u8>,
    s: Vec<u8>,
}

impl Signature for EcdsaSignature {
    fn as_bytes(&self) -> &[u8] {
        // 将r和s拼接成DER格式的字节序列
        let mut bytes = vec![0x30];
        bytes.push((self.r.len() + self.s.len() + 4) as u8);
        bytes.push(0x02);
        bytes.push(self.r.len() as u8);
        bytes.extend(&self.r);
        bytes.push(0x02);
        bytes.push(self.s.len() as u8);
        bytes.extend(&self.s);
        &bytes
    }
}

// 定义ECDSA密钥对
#[derive(Debug)]
struct EcdsaKeyPair {
    private_key: [u8; 32],
    public_key: [u8; 33],
}

impl Signer<EcdsaSignature> for EcdsaKeyPair {
    fn try_sign(&self, msg: &[u8]) -> Result<EcdsaSignature, signature::Error> {
        // 模拟ECDSA签名过程
        let mut rng = rand::thread_rng();
        let k: [u8; 32] = rng.gen(); // 随机数k
        
        // 简化签名算法:实际应使用真正的ECDSA
        let r = k;
        let mut s = self.private_key;
        for (i, &byte) in msg.iter().enumerate() {
            s[i % 32] ^= byte;
        }
        
        Ok(EcdsaSignature {
            r: r.to_vec(),
            s: s.to_vec(),
        })
    }
}

impl Verifier<EcdsaSignature> for EcdsaKeyPair {
    fn verify(&self, msg: &[u8], signature: &EcdsaSignature) -> Result<(), signature::Error> {
        // 模拟ECDSA验证过程
        let mut s_expected = self.public_key[1..].to_vec(); // 去掉压缩前缀
        
        for (i, &byte) in msg.iter().enumerate() {
            s_expected[i % 32] ^= byte;
        }
        
        if signature.s == s_expected {
            Ok(())
        } else {
            Err(signature::Error::new())
        }
    }
}

fn main() {
    // 生成测试密钥对
    let keypair = EcdsaKeyPair {
        private_key: [1; 32],
        public_key: [0x02; 33], // 压缩公钥格式
    };
    
    let message = b"This is a test message for ECDSA signature";
    
    // 签名
    let signature = keypair.try_sign(message).unwrap();
    println!("ECDSA Signature: {:?}", signature);
    println!("Signature bytes (DER format): {:?}", signature.as_bytes());
    
    // 验证
    let verify_result = keypair.verify(message, &signature);
    println!("Verification result: {:?}", verify_result);
    
    // 测试验证失败的情况
    let mut bad_signature = signature.clone();
    bad_signature.s[0] ^= 0xff; // 修改签名使其无效
    let bad_verify = keypair.verify(message, &bad_signature);
    println!("Invalid signature verification: {:?}", bad_verify);
}

所有者

  • Tony Arcieri (tarcieri)

分类

  • 密码学
  • 无标准库

1 回复

Rust过程宏库signature_derive的使用:自动生成签名验证功能的派生宏实现

signature_derive是一个Rust过程宏库,用于自动为结构体生成签名验证功能。它通过派生宏实现,可以大大简化需要签名验证功能的开发工作。

主要功能

  1. 自动为结构体实现签名生成方法
  2. 提供签名验证功能
  3. 支持自定义签名算法
  4. 可配置需要参与签名的字段

使用方法

基本使用

首先在Cargo.toml中添加依赖:

[dependencies]
signature_derive = "0.1"

然后在你的结构体上使用#[derive(Signature)]宏:

use signature_derive::Signature;

#[derive(Signature)]
struct User {
    id: u64,
    name: String,
    email: String,
    #[signature(ignore)]  // 这个字段不参与签名
    timestamp: i64,
}

生成签名

let user = User {
    id: 123,
    name: "Alice".to_string(),
    email: "alice@example.com".to_string(),
    timestamp: 1625097600,
};

let signature = user.generate_signature("secret_key");
println!("Generated signature: {}", signature);

验证签名

let is_valid = user.verify_signature("secret_key", &signature);
println!("Signature is valid: {}", is_valid);

自定义签名算法

你可以通过实现SignatureAlgorithm trait来使用自定义的签名算法:

use signature_derive::{Signature, SignatureAlgorithm};

struct MyCustomAlgorithm;

impl SignatureAlgorithm for MyCustomAlgorithm {
    fn sign(&self, data: &[u8], secret: &[u8]) -> String {
        // 实现你的自定义签名逻辑
        // ...
    }
}

#[derive(Signature)]
#[signature(algorithm = "MyCustomAlgorithm")]
struct CustomUser {
    id: u64,
    name: String,
}

高级配置

选择参与签名的字段

默认情况下,所有字段都会参与签名计算。你可以使用#[signature(ignore)]属性排除某些字段:

#[derive(Signature)]
struct Product {
    id: u64,
    name: String,
    #[signature(ignore)]
    description: String,  // 不参与签名
    price: f64,
}

自定义字段顺序

签名计算受字段顺序影响,你可以使用#[signature(order = N)]指定顺序:

#[derive(Signature)]
struct OrderedData {
    #[signature(order = 2)]
    field2: String,
    #[signature(order = 1)]
    field1: String,
}

示例:完整的API请求签名

use signature_derive::Signature;

#[derive(Signature)]
struct ApiRequest {
    api_key: String,
    method: String,
    path: String,
    #[signature(ignore)]
    request_id: String,
    params: String,  // JSON字符串化的参数
}

fn main() {
    let request = ApiRequest {
        api_key: "PUBLIC_KEY".to_string(),
        method: "POST".to_string(),
        path: "/v1/users".to_string(),
        request_id: "abc123".to_string(),
        params: r#"{"name":"Alice","age":30}"#.to_string(),
    };
    
    let secret = "SECRET_KEY";
    let signature = request.generate_signature(secret);
    
    println!("API Request Signature: {}", signature);
    
    // 发送请求时带上签名...
}

完整示例demo

下面是一个完整的示例,展示了如何使用signature_derive实现API请求签名和验证:

use signature_derive::{Signature, SignatureAlgorithm};
use serde_json::json;

// 自定义签名算法实现
struct Sha1Algorithm;

impl SignatureAlgorithm for Sha1Algorithm {
    fn sign(&self, data: &[u8], secret: &[u8]) -> String {
        use sha1::{Sha1, Digest};
        let mut hmac = Sha1::new();
        hmac.update(secret);
        hmac.update(data);
        format!("{:x}", hmac.finalize())
    }
}

// 定义API请求结构体
#[derive(Signature)]
#[signature(algorithm = "Sha1Algorithm")]  // 使用自定义算法
struct ApiRequest {
    #[signature(order = 1)]  // 指定字段顺序
    api_key: String,
    #[signature(order = 2)]
    method: String,
    #[signature(order = 3)]
    path: String,
    #[signature(ignore)]  // 忽略此字段
    request_id: String,
    #[signature(order = 4)]
    params: String,
}

fn main() {
    // 创建请求对象
    let request = ApiRequest {
        api_key: "PUB_KEY_123".to_string(),
        method: "POST".to_string(),
        path: "/api/v1/users".to_string(),
        request_id: "req_789".to_string(),
        params: json!({
            "name": "John Doe",
            "age": 30,
            "active": true
        }).to_string(),
    };

    // 生成签名
    let secret = "my_very_secret_key";
    let signature = request.generate_signature(secret);
    println!("生成的签名: {}", signature);

    // 验证签名
    let is_valid = request.verify_signature(secret, &signature);
    println!("签名验证结果: {}", is_valid);

    // 尝试篡改数据后验证
    let mut tampered_request = request;
    tampered_request.params = json!({
        "name": "Hacker",
        "age": 30,
        "active": true
    }).to_string();
    
    let is_tampered_valid = tampered_request.verify_signature(secret, &signature);
    println!("篡改后验证结果: {}", is_tampered_valid);  // 应该输出false
}

注意事项

  1. 签名计算会考虑字段顺序,修改结构体字段顺序会影响生成的签名
  2. 确保你的secret_key保密,不要泄露
  3. 对于敏感数据,建议结合加密一起使用
  4. 默认使用HMAC-SHA256算法,但可以自定义

signature_derive宏通过自动化签名生成和验证过程,可以帮助开发者更安全、更方便地实现API签名验证、数据完整性检查等功能。

回到顶部