Demo entry 6632206

RSA

   

Submitted by uetiko on Jul 22, 2017 at 09:02
Language: Python. Code size: 3.7 kB.

# -*- coding: utf-8 -*-

import random
from sys import exit


class MathUtil(object):
    '''Funciones básicas de teoría de números.
    '''

    @staticmethod
    def is_prime(n):
        '''Determina si el número es primo

        Args:
            n: Número

        Returns:
            True si el número primo, False en cualquier caso.
        '''
        if 2 == n:
            return True
        if n < 2 or 0 == n % 2:
            return False
        for k in range(3, int(n**0.5) + 2, 2):
            if 0 == n % k:
                return False

        return True

    @staticmethod
    def gcd(a, b):
        '''Máximo común divisor de dos números

        Args:
            a: Número.
            b: Número.

        Returns:
            El máximo común divisor.
        '''
        while 0 != b:
            a, b = b, a % b

        return a

    @staticmethod
    def get_coprime(p):
        '''Generar un número coprimo.

        Args:
            p: Número.

        Returns:
            Un número coprimo de p.
        '''
        e = random.randrange(1, p)

        g = MathUtil.gcd(e, p)
        while 1 != g:
            e = random.randrange(1, p)
            g = MathUtil.gcd(e, p)

        return e

    @staticmethod
    def multiplicative_inverse(a, b):
        '''Obetener el inverso multiplicativo de dos números

        Args:
            a: Número.
            b: Número.

        Returns:
            El inverso multiplicativo de a y b.
        '''
        d = 0
        x1 = 0
        x2 = 1
        y1 = 1
        temp_phi = b

        while a > 0:
            temp1 = temp_phi / a
            temp2 = temp_phi - temp1 * a
            temp_phi = a
            a = temp2

            x = x2 - temp1 * x1
            y = d - temp1 * y1

            x2 = x1
            x1 = x
            d = y1
            y1 = y

        if 1 == temp_phi:
            return d + b


class RSA(object):
    '''Implementación básica del algoritmo RSA.

    Attributes:
        public_key (tuple): Llave pública para decifrar mensajes.
        private_key (tuple): Llave privada para cifrar mensajes.
    '''

    def __init__(self):
        self.public_key = None
        self.private_key = None

    def generate_keys(self, p, q):
        '''Genera las llaves pública y privada.

        Args:
            p: Número primo.
            q: Número primo.
        '''
        if p == q:
            raise ValueError("'p' y 'q' tienen que ser diferentes.")
        elif not MathUtil.is_prime(p) or not MathUtil.is_prime(q):
            raise ValueError('Ambos valores tienen de ser primos.')

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

        e = MathUtil.get_coprime(phi)
        d = MathUtil.multiplicative_inverse(e, phi)

        self.public_key = (e, n)
        self.private_key = (d, n)

    def encrypt(self, message):
        '''Cifra el mensaje.

        Args:
            message: Mensaje a cifrar.
        '''
        e, n = self.public_key
        cipher = [pow(ord(c), e, n) for c in message]
        return cipher

    def decrypt(self, encripted_message):
        '''Descifra el mensaje.

        Args:
            encrypted_message: Mensaje a descifrar.
        '''
        d, n = self.private_key
        plain = [pow(c, d, n) for c in encripted_message]
        return ''.join(map(lambda c: chr(c), plain))

# Ejemplo
rsa = RSA()
try:
    rsa.generate_keys(36857, 104693)
except Exception as e:
    print('error: {}'.format(str(e)))
    exit(2)

mensaje = 'Voy a encriptar este mensaje.'
print(mensaje)
print('cifrando')
cipher = rsa.encrypt(mensaje)
print(cipher)
message = rsa.decrypt(cipher)
print('desifrando')
print(message)

This snippet took 0.00 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).