【加解密与C】非对称加解密(二)ELGamel

ELGamel 加密算法概述

ELGamel 是一种基于离散对数问题的公钥加密算法,由 Taher Elgamal 在 1985 年提出。它是 Diffie-Hellman 密钥交换协议的扩展,广泛应用于数字签名和加密场景。ELGamel 的安全性依赖于有限域上离散对数问题的计算难度。

ELGamel 密钥生成

选择一个大素数 ( p ) 和一个生成元 ( g )(即 ( g ) 是 ( \mathbb{Z}_p^* ) 的生成元)。 选择一个私钥 ( x ),满足 ( 1 \leq x \leq p-2 )。 计算公钥 ( y = g^x \mod p )。 公钥为 ( (p, g, y) ),私钥为 ( x )。

ELGamel 加密过程

假设明文为 ( m )(( 0 \leq m \leq p-1 )),选择一个随机数 ( k )(( 1 \leq k \leq p-2 ))。 计算密文的两部分:

  • ( c_1 = g^k \mod p )
  • ( c_2 = m \cdot y^k \mod p ) 密文为 ( (c_1, c_2) )。

ELGamel 解密过程

使用私钥 ( x ) 解密密文 ( (c_1, c_2) ): 计算 ( s = c_1^x \mod p )。 恢复明文 ( m = c_2 \cdot s^{-1} \mod p )。

ELGamel 安全性

ELGamel 的安全性依赖于离散对数问题的困难性。若攻击者无法从 ( g^k ) 或 ( g^x ) 中恢复 ( k ) 或 ( x ),则无法破解密文。为了确保安全性,素数 ( p ) 应足够大(通常至少 2048 位),且 ( g ) 应为大阶生成元。

ELGamel 应用场景

ELGamel 常用于混合加密系统,如与 AES 结合使用(用 ELGamel 加密 AES 密钥)。它还用于数字签名(如 DSA 算法)和多方安全协议中。

注意事项

  • 实际应用中需使用更安全的随机数生成器和更大的密钥长度。
  • 生成元 ( g ) 的选择需验证其是否为 ( \mathbb{Z}_p^* ) 的生成元。
  • 明文 ( m ) 应通过编码方式映射到 ( \mathbb{Z}_p ),或使用混合加密方案。

ELGamel.h

cpp 复制代码
#ifndef _ELGAMEL_H_
#define _ELGAMEL_H_
void Encryption(int m, int y, int g, int p, int *C1, int *C2);
int Decryption(int c2, int c1, int x, int p);
void Sign(int c1, int c2, int g, int p, int x, int *R1, int *S1, int *R2, int *S2);
int Vrfy(int y, int g, int r, int s, int m, int p);
#endif

ELGamel.cpp

cpp 复制代码
#include "SDELGamel.h"

// 判断一个数是否为素数
// 输入一个数a 
// 返回:如果a是素数,返回true ; 否则返回false
int Prime(int a)
{
    for (int i = 2; i <= (a / 2); i++)
    {
        if ((a % i) == 0)
        {
            return 0;
        }
    }
    return 1;
}

// 快速模幂运算
// 形式为 (a^b) mod c
// 输入 a 、b 和 c  因为要求a^b , 因此是长整数
// 返回 (a^b) mod c 计算结果
int modpow(long long a, long long b, int c)
{
    int res = 1;
    while (b > 0)
    {
        if (b & 1)
        {
            res = (res * a) % c;
        }

        b = b >> 1;
        a = (a * a) % c;
    }
    return res;
}


// 求解乘法逆元
// 输入num 和 mod。 求num 在 mod 下的乘法逆元
// 返回num 在 mod 下的乘法逆元
int inverse(int num, int mod)
{
    int a = num;
    int b = mod;
    int x = 0, x0 = 1;
    int qt, temp;

    while (b != 0)
    {
        qt = a / b;
        temp = a % b;

        a = b;
        b = temp;

        temp = x; x = x0 - qt * x; x0 = temp;
        //temp = y; y = y0 - qt * y; y0 = temp;
    }

    if (x0 < 0)
    {
        x0 += mod;
    }

    return x0;
}

// ElGamal算法加密过程
// 输入公钥{g,y,p} , 明文m
// 返回密文对:C = {c1,c2} , 以数组形式
void Encryption(int m, int y, int g, int p, int *C1, int *C2)
{
    long long temp;
    //int c1, c2;
    int k = 7;
    *C1 = modpow(g, k, p);

    temp = modpow(y, k, p);
    *C2 = (m * temp) % p;
}

// ElGamal解密过程
// 输入密文对:{c1,c2} ,密钥d 以及公钥p
// 返回明文m
int Decryption(int c2, int c1, int x, int p)
{
    int temp;
    temp = modpow(c1, x, p);
    long long temp1 = inverse(temp, p);
    int m = (c2 * temp1) % p;

    return m;
}


//ElGamal数字签名函数
void Sign(int c1, int c2, int g, int p, int x, int *R1, int *S1, int *R2, int *S2)
{
    int k, k1;
    long long temp;
    int r1, r2, s1, s2;

    k =  7;
    int base = p - 1;
    r1 = modpow(g, k, p);
    temp = c1 - (long long)x * r1;
    k1 = inverse(k, base);
    s1 = (temp * k1) % base;

    r2 = modpow(g, k, p);
    temp = c2 - (long long)x * r2;
    k1 = inverse(k, base);
    s2 = (temp * k1) % base;

    if (s1 < 0)
    {
        s1 = s1 + p - 1;
    }

    if (s2 < 0)
    {
        s2 = s2 + p - 1;
    }

    *R1 = r1;
    *S1 = s1;
    *R2 = r2;
    *S2 = s2;

}

//数字签名验证函数
int Vrfy(int y, int g, int r, int s, int m, int p)
{
    long long temp1, temp2;
    long long i, j;

    temp1 = modpow(y, r, p);
    temp2 = modpow(r, s, p);

    i = (temp1 * temp2) % p;
    j = modpow(g, m, p);

    if (i == j)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

※说明:该代码仅实现了32位即int型密钥的加解密及签名验签,如果需要更大的密钥程度,需自行实现大整数的运算,建议实际生产时使用第三方库

相关推荐
秋说1 小时前
【PTA数据结构 | C语言版】将数组中元素反转存放
c语言·数据结构·算法
森焱森2 小时前
APM与ChibiOS系统
c语言·单片机·算法·架构·无人机
kyle~3 小时前
C/C++字面量
java·c语言·c++
蜡笔小电芯4 小时前
【C语言】指针与回调机制学习笔记
c语言·笔记·学习
qq_401700414 小时前
C语言中位运算以及获取低8位和高8位、高低位合并
c语言·开发语言·算法
墨小傲5 小时前
基于Linux下的vscode c/c++开发环境搭建详细教程
linux·c语言·vscode
1024小神6 小时前
tauri项目在windows上的c盘没有权限写入文件
c语言·开发语言·windows
学不动CV了15 小时前
ARM单片机启动流程(二)(详细解析)
c语言·arm开发·stm32·单片机·51单片机
猫猫的小茶馆17 小时前
【STM32】通用定时器基本原理
c语言·stm32·单片机·嵌入式硬件·mcu·51单片机