(Conceptos básicos de cifrado) RSA

Algoritmo RSA

RSA es un algoritmo de cifrado asimétrico. Si A quiere comunicarse con B, A utiliza la clave pública A para cifrar y transfiere el texto cifrado a B, y B utiliza la clave privada B para descifrar el texto sin formato, donde la clave pública se transmite en la red. La clave privada solo es propiedad de B y no se transmite en la red, por lo que incluso si se conoce la clave pública A, la información transmitida no se puede descifrar

Principio del algoritmo RSA e implementación del código Python

1. Genera claves públicas y privadas

1.1 Dados dos números primos P, Q

Cuanto más grandes sean P y Q aquí, más seguro será el algoritmo. Para la conveniencia de la descripción, dado P = 67 y Q = 71, entonces su producto n = 4757

1.2 Calcular la función de Euler φ (n) de n

Según la definición de la función de Euler, φ (n) es igual al número de enteros positivos menores o iguales an que son relativamente primos an , y como P * Q = n y PQ son todos números primos, φ (n) = (P -1) (Q-1) = 66 * 70 = 4620

1.3 Seleccione aleatoriamente un número entero e (1 <e <m) ye y m son primos relativos

Aquí e = 101 se selecciona al azar. Tenga en cuenta que cuando e = m, las claves pública y privada serán las mismas

1.4 Dado un número entero d, haga (e * d)% m = 1
因为 (e*d)%m=1  

所以 e*d-m*y=1(y为整数),由上述可知 e = 101,m = 4620 

所以 101d-4620y=1

根据相关定理(d,y)=1=101d-4620y

根据扩展欧几里得算法:

4620=101x4+75
101=75x1+26
75=26x2+23
23=3x7+1
3=2x1+1
---->
101x1601-35x4620

得到d等于1601

Una vez completado el cálculo, se obtienen la clave pública (n, e) = (4757,101) y la clave privada (n, d) = (4757,1601) . Según el efecto del algoritmo RSA, nadie conoce la clave privada excepto el receptor . Entonces, ¿puede obtener la clave privada a través de la clave pública?

已知(e*d)%m=1,已知n,e,那么要求d只需要求出n

而我们知道m是n的欧拉函数φ(n),想要知道m就必须将n分解成两个质数的乘积
这里由于数比较小,我们很容易分解出PQ的值,而随着n的增大,分解会变得异常困难

2. Cifrado para generar texto cifrado

Suponiendo que el número cifrado es a,
convertir a en int es 97. El
proceso de cálculo es el siguiente:

97 ^ 101% 4757 = 3589

Inserte la descripción de la imagen aquí

3. Descifre el texto cifrado

Según la fórmula
a ^ d% n = b

Podemos obtener el texto sin formato

Inserte la descripción de la imagen aquí

Implementación de código Python

Dado que el lenguaje C no admite números grandes, es muy problemático usar el lenguaje C para implementar el código Python aquí


# -*- coding: cp936 -*-


def isPrime(number):
    import math
    i = 2
    sqrtnum = (int)(math.sqrt(number))
    for i in range(2, sqrtnum + 1):
        if number % i == 0:
            return False
        i = i + 1
    return True


def is_ET_Prime(ee, tt):
    while tt != 0:
        a = ee
        ee = tt
        tt = a % tt
    if ee == 1:
        return True
    else:
        return False


def get_publickey(k, t):
    d = 0
    while ((d * k) % t != 1):
        d += 1
    return d


def encryption(plain, d, n):
    re = (plain ** d) % n

    return re


if __name__ == "__main__":
    print
    "~" * 70
    Flag = False
    while True:
        p = int(input("please input a prime p:"))
        q = int(input("please input a prime q:"))

        if (isPrime(p) and isPrime(q)):
            break
        else:
            print
            "p or q is not prime!"
            continue

    print
    "p=", p, "q=", q

    n = q * p
    t = (q - 1) * (p - 1)
    print("n=", n, "t=", t)

    print("~" * 70)

    Flag == False
    while Flag == False:
        e = int(input("please input a private key:"))
        Flag = is_ET_Prime(e, t)
        if Flag == False:
            print("e is not prime with the t!")

    print("the private key e=", e)

    d = get_publickey(e, t)
    print("the public key d=", d)

    plain = int(ord(input("please input the plain you want to entrypted:")))

    encry = encryption(plain, d, n)
    print("plain", plain, "is encrypted as", encry)
    #print(encry)
    plain1 = encryption(encry, e, n)
    print("encrypt", encry, "is decrypted as", plain1)

Ataque de modo común RSA

Suponga que hay una pieza de información m, que está encriptada por dos usuarios diferentes usando claves públicas (la e de los dos usuarios es generalmente diferente y el módulo n es generalmente el mismo)

c1 = m^e1 mod n
c2 = m^e2 mod n

Tengo dos textos cifrados diferentes c1, c2

Ataque en modo común Esto obtiene estos dos textos cifrados c1, c2, porque la clave pública es pública (e1, e2, n) se conoce

Entonces el atacante conoce la siguiente información en total

gcd(e1, e2) = 1
m = c1^d1 mod n
m = c2^d2 mod n

Entonces de acuerdo con lo anterior, el texto llano m se puede obtener directamente, porque gcd(e1,e2)entonces hay enteros s1, s2 e1*s1+e2*s2=1, y porque

c1=m^e1 mod n
c2=m^e2 mod n

y entonces:

c1^s1 mod n=m^(e1*s1) mod n
c2^s2 mod n=m^(e2*s2) mod n
c1^s1*c2^s2 mod n=m^(e1*s1+e2*s2) mod n
又因为e1*s1+e2*s2=1
所以
c1^s1*c2^s2  =m mod n
再由扩展欧几里得算法和e1*s1+e2*s2=1,即可求出s1,s2

Plantilla de código:

from libnum import n2s,s2n
from gmpy2 import invert

def egcd(a, b):
if a == 0:
    return (b, 0, 1)
else:
    g, y, x = egcd(b % a, a)
    return (g, x - (b // a) * y, y)

def main():
    n = int(input("请输入一个十六进制数n"),16)
    c1 = int(input("请输入一个十六进制数c1"),16)
    c2 = int(input("请输入一个十六进制数c2"),16)
    e1 = int(input("请输入一个十六进制数e1"),16)
    e2 = int(input("请输入一个十六进制数e2"),16)
    s = egcd(e1, e2)
    s1 = s[1]
    s2 = s[2]
    # 求模反元素
    if s1<0:
        s1 = - s1
        c1 = invert(c1, n)
    elif s2<0:
        s2 = - s2
        c2 = invert(c2, n)

    m = pow(c1,s1,n)*pow(c2,s2,n) % n
    print n2s(m)

if __name__ == '__main__':
  main()

Supongo que te gusta

Origin blog.csdn.net/weixin_43632667/article/details/106415454
Recomendado
Clasificación