
List of unsafe ed25519 signature libs
비밀 키와 공개 키를 서명 함수 입력으로 독립적으로 제공할 수 있는 공개 API를 허용하는 잠재적으로 안전하지 않은 ed25519 서명 라이브러리 목록입니다. 이러한 공개 API를 잘못 사용하면 개인 키가 노출될 수 있습니다.
분석 대상 저장소 대부분은 IANIX :: Things that use Ed25519에 등재되어 있습니다.
영향을 받는 라이브러리 수: 45
공지 후 문제를 수정한 라이브러리 수: 8
마지막 업데이트: 2023년 5월 4일
참고로 일반적으로 관련 rfc8032에 따르면 EdDSA 서명은 결정적(deterministic)이므로, 서명할 동일한 입력 메시지에 대해 곡선 점 R과 스칼라 S라는 두 요소를 포함하는 고유한 서명 출력이 반환됩니다.
알고리즘적 세부 사항으로는 서명자의 공개 키가 서명의 S 부분의 결정적 계산에만 관여하고 R 값에는 관여하지 않는다는 점입니다. 이는 공격자가 어떻게든 서명 함수를 오라클(임의의 공개 키를 입력으로 기대하는)로 사용할 수 있다면, 동일한 메시지에 대해 동일한 R을 공유하고 S 부분만 다른 두 개의 서명을 얻을 수 있다는 것을 의미합니다. 불행히도 이런 일이 발생하면 개인 키를 쉽게 추출할 수 있습니다. 이 StackOverflow 게시물이 이것이 가능한 이유를 설명합니다.
즉, 공개 API는 분리된 개인/공개 키 쌍을 서명 입력으로 허용해서는 안 됩니다. 이를 방지하기 위해 많은 구현은 공개 키를 개인 키(또는 시드)와 함께 저장하고 전체 키 쌍을 비밀로 간주하거나, 서명 함수 내부에서 항상 공개 키를 다시 파생합니다. 불행히도 많은 수의 기존 라이브러리가 입력 공개 키가 입력 개인 키와 일치하는지 확인하지 않고 임의의 공개 키를 입력으로 허용함으로써 이 문제를 해결하지 못하고 있습니다.
물론 이것이 이러한 라이브러리에 의존하는 모든 애플리케이션이 키 노출 공격에 취약하다는 것을 의미하지는 않습니다. 실제로 대부분은 일반적으로 영향을 받는 API를 사용자에게 공개하지 않고 sign 호출 직전에 공개/개인 키 쌍을 결합하기 때문에 안전할 가능성이 높습니다. 반면, 이러한 API가 노출되지 않은 경우에도 개인 키와 공개 키를 관리하고 저장하는 방식에 대해 서로 다른 TCB 위협 모델 전략을 가진 애플리케이션이 있습니다. 즉, 이 공격을 방지하려면 개발자는 공개 키에 대한 무결성 보호 프로토콜도 적용해야 합니다.
여기에서는 관련 코드 참조와 함께 일부 영향을 받는 라이브러리를 나열합니다.
그림 1. ed25519-dalek Rust 크레이트에서의 API 오용 예.
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
및
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
이 PR에서 수정됨: https://github.com/trezor/trezor-firmware/pull/2349 (2022년 6월 27일 수정 병합)
Java: ed25519-elisabeth (Jack Grigg)
이 커밋에서 수정됨: https://github.com/cryptography-cafe/ed25519-elisabeth/commit/49545ce47d550fed807522dff86546c812ccbbac (2022년 6월 19일 수정 병합)
C: Harbour (Viktor Szakats)
이 커밋에서 수정됨: https://github.com/vszakats/hb/commit/bae610b63d35c6c1793d94a3bf9467c3b1eded18 (2022년 6월 30일 수정 병합)
Rust/Wasm: polkadot-js/wasm
이 PR에서 수정됨: https://github.com/polkadot-js/wasm/pull/381/files (2022년 7월 3일 수정 병합)
C: horse25519 (Yawning Angel)
이 PR에서 수정됨: https://github.com/Yawning/horse25519/pull/3 (2022년 8월 15일 수정 병합)
Erlang: erlang-libdecaf
이 커밋에서 수정됨: https://github.com/potatosalad/erlang-libdecaf/commit/16ba07ea122660e95f6cfa9107e28ed58bada713. 로직은 이 이슈에서 다루어짐: ed25519-unsafe-libs/issues/7 (2022년 8월 28일 수정 병합)
Rust: ed25519-dalek (Isis Agora Lovecruft)
이 PR에서 수정됨: https://github.com/dalek-cryptography/ed25519-dalek/pull/205 (2022년 10월 22일 수정 병합)
C: Monocypher (Loup Vaillant)
이 커밋에서 수정됨: https://github.com/LoupVaillant/Monocypher/commit/da7b5407d20329f21a53ea993f516fb55e2f5e26 (2023년 2월 27일 수정 병합)
원래 취약한 것으로 보고되었지만 커뮤니티 피드백에 따라 목록에서 제거된 라이브러리입니다.
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
(저자들은 어차피 사이드 채널에 대해 안전하지 않다고 언급함)
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: 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 and 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 (저자들은 마지막 32바이트에 pk를 포함하는 원래 nacl 64바이트 sk 대신 pk를 받도록 함수를 수정함)
C++: amber (Pelayo Bernedo)
https://github.com/bernedogit/amber/blob/master/src/group25519.cpp#L1661
C: FLD ECC AVX2 (Armando Faz-Hern'{a}ndez and Julio L'{o}pez and 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(공개 키는 선택 사항입니다. 작성자 주석에 따르면: 비밀 키만 제공되면 공개 키는そこ에서 파생됩니다. 이로 인해 상당한 오버헤드가 발생합니다)
PHP (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 (공개 키는 선택 사항)
Javascript: KinomaJS
https://github.com/Kinoma/kinomajs/blob/701879d37e7fe5001420e0053cd60df6b91e4553/xs6/extensions/crypt/crypt_ed25519.js#L92 (공개 키는 선택 사항)
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 참고: 이 저장소는 추가 의존성을 가져오지 않기 위해 supercop에서 가져온 djb의 ref10 ed25519 구현 사본을 포함하지만, 의도는 ed25519 배니티 키 쌍 생성을 수행하는 독립 실행형 실행 파일을 제공하는 것입니다. API를 특이한 방식으로 사용하기는 하지만, 키 생성과 관련하여 이미 극도로 이국적이고 비정상적인 작업을 수행하고 있으며 이 라이브러리는 서명용으로 사용되지 않으므로 이는 의도적입니다.