编写代码,使用openssl库,获取256位的质数p,求取p的原根g
时间: 2023-08-31 08:19:10 浏览: 237
### 回答1:
以下是使用 openssl 库获取 256 位质数 p 并求取原根 g 的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
int main() {
BIGNUM *p = BN_new();
BIGNUM *one = BN_new();
BIGNUM *two = BN_new();
BIGNUM *phi = BN_new();
BIGNUM *g = BN_new();
BN_CTX *ctx = BN_CTX_new();
// 初始化
BN_one(one);
BN_set_word(two, 2);
// 生成 256 位质数 p
while (1) {
if (!BN_generate_prime_ex(p, 256, 1, NULL, NULL, NULL)) {
printf("Error generating prime number.\n");
return 1;
}
// 判断 p 是否满足要求
BN_sub(phi, p, one); // phi = p - 1
BN_div(phi, NULL, phi, two, ctx); // phi = (p - 1) / 2
if (BN_is_prime_ex(phi, BN_prime_checks, NULL, NULL, NULL, ctx)) {
break;
}
}
// 查找原根 g
BN_set_word(g, 2);
while (1) {
int found = 1;
for (unsigned long i = 1; i < BN_get_word(phi); i++) {
BIGNUM *tmp = BN_new();
BN_set_word(tmp, i);
BN_mod_exp(tmp, g, tmp, p, ctx); // tmp = g^i mod p
if (BN_is_one(tmp)) {
found = 0;
break;
}
}
if (found) {
break;
}
BN_add(g, g, one); // g++
}
// 输出结果
char *p_str = BN_bn2hex(p);
char *g_str = BN_bn2hex(g);
printf("p = %s\n", p_str);
printf("g = %s\n", g_str);
// 释放内存
OPENSSL_free(p_str);
OPENSSL_free(g_str);
BN_free(p);
BN_free(one);
BN_free(two);
BN_free(phi);
BN_free(g);
BN_CTX_free(ctx);
return 0;
}
```
解释:
1. 首先定义了几个 BIGNUM 类型的变量,分别表示生成的质数 p、1、2、p-1 和原根 g,以及一个 BN_CTX 上下文对象用于进行数学运算。
2. 调用 BN_generate_prime_ex 函数生成 256 位质数 p,并使用 BN_sub 和 BN_div 函数计算出 p-1 的一半 phi,判断 phi 是否也是质数,以确保 p 的安全性。
3. 使用 BN_set_word 将 g 初始化为 2,然后使用 BN_mod_exp 函数计算出 g^i mod p,判断 1 <= i < phi 时是否都不等于 1,如果都不等于 1,则说明 g 是 p 的原根。
4. 输出结果,释放内存。
注意事项:
1. 生成的质数 p 要满足一定的安全性要求,所以在调用 BN_generate_prime_ex 函数时,第三个参数传入 1 表示要求 p 是强素数,即要求 (p-1)/2 也是质数。此外,还应进行一定的检验,如本代码中使用 BN_is_prime_ex 函数判断 (p-1)/2 是否为质数。
2. 查找原根 g 的过程可能需要多次尝试,因为不是所有的数都有原根。
注意:该代码仅供学习参考,请勿用于生产环境。
### 回答2:
首先,使用openssl库生成一个256位的随机数,判断该随机数是否为质数。如果不是质数,则继续生成下一个随机数,直到生成一个质数为止。
判断一个数是否为质数可以使用openssl库中提供的函数来实现。具体步骤如下:
1. 导入openssl库头文件:
```c
#include <openssl/bn.h>
```
2. 利用openssl的BN_new函数创建一个大数对象,并初始化为0:
```c
BIGNUM *num = BN_new();
```
3. 利用openssl的BN_rand函数生成一个256位的随机数:
```c
BN_rand(num, 256, -1, 0);
```
4. 利用openssl的BN_is_prime_ex函数判断该随机数是否为质数:
```c
int is_prime = BN_is_prime_ex(num, BN_prime_checks, NULL, NULL);
```
其中,`BN_prime_checks`是用于判断质数的迭代次数,默认为2。
5. 如果生成的随机数不是质数,则继续生成下一个随机数,直到生成一个质数为止:
```c
while (!is_prime) {
BN_rand(num, 256, -1, 0);
is_prime = BN_is_prime_ex(num, BN_prime_checks, NULL, NULL);
}
```
6. 最后,通过openssl的BN_print_fp函数将生成的质数打印出来:
```c
BN_print_fp(stdout, num);
```
接下来,需要求取质数p的原根g。原根是指一个数对于模p的求幂运算得到的结果的集合中,每一个数都不相同。求解原根可以使用一个简单的算法。
具体求解原根的步骤如下:
1. 设置一个变量g并初始化为2。
2. 使用循环判断g是否为p的原根。若不是,则将g加1并继续判断,直到找到一个原根为止。
判断g是否为p的原根可以使用一个嵌套的循环来实现。具体步骤如下:
1. 设置一个变量is_primitive并初始化为1。
2. 使用循环遍历从1到p-1的所有数,假设当前数为i。
3. 使用循环计算g的i次幂对p取模的结果,假设当前结果为temp。
4. 判断temp是否等于1,并判断i是否等于p-1。若两者同时成立,则将is_primitive置为0。
5. 如果is_primitive仍然为1,说明g为p的原根。否则,将g加1并继续判断,直到找到一个原根为止。
最终,将得到质数p和其原根g的值。完成整个过程后,可以使用openssl的BN_free函数释放之前创建的大数对象:
```c
BN_free(num);
```
这样就完成了使用openssl库编写代码来获取256位质数p,并求取p的原根g的过程。
### 回答3:
使用OpenSSL库可以通过以下步骤获取256位的质数p并求取原根g:
Step 1: 导入OpenSSL库
首先需要在代码中导入OpenSSL库,确保能够使用其中的函数和算法。可以使用以下语句导入库:
```
#include <openssl/bn.h>
#include <openssl/dh.h>
```
Step 2: 定义DH结构体和变量
DH(Diffie-Hellman)结构体用于存储DH算法相关的参数和计算过程中的临时变量。我们可以使用以下语句定义DH结构体和变量:
```
DH* dh;
```
Step 3: 生成质数p
使用OpenSSL库可以方便地生成大数(BIGNUM),然后经过计算得到质数p。可以使用以下步骤生成质数p:
```
BIGNUM* p = BN_new();
int bits = 256; // 指定位数为256
int generator = 2; // 指定默认的生成器
dh = DH_new();
DH_generate_parameters_ex(dh, bits, generator, NULL);
DH_check(dh, &check);
p = dh->p;
```
在上述代码中,先创建一个空的BIGNUM结构体p,并且使用DH_generate_parameters_ex函数生成DH结构体dh,并将质数p赋值给p变量。
Step 4: 求取原根g
求取质数p的原根可以使用以下步骤:
```
BIGNUM* g = BN_new();
BIGNUM* order = BN_new();
DH_generate_key(dh);
DH_get0_key(dh, NULL, &keyPair);
DH_get0_pqg(dh, NULL, NULL, &order);
g = BN_dup(dh->g);
```
在上述代码中,先创建两个空的BIGNUM结构体g和order,然后使用DH_generate_key函数生成DH结构体dh中的公私钥对,使用DH_get0_key函数获取DH结构体dh中的公私钥对,使用DH_get0_pqg函数获取DH结构体dh中的质数p和阶次order,最后将原根g赋值给g变量。
最终,p的值存储在p变量中,g的值存储在g变量中,即可获取256位的质数p和其原根g。
阅读全文