加密算法DH实现

Aki 发布于 2023-07-29 306 次阅读


gmp库下载:Linux下如何安装GMP库 (linux装gmp库)-数据库远程运维 (dbs724.com)

视频:【不懂数学没关系】DH算法 | 迪菲-赫尔曼Diffie–Hellman 密钥交换_哔哩哔哩_bilibili

#include<iostream>
#include<gmp.h>
#include<fstream>
#include<cstring>
using namespace std;


int main()
{

        //设置默认随机状态为跟着时间改变,也就是引入时间随机数种子
        gmp_randstate_t state;
        gmp_randinit_default(state);
        gmp_randseed_ui(state,time(0));

        //创建p,g,r完成初始化
        mpz_t p,g,r1,r2,r3,r4,r5,r6;
        mpz_init(p);
        mpz_init(g);
        mpz_init(r1);
        mpz_init(r2);
        mpz_init(r3);
        mpz_init(r4);
        mpz_init(r5);
        mpz_init(r6);

        //获取质数p
        mpz_urandomb(p,state,2048);
        mpz_nextprime(p,p);

        //验证p是不是素数
        if(mpz_probab_prime_p(p,15) == 0)
        {
                cerr << "p不是素数!" << endl;
                exit(0);
        }

        //设置g为5,r1和r2为随机生成的32位随机数
        mpz_set_ui(g,5);
        mpz_urandomb(r1,state,32);
        mpz_urandomb(r2,state,32);

        //执行公式计算
        //g ** r mod p
        mpz_powm(r3,g,r1,p);
        mpz_powm(r4,g,r2,p);

        //计算密钥
        mpz_powm(r5,r4,r1,p);
        mpz_powm(r6,r3,r2,p);

        fstream file;
        file.open("DH",ios::out);
        if(!file.is_open())
        {
                cerr << "打开文件错误!" << endl;
                exit(1);
        }

        //将mpz_t的数据类型转换为字符串类型
        char p_buffer[1024];
        char g_buffer[256];
        char random_1[256];
        char random_2[256];
        char key[1024];
        mpz_get_str(p_buffer,10,p);
        mpz_get_str(g_buffer,10,g);
        mpz_get_str(random_1,10,r1);
        mpz_get_str(random_2,10,r2);

        //检验计算结果是否正确
        if(mpz_cmp(r5,r6) != 0)
        {
                cerr << "生成key错误!" << endl;
                exit(0);
        }
        mpz_get_str(key,10,r5);

        //写入到文件中
        file << "Genarator:" << g_buffer << endl;
        file << "Primer:" << p_buffer << endl;
        file << "Random_1:" << random_1 << endl;
        file << "Random_2:" << random_2 << endl;
        file << "Key:" << key << endl;

        //清理资源
        file.close();
        mpz_clear(p);
        mpz_clear(g);
        mpz_clear(r1);
        mpz_clear(r2);
        mpz_clear(r3);
        mpz_clear(r4);
        mpz_clear(r5);
        mpz_clear(r6);

        return 0;
}

要判断一个mpz_t类型的数据是否为素数,可以使用GMP库中的函数mpz_probab_prime_p。该函数使用概率方法来检测给定的整数是否为素数。以下是使用mpz_probab_prime_p函数进行素数判断的基本步骤:

#include <gmp.h>

bool isPrime(mpz_t num)
{
    int result = mpz_probab_prime_p(num, 15); // 第二个参数是测试的次数,可以根据需要调整

    if (result == 2 || result == 1)
    {
        return true; // 可能是素数,或者错误概率非常低
    }
    else
    {
        return false; // 不是素数
    }
}

上述代码中,mpz_probab_prime_p函数的返回值result表示给定整数是否为素数的概率结果。具体取值如下:

  • result == 2:给定整数是素数的概率极高(接近100%)。
  • result == 1:给定整数可能是素数,但可能存在较小的错误概率。
  • result == 0:给定整数不是素数。

可以根据自己的需求和精确性要求选择合适的测试次数。通常,使用15次的测试已经可以给出较高的准确性。请注意,由于这是一个概率性的测试方法,所以结果并非百分之百准确。对于需要确切判断是否为素数的场景,可能需要使用更复杂的算法,如Miller-Rabin测试或AKS素性测试。

要将mpz_t类型的高精度整数转换为字符串,可以使用GMP库中的mpz_get_str函数。以下是将mpz_t转换为字符串的基本步骤:

  1. 创建一个字符数组来存储转换后的字符串。确保该数组具有足够的大小来存储转换后的整数字符串。
char buffer[MAX_SIZE]; // 假设 MAX_SIZE 是足够大的数组大小
  1. 使用mpz_get_str函数将mpz_t类型的整数转换为字符串。该函数的原型如下:
char *mpz_get_str(char *str, int base, const mpz_t integer);
  • str是目标字符串的指针,表示将转换结果存储在该字符串中。
  • base是转换的进制数,例如十进制为 10,十六进制为 16。
  • integer是要转换的mpz_t类型整数。

确保str指向足够大的缓冲区。

  1. 使用mpz_get_str进行转换:
mpz_get_str(buffer, 10, your_mpz_t_variable);

上述代码将将your_mpz_t_variable转换为十进制字符串,并将结果存储在buffer中。

请注意,mpz_get_str函数可用于转换为不同的进制。例如,如果想转换为十六进制字符串,可以将第二个参数设置为 16。