【密码学】一文读懂基于Elgamal的数字签名

简介: 本文来先填一下之前挖的坑,简单介绍一个实际的数字签名的方案,给自己挖的坑总是要自己来填的。

一文读懂基于Elgaml的数字签名


6JQ5NHU1M)MD@WQYI)2L9]C.jpg基于Elgamal的数字签名方案

本文来先填一下之前挖的坑,简单介绍一个实际的数字签名的方案,给自己挖的坑总是要自己来填的。


知识回顾

在介绍具体的签名算法之前,首先来回顾一下之前讲过的离散对数和数论相关的知识,对于素数p, 如果是p的原根,那么对于取模p之后的值是不同的,然后,我们可以得到下面两个结论。

  • 对于任意的整数m,  , 当且仅当
  • 对于任意整数i, j,, 当且仅当


密钥选择

如果读者看过我之前聊过的基于elgamal的加密,理解后面这些内容相对来说会轻松不少,不过要是没看过也没有关系,我尽量也是把每个细节聊清楚。

基于Elgamal的数字签名,全局元素是p和  , 其中  是p的原根,然后根据下面的方法生成公私钥对。

  • 生成随机整数 , 使得
  • 计算
  • A的私钥是, A的公钥是


签名过程

如果用户A需要对消息M进行签名,则按照如下的步骤进行处理

  • 计算消息M的哈希值m = H(M),其中 m 在
  • 随机选择一个整数K, 使  并且 , 也就是K和p-1互素
  • 计算
  • 计算, 这里可不是普通的指数运算,而是求逆运算这也就是前面要求互素的原因, 因为不互素是没有逆的。
  • 计算
  • 最终生成的签名(, )


签名验证过程

对于任意的用户, 都能按照如下的方式对签名进行验证

image.png

如果, 说明签名有效。

接下来,简单证明一下,为什么上面, 就可以说明签名是有效的吧, 假设这个等式成立,则有。

image.png

代码实现

好久没给出具体的实现了,这篇文章回归一下,来用rust简单的实现一下这个数字签名算法。

use std::ops::{Mul, Sub};
use num_bigint::{BigInt, RandBigInt, ToBigInt};
use num_traits::{zero, one};
pub struct Elgamal {}
pub struct PublicKey {
    alpha: BigInt,
    p: BigInt,
    y: BigInt,
}
pub struct PrivateKey {
    alpha: BigInt,
    p: BigInt,
    x: BigInt,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ElGamalSign {
    s1: BigInt,
    s2: BigInt,
}
pub fn mod_inv(u: &BigInt, v: &BigInt) -> BigInt {
    let mut q: BigInt;
    let mut t1: BigInt;
    let mut t3: BigInt;
    let (mut u1, mut u3, mut v1, mut v3) =
        (BigInt::from(1u8), u.clone(), BigInt::from(0u8), v.clone());
    let mut iter: i8 = 1;
    while &v3 != &zero() {
        q = &u3 / &v3;
        t3 = &u3 % &v3;
        t1 = &u1 + &q * &v1;
        u1 = v1;
        v1 = t1;
        u3 = v3;
        v3 = t3;
        iter = -iter;
    }
    if &u3 != &one() {
        return zero();
    }
    if iter < 0 {
        return v - u1;
    }
    u1
}
impl Elgamal {
    fn sign(m: &BigInt, sk: &PrivateKey) -> ElGamalSign {
        let mut rng = rand::thread_rng();
        let mut k = rng.gen_bigint_range(&BigInt::from(1u8), &(&sk.p - BigInt::from(1u8)));
        let p_sub_one = &sk.clone().p.clone().sub(1.to_bigint().unwrap());
        let mut key_inv = mod_inv(&k, p_sub_one);
        while key_inv.eq(&zero()) {
            k = rng.gen_bigint_range(&BigInt::from(1u8), &(&sk.p - BigInt::from(1u8)));
            key_inv = mod_inv(&k, p_sub_one);
        }
        let s1 = sk.alpha.modpow(&k, &sk.p) % &sk.p;
        let s2 = key_inv.mul(m.sub(&sk.clone().x.clone().mul(&s1))) % &sk.clone().p.clone().sub(1.to_bigint().unwrap()) % (&sk.clone().p.clone().sub(1.to_bigint().unwrap()));
        ElGamalSign {
            s1: s1.clone(),
            s2,
        }
    }
    fn verify(m: &BigInt, s1: &BigInt, s2: &BigInt, pk: &PublicKey) -> bool {
        let v1 = pk.alpha.modpow(&m, &pk.p);
        let v2 = pk.y.modpow(&s1, &pk.p).mul(s1.modpow(&s2, &pk.p)) % &pk.p;
        v1.eq(&v2)
    }
}
#[cfg(test)]
mod test {
    use num_bigint::BigInt;
    use crate::elgamal_sign::{PublicKey, PrivateKey, Elgamal};
    #[test]
    fn test() {
        let p = BigInt::from(19u8);
        let alpha = BigInt::from(10u8);
        let x = BigInt::from(5u8);
        let y = alpha.modpow(&x, &p);
        let pk = PublicKey {
            p: p.clone(),
            alpha: alpha.clone(),
            y,
        };
        let sk = PrivateKey {
            p: p.clone(),
            alpha: alpha.clone(),
            x,
        };
        let m = BigInt::from(17u8);
        let sign = Elgamal::sign(&m, &sk);
        println!("{:?}", sign);
        let result = Elgamal::verify(&m, &sign.s1, &sign.s2, &pk);
        println!("{:?}", result);
    }
}


相关文章
|
算法 安全 关系型数据库
密码学系列之七:数字签名
密码学系列之七:数字签名
2053 0
|
Rust 算法 安全
【密码学】一文读懂HMAC
本文将来聊一聊基于哈希函数的消息认证码,在此之前,先来科普一下什么是 「消息认证码」 (MAC), 先来看一个简单的栗子
2347 0
【密码学】一文读懂HMAC
|
23天前
|
运维 Java Serverless
Serverless 架构模式深度解析
Serverless并非“无服务器”,而是开发者无需管理服务器,专注业务逻辑。具备按需付费、弹性伸缩、事件驱动等优势,适用于突发流量、定时任务等场景,结合FaaS与BaaS可构建高效应用,是云原生发展的重要方向。
187 1
|
4月前
|
数据采集 数据可视化 关系型数据库
基于python大数据的电影数据可视化分析系统
电影分析与可视化平台顺应电影产业数字化趋势,整合大数据处理、人工智能与Web技术,实现电影数据的采集、分析与可视化展示。平台支持票房、评分、观众行为等多维度分析,助力行业洞察与决策,同时提供互动界面,增强观众对电影文化的理解。技术上依托Python、MySQL、Flask、HTML等构建,融合数据采集与AI分析,提升电影行业的数据应用能力。
|
算法 测试技术 数据库
性能测试 (performance measurement)
性能测试 (performance measurement) 是一种测试方法,用于评估系统、应用程序或算法在特定负载条件下的性能表现。性能测试可以测量系统的响应时间、吞吐量、并发用户数等指标,以评估系统在高负载情况下的稳定性和可靠性。通过性能测试,可以找出系统的瓶颈和潜在的优化点,从而提高系统的性能。
581 3
|
6月前
|
机器学习/深度学习 人工智能 算法
最大熵逆强化学习:理论基础、数学推导与工程实现
本文重点讨论逆强化学习(Inverse Reinforcement Learning, IRL),这是模仿学习的重要分支,其核心目标是基于演示数据学习能够最大化期望奖励的最优策略。
185 0
|
10月前
|
存储 人工智能 运维
idc机房智能运维解决方案
华汇数据中心一体化智能运维方案应运而生,以“自主可控、精准洞察、智能决策”三大核心能力,助力企业实现运维效率提升与综合成本下降的数字化转型目标。
546 24
|
11月前
|
Cloud Native 安全 Serverless
云原生应用实战:基于阿里云Serverless的API服务开发与部署
随着云计算的发展,Serverless架构日益流行。阿里云函数计算(Function Compute)作为Serverless服务,让开发者无需管理服务器即可运行代码,按需付费,简化开发运维流程。本文从零开始,介绍如何使用阿里云函数计算开发简单的API服务,并探讨其核心优势与最佳实践。通过Python示例,演示创建、部署及优化API的过程,涵盖环境准备、代码实现、性能优化和安全管理等内容,帮助读者快速上手Serverless开发。
|
关系型数据库 MySQL 大数据
MySQL分区与分表:优化性能与提升可扩展性
本文深入探讨了MySQL数据库中的分区与分表策略,通过详细的代码示例,解释了分区的概念与用途、不同的分区类型以及创建分区表的步骤。同时,文章还介绍了分表的概念、策略和实际操作方法,以代码演示展示了如何创建分表、插入数据以及查询数据。分区和分表作为优化数据库性能和提升可扩展性的关键手段,通过本文的阐述,读者将能够深入了解如何根据数据特点选择合适的分区方式,以及如何灵活地处理大量数据,提高查询和维护效率。这些技术将为数据库设计和优化提供有力支持,确保在大数据场景下能够高效地管理和查询数据。
2682 0
|
存储 缓存 移动开发
PixiJS源码分析系列:第三章 使用 canvas 作为渲染器
PixiJS源码分析系列:第三章 使用 canvas 作为渲染器