Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
python-ecdsa — pure-python firma/verificación ECDSA y acuerdo de claves ECDH | Kitploit
Herramientas/GitHubGitHub/tlsfuzzer/python-ecdsa
Herramientas de Cifrado/DescifradoCriptografíaUtilidades y FrameworksAutenticaciónAprendizaje y Educación
GitHubtlsfuzzer/python-ecdsa

python-ecdsa

pure-python firma/verificación ECDSA y acuerdo de claves ECDH

Ver Repositorio
975342hace 2 mesesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

ECDSA y ECDH en Python puro

GitHub CI Documentation Status Coverage Status condition coverage mutation score CodeQL Latest Version Code style: black

Esta es una implementación fácil de usar de ECC (Criptografía de Curva Elíptica) con soporte para ECDSA (Algoritmo de Firma Digital de Curva Elíptica), EdDSA (Algoritmo de Firma Digital de Curva Edwards) y ECDH (Diffie-Hellman de Curva Elíptica), implementada puramente en Python, publicada bajo la licencia MIT. Con esta biblioteca, puede crear rápidamente pares de claves (clave de firma y clave de verificación), firmar mensajes y verificar las firmas. También puede acordar una clave secreta compartida basada en claves públicas intercambiadas. Las claves y las firmas son muy cortas, lo que facilita su manejo e incorporación en otros protocolos.

NOTA: Esta biblioteca no debería utilizarse en entornos de producción; consulte Seguridad para más detalles.

Características

Esta biblioteca proporciona generación de claves, firma, verificación y derivación de secreto compartido para cinco curvas NIST "Suite B" GF(p) (campo primo) populares, con longitudes de clave de 192, 224, 256, 384 y 521 bits. Los "nombres cortos" de estas curvas, conocidos por la herramienta OpenSSL (openssl ecparam -list_curves), son: prime192v1, secp224r1, prime256v1, secp384r1 y secp521r1. Incluye la curva de 256 bits secp256k1 utilizada por Bitcoin. También hay soporte para las variantes normales (no retorcidas) de las curvas Brainpool de 160 a 512 bits. Los "nombres cortos" de estas curvas son: brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, brainpoolP320r1, brainpoolP384r1, . También se incluyen algunas de las curvas pequeñas del estándar SEC (principalmente para acelerar las pruebas de la biblioteca), que son: , , y . La generación de claves, la firma y la verificación también son compatibles con las curvas Ed25519 y Ed448. No se incluyen otras curvas, pero no es demasiado difícil añadir soporte para más curvas sobre campos primos.

Dependencias

Esta biblioteca utiliza solo Python y el paquete 'six'. Es compatible con Python 2.6, 2.7 y 3.6+. También admite la ejecución en implementaciones alternativas como pypy y pypy3.

Si gmpy2 o gmpy están instalados, se utilizarán para una aritmética más rápida. Cualquiera de ellos puede instalarse después de que esta biblioteca esté instalada; python-ecdsa detectará su presencia al inicio y los utilizará automáticamente. Debería preferir gmpy2 en Python3 para un rendimiento óptimo.

Para ejecutar las pruebas de compatibilidad con OpenSSL, la herramienta 'openssl' debe estar en su PATH. Esta versión se ha probado con éxito contra OpenSSL 0.9.8o, 1.0.0a, 1.0.2f, 1.1.1d y 3.0.1 (entre otros).

Instalación

Esta biblioteca está disponible en PyPI; se recomienda instalarla con pip:``` pip install ecdsa

root@kitploit:~
En caso de que se quiera un mayor rendimiento y el uso de código nativo no sea un problema, es posible especificar la instalación junto con `gmpy2`:```
pip install ecdsa[gmpy2]

o (opción más lenta, heredada):``` pip install ecdsa[gmpy]

root@kitploit:~
## Velocidad

La siguiente tabla muestra cuánto tarda esta librería en generar pares de claves (`keygen`), en firmar datos (`sign`), en verificar esas firmas (`verify`), en derivar un secreto compartido (`ecdh`) y en verificar las firmas sin precomputación específica de clave (`no PC verify`). Todos esos valores están en segundos. Por conveniencia, también se proporcionan los inversos de esos valores: cuántas claves por segundo se pueden generar (`keygen/s`), cuántas firmas se pueden realizar por segundo (`sign/s`), cuántas firmas se pueden verificar por segundo (`verify/s`), cuántos secretos compartidos se pueden derivar por segundo (`ecdh/s`) y cuántas firmas sin precomputación específica de clave se pueden verificar por segundo (`no PC verify/s`). El tamaño de la firma bruta (generalmente la forma más pequeña en que se puede codificar una firma) también se proporciona en la columna `siglen`. Usa `tox -e speed` para generar esta tabla en tu propio equipo. En un Intel Core i7 4790K @ 4.0GHz obtengo el siguiente rendimiento:```
                  siglen    keygen   keygen/s      sign     sign/s    verify   verify/s  no PC verify  no PC verify/s
        NIST192p:     48   0.00032s   3134.06   0.00033s   2985.53   0.00063s   1598.36       0.00129s         774.43
        NIST224p:     56   0.00040s   2469.24   0.00042s   2367.88   0.00081s   1233.41       0.00170s         586.66
        NIST256p:     64   0.00051s   1952.73   0.00054s   1867.80   0.00098s   1021.86       0.00212s         471.27
        NIST384p:     96   0.00107s    935.92   0.00111s    904.23   0.00203s    491.77       0.00446s         224.00
        NIST521p:    132   0.00210s    475.52   0.00215s    464.16   0.00398s    251.28       0.00874s         114.39
       SECP256k1:     64   0.00052s   1921.54   0.00054s   1847.49   0.00105s    948.68       0.00210s         477.01
 BRAINPOOLP160r1:     40   0.00025s   4003.88   0.00026s   3845.12   0.00053s   1893.93       0.00105s         949.92
 BRAINPOOLP192r1:     48   0.00033s   3043.97   0.00034s   2975.98   0.00063s   1581.50       0.00135s         742.29
 BRAINPOOLP224r1:     56   0.00041s   2436.44   0.00043s   2315.51   0.00078s   1278.49       0.00180s         556.16
 BRAINPOOLP256r1:     64   0.00053s   1892.49   0.00054s   1846.24   0.00114s    875.64       0.00229s         437.25
 BRAINPOOLP320r1:     80   0.00073s   1361.26   0.00076s   1309.25   0.00143s    699.29       0.00322s         310.49
 BRAINPOOLP384r1:     96   0.00107s    931.29   0.00111s    901.80   0.00230s    434.19       0.00476s         210.20
 BRAINPOOLP512r1:    128   0.00207s    483.41   0.00212s    471.42   0.00425s    235.43       0.00912s         109.61
       SECP112r1:     28   0.00015s   6672.53   0.00016s   6440.34   0.00031s   3265.41       0.00056s        1774.20
       SECP112r2:     28   0.00015s   6697.11   0.00015s   6479.98   0.00028s   3524.72       0.00058s        1716.16
       SECP128r1:     32   0.00018s   5497.65   0.00019s   5272.89   0.00036s   2747.39       0.00072s        1396.16
       SECP160r1:     42   0.00025s   3949.32   0.00026s   3894.45   0.00046s   2153.85       0.00102s         985.07
         Ed25519:     64   0.00076s   1324.48   0.00042s   2405.01   0.00109s    918.05       0.00344s         290.50
           Ed448:    114   0.00176s    569.53   0.00115s    870.94   0.00282s    355.04       0.01024s          97.69

                       ecdh     ecdh/s
        NIST192p:   0.00104s    964.89
        NIST224p:   0.00134s    748.63
        NIST256p:   0.00170s    587.08
        NIST384p:   0.00352s    283.90
        NIST521p:   0.00717s    139.51
       SECP256k1:   0.00154s    648.40
 BRAINPOOLP160r1:   0.00082s   1220.70
 BRAINPOOLP192r1:   0.00105s    956.75
 BRAINPOOLP224r1:   0.00136s    734.52
 BRAINPOOLP256r1:   0.00178s    563.32
 BRAINPOOLP320r1:   0.00252s    397.23
 BRAINPOOLP384r1:   0.00376s    266.27
 BRAINPOOLP512r1:   0.00733s    136.35
       SECP112r1:   0.00046s   2180.40
       SECP112r2:   0.00045s   2229.14
       SECP128r1:   0.00054s   1868.15
       SECP160r1:   0.00080s   1243.98

Para probar el rendimiento con gmpy2 cargado, usa tox -e speedgmpy2. En la misma máquina obtengo el siguiente rendimiento con gmpy2:``` siglen keygen keygen/s sign sign/s verify verify/s no PC verify no PC verify/s NIST192p: 48 0.00017s 5933.40 0.00017s 5751.70 0.00032s 3125.28 0.00067s 1502.41 NIST224p: 56 0.00021s 4782.87 0.00022s 4610.05 0.00040s 2487.04 0.00089s 1126.90 NIST256p: 64 0.00023s 4263.98 0.00024s 4125.16 0.00045s 2200.88 0.00098s 1016.82 NIST384p: 96 0.00041s 2449.54 0.00042s 2399.96 0.00083s 1210.57 0.00172s 581.43 NIST521p: 132 0.00071s 1416.07 0.00072s 1389.81 0.00144s 692.93 0.00312s 320.40 SECP256k1: 64 0.00024s 4245.05 0.00024s 4122.09 0.00045s 2206.40 0.00094s 1068.32 BRAINPOOLP160r1: 40 0.00014s 6939.17 0.00015s 6681.55 0.00029s 3452.43 0.00057s 1769.81 BRAINPOOLP192r1: 48 0.00017s 5920.05 0.00017s 5774.36 0.00034s 2979.00 0.00069s 1453.19 BRAINPOOLP224r1: 56 0.00021s 4732.12 0.00022s 4622.65 0.00041s 2422.47 0.00087s 1149.87 BRAINPOOLP256r1: 64 0.00024s 4233.02 0.00024s 4115.20 0.00047s 2143.27 0.00098s 1015.60 BRAINPOOLP320r1: 80 0.00032s 3162.38 0.00032s 3077.62 0.00063s 1598.83 0.00136s 737.34 BRAINPOOLP384r1: 96 0.00041s 2436.88 0.00042s 2395.62 0.00083s 1202.68 0.00178s 562.85 BRAINPOOLP512r1: 128 0.00063s 1587.60 0.00064s 1558.83 0.00125s 799.96 0.00281s 355.83 SECP112r1: 28 0.00009s 11118.66 0.00009s 10775.48 0.00018s 5456.00 0.00033s 3020.83 SECP112r2: 28 0.00009s 11322.97 0.00009s 10857.71 0.00017s 5748.77 0.00032s 3094.28 SECP128r1: 32 0.00010s 10078.39 0.00010s 9665.27 0.00019s 5200.58 0.00036s 2760.88 SECP160r1: 42 0.00015s 6875.51 0.00015s 6647.35 0.00029s 3422.41 0.00057s 1768.35 Ed25519: 64 0.00030s 3322.56 0.00018s 5568.63 0.00046s 2165.35 0.00153s 654.02 Ed448: 114 0.00060s 1680.53 0.00039s 2567.40 0.00096s 1036.67 0.00350s 285.62

root@kitploit:~
                   ecdh     ecdh/s
    NIST192p:   0.00050s   1985.70
    NIST224p:   0.00066s   1524.16
    NIST256p:   0.00071s   1413.07
    NIST384p:   0.00127s    788.89
    NIST521p:   0.00230s    434.85
   SECP256k1:   0.00071s   1409.95

BRAINPOOLP160r1: 0.00042s 2374.65 BRAINPOOLP192r1: 0.00051s 1960.01 BRAINPOOLP224r1: 0.00066s 1518.37 BRAINPOOLP256r1: 0.00071s 1399.90 BRAINPOOLP320r1: 0.00100s 997.21 BRAINPOOLP384r1: 0.00129s 777.51 BRAINPOOLP512r1: 0.00210s 475.99 SECP112r1: 0.00022s 4457.70 SECP112r2: 0.00024s 4252.33 SECP128r1: 0.00028s 3589.31 SECP160r1: 0.00043s 2305.02

root@kitploit:~
(también hay una versión `gmpy`, ejecútala usando `tox -e speedgmpy`)

Para comparar, una implementación altamente optimizada (incluido ensamblador específico para algunas curvas), como la de OpenSSL 1.1.1d, proporciona los siguientes números de rendimiento en la misma máquina.
Ejecuta `openssl speed ecdsa` y `openssl speed ecdh` para reproducirlo:```
                              sign    verify    sign/s verify/s
 192 bits ecdsa (nistp192)   0.0002s   0.0002s   4785.6   5380.7
 224 bits ecdsa (nistp224)   0.0000s   0.0001s  22475.6   9822.0
 256 bits ecdsa (nistp256)   0.0000s   0.0001s  45069.6  14166.6
 384 bits ecdsa (nistp384)   0.0008s   0.0006s   1265.6   1648.1
 521 bits ecdsa (nistp521)   0.0003s   0.0005s   3753.1   1819.5
 256 bits ecdsa (brainpoolP256r1)   0.0003s   0.0003s   2983.5   3333.2
 384 bits ecdsa (brainpoolP384r1)   0.0008s   0.0007s   1258.8   1528.1
 512 bits ecdsa (brainpoolP512r1)   0.0015s   0.0012s    675.1    860.1

                              sign    verify    sign/s verify/s
 253 bits EdDSA (Ed25519)   0.0000s   0.0001s  28217.9  10897.7
 456 bits EdDSA (Ed448)     0.0003s   0.0005s   3926.5   2147.7

                               op      op/s
 192 bits ecdh (nistp192)   0.0002s   4853.4
 224 bits ecdh (nistp224)   0.0001s  15252.1
 256 bits ecdh (nistp256)   0.0001s  18436.3
 384 bits ecdh (nistp384)   0.0008s   1292.7
 521 bits ecdh (nistp521)   0.0003s   2884.7
 256 bits ecdh (brainpoolP256r1)   0.0003s   3066.5
 384 bits ecdh (brainpoolP384r1)   0.0008s   1298.0
 512 bits ecdh (brainpoolP512r1)   0.0014s    694.8

Las claves y las firmas se pueden serializar de diferentes maneras (consulte Uso, más abajo). Para una clave NIST192p, las tres representaciones básicas requieren cadenas de las siguientes longitudes (en bytes):

root@kitploit:~
to_string:  signkey= 24, verifykey= 48, signature=48
compressed: signkey=n/a, verifykey= 25, signature=n/a
DER:        signkey=106, verifykey= 80, signature=55
PEM:        signkey=278, verifykey=162, (no support for PEM signatures)

Historia

En 2006, Peter Pearson anunció su implementación de ECDSA en Python puro en un mensaje para sci.crypt, disponible desde su sitio de descarga. En 2010, Brian Warner escribió un envoltorio alrededor de este código, para hacerlo un poco más fácil y seguro de usar. En 2020, Hubert Kario incluyó una implementación de criptografía de curva elíptica que utiliza coordenadas jacobianas internamente, mejorando el rendimiento unas 20 veces. Está viendo el README de este envoltorio.

Pruebas

Para ejecutar la suite de pruebas completa, haga esto:

root@kitploit:~
tox -e coverage

En un Intel Core i7 4790K @ 4.0GHz, las pruebas tardan unos 18 segundos en ejecutarse. La suite de pruebas utiliza hypothesis, por lo que hay cierta variabilidad inherente en el tiempo de ejecución de la suite de pruebas.

Una parte de test_pyecdsa.py y test_ecdh.py comprueba la compatibilidad con OpenSSL, ejecutando la herramienta CLI "openssl"; asegúrese de que esté en su PATH si desea probar la compatibilidad con ella (si OpenSSL falta, es demasiado antiguo o no admite todas las curvas soportadas en las versiones upstream, verá pruebas omitidas en la ejecución de coverage anterior).

Seguridad

Esta biblioteca no fue diseñada teniendo en cuenta la seguridad. Si está procesando datos que necesitan protección, le sugerimos que utilice un envoltorio de calidad alrededor de OpenSSL. pyca/cryptography es un ejemplo de dicho envoltorio. El caso de uso principal de esta biblioteca es como biblioteca portátil para pruebas de interoperabilidad y como herramienta educativa.

Esta biblioteca no protege contra ataques de canal lateral.

No permita que los atacantes midan cuánto tiempo le lleva generar un par de claves o firmar un mensaje. No permita que los atacantes ejecuten código en la misma máquina física mientras se lleva a cabo la generación del par de claves o la firma (esto incluye máquinas virtuales). No permita que los atacantes midan cuánta energía consume su computadora mientras genera el par de claves o firma un mensaje. No permita que los atacantes midan la interferencia de radiofrecuencia proveniente de su computadora mientras genera un par de claves o firma un mensaje. Nota: simplemente cargar la clave privada provocará la generación del par de claves. Otras operaciones o vectores de ataque también pueden ser vulnerables a ataques. Para un atacante sofisticado, observar una sola operación con una clave privada será suficiente para reconstruir completamente la clave privada.

Tenga en cuenta también que cualquier biblioteca criptográfica en Python puro será vulnerable a los mismos ataques de canal lateral. Esto se debe a que Python no proporciona primitivas seguras contra canales laterales (con la excepción de hmac.compare_digest()), lo que hace la programación segura contra canales laterales imposible.

Esta biblioteca depende de una fuente sólida de números aleatorios. No la utilice en un sistema donde os.urandom() no proporcione números aleatorios criptográficamente seguros.

Uso

Comience creando una SigningKey. Puede usarla para firmar datos, pasando los datos como una cadena de bytes y obteniendo la firma (también una cadena de bytes). También puede pedirle a una SigningKey que le proporcione la VerifyingKey correspondiente. La VerifyingKey se puede usar para verificar una firma, pasándole tanto la cadena de datos como la cadena de bytes de la firma: devuelve True o lanza BadSignatureError.```python from ecdsa import SigningKey sk = SigningKey.generate() # uses NIST192p vk = sk.verifying_key signature = sk.sign(b"message") assert vk.verify(signature, b"message")

root@kitploit:~
Cada `SigningKey`/`VerifyingKey` está asociada con una curva específica, como
NIST192p (la predeterminada). Las curvas más largas son más seguras, pero
tardan más en usarse y generan claves y firmas más largas.```python
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
vk = sk.verifying_key
signature = sk.sign(b"message")
assert vk.verify(signature, b"message")

La SigningKey se puede serializar en varios formatos diferentes: el más corto es llamar a s=sk.to_string(), y luego recrearla con SigningKey.from_string(s, curve) . Esta forma corta no registra la curva, por lo que debe asegurarse de pasar a from_string() la misma curva que usó para la clave original. La forma corta de una clave de firma basada en NIST192p tiene solo 24 bytes de longitud. Si una codificación de punto es inválida o no se encuentra en la curva especificada, from_string() lanzará MalformedPointError.```python from ecdsa import SigningKey, NIST384p sk = SigningKey.generate(curve=NIST384p) sk_string = sk.to_string() sk2 = SigningKey.from_string(sk_string, curve=NIST384p) print(sk_string.hex()) print(sk2.to_string().hex())

root@kitploit:~
Nota: aunque los métodos se llaman `to_string()`, el tipo que devuelven es
en realidad `bytes`, la parte de "string" es un remanente de Python 2.

`sk.to_pem()` y `sk.to_der()` serializarán la clave de firma en los mismos
formatos que usa OpenSSL. El archivo PEM tiene el conocido formato
ASCII-armored `"-----BEGIN EC PRIVATE KEY-----"` codificado en base64, y el
formato DER es una forma binaria más corta de los mismos datos.
`SigningKey.from_pem()/.from_der()` desharán esta serialización. Estos
formatos incluyen el nombre de la curva, por lo que no es necesario pasar un
identificador de curva al deserializador. En caso de que el archivo esté
malformado, `from_der()` y `from_pem()` lanzarán `UnexpectedDER` o` MalformedPointError`.```python
from ecdsa import SigningKey, NIST384p
sk = SigningKey.generate(curve=NIST384p)
sk_pem = sk.to_pem()
sk2 = SigningKey.from_pem(sk_pem)
# sk and sk2 are the same key

Del mismo modo, VerifyingKey se puede serializar de la misma manera: vk.to_string()/VerifyingKey.from_string(), to_pem()/from_pem(), y to_der()/from_der(). El mismo argumento curve= se necesita para VerifyingKey.from_string().```python from ecdsa import SigningKey, VerifyingKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk_string = vk.to_string() vk2 = VerifyingKey.from_string(vk_string, curve=NIST384p)

vk and vk2 are the same key

from ecdsa import SigningKey, VerifyingKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk_pem = vk.to_pem() vk2 = VerifyingKey.from_pem(vk_pem)

vk and vk2 are the same key

root@kitploit:~
Hay un par de formas diferentes de calcular una firma. Fundamentalmente,
ECDSA toma un número que representa los datos que se están firmando y devuelve un
par de números que representan la firma. El argumento `hashfunc=` de
`sk.sign()` y `vk.verify()` se utiliza para convertir una cadena arbitraria en un
resumen de longitud fija, que luego se convierte en un número que ECDSA puede firmar,
y tanto la firma como la verificación deben usar el mismo enfoque. El valor predeterminado es
`hashlib.sha1`, pero si usas NIST256p o una curva más larga, puedes usar
`hashlib.sha256` en su lugar.

También hay múltiples formas de representar una firma. Los métodos
`sk.sign()` y `vk.verify()` predeterminados la presentan como una cadena corta, por
simplicidad y mínima sobrecarga. Para usar un esquema diferente, utiliza los
argumentos `sk.sign(sigencode=)` y `vk.verify(sigdecode=)`. Hay funciones
auxiliares en el módulo `ecdsa.util` que pueden ser útiles aquí.

También es posible crear un `SigningKey` a partir de una "semilla", que es
determinista. Esto se puede usar en protocolos donde quieras derivar
claves de firma consistentes de algún otro secreto, por ejemplo cuando quieras
tres claves separadas y solo quieras almacenar un único secreto maestro. Debes
comenzar con una semilla uniformemente distribuida e imposible de adivinar con aproximadamente `curve.baselen`
bytes de entropía, y luego usar una de las funciones auxiliares en `ecdsa.util` para
convertirla en un entero en el rango correcto, y finalmente pasarla
a `SigningKey.from_secret_exponent()`, de esta manera:```python
import os
from ecdsa import NIST384p, SigningKey
from ecdsa.util import randrange_from_seed__trytryagain

def make_key(seed):
  secexp = randrange_from_seed__trytryagain(seed, NIST384p.order)
  return SigningKey.from_secret_exponent(secexp, curve=NIST384p)

seed = os.urandom(NIST384p.baselen) # or other starting point
sk1a = make_key(seed)
sk1b = make_key(seed)
# note: sk1a and sk1b are the same key
assert sk1a.to_string() == sk1b.to_string()
sk2 = make_key(b"2-"+seed)  # different key
assert sk1a.to_string() != sk2.to_string()

En caso de que la aplicación verifique muchas firmas realizadas con una sola clave, es posible precalcular algunos de los valores internos para que la verificación de firmas sea significativamente más rápida. El punto de equilibrio se produce alrededor de 100 firmas verificadas.

Para realizar el precálculo, puede llamar al método precompute() en una instancia de VerifyingKey:```python from ecdsa import SigningKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk.precompute() signature = sk.sign(b"message") assert vk.verify(signature, b"message")

root@kitploit:~
Una vez que se llamó a `precompute()`, todas las verificaciones de firma con esta clave serán
más rápidas de ejecutar.

## Compatibilidad con OpenSSL

Para producir firmas que puedan ser verificadas por herramientas OpenSSL, o para verificar
firmas producidas por esas herramientas, use:```python
# openssl ecparam -name prime256v1 -genkey -out sk.pem
# openssl ec -in sk.pem -pubout -out vk.pem
# echo "data for signing" > data
# openssl dgst -sha256 -sign sk.pem -out data.sig data
# openssl dgst -sha256 -verify vk.pem -signature data.sig data
# openssl dgst -sha256 -prverify sk.pem -signature data.sig data

import hashlib
from ecdsa import SigningKey, VerifyingKey
from ecdsa.util import sigencode_der, sigdecode_der

with open("vk.pem") as f:
   vk = VerifyingKey.from_pem(f.read())

with open("data", "rb") as f:
   data = f.read()

with open("data.sig", "rb") as f:
   signature = f.read()

assert vk.verify(signature, data, hashlib.sha256, sigdecode=sigdecode_der)

with open("sk.pem") as f:
   sk = SigningKey.from_pem(f.read(), hashlib.sha256)

new_signature = sk.sign_deterministic(data, sigencode=sigencode_der)

with open("data.sig2", "wb") as f:
   f.write(new_signature)

# openssl dgst -sha256 -verify vk.pem -signature data.sig2 data

Nota: si es necesaria la compatibilidad con OpenSSL 1.0.0 o anterior, se pueden usar sigencode_string y sigdecode_string de ecdsa.util para escribir y leer las firmas, respectivamente.

Las claves también se pueden escribir en un formato que openssl pueda manejar:```python from ecdsa import SigningKey, VerifyingKey

with open("sk.pem") as f: sk = SigningKey.from_pem(f.read()) with open("sk.pem", "wb") as f: f.write(sk.to_pem())

with open("vk.pem") as f: vk = VerifyingKey.from_pem(f.read()) with open("vk.pem", "wb") as f: f.write(vk.to_pem())

root@kitploit:~
## Entropía

Crear una clave de firma con `SigningKey.generate()` requiere alguna forma de
entropía (a diferencia de
`from_secret_exponent`/`from_string`/`from_der`/`from_pem`,
que son deterministas y no requieren una fuente de entropía). La fuente
predeterminada es `os.urandom()`, pero puedes pasar cualquier otra función que se
comporte como `os.urandom` como el argumento `entropy=` para hacer algo diferente. Esto
puede ser útil en pruebas unitarias, donde quieras lograr resultados repetibles. La
utilidad `ecdsa.util.PRNG` es práctica aquí: toma una semilla y produce un flujo
pseudoaleatorio fuerte a partir de ella:```python
from ecdsa.util import PRNG
from ecdsa import SigningKey
rng1 = PRNG(b"seed")
sk1 = SigningKey.generate(entropy=rng1)
rng2 = PRNG(b"seed")
sk2 = SigningKey.generate(entropy=rng2)
# sk1 and sk2 are the same key

Del mismo modo, la generación de firmas ECDSA requiere un número aleatorio, y cada firma debe usar uno diferente (usar el mismo número dos veces revelará inmediatamente la clave de firma privada). El método sk.sign() toma un argumento entropy= que se comporta igual que SigningKey.generate(entropy=).

Firmas Deterministas

Si llamas a SigningKey.sign_deterministic(data) en lugar de .sign(data), el código generará una firma determinista en lugar de una aleatoria. Esto utiliza el algoritmo de RFC6979 para generar de forma segura un valor k único, derivado de la clave privada y del mensaje que se está firmando. Cada vez que firmes el mismo mensaje con la misma clave, obtendrás la misma firma (usando el mismo k).

Esto podría convertirse en el comportamiento predeterminado en una versión futura, ya que no es vulnerable a fallos de la fuente de entropía.

Ejemplos

Crea un par de claves NIST192p y guarda ambas inmediatamente en disco:```python from ecdsa import SigningKey sk = SigningKey.generate() vk = sk.verifying_key with open("private.pem", "wb") as f: f.write(sk.to_pem()) with open("public.pem", "wb") as f: f.write(vk.to_pem())

root@kitploit:~
Carga una clave de firma desde el disco, úsala para firmar un mensaje (usando SHA-1) y escribe
la firma en el disco:```python
from ecdsa import SigningKey
with open("private.pem") as f:
    sk = SigningKey.from_pem(f.read())
with open("message", "rb") as f:
    message = f.read()
sig = sk.sign(message)
with open("signature", "wb") as f:
    f.write(sig)

Cargue la clave de verificación, el mensaje y la firma desde el disco, y verifique la firma (suponga hash SHA-1):```python from ecdsa import VerifyingKey, BadSignatureError vk = VerifyingKey.from_pem(open("public.pem").read()) with open("message", "rb") as f: message = f.read() with open("signature", "rb") as f: sig = f.read() try: vk.verify(sig, message) print "good signature" except BadSignatureError: print "BAD SIGNATURE"

root@kitploit:~
Crea un par de claves NIST521p:```python
from ecdsa import SigningKey, NIST521p
sk = SigningKey.generate(curve=NIST521p)
vk = sk.verifying_key

Crear tres claves de firma independientes a partir de una semilla maestra:```python from ecdsa import NIST192p, SigningKey from ecdsa.util import randrange_from_seed__trytryagain

def make_key_from_seed(seed, curve=NIST192p): secexp = randrange_from_seed__trytryagain(seed, curve.order) return SigningKey.from_secret_exponent(secexp, curve)

sk1 = make_key_from_seed("1:%s" % seed) sk2 = make_key_from_seed("2:%s" % seed) sk3 = make_key_from_seed("3:%s" % seed)

root@kitploit:~
Cargue una clave de verificación desde el disco e imprímala usando codificación hexadecimal en
formato sin comprimir y comprimido (definido en los estándares X9.62 y SEC1):```python
from ecdsa import VerifyingKey

with open("public.pem") as f:
    vk = VerifyingKey.from_pem(f.read())

print("uncompressed: {0}".format(vk.to_string("uncompressed").hex()))
print("compressed: {0}".format(vk.to_string("compressed").hex()))

Cargar una clave de verificación desde una cadena hexadecimal en formato comprimido, salida sin comprimir:```python from ecdsa import VerifyingKey, NIST256p

comp_str = '022799c0d0ee09772fdd337d4f28dc155581951d07082fb19a38aa396b67e77759' vk = VerifyingKey.from_string(bytearray.fromhex(comp_str), curve=NIST256p) print(vk.to_string("uncompressed").hex())

root@kitploit:~
Intercambio de claves ECDH con la parte remota:```python
from ecdsa import ECDH, NIST256p

ecdh = ECDH(curve=NIST256p)
ecdh.generate_private_key()
local_public_key = ecdh.get_public_key()
#send `local_public_key` to remote party and receive `remote_public_key` from remote party
with open("remote_public_key.pem") as e:
    remote_public_key = e.read()
ecdh.load_received_public_key_pem(remote_public_key)
secret = ecdh.generate_sharedsecret_bytes()
Descargar herramienta
brainpoolP512r1
secp112r1
secp112r2
secp128r1
secp160r1