
List of unsafe ed25519 signature libs
Uma lista de bibliotecas de assinatura ed25519 potencialmente inseguras que permitem uma API pública onde a chave secreta e a chave pública podem ser fornecidas independentemente como entradas da função de assinatura. O uso indevido dessas APIs públicas pode resultar na exposição da chave privada.
A maioria dos repositórios em nossa análise está listada em IANIX :: Things that use Ed25519.
Número de bibliotecas afetadas: 45
Número de bibliotecas que corrigiram o problema após o anúncio: 8
última atualização: 4 de maio de 2023
Observe que, normalmente e de acordo com a rfc8032 relacionada, as assinaturas EdDSA são determinísticas e, portanto, para a mesma mensagem de entrada a ser assinada, é retornada uma saída de assinatura única que inclui dois elementos: um ponto da curva R e um escalar S.
Um detalhe algorítmico é que a chave pública do signatário está envolvida apenas no cálculo determinístico da parte S da assinatura, mas não no valor R. Isso implica que, se um adversário puder, de alguma forma, usar a função de assinatura como um Oráculo (que espera chaves públicas arbitrárias como entradas), então é possível que, para a mesma mensagem, se obtenham duas assinaturas que compartilham o mesmo R e diferem apenas na parte S. Infelizmente, quando isso acontece, é possível extrair facilmente a chave privada; esta publicação no StackOverflow explica por que isso é viável.
Dito isso, APIs públicas NÃO devem permitir um par de chaves privada/pública desacoplado como entrada de assinatura. Para contornar isso, muitas implementações armazenam a chave pública juntamente com a chave privada (ou seed) e consideram todo o par de chaves como o segredo OU sempre rederivam a chave pública dentro da função de assinatura. Infelizmente, um grande número de bibliotecas existentes não resolve esse problema, permitindo chaves públicas arbitrárias como entradas sem verificar se a chave pública de entrada corresponde à chave privada de entrada.
É claro que isso não significa que todas as aplicações com dependências dessas bibliotecas estão sujeitas a ataques de exposição de chave; na verdade, a maioria provavelmente está segura, pois normalmente não expõe publicamente a API afetada aos seus usuários e acopla seu par de chaves pública/privada imediatamente antes da invocação do sign. Por outro lado, mesmo quando essas APIs não são expostas, há aplicações com diferentes estratégias de modelo de ameaça de TCB sobre como as chaves privadas e públicas são gerenciadas e armazenadas. Dito isso, para prevenir este ataque, os desenvolvedores também devem aplicar um protocolo de proteção de integridade para as chaves públicas.
Aqui, listamos algumas bibliotecas afetadas juntamente com as referências de código relacionadas.
Fig 1. Um exemplo de uso indevido da API na crate ed25519-dalek do Rust.
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
e
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
Corrigido neste PR: https://github.com/trezor/trezor-firmware/pull/2349 (Correção incorporada em 27 de junho de 2022)
Java: ed25519-elisabeth (Jack Grigg)
Corrigido neste commit: https://github.com/cryptography-cafe/ed25519-elisabeth/commit/49545ce47d550fed807522dff86546c812ccbbac (Correção incorporada em 19 de junho de 2022)
C: Harbour (Viktor Szakats)
Corrigido neste commit: https://github.com/vszakats/hb/commit/bae610b63d35c6c1793d94a3bf9467c3b1eded18 (Correção incorporada em 30 de junho de 2022)
Rust/Wasm: polkadot-js/wasm
Corrigido neste PR: https://github.com/polkadot-js/wasm/pull/381/files (Correção incorporada em 3 de julho de 2022)
C: horse25519 (Yawning Angel)
Corrigido neste PR: https://github.com/Yawning/horse25519/pull/3 (Correção incorporada em 15 de agosto de 2022)
Erlang: erlang-libdecaf
Corrigido neste commit: https://github.com/potatosalad/erlang-libdecaf/commit/16ba07ea122660e95f6cfa9107e28ed58bada713. Lógica tratada nesta issue: ed25519-unsafe-libs/issues/7 (Correção incorporada em 28 de agosto de 2022)
Rust: ed25519-dalek (Isis Agora Lovecruft)
Corrigido neste PR: https://github.com/dalek-cryptography/ed25519-dalek/pull/205 (Correção incorporada em 22 de outubro de 2022)
C: Monocypher (Loup Vaillant)
Corrigido neste commit: https://github.com/LoupVaillant/Monocypher/commit/da7b5407d20329f21a53ea993f516fb55e2f5e26 (Correção incorporada em 27 de fevereiro de 2023)
Bibliotecas originalmente reportadas como vulneráveis, mas removidas da lista com base no feedback da comunidade.
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 (Ed25519 authors)
https://ed25519.cr.yp.to/python/ed25519.py
Python: ed25519 (Python Cryptographic Authority)
https://github.com/pyca/ed25519/blob/main/ed25519.py#L243
(os autores mencionam que ela é insegura contra canais laterais de qualquer forma)
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 for 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 e 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 (os autores modificaram a função para aceitar pk em vez da sk original de 64 bytes do nacl, que inclui a pk como os ú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 e Julio L'{o}pez e 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(A chave pública é opcional. Segundo o comentário do autor: se apenas a chave secreta for fornecida, a chave pública será derivada dela. Isso adiciona uma sobrecarga significativa)
PHP (C wrapper): 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 (A chave pública é opcional)
Javascript: KinomaJS
https://github.com/Kinoma/kinomajs/blob/701879d37e7fe5001420e0053cd60df6b91e4553/xs6/extensions/crypt/crypt_ed25519.js#L92 (A chave pública é 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 repositório inclui uma cópia da implementação ref10 ed25519 de djb extraída do supercop para evitar adicionar outra dependência, mas a intenção é fornecer um executável autônomo que gera pares de chaves ed25519 "vanity". Embora use a API de uma forma incomum, isso é intencional, pois já faz algo extremamente exótico e incomum em relação à geração de chaves, e a biblioteca não se destina a ser usada para assinatura.