C语言 加密:RSA算法

zi8p0yeb  于 2023-06-05  发布在  其他
关注(0)|答案(5)|浏览(486)

我正在实现RSA加密和解密算法,如下所示:
http://www.di-mgt.com.au/rsa_alg.html
但无法理解密钥生成中的随机素数生成部分。所以我从用户那里得到两个素数作为输入。我也很难生成e。所以我把它设为常数(e= 17)
一些素数输入在linux下的gcc中工作正常(即编码和解码正常),但在windows下的devcpp中不正常。(例如53,61)
下面是密钥生成代码:

/* Generates private and public keys and saves into two separate files */
void keygen()
{
    int p,q,phi,d,e,n,s;

    printf("\n Enter two prime numbers: ");
    scanf("%d%d",&p,&q);

    n = p*q;
    phi=(p-1)*(q-1);

    e=17;

    // selec d such that d*e = 1+ k*phi for some integer k.
    d = 0;
    do
    {
        d++;
        s = (d*e)%phi;
    }while(s!=1);

    printf("\n public key: { e=%d n=%d }",e,n);
    printf("\n private key: { d=%d n=%d }\n",d,n);

}

需要帮助和建议在素数和e代。

rxztt3cl

rxztt3cl1#

所以你已经知道e * d需要与1 mod phi(n)全等
因为你知道phi(n),所以元组(e,d)可以通过使用扩展的欧几里德算法(EEA)来计算:
为e选择一个整数(通常是一个小整数;这将是公共指数,用较小的指数加密将更快),其小于φ(n)且大于2(?…我想)
当你有一个e的候选者时,计算e和phi(n)的最大公约数(gcd)...应该是1…如果不是,则为e选择新候选并重复(因为将不存在模逆,换句话说,对于该e和phi(n)不存在私有指数d)
在你知道gcd(e,phi(n))==1之后,你可以使用EEA来计算d(或者作为一种快捷方式,直接计算EEA,因为它也会提供GCD...如果不是1,则为e选择一个新值)
EEA(快速和肮脏的计算模逆):
假设一个表有3列:
假设这些列被命名为:B、q和t
因此,该表的行将如下所示:
b0、q0、t0
b1、q1、t1
...
(and等)
最初将填充前2行。对于所有其他行,有一个迭代规则可应用于前两行,该规则将产生下一行的值
前两行是:
phi(n),NO_VALUE,0
e,floor(phi(n)/e),1
创建下一行的迭代规则是:(其中[]是用于选择行的索引运算符)
B[i] = b[i-2] mod b[i-1]
q[i] = B[i-1] / b[i](整数除法,无分数…)
t[i] = t[i-2] -(q[i-1] * t[i-1])
当b[i]变为0或1时,可以中止该方案…最后一行不需要q
所以如果B[i]是0,那么b[i-1]就不能是1,因为如果b[i-1]是1的话,你应该在计算b[i-1]的时候就放弃了...
如果你达到B[i]==0,b[i-1]就是你的gcd……因为它不是1,所以需要为e取一个新值
如果B[i]==1,你的gcd是1,有一个逆...即t[i](如果t为负,则加上phi(n))
真实的值示例:
假设φ(n)是120假设我们选择23作为e的候选
我们的表看起来像:

b     q     t
120   –     0
23    5     1
5     4     -5
3     1     21
2     1     -26
1     2     47

最后计算的B是1,所以=> gcd(23,120)== 1(证明:存在相反情况)
最后计算的t是47 => 23*47 mod 120 == 1(t是倒数)

htrmnn0y

htrmnn0y2#

我没有答案,但是如果用两个不同的编译器编译的同一段代码给出了不同的答案,我会猜测一些类型的大小不同,或者你在某个地方隐式地依赖于未定义的行为。
你应该做的第一件事是,给定相同的素数对,检查你生成的所有常数在两个实现中是否相同。如果没有,则您的密钥对生成算法有问题。
接下来要做的是确保两个系统上用于加密的输入数据完全相同。要特别注意如何处理行尾字符。请记住,在Windows上,行尾是\r\n,在Linux上是\n。如果将"r"作为mode参数提供给fopen(),则大多数Windows库实现将在读入文件时将\r\n转换为\n。您的实现可能会有所不同。
最后,无论问题是什么,**永远不要使用gets()**如果你发现自己想再次使用它,你应该用冰锥切除大脑的额叶。

mec1mxoz

mec1mxoz3#

按照链接页面末尾的实用说明,您将为主要一代提供以下内容:

unsigned int get_prime(int e)
{
    while (true)
    {
        unsigned int suspect = 1 + (unsigned int)(65535.0 * rand() / (RAND_MAX + 1.0));
        suspect &= 0x0000FFFF; // make sure only the lower 16bit are set
        suspect |= 0xC001; // set the two highest and the lowest bit
        while (!test_prime(suspect))
        {
            suspect += 2;
        }
        if (suspect < 65536 && gcd(e, suspect - 1) == 1)
            return suspect;
    }
}

test_prime应该是Miller-Rabin test的实现。上面的函数做了一些假设,并有一些缺点:

  • int为32位
  • 兰德_MAX大于65536
  • rand()通常不是用于严格加密的好随机数生成器
  • 生成的素数是16位的,所以显然不足以进行严格的加密

不要在任何生产代码中使用它。
根据这篇文章,似乎可以选择e固定。

byqmnocz

byqmnocz4#

Dear Friend just follow this algorithm

 Key generation
1) Pick two large prime numbers p and q, p != q;
2) Calculate n = p × q;
3) Calculate ø (n) = (p − 1)(q − 1);
4) Pick e, so that gcd(e, ø (n)) = 1, 1 < e <  ø (n);
5) Calculate d, so that d · e mod ø (n) = 1, i.e., d is the multiplicative inverse of e in mod  ø (n);
6) Get public key as KU = {e, n};
7) Get private key as KR = {d, n}.
Encryption
For plaintext block P < n, its ciphertext C = P^e (mod n).
Decryption
For ciphertext block C, its plaintext is P = C^d (mod n).

Code:
#include<stdio.h> 
#include<conio.h> 
#include<stdlib.h> 
#include<math.h> 
#include<string.h> 

long int p,q,n,t,flag,e[100],d[100],temp[100],j,m[100],en[100],i; 
char msg[100]; 
int prime(long int); 
void ce(); 
long int cd(long int); 
void encrypt(); 
void decrypt(); 
void main() 
{ 
clrscr(); 
printf("\nENTER FIRST PRIME NUMBER\n"); 
scanf("%d",&p); 
flag=prime(p); 
if(flag==0) 
{ 
    printf("\nWRONG INPUT\n"); 
    getch(); 
    exit(1); 
} 
printf("\nENTER ANOTHER PRIME NUMBER\n"); 
scanf("%d",&q); 
flag=prime(q); 
if(flag==0||p==q) 
{ 
    printf("\nWRONG INPUT\n"); 
    getch(); 
    exit(1); 
} 
printf("\nENTER MESSAGE\n"); 
fflush(stdin); 
scanf("%s",msg); 
for(i=0;msg[i]!=NULL;i++) 
m[i]=msg[i]; 
n=p*q; 
t=(p-1)*(q-1); 
ce(); 
printf("\nPOSSIBLE VALUES OF e AND d ARE\n"); 
for(i=0;i<j-1;i++) 
printf("\n%ld\t%ld",e[i],d[i]); 
encrypt(); 
decrypt(); 
getch(); 
} 
int prime(long int pr) 
{ 
int i; 
j=sqrt(pr); 
for(i=2;i<=j;i++) 
{ 
    if(pr%i==0) 
    return 0; 
} 
return 1; 
} 
void ce() 
{ 
int k; 
k=0; 
for(i=2;i<t;i++) 
{ 
    if(t%i==0) 
    continue; 
    flag=prime(i); 
    if(flag==1&&i!=p&&i!=q) 
    { 
        e[k]=i; 
        flag=cd(e[k]); 
        if(flag>0) 
        { 
            d[k]=flag; 
            k++; 
        } 
        if(k==99) 
        break; 
    } 
} 
} 
long int cd(long int x) 
{ 
long int k=1; 
while(1) 
{ 
    k=k+t; 
    if(k%x==0) 
    return(k/x); 
} 
} 
void encrypt() 
{ 
long int pt,ct,key=e[0],k,len; 
i=0; 
len=strlen(msg); 
while(i!=len) 
{ 
    pt=m[i]; 
    pt=pt-96; 
    k=1; 
    for(j=0;j<key;j++) 
    { 
        k=k*pt; 
        k=k%n; 
    } 
    temp[i]=k; 
    ct=k+96; 
    en[i]=ct; 
    i++; 
} 
en[i]=-1; 
printf("\nTHE ENCRYPTED MESSAGE IS\n"); 
for(i=0;en[i]!=-1;i++) 
printf("%c",en[i]); 
} 
void decrypt() 
{ 
long int pt,ct,key=d[0],k; 
i=0; 
while(en[i]!=-1) 
{ 
    ct=temp[i]; 
    k=1; 
    for(j=0;j<key;j++) 
    { 
        k=k*ct; 
        k=k%n; 
    } 
    pt=k+96; 
    m[i]=pt; 
    i++; 
} 
m[i]=-1; 
printf("\nTHE DECRYPTED MESSAGE IS\n"); 
for(i=0;m[i]!=-1;i++) 
printf("%c",m[i]); 
}
uqzxnwby

uqzxnwby5#

该公式适用于该特定情况,但不是所有情况。

import math

p = 19
q = 17
e = 7

n = p * q #public key

m = 88 #message

c = (m**e) % n #encoded message

phi_of_N = (p-1) * (q-1)

ed = (phi_of_N * (e-1)) + 1

d = math.ceil(ed / e)

ed_valid_check = ed % phi_of_N

decoded = (c**d) % n

print(f'public key = n == {n}')
print(f'message = m == {m}')
print(f'encoded message = c == {c}')
print(f'phi_of_N == {phi_of_N}')
print(f'ed == {ed}')
print(f'd == {d}')
print(f'ed_valid_check. Should equal 1 == {ed_valid_check}')
print(f'Decoded Message: {decoded}')

它也适用于这些价值观。

p = 23
q = 29
e = 3

相关问题