惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
Vercel News
Vercel News
Blog — PlanetScale
Blog — PlanetScale
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
WordPress大学
WordPress大学
V
V2EX
The Register - Security
The Register - Security
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
D
DataBreaches.Net
G
Google Developers Blog
O
OpenAI News
S
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
Engineering at Meta
Engineering at Meta
Recorded Future
Recorded Future
T
Threatpost
The Hacker News
The Hacker News
Cisco Talos Blog
Cisco Talos Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
B
Blog RSS Feed
Apple Machine Learning Research
Apple Machine Learning Research
T
The Exploit Database - CXSecurity.com
L
LINUX DO - 热门话题
G
GRAHAM CLULEY
博客园 - 叶小钗
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
L
LangChain Blog
Scott Helme
Scott Helme
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
Google Online Security Blog
Google Online Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
N
News | PayPal Newsroom
NISL@THU
NISL@THU
M
MIT News - Artificial intelligence
Cloudbric
Cloudbric
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
Recent Announcements
Recent Announcements

博客园 - 会长

本地部署DeepSeek并用Python调用 一个用来将数字转换为英文的MySql函数 Snowflake算法生成Id 如何用C#代码验证XML文件是否符合DTD规范 如何调试WebBrowser控件中的JS代码 解决Devexpress的RichEditControl控件保存为docx文件后在word里打开字体显示不正确的问题 《水浒传》中的物价 诗词记录 对开发流程优化的建议 如何在HP ProLiant-DL580 Gen9 上安装ESXi NumPy基础 闪存客户端 北京某软件园小公园 MySQL优化技巧 大叔学ML第五:逻辑回归 大叔学ML第四:线性回归正则化 大叔学ML第三:多项式回归 大叔学ML第二:线性回归 大叔学ML第一:梯度下降
用C语言实现ElGamal算法
会长 · 2023-03-25 · via 博客园 - 会长

缘起

是我侄子问的题目,参考了书籍、博客,花了一些时间完成的,丢掉可惜了,记录下来吧。这个程序还有些缺陷,数值太大时计算结果会溢出

代码

#include<stdio.h>
#include<time.h>
#include<stdlib.h>

#define longint long long

// 得到一个随机数
int random(int minValue, int maxValue)
{
	return rand() % (maxValue - minValue + 1) + minValue;
}

// 交换两个变量的值 
void swap(longint a, longint b)
{
	longint temp = a;
	a = b;
	b = temp;
}

// 欧几里得算法求最大公约数
longint gcd(longint a, longint b)
{
    if (a < b)
    {
        swap(a, b);
    }

    while (true)
    {
        longint mod = a % b;
        if (mod == 0)
        {
            return b;
        }
        return gcd(b, mod);
    }
}

// 求与baseNum的power次方同余的一个数
longint powAndMod(longint baseNum, longint power, longint p)
{
    if (power == 0)
    {
        return 1;
    }
    if (power % 2 == 1)
    {
        return (powAndMod(baseNum, power - 1, p) * baseNum) % p;
    }
    else
    {
        longint temp = (powAndMod(baseNum, power / 2, p) % p);
        return temp * temp;
    }
}

// 费马小定理判断是否为质数
bool probablyPrime(longint p)
{
    if (p == 1)
    {
        return false;
    }
    if (p == 2)
    {
        return true;
    }
    if (p % 2 == 0)
    {
        return false;
    }
    return powAndMod(2, p - 1, p) % p == 1;
}

// 随机得到一个质数
int getPrimeNumber(int minValue, int maxValue)
{
    while (true)
    {
        int num = random(minValue, maxValue);
        if (probablyPrime(num))
        {
            return num;
        }
    }
}

// 求 群Z_p^*的本原元,p为素数
longint findGenerator(longint p)
{
    for (longint i = 2; i < p; i++)
    {
        if (gcd(i, p) == 1)
        {
            if (powAndMod(i, p - 1, p) % p == 1)
            {
                return i;
            }
        }
    }
    return -1;
}

int main()
{
	srand(time(NULL));

	int p = getPrimeNumber(1000000, 2000000);
    printf("选择一个素数 p = %d\n", p);

    longint alpha = findGenerator(p);
	printf("选择本原元 α = %d\n", alpha);

	longint privateKey = random(2, p - 2);
	printf("选择 privateKey = %d\n", privateKey);

	longint publicKey = powAndMod(alpha, privateKey, p) % p;
	printf("计算 publicKey = α^privateKey mod p = %d\n", publicKey);

	printf("\n\n---加密---\n\n");

	longint x = random(1, p - 1);
	printf("选择明文 x属于Z_p^* = %d\n", x);

	longint i = random(2, p - 2);
	printf("选择 i = %d\n", i);

	longint ke = powAndMod(alpha, i, p) % p;
	printf("计算临时密钥 ke = α^i mod p = %d\n", ke);

	longint km = powAndMod(publicKey, i, p) % p;
	printf("计算掩码密钥 km = publicKey^i mod p = %d\n", km);

	longint y = (x % p) * (km % p);
	printf("加密消息,得到密文 y = x * km mod p = %d\n", y);

	printf("\n\n---解密---\n\n");

	longint km2 = powAndMod(ke, privateKey, p) % p;
	printf("计算掩码密钥 km = ke^privateKey mod p = %d\n", km);

	longint x2 = (y / km2) % p;
	printf("解密 x = y * km^{-1} mod p = %d\n", x2);
}

参考

-《深入浅出密码学》