Esquemas criptográficos

Esquemas criptográficos con curvas elípticas.

Este módulo permite trabajar con protocolos criptográficos asimétricos, como el esquema Diffie-Hellman conocido como ECDH o el algoritmo de firmas digitales conocido como ECDSA.

Para utilizar las funciones y las clases de este módulo, debe importarlo previamente:

# reemplace ... por la función/clase que desea utilizar
from ccepy.esquemas_criptograficos import ...

Para trabajar con un protocolo, basta iniciar las entidades involucradas y llamar a los métodos correspondientes. Veamos un ejemplo con EDCH:

>>> # definimos los parámetros
>>> E = curva_eliptica_sobre_Fq(a=324, b=1287, p=3851)  # y^2 = x^3 + a x + b sobre Fp
>>> generador = E(920, 303)
>>> orden_generador = 8
>>> # definimos los participantes
>>> alicia = ECDH(E, generador, orden_generador)
>>> bob = ECDH(E, generador, orden_generador)
>>> # la pareja de llaves se genera automáticamente
>>> alicia.llave_publica
(2373,2607)
>>> alicia.llave_privada
2
>>> alicia.calcula_secreto_compartido(bob.llave_publica)
1136
>>> bob.calcula_secreto_compartido(alicia.llave_publica)
1136

Lista de esquemas criptográficos:

ECDH Representa un participante del protocolo ECDH.
ECDSA Representa un participante del protocolo ECDSA.
class ECDH(curva_eliptica, generador, orden)[fuente]

Representa un participante del protocolo ECDH.

El protocolo Diffie-Hellman para curvas elípticas o ECDH es un protocolo de establecimiento de llaves, esto es, permite a dos entidades establecer un secreto compartido sobre un canal inseguro. Para ello se cálcula un punto secreto de una curva elíptica que solo es conocido por las entidades involucradas.

Veamos un ejemplo de la creación de un participante:

>>> # definimos los parámetros
>>> E = curva_eliptica_sobre_Fq(a=324, b=1287, p=3851)
>>> generador = E(920, 303)
>>> orden_generador = 8
>>> # definimos el participante
>>> alicia = ECDH(E, generador, orden_generador)
>>> # la pareja de llaves se genera automáticamente
>>> alicia.llave_publica
(2373,2607)
>>> alicia.llave_privada
2

Una vez se tienen dos participantes, se puede establecer un secreto compartido llamando a calcula_secreto_compartido():

>>> bob = ECDH(E, generador, orden_generador)
>>> alicia.calcula_secreto_compartido(bob.llave_publica)
1136
>>> bob.calcula_secreto_compartido(alicia.llave_publica)
1136

Para la inicialización de un participante es necesario pasarle como primer argumento una curva elíptica. Para ello puede usar las funciones del tipo curva_eliptica_sobre_* del módulo curvas_elipticas.

Además, en la inicialización se genera un par de llaves pública y privada de forma aleatoria. Si quiere utilizar un par concreto, basta machacar el valor de llave_privada y llave_publica tras la inicialización. La única restricción es que la llave pública sea la multiplicación escalar de la llave privada por el generador:

>>> eva = ECDH(E, generador, orden_generador)
>>> eva.llave_privada = 3
>>> eva.llave_publica = eva.generador * eva.llave_privada
Parámetros:
  • curva_eliptica – el constructor de puntos de una curva elíptica.
  • generador – un punto de la curva elíptica.
  • orden (int) – el orden del generador.
curva_eliptica

el constructor de puntos de una curva elíptica.

generador

un punto de la curva elíptica.

orden

int – el orden del generador.

llave_privada

int – un entero que hace de llave privada del participante.

llave_publica

un punto de la curva elíptica que hace de llave pública del participante.

calcula_secreto_compartido(otra_llave_publica)[fuente]

Devuelve el punto de la curva elíptica que hace de secreto compartido.

Parámetros:otra_llave_publica – la llave pública del otro participante.
Devuelve:el secreto compartido.
class ECDSA(curva_eliptica, generador, orden)[fuente]

Representa un participante del protocolo ECDSA.

El algoritmo de firmas digitales para curvas elípticas o ECDSA es un esquema de firmado análogo al esquema DSA pero utilizando la multiplicación escalar de una curva elíptica en vez de la exponenciación modular.

Veamos un ejemplo de la creación del participante que hará de firmante:

>>> # definimos los parámetros
>>> E = curva_eliptica_sobre_Fq(a=5, b=7, p=113)
>>> generador = E(16, 51)
>>> orden_generador = 127
>>> # definimos el participante
>>> alicia = ECDH(E, generador, orden_generador)
>>> # la pareja de llaves se genera automáticamente
>>> alicia.llave_publica
(14,83)
>>> alicia.llave_privada
32

Para firmar, basta llamar al método firma() pasándole el mensaje que se desea firmar:

>>> r, s = alicia.firma(mensaje)
>>> r, s
13, 73

Para que otra entidad compruebe la firma, basta llamar a verifica() pasándole como argumentos el mensaje, la firma y la llave pública del firmante:

>>> bob = ECDSA(E, generador, orden)
>>> bob.verifica(mensaje, r, s, alicia.llave_publica)
True

Para la inicialización de un participante es necesario pasarle como primer argumento una curva elíptica sobre un cuerpo finito de orden un primo (no una potencia de un primo). Para ello puede usar la función curva_eliptica_sobre_Fq() (del módulo curvas_elipticas) paśandole como argumento n=1

Además, en la inicialización se genera un par de llaves pública y privada de forma aleatoria. Si quiere utilizar un par concreto, basta machacar el valor de llave_privada y llave_publica tras la inicialización. La única restricción es que la llave pública sea la multiplicación escalar de la llave privada por el generador:

>>> eva = ECDH(E, generador, orden_generador)
>>> eva.llave_privada = 3
>>> eva.llave_publica = eva.generador * eva.llave_privada
Parámetros:
  • curva_eliptica – el constructor de puntos de una curva elíptica.
  • generador – un punto de la curva elíptica.
  • orden (int) – el orden del generador.
curva_eliptica

el constructor de puntos de una curva elíptica.

generador

un punto de la curva elíptica.

orden

int – el orden del generador.

llave_privada

int – un entero que hace de llave privada del participante.

llave_publica

un punto de la curva elíptica que hace de llave pública del participante.

firma(mensaje)[fuente]

Firma el mensaje utilizando la llave pública del participante.

No se firma todo el mensaje, sino que previo al firmado se le aplica la función hash SHA-1 (del módulo hashlib) al mensaje y se firma sobre dicho hash.

Parámetros:mensaje (str) – el mensaje que se desea firmar.
Devuelve:el par (r, s) que forma la firma del mensaje.
Tipo del valor devuelto:
 Tuple[int]
verifica(mensaje, r, s, llave_publica_firmante)[fuente]

Comprueba la firma de un mensaje.

No se firma todo el mensaje, sino que previo al firmado se le aplica la función hash SHA-1 (del módulo hashlib) al mensaje y se firma sobre dicho hash.

Los parámetros (r, s) es el par que devuelve el método firma().

Parámetros:
  • mensaje (str) – el mensaje que se desea comprobar su firma.
  • r (int) – la primera componente de la firma.
  • s (int) – la segunda componente de la firma.
  • llave_publica_firmante – la llave pública del firmado.
Devuelve:

verdadero o falso.

Tipo del valor devuelto:
 

bool