|

楼主 |
发表于 2022-5-3 11:18:05
|
显示全部楼层
本帖最后由 信计2班蔡冉平 于 2022-5-20 15:43 编辑
- <div class="blockcode"><blockquote> #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <string.h>
-
- #define ACCURACY 5
- #define SINGLE_MAX 250
- #define EXPONENT_MAX 1
- #define BUF_SIZE 1024
- //计算a^b mod c
- int modpow( long a, 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;
- }
- //计算Jacobi符号(a,n)
- int jacobi(int a, int n) {
- int twos, temp;
- int mult = 1;
- while(a > 1 && a != n) {
- a = a % n;
- if(a <= 1 || a == n) break;
- twos = 0;
- while(a % 2 == 0 && ++twos) a /= 2; //减去2的倍数
- if(twos > 0 && twos % 2 == 1) mult *= (n % 8 == 1 || n % 8 == 7) * 2 - 1;
- if(a <= 1 || a == n) break;
- if(n % 4 != 1 && a % 4 != 1) mult *= -1;//翻转系数
- temp = a;
- a = n;
- n = temp;
- }
- if(a == 0) return 0;
- else if(a == 1) return mult;
- else return 0;
- }
- //检查a是否为n的欧拉见证
- int solovayPrime(int a, int n) {
- int x = jacobi(a, n);
- if(x == -1) x = n - 1;
- return x != 0 && modpow(a, (n - 1)/2, n) == x;
- }
- //用k的精度检查n是否可能是素数
- int probablePrime(int n, int k) {
- if(n == 2) return 1;
- else if(n % 2 == 0 || n == 1) return 0;
- while(k-- > 0) {
- if(!solovayPrime(rand() % (n - 2) + 2, n)) return 0;
- }
- return 1;
- }
- // 在3和(n-1)之间找一个随机素数
- int randPrime(int n) {
- int prime = rand() % n;
- n += n % 2;
- prime += 1 - prime % 2;
- while(1) {
- if(probablePrime(prime, ACCURACY)) return prime;
- prime = (prime + 2) % n;
- }
- }
- //计算gcd(a,b)
- int gcd(int a, int b) {
- int temp;
- while(b != 0) {
- temp = b;
- b = a % b;
- a = temp;
- }
- return a;
- }
-
- //在3和n-1之间找到随机指数x,使得gcd(x,phi)=1,这种分布同样不接近制服
- int randExponent(int phi, int n) {
- int e = rand() % n;
- while(1) {
- if(gcd(e, phi) == 1) return e;
- e = (e + 1) % n;
- if(e <= 2) e = 3;
- }
- }
-
- // 用扩展欧几里得法计算n^-1 mod m
- int inverse(int n, int modulus) {
- int a = n, b = modulus;
- int x = 0, y = 1, x0 = 1, y0 = 0, q, temp;
- while(b != 0) {
- q = a / b;
- temp = a % b;
- a = b;
- b = temp;
- temp = x; x = x0 - q * x; x0 = temp;
- temp = y; y = y0 - q * y; y0 = temp;
- }
- if(x0 < 0) x0 += modulus;
- return x0;
- }
- //将文件fd读入准备加密的字节数组,数组将填充零,知道它划分每个块加密的字节数,返回读取的字节数
- int readFile(FILE* fd, char** buffer, int bytes) {
- int len = 0, cap = BUF_SIZE, r;
- char buf[BUF_SIZE];
- *buffer = (char *)malloc(BUF_SIZE * sizeof(char));
- while((r = fread(buf, sizeof(char), BUF_SIZE, fd)) > 0) {
- if(len + r >= cap) {
- cap *= 2;
- *buffer = (char *)realloc(*buffer, cap);
- }
- memcpy(&(*buffer)[len], buf, r);
- len += r;
- }
- //将最后一个带有零的块插入密码的信号端。 如果没有多余,则额外增加一个
- if(len + bytes - len % bytes > cap) *buffer = (char *)realloc(*buffer, len + bytes - len % bytes);
- do {
- (*buffer)[len] = '\0';
- len++;
- }
- while(len % bytes != 0);
- return len;
- }
- //c = m^e mod n使用公共指数和模量对消息m进行编码,c = m^e Mod n
- int encode(int m, int e, int n) {
- return modpow(m, e, n);
- }
- //m = c^d mod n,用私有指数和公共模量解码密码c,m = c^d Mod
- int decode(int c, int d, int n) {
- return modpow(c, d, n);
- }
-
- // 使用公钥(指数、模数)对给定长度的消息进行编码),得到的数组将是大小为len/字节,每个索引是由m=(m1m2*128m3*128^2.)给出的“字节”连续字符的加密,编码=m^指数mod模量
- int* encodeMessage(int len, int bytes, char* message, int exponent, int modulus) {
- int *encoded = (int *)malloc((len/bytes) * sizeof(int));
- int x, i, j;
- for(i = 0; i < len; i += bytes) {
- x = 0;
- for(j = 0; j < bytes; j++) x += message[i + j] * (1 << (7 * j));
- encoded[i/bytes] = encode(x, exponent, modulus);
- #ifndef MEASURE
- printf("%d ", encoded[i/bytes]);
- #endif
- }
- return encoded;
- }
- //使用私钥(指数、模数)解码给定长度的密码), 每个加密的数据包应该按照编码消息表示“字节”字符,返回的消息大小为len*字节。
- int* decodeMessage(int len, int bytes, int* cryptogram, int exponent, int modulus) {
- int *decoded = (int *)malloc(len * bytes * sizeof(int));
- int x, i, j;
- for(i = 0; i < len; i++) {
- x = decode(cryptogram[i], exponent, modulus);
- for(j = 0; j < bytes; j++) {
- decoded[i*bytes + j] = (x >> (7 * j)) % 128;
- #ifndef MEASURE
- if(decoded[i*bytes + j] != '\0') printf("%c", decoded[i*bytes + j]);
- #endif
- }
- }
- return decoded;
- }
- //系统降级的主要方法。 设置素数p,q,并开始编码和解码“text.txt”中给出的消息;
- int main(void) {
- int p, q, n, phi, e, d, bytes, len;
- int *encoded, *decoded;
- char *buffer;
- FILE *f;
- srand(time(NULL));
- while(1) {
- p = randPrime(SINGLE_MAX);
- printf("生成第一个随机素数, p = %d ", p);
- getchar();
- q = randPrime(SINGLE_MAX);
- printf("生成第二个随机素数, q = %d ", q);
- getchar();
- n = p*q;
- printf("计算p和q的乘积n, n = p * q = %d ", n);
- if(n < 128) {
- printf("模数小于 128,不能编码单个字节。 再试一次\n");
- getchar();
- }
- else break;
- }
- if(n >> 21) bytes = 3;
- else if(n >> 14) bytes = 2;
- else bytes = 1;
- getchar();
- phi = (p - 1) * (q - 1);
- printf("计算欧拉函数的值phi, phi = %d ", phi);
- getchar();
- e = randExponent(phi, EXPONENT_MAX);
- printf("选取一个随机素数e, e = %d \n获得公钥 (%d, %d) ", e, e, n);
- getchar();
- d = inverse(e, phi);
- printf("计算模反元素d, d = %d \n获得密钥 (%d, %d) ", d, d, n);
- getchar();
- printf("打开文件 “text.txt” 用于读取信息");
- f = fopen("text.txt", "r");
- if(f == NULL) {
- printf("无法打开文件 “text.txt” 它存在吗?\n");
- return EXIT_FAILURE;
- }
- len = readFile(f, &buffer, bytes);
- fclose(f);
- printf("文件 “text.txt” 读取成功, 读取到%d字节. 以%d字节的字节流编码", len, bytes);
- getchar();
- printf("加密得密文为:\n");
- encoded = encodeMessage(len, bytes, buffer, e, n);
- printf("编码成功完成 \n");
- getchar();
- printf("正在解码编码的信息 .........\n ");
- getchar();
- printf("解码得明文为:\n");
- decoded = decodeMessage(len/bytes, bytes, encoded, d, n);
- printf("\n");
- free(encoded);
- free(decoded);
- free(buffer);
- return EXIT_SUCCESS;
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|