Rust过程宏库signature_derive的使用:自动生成签名验证功能的派生宏实现
Rust过程宏库signature_derive的使用:自动生成签名验证功能的派生宏实现
关于signature_derive
signature_derive
是signature
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)
分类
- 密码学
- 无标准库
Rust过程宏库signature_derive的使用:自动生成签名验证功能的派生宏实现
signature_derive
是一个Rust过程宏库,用于自动为结构体生成签名验证功能。它通过派生宏实现,可以大大简化需要签名验证功能的开发工作。
主要功能
- 自动为结构体实现签名生成方法
- 提供签名验证功能
- 支持自定义签名算法
- 可配置需要参与签名的字段
使用方法
基本使用
首先在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
}
注意事项
- 签名计算会考虑字段顺序,修改结构体字段顺序会影响生成的签名
- 确保你的secret_key保密,不要泄露
- 对于敏感数据,建议结合加密一起使用
- 默认使用HMAC-SHA256算法,但可以自定义
signature_derive
宏通过自动化签名生成和验证过程,可以帮助开发者更安全、更方便地实现API签名验证、数据完整性检查等功能。