Rust :公钥、私钥与keypair、signature、verify 三部曲

72 篇文章 3 订阅

如何理解签名体制包含3个算法:KeyGen(密钥生成算法),Sign(签名算法),Verify(验证算法);

以及以下话:

“公钥加密,私钥解密是密送,保证消息即使公开也只有私钥持有者能读懂。
私钥加密,公钥解密是签名,保证消息来源是私钥持有者。”

什么是公钥,什么是私钥?长什么形状?

一、标准库的hash值

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
fn calculate_hash<T: Hash>(t: &T) -> u64 {
    let mut s = DefaultHasher::new();
    t.hash(&mut s);
    s.finish()
}
fn main() {
    let st = SystemTime::now();
    let text = "10086".as_bytes();
    println!("text:{:?}", text);
    let mut hasher1 = DefaultHasher::new();
    hasher1.write(text);

    println!("Hash1(低16位表示) is {:x}", hasher1.finish());
    println!("Hash1 is {}", hasher1.finish());


    let mut hasher2 = DefaultHasher::new();
    text.hash(&mut hasher2);
    println!("Hash2(低16位表示) is {:x}", hasher2.finish());
    println!("Hash2 is {}", hasher2.finish()); 
    println!("calculate_hash:->Hash :{:?}", calculate_hash(&text));

    let mt1 = SystemTime::now();
    println!("is_fit_num time:{:?}", mt1.duration_since(st).unwrap());
    thread::sleep_ms(500000);
}

output:

text:[49, 48, 48, 56, 54]

Hash1(低16位表示) is 85f84a89780553ce
Hash1 is 9653547755553248206

Hash2(低16位表示) is 4b5a264ac7932dc5
Hash2 is 5429694403366301125

calculate_hash:->Hash :5429694403366301125

思考 : hash1为什么和hash2不同?

二、关于keypair、signature、verify 三部曲

我们看rust-crypto库的原代码的例子
https://github.com/DaGenix/rust-crypto/blob/cc1a5fde1ce957bd1a8a2e30169443cdb4780111/src/ed25519.rs

use digest::Digest;
use sha2::{Sha512};
use curve25519::{GeP2, GeP3, ge_scalarmult_base, sc_reduce, sc_muladd, curve25519, Fe};
use util::{fixed_time_eq};
use std::ops::{Add, Sub, Mul};

static L: [u8; 32] =
      [ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6,
        0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed ];

pub fn keypair(seed: &[u8]) -> ([u8; 64], [u8; 32]) {
    let mut secret: [u8; 64] = {
        let mut hash_output: [u8; 64] = [0; 64];
        let mut hasher = Sha512::new();
        hasher.input(seed);
        hasher.result(&mut hash_output);
        hash_output[0] &= 248;
        hash_output[31] &= 63;
        hash_output[31] |= 64;
        hash_output
    };

    let a = ge_scalarmult_base(&secret[0..32]);
    let public_key = a.to_bytes();
    for (dest, src) in (&mut secret[32..64]).iter_mut().zip(public_key.iter()) {
        *dest = *src;
    }
    for (dest, src) in (&mut secret[0..32]).iter_mut().zip(seed.iter()) {
        *dest = *src;
    }
    (secret, public_key)
}

pub fn signature(message: &[u8], secret_key: &[u8]) -> [u8; 64] {
    let seed = &secret_key[0..32];
    let public_key = &secret_key[32..64];
    let az: [u8; 64] = {
        let mut hash_output: [u8; 64] = [0; 64];
        let mut hasher = Sha512::new();
        hasher.input(seed);
        hasher.result(&mut hash_output);
        hash_output[0] &= 248;
        hash_output[31] &= 63;
        hash_output[31] |= 64;
        hash_output
    };

    let nonce = {
        let mut hash_output: [u8; 64] = [0; 64];
        let mut hasher = Sha512::new();
        hasher.input(&az[32..64]);
        hasher.input(message);
        hasher.result(&mut hash_output);
        sc_reduce(&mut hash_output[0..64]);
        hash_output
    };

    let mut signature: [u8; 64] = [0; 64];
    let r: GeP3 = ge_scalarmult_base(&nonce[0..32]);
    for (result_byte, source_byte) in (&mut signature[0..32]).iter_mut().zip(r.to_bytes().iter()) {
        *result_byte = *source_byte;
    }
    for (result_byte, source_byte) in (&mut signature[32..64]).iter_mut().zip(public_key.iter()) {
        *result_byte = *source_byte;
    }

    {
        let mut hasher = Sha512::new();
        hasher.input(signature.as_ref());
        hasher.input(message);
        let mut hram: [u8; 64] = [0; 64];
        hasher.result(&mut hram);
        sc_reduce(&mut hram);
        sc_muladd(&mut signature[32..64], &hram[0..32], &az[0..32], &nonce[0..32]);
    }

    signature
}

fn check_s_lt_l(s: &[u8]) -> bool
{
    let mut c: u8 = 0;
    let mut n: u8 = 1;

    let mut i = 31;
    loop {
        c |= ((((s[i] as i32) - (L[i] as i32)) >> 8) as u8) & n;
        n &= (((((s[i] ^ L[i]) as i32)) - 1) >> 8) as u8;
        if i == 0 {
            break;
        } else {
            i -= 1;
        }
    }

    c == 0
}

pub fn verify(message: &[u8], public_key: &[u8], signature: &[u8]) -> bool {
    if check_s_lt_l(&signature[32..64]) {
        return false;
    }

    let a = match GeP3::from_bytes_negate_vartime(public_key) {
        Some(g) => g,
        None => { return false; }
    };
    let mut d = 0;
    for pk_byte in public_key.iter() {
        d |= *pk_byte;
    }
    if d == 0 {
        return false;
    }

    let mut hasher = Sha512::new();
    hasher.input(&signature[0..32]);
    hasher.input(public_key);
    hasher.input(message);
    let mut hash: [u8; 64] = [0; 64];
    hasher.result(&mut hash);
    sc_reduce(&mut hash);

    let r = GeP2::double_scalarmult_vartime(hash.as_ref(), a, &signature[32..64]);
    let rcheck = r.to_bytes();

    fixed_time_eq(rcheck.as_ref(), &signature[0..32])
}

pub fn exchange(public_key: &[u8], private_key: &[u8]) -> [u8; 32] {
    let ed_y = Fe::from_bytes(&public_key);
    // Produce public key in Montgomery form.
    let mont_x = edwards_to_montgomery_x(ed_y);

    // Produce private key from seed component (bytes 0 to 32)
    // of the Ed25519 extended private key (64 bytes).
    let mut hasher = Sha512::new();
    hasher.input(&private_key[0..32]);
    let mut hash: [u8; 64] = [0; 64];
    hasher.result(&mut hash);
    // Clamp the hash such that it is a valid private key
    hash[0] &= 248;
    hash[31] &= 127;
    hash[31] |= 64;

    let shared_mont_x : [u8; 32] = curve25519(&hash, &mont_x.to_bytes()); // priv., pub.

    shared_mont_x
}

三、如何用?

看一个私钥签名,公钥解密的例子。

extern crate crypto;
use crypto::*;
use ed25519::{keypair, signature, verify, exchange};
use curve25519::{curve25519_base, curve25519};
use digest::Digest;
use sha2::Sha512;
fn main() {
    let seed: &[u8] = &[0x26, 0x27, 0xf6, 0x85, 0x97, 0x15, 0xad, 0x1d, 0xd2, 0x94, 0xdd, 0xc4, 0x76, 0x19, 0x39, 0x31, 0xf1, 0xad, 0xb5, 0x58, 0xf0, 0x93, 0x97, 0x32, 0x19, 0x2b, 0xd1, 0xc0, 0xfd, 0x16, 0x8e, 0x4e];//32位

    // KEYGEN 
    let (private_key, public_key) = keypair(seed); //[U8,64]

    let message = b"This is my message!";

    //私钥签名
    let sig = signature(message, &private_key); //[U8,64]

    //private_key
    println!("private_key: {:?} ", private_key.to_vec());
    println!("private_key_len :{:? }", private_key.len());

    // public_key
    println!("public_key :{:?}", public_key.to_vec());
    println!("public_key_len :{:?}", public_key.len());

    //signature
    println!("signature:{:?}", sig.to_vec());
    println!("signature_len:{:?}", sig.len());

    // verify
    println!("验证是否成功:{:?} ",verify(message, &public_key, &sig));
}
private_key: [38, 39, 246, 133, 151, 21, 173, 29, 210, 148, 221, 196, 118, 25, 57, 49, 241, 173, 181, 88, 240, 147, 151, 50, 25, 43, 209, 192, 253, 22, 142, 78, 93, 109, 35,
 107, 82, 209, 142, 58, 182, 214, 7, 47, 182, 228, 199, 212, 107, 213, 154, 217, 204, 25, 71, 38, 95, 0, 183, 32, 250, 44, 143, 102]
private_key_len :64

public_key :[93, 109, 35, 107, 82, 209, 142, 58, 182, 214, 7, 47, 182, 228, 199, 212, 107, 213, 154, 217, 204, 25, 71, 38, 95, 0, 183, 32, 250, 44, 143, 102]
public_key_len :32
signature:[163, 41, 56, 4, 173, 251, 241, 219, 149, 58, 146, 122, 98, 42, 27, 108, 25, 3, 130, 238, 94, 244, 235, 181, 70, 68, 226, 117, 98, 88, 135, 182, 110, 110, 122, 203
, 190, 66, 6, 139, 6, 242, 94, 98, 107, 99, 144, 208, 145, 218, 120, 236, 223, 60, 87, 19, 245, 249, 177, 246, 212, 160, 10, 10]
signature_len:64

验证是否成功:true
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值