
List of unsafe ed25519 signature libs
Una lista de librerías de firmas ed25519 potencialmente inseguras que permiten una api pública donde la clave secreta y la clave pública pueden proporcionarse de forma independiente como entradas de la función de firma. El uso indebido de estas apis públicas puede resultar en la exposición de la clave privada.
La mayoría de los repositorios de nuestro análisis están incluidos en IANIX :: Things that use Ed25519.
Número de librerías afectadas: 45
Número de librerías que corrigieron el problema tras el anuncio: 8
última actualización: 4 de mayo de 2023
Ten en cuenta que, normalmente y de acuerdo con el rfc8032 relacionado, las firmas EdDSA son deterministas y, por lo tanto, para el mismo mensaje de entrada a firmar se devuelve una salida de firma única que incluye dos elementos: un punto de la curva R y un escalar S.
Un detalle algorítmico es que la clave pública del firmante solo interviene en el cálculo determinista de la parte S de la firma, pero no en el valor R. Esto último implica que, si un adversario pudiera usar de alguna manera la función de firma como un oráculo (que espera claves públicas arbitrarias como entradas), entonces es posible que para el mismo mensaje se obtengan dos firmas que compartan el mismo R y solo difieran en la parte S. Desafortunadamente, cuando esto sucede, se puede extraer fácilmente la clave privada; esta publicación de StackOverflow explica por qué esto es factible.
Dicho esto, las apis públicas NO deberían permitir un par de claves privada/pública desacoplado como entrada de firma. Para evitar esto, muchas implementaciones almacenan la clave pública junto con la clave privada (o semilla) y consideran todo el par de claves como el secreto, O siempre vuelven a derivar la clave pública dentro de la función de firma. Desafortunadamente, un gran número de librerías existentes no abordan este problema al permitir claves públicas arbitrarias como entradas sin comprobar si la clave pública de entrada corresponde con la clave privada de entrada.
Por supuesto, esto no significa que todas las aplicaciones con dependencias de estas librerías sean propensas a ataques de exposición de claves; de hecho, la mayoría probablemente sean seguras, ya que normalmente no exponen públicamente la api afectada a sus usuarios y acoplan su par de claves pub/priv justo antes de la invocación de sign. Por otro lado, incluso cuando estas apis no están expuestas, hay aplicaciones con diferentes estrategias de modelo de amenaza TCB sobre cómo se gestionan y almacenan las claves privadas y públicas. Dicho esto, para prevenir este ataque, los desarrolladores también deberían imponer un protocolo de protección de integridad para las claves públicas.
Aquí enumeramos algunas librerías afectadas junto con las referencias de código relacionadas.
Fig. 1. Un ejemplo de uso indebido de la api en el crate Rust ed25519-dalek.
C: OpenGNB
https://github.com/gnbdev/opengnb/blob/master/libs/ed25519/sign.c#L7
C: GNU Nettle
https://github.com/gnutls/nettle/blob/fe7ae87d1b837e82f7c7968b068bca7d853a4cec/ed25519-sha512-sign.c#L43
ASM/C: iroha-ed25519 (Hyperledger Project)
https://github.com/hyperledger/iroha-ed25519/blob/main/lib/ed25519/ref10/ed25519.c#L27
y
https://github.com/hyperledger/iroha-ed25519/blob/main/lib/ed25519/amd64-64-24k-pic/ed25519.c#L30
C: ed25519-donna (Andrew Moon)
https://github.com/floodyberry/ed25519-donna/blob/master/ed25519.c#L59
C: ed25519 (Orson Peters)
https://github.com/orlp/ed25519/blob/master/src/sign.c#L7
C: libbrine (Kevin Smith)
https://github.com/kevsmith/libbrine/blob/master/src/ed25519/sign.c#L7
C++: Ed25519 (ArduinoLibs)
https://rweather.github.io/arduinolibs/classEd25519.html#a36ecf67b4c5d2d39a31888f56af1f8a5
C#: ed25519 (Hans Wolff)
https://github.com/hanswolff/ed25519/blob/master/Ed25519/Ed25519.cs#L146
C#: Ed25519 (CryptoManiac)
https://github.com/CryptoManiac/Ed25519/blob/972829ac688847895d5105f19ca1e5777131b421/Chaos.NaCl/Internal/Ed25519Ref10/keypair.cs#L7
Dart: ed25519_dart (Oleksii Semeshchuk)
https://github.com/semolex/ed25519_dart/blob/master/lib/src/ed25519_dart_base.dart#L200
C: Trezor firmware
Corregido en este PR: https://github.com/trezor/trezor-firmware/pull/2349 (Corrección fusionada el 27 de junio de 2022)
Java: ed25519-elisabeth (Jack Grigg)
Corregido en este commit: https://github.com/cryptography-cafe/ed25519-elisabeth/commit/49545ce47d550fed807522dff86546c812ccbbac (Corrección fusionada el 19 de junio de 2022)
C: Harbour (Viktor Szakats)
Corregido en este commit: https://github.com/vszakats/hb/commit/bae610b63d35c6c1793d94a3bf9467c3b1eded18 (Corrección fusionada el 30 de junio de 2022)
Rust/Wasm: polkadot-js/wasm
Corregido en este PR: https://github.com/polkadot-js/wasm/pull/381/files (Corrección fusionada el 3 de julio de 2022)
C: horse25519 (Yawning Angel)
Corregido en este PR: https://github.com/Yawning/horse25519/pull/3 (Corrección fusionada el 15 de agosto de 2022)
Erlang: erlang-libdecaf
Corregido en este commit: https://github.com/potatosalad/erlang-libdecaf/commit/16ba07ea122660e95f6cfa9107e28ed58bada713. La lógica se abordó en este issue: ed25519-unsafe-libs/issues/7 (Corrección fusionada el 28 de agosto de 2022)
Rust: ed25519-dalek (Isis Agora Lovecruft)
Corregido en este PR: https://github.com/dalek-cryptography/ed25519-dalek/pull/205 (Corrección fusionada el 22 de octubre de 2022)
C: Monocypher (Loup Vaillant)
Corregido en este commit: https://github.com/LoupVaillant/Monocypher/commit/da7b5407d20329f21a53ea993f516fb55e2f5e26 (Corrección fusionada el 27 de febrero de 2023)
Librerías reportadas originalmente como vulnerables, pero eliminadas de la lista según los comentarios de la comunidad.
Dart: riclava_ed25519 (riclava)
https://github.com/riclava/ed25519/blob/master/lib/ed25519.dart#L125
Clojure: ed25519 (Kevin Downey)
https://github.com/hiredman/ed25519/blob/master/src/ed25519/core.clj#L168
Haskell: hs-scraps (Vincent Hanquez)
https://github.com/vincenthz/hs-scraps/blob/master/Crypto/Signature/Ed25519.hs#L115
Java: ed25519-java (k3d3)
https://github.com/k3d3/ed25519-java/blob/master/ed25519.java#L144
Java: ed25519 (Bjorn Arnelid)
https://github.com/BjornArnelid/ed25519/blob/master/src/ed25519/application/Ed25519.java#L32
Java: Punisher.NaCl (Arpan Jati)
https://github.com/arpanj/Punisher.NaCl/blob/c9619ca3028b90d0556c0473e4eba1d429a3744c/Punisher.NaCl/src/Punisher/NaCl/Ed25519Operations.java#L72
Java: ED25519 (Mick Michalski)
https://github.com/michami/ED25519/blob/master/ED25519.java#L60
Java: vRallev/ECC-25519 (Ralf Wondratschek)
https://github.com/vRallev/ECC-25519/blob/master/ECC-25519-Java/src/main/java/net/vrallev/java/ecc/Ecc25519Helper.java#L102
Perl: Crypt::Ed25519 (Marc Lehmann)
https://metacpan.org/release/MLEHMANN/Crypt-Ed25519-0.9/view/Ed25519.pm#$signature-=-Crypt::Ed25519::sign-$message,-$public_key,-$private_key
Python: ed25519.py (autores de Ed25519)
https://ed25519.cr.yp.to/python/ed25519.py
Python: ed25519 (Python Cryptographic Authority)
https://github.com/pyca/ed25519/blob/main/ed25519.py#L243
(los autores mencionan que de todos modos es inseguro contra canales laterales)
Python: python-pure25519 (Brian Warner)
https://github.com/warner/python-pure25519/blob/master/pure25519/eddsa.py#L21
Python: nmed25519 (naturalmessage)
https://github.com/naturalmessage/nmed25519/blob/master/nmed25519.py#L150
Python: ed25519.py (Shiho Midorikawa)
https://gist.github.com/elliptic-shiho/f41fd75cc30646a61d7ad63043fdd56e#file-ed25519-py-L77
Python: bindings para ed25519-dalek: py-ed25519-bindings
https://github.com/polkascan/py-ed25519-bindings/blob/master/src/lib.rs#L111
Swift: ed25519swift (pebble8888)
https://github.com/pebble8888/ed25519swift/blob/master/Ed25519ref/ed25519s.swift#L120
JS: supercop.js (1p6 Flynx)
https://github.com/1p6/supercop.js/blob/master/index.js#L29
JS: substack/ed25519-supercop (James Halliday)
https://github.com/substack/ed25519-supercop/blob/master/index.js#L3
C: libeddsa (Philipp Lay)
https://github.com/phlay/libeddsa/blob/master/lib/ed25519-sha512.c#L85
C#: SommerEngineering/Ed25519 (Thorsten Sommer)
https://github.com/SommerEngineering/Ed25519/blob/master/Ed25519/Signer.cs#L80
CUDA: ChorusOne/solanity
https://github.com/ChorusOne/solanity/blob/master/src/cuda-ecc-ed25519/sign.cu#L10
C: ncme/c25519 (Daniel Beer y Nikolas Rösener)
https://github.com/ncme/c25519/blob/master/src/edsign.c#L115
C: luazen (Phil Leblanc)
https://github.com/philanc/luazen/blob/master/src/x25519.c#L508 (los autores modificaron la función para aceptar pk en lugar de la sk original de 64 bytes de nacl, que incluye pk como los últimos 32 bytes)
C++: amber (Pelayo Bernedo)
https://github.com/bernedogit/amber/blob/master/src/group25519.cpp#L1661
C: FLD ECC AVX2 (Armando Faz-Hern'{a}ndez y Julio L'{o}pez y Ricardo Dahab)
https://github.com/armfazh/fld-ecc-vec/blob/master/src/sign255.c#L391
Elixir: mwmiller/ed25519_ex (Matt Miller)
https://github.com/mwmiller/ed25519_ex/blob/master/lib/ed25519.ex#L146(La clave pública es opcional. Según el comentario del autor: si solo se proporciona la clave secreta, la clave pública se derivará de ella. Esto añade una sobrecarga significativa)
PHP (wrapper de C): php-ed25519-ext
https://github.com/encedo/php-ed25519-ext/blob/master/ed25519-ext.c#L93
Nim: niv/ed25519.nim (Bernhard Stöckner)
https://github.com/niv/ed25519.nim/blob/master/ed25519.nim#L26
Typescript: mipher (Marco Paland)
https://github.com/mpaland/mipher/blob/master/src/x25519.ts#L936
Lua: LuaMonocypher
https://github.com/philanc/luamonocypher/blob/main/src/luamonocypher.c#L268
Crystal: monocypher.cr
https://github.com/konovod/monocypher.cr/blob/master/src/monocypher.cr#L39
Python: py_ssh_keygen_ed25519 (Péter Szabó)
https://github.com/pts/py_ssh_keygen_ed25519/blob/master/ed25519_compact.py#L128 (La clave pública es opcional)
Javascript: KinomaJS
https://github.com/Kinoma/kinomajs/blob/701879d37e7fe5001420e0053cd60df6b91e4553/xs6/extensions/crypt/crypt_ed25519.js#L92 (La clave pública es opcional)
Haskell: gen-ed25-keypair
https://github.com/awakesecurity/gen-ed25-keypair
C: horse25519 (Yawning Angel)
https://github.com/Yawning/horse25519/blob/master/src/ref10/sign.c#L7 Nota: Este repo incluye una copia de la implementación ref10 ed25519 de djb extraída de supercop para evitar añadir otra dependencia, pero la intención es proporcionar un ejecutable independiente que realice la generación de pares de claves vanity ed25519. Aunque utiliza la API de una manera extraña, esto es intencional, ya que está haciendo algo extremadamente exótico e inusual con respecto a la generación de claves y la librería no está pensada para firmar.