RSA Public-Key Encryption and Signature Lab
1 Introduction
1.1 Lab environment
实验室环境。这个实验室已经在预先构建的Ubuntu 12.04 VM和Ubuntu 16.04 VM上进行了测试,两者都可以从种子网站下载。该实验室需要openssl库已经安装在Ubuntu 16.04上,但还没有安装在Ubuntu 12.04 VM上。如果你使用Ubuntu 12.04,请运行以下两个命令来安装openssl:
为了方便之后的实验,我已经下载了Ubuntu 16.04 VM, openssl库已经安装好,所以不需要执行上诉两条命令.
1.2 Acknowledgment
这个实验室是在Shatadiya Saha的帮助下发展起来的,Shatadiya Saha是印度理工学院的一名研究生雪城大学电子工程和计算机科学系。
2 Background
2.1 BIGNUM APIs
所有大型API都可以从https://linux.die.net/man/3/bn找到。在下面,我们描述了这个实验室需要的一些API。
-
一些库函数需要临时变量。因为动态内存分配到create BIGNUMs在与重复的子程序调用(BN CTX)一起使用时是相当昂贵的结构用于保存库函数使用的BIGNUM临时变量。我们需要创建这样一个结构,并将其传递给需要它的函数。
-
初始化BIGNUM变量
-
有许多方法可以为BIGNUM变量分配值。
-
打印出一个大数字。
-
其他
2.2 A Complete Example
下面我们将展示一个完整的示例。在这个例子中,我们初始化了三个BIGNUM变量a,b和n;然后我们计算一个a∗b
和(a^b mod n
)
2.2.1 Compilation
编译。我们可以使用以下命令编译bn sample.c(-后面的字符是字母,不是数字;它告诉编译器使用crypto库)
3 Lab Tasks
为了避免错误,请避免手动输入实验任务使用的数字。相反,从这个PDF文件复制和粘贴数字。
提交要求:在你的报告中,你应该描述你的步骤,包括你的代码和运行结果
3.1 Task 1: Deriving the Private Key
设p q e是三个素数。设n = p * q,我们用(e, n)作为公钥。请计算私钥d。下面列出了p、q和e的十六进制值。请注意,尽管在此任务中使用的p和q是相当大的数字,但它们不够大,不足以保证安全。为了简单,我们故意把它们做得很小。实际上,这些数字至少应该是512位长(这里使用的只有128位)。
编写代码
//task1.c
#include <stdio.h>
#include <openssl/bn.h>
#define NBITS 128
void printBN(char *msg, BIGNUM *a, BIGNUM *b)
{
char *number_str_a = BN_bn2hex(a);
char *number_str_b = BN_bn2hex(b);
printf("%s (%s,%s)\n", msg, number_str_a, number_str_b);
OPENSSL_free(number_str_a);
OPENSSL_free(number_str_b);
}
int main()
{
// init
BN_CTX *ctx = BN_CTX_new();
BIGNUM *p = BN_new();
BIGNUM *q = BN_new();
BIGNUM *n = BN_new();
BIGNUM *phi = BN_new();
BIGNUM *e = BN_new();
BIGNUM *d = BN_new();
BIGNUM *res = BN_new();
BIGNUM *p_minus_1 = BN_new();
BIGNUM *q_minus_1 = BN_new();
// assign value
BN_hex2bn(&p, "F7E75FDC469067FFDC4E847C51F452DF");
BN_hex2bn(&q, "E85CED54AF57E53E092113E62F436F4F");
BN_hex2bn(&e, "0D88C3");
// n = pq
BN_mul(n, p, q, ctx);
printBN("public key", e, n);
// phi(n) = (p-1)*(q-1)
BN_sub(p_minus_1, p, BN_value_one());
BN_sub(q_minus_1, q, BN_value_one());
BN_mul(phi, p_minus_1, q_minus_1, ctx);
// check if e and phi(n) is relatively prime
BN_gcd(res, phi, e, ctx);
if (!BN_is_one(res))
{
printf("Error: e and phi(n) is not relatively prime \n ");
exit(0);
}
BN_mod_inverse(d, e, phi, ctx);
printBN("private key", d, n);
BN_clear_free(p);
BN_clear_free(q);
BN_clear_free(n);
BN_clear_free(res);
BN_clear_free(phi