lamport签名:one time签名方案

本文详细介绍了如何在Rust中实现Lamport单次签名方案,包括生成密钥对、消息哈希、签名过程以及公钥验证。作者使用SHA256作为one-waypermutation函数,展示了如何创建和验证数字签名以确保消息的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 引言

开源代码实现见:

所谓one-time signature方案,是指:

  • 其仅可用于安全地签署一个消息

Lamport One Time Signature方案,所构建的数字签名中,通常需使用某密码学哈希函数(如某one way permutation函数 f f f)。

假设消息长度为 n n n(可借助另一哈希函数,如SHA256之类的,对消息先进行处理,那样待签名的消息长度 n = 256 n=256 n=256),所选择的one-way permutation函数为 f : { 0 , 1 } n → { 0 , 1 } n f:\{0,1\}^n\rightarrow \{0,1\}^n f:{0,1}n{0,1}n,则整个
在这里插入图片描述
具体示例为:【其中的 f f f函数为digest::SHA256

extern crate lamport_signatures;
use lamport_signatures::lamport_utils;

// generate private key
let priv_key = lamport_utils::gen_secret_key().unwrap();
// derive public key
let pub_key = lamport_utils::derive_pub_key(&priv_key);
// create some message
let msg = "hi elichai2, some secret msg";
// digest the msg
let msg_digest = lamport_utils::hash(msg.as_bytes());
// sign the digest
let signature : Vec<[u8;32]> = priv_key.sign(&msg_digest);
// verify signature against public key
let is_valid = pub_key.verify(&msg_digest, &signature);

其中:

use ring::rand::{SecureRandom, SystemRandom};
use ring::error::Unspecified;
use ring::digest;
use bit::BitIndex;

#[derive(Debug)]
pub struct PrivKey {
    tuples : Vec<([u8;32],[u8;32])>
}

impl PrivKey{
    pub fn get_tuple(&self,i : usize )->([u8;32],[u8;32]){
        return self.tuples[i]
    }

    pub fn tuples_amount(&self)->usize{
        256
    }

    pub fn sign(&self, h : &[u8;32])->Vec<[u8;32]>{
        let mut counter = 0;
        let mut signature : Vec<[u8;32]> = Vec::with_capacity(256);
        for (_index,b) in h.iter().enumerate(){
            let val = b;
            for i in 0..u8::bit_length(){
                let is_on = val.bit(i);
                let t = self.get_tuple(counter);
                let secret_num = match is_on {
                    true => t.1,
                    false => t.0
                };
                signature.push(secret_num);
                counter += 1;
            }
        }
        signature
    }
}

#[derive(Debug)]
pub struct PubKey {
    hashes : Vec<([u8; 32], [u8; 32])>,
}

impl PubKey{
    pub fn get_tuple(&self, i : usize)->([u8; 32], [u8; 32]){
        return self.hashes[i];
    }
    pub fn flat_hashes(&self)->Vec<[u8;32]>{
        let mut flat = Vec::new();
        for i in 0..256{
            let (a,b) = self.get_tuple(i);
            flat.push(a);
            flat.push(b);
        }
        flat
    }
    /*
    for each bit in digest:
    -  if bit==1 :
        get hash from bit index, tuple 1
    -  if bit ==0 :
        get hash from bit index, tuple 0

    hash the value in signature[bit index]
    and compare the hashes.
    */
    pub fn verify(&self,digest : &[u8;32],  signature : &Vec<[u8;32]>)->bool{
        let mut counter = 0;
        let mut verified = true;
        for (_index,b) in digest.iter().enumerate(){
            let val = b;
            for i in 0..u8::bit_length(){
                let is_on = val.bit(i);
                let t = self.get_tuple(counter);
                let secret_num_hash = match is_on {
                    true => t.1,
                    false => t.0
                };
                //
                let test_hash = hash(&signature[counter]);
                if test_hash != secret_num_hash{
                    verified = false;
                    break;
                }
                counter += 1;
            }
        }
        verified
    }
}

fn generate_pair(sr : &SystemRandom)->Result<([u8;32],[u8;32]),Box<Unspecified>>{
    let mut a = [0u8; 32];
    let mut b = [0u8; 32];
    sr.fill(&mut a[..])?;
    sr.fill(&mut b[..])?;
    Ok((a,b))
}

pub fn gen_secret_key_with_input(_entrophy : [u8;256])->Result<PrivKey,Box<Unspecified>>{
    let sr = SystemRandom::new();

    // entrophy.into_iter().map(|s| s % 255);
    let mut pairs = Vec::with_capacity(256);
    for _i in 0..256{
        let (a,b) = generate_pair(&sr)?;
        //TODO:: add entrophy here .... to a and b
        pairs.push((a,b));
    }
    Ok(PrivKey{tuples : pairs})
}

pub fn gen_secret_key()->Result<PrivKey,Box<Unspecified>>{
    let sr = SystemRandom::new();
    let mut pairs = Vec::with_capacity(256);
    for _i in 0..256{
        let (a,b) = generate_pair(&sr)?;
        pairs.push((a,b));
    }
    Ok(PrivKey{tuples : pairs})
}

pub fn derive_pub_key(priv_key : &PrivKey)-> PubKey{
    let mut hashes: Vec<([u8; 32], [u8; 32])> = Vec::with_capacity(priv_key.tuples_amount());
    for i in 0..priv_key.tuples_amount(){
        let (sec_a,sec_b) = priv_key.get_tuple(i);
        let hash_a = digest::digest(&digest::SHA256, &sec_a);
        let hash_b = digest::digest(&digest::SHA256, &sec_b);
        let mut array_hash_a = [0u8; 32];
        let mut array_hash_b = [0u8; 32];
        array_hash_a.copy_from_slice(hash_a.as_ref());
        array_hash_b.copy_from_slice(hash_b.as_ref());
        hashes.push((array_hash_a,array_hash_b));
    }
    PubKey{hashes: hashes}
}

pub fn hash(data : &[u8])->[u8;32]{
    let digest = digest::digest(&digest::SHA256,&data);
    let mut byte_result = [0u8;32];
    byte_result.copy_from_slice(digest.as_ref());
    byte_result
}

参考资料

[1] Lamport One Time Signature Scheme
[2] Digital Signatures – CS 282A/MATH 209A: Foundations of Cryptography Prof. Rafail Ostrovsky

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值