# Libsodium의 취약점

> Clean Markdown view of GeekNews topic #25472. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=25472](https://news.hada.io/topic?id=25472)
- GeekNews Markdown: [https://news.hada.io/topic/25472.md](https://news.hada.io/topic/25472.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-01-01T04:37:06+09:00
- Updated: 2026-01-01T04:37:06+09:00
- Original source: [00f.net](https://00f.net/2025/12/30/libsodium-vulnerability/)
- Points: 2
- Comments: 1

## Topic Body

- **libsodium**의 저수준 함수 `crypto_core_ed25519_is_valid_point()`에서 **Edwards25519 곡선의 부적절한 점 검증 오류**가 발견됨  
- 이 함수는 점이 주된 암호학적 그룹에 속하는지 확인해야 하지만, **혼합 차수(subgroup)** 의 일부 점을 잘못 통과시킴  
- 원인은 내부 좌표 검증 시 **X=0만 확인하고 Y=Z 검증을 누락**한 코드 오류로, 잘못된 점이 유효하다고 처리될 수 있었음  
- 수정 버전에서는 두 조건(X=0, Y=Z)을 모두 검사하도록 변경되었으며, **1.0.20 이하 버전** 또는 **2025년 12월 30일 이전 릴리스**가 영향을 받음  
- 고수준 API(`crypto_sign_*`)는 영향을 받지 않으며, **Ristretto255 그룹 사용**이 안전성과 성능 면에서 권장됨  

---

### libsodium 프로젝트 개요
- **libsodium**은 13년 전 시작된 프로젝트로, **암호학을 쉽게 사용할 수 있도록 단순한 API**를 제공하는 것을 목표로 함  
  - 내부 알고리듬을 사용자가 알 필요 없이 고수준 연산만 수행할 수 있도록 설계  
- API의 **호환성 유지**를 중시하며, NaCl API를 기반으로 현재까지 일관성을 유지  
- 일부 사용자가 문서에 명시된 제한을 넘어 **저수준 함수**를 직접 사용하면서, 라이브러리가 **암호학 툴킷**처럼 활용되는 사례가 늘어남  

### 발견된 버그의 원인
- 문제 함수: `crypto_core_ed25519_is_valid_point()`  
  - Edwards25519 곡선에서 주된 그룹(L 차수)에 속하지 않은 점을 거부해야 함  
  - 그러나 **혼합 차수(2L, 4L, 8L 등)** 의 점 일부가 검증을 통과함  
- 내부적으로 점의 차수를 확인하기 위해 L을 곱한 뒤, 결과가 **항등점(identity)** 인지 검사  
  - 항등점은 X=0, Y=Z 형태로 표현되지만, 기존 코드는 **X=0만 검사**  
  - 이로 인해 Y≠Z인 잘못된 점이 유효하다고 처리됨  
- 예시: 주된 그룹의 점 Q에 차수 2의 점 (0, -1)을 더한 Q+(0, -1)은 잘못된 점이지만, 수정 전에는 통과함  

### 수정 내용
- [패치 커밋](https://github.com/jedisct1/libsodium/commit/f2da4cd8cb26599a0285a6ab0c02948e361a674a)은 다음과 같이 변경됨  
  - **기존 코드:** `return fe25519_iszero(pl.X);`  
  - **수정 코드:** `fe25519_sub(t, pl.Y, pl.Z); return fe25519_iszero(pl.X) & fe25519_iszero(t);`  
- 이제 X=0과 Y=Z 두 조건을 모두 확인하여 올바른 검증 수행  

### 영향 범위
- 다음 조건에 해당하는 경우 영향 가능  
  - 버전 **1.0.20 이하** 또는 **2025년 12월 30일 이전 릴리스** 사용  
  - `crypto_core_ed25519_is_valid_point()`로 **신뢰할 수 없는 입력 점을 검증**  
  - **Edwards25519 곡선 연산을 직접 구현**하는 사용자  
- 그러나 대부분의 사용자는 영향 없음  
  - 고수준 API(`crypto_sign_*`)는 해당 함수를 사용하지 않음  
  - `crypto_scalarmult_ed25519`는 잘못된 공개키로도 정보 누출 없음  
  - `crypto_sign_keypair` 및 `crypto_sign_seed_keypair`로 생성된 키는 올바른 그룹에 속함  

### 권장 조치
- **Ristretto255 그룹** 사용 권장  
  - 2019년부터 libsodium에 포함되어 있으며, **cofactor 관련 문제를 해결**  
  - 디코딩된 점은 자동으로 안전하며, 추가 검증 불필요  
  - **Edwards25519보다 빠른 연산 성능** 제공  
- 업데이트가 불가능한 경우, 제시된 **애플리케이션 수준 대체 함수**(`is_on_main_subgroup`)를 사용해 검증 가능  

### 수정된 배포 및 지원
- 문제 발견 직후 즉시 수정되어, **2025년 12월 30일 이후 배포된 모든 안정 버전**에 포함  
  - 공식 tarball, Visual Studio/MingW 바이너리, NuGet 패키지, Android용 빌드, `swift-sodium` xcframework, Rust `libsodium-sys-stable`, `libsodium.js` 포함  
- 새로운 **point release**도 예정  
- 프로젝트는 **1인 유지보수**로 운영되며, [OpenCollective 후원](https://opencollective.com/libsodium/contribute)을 통해 지속적인 개선 지원 가능

## Comments



### Comment 48532

- Author: neo
- Created: 2026-01-01T04:37:07+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46435614) 
- PHP 라이브러리 **sodium_compat**도 이번 문제의 영향을 받았음  
  관련 내용은 [security-advisories PR #756](https://github.com/FriendsOfPHP/security-advisories/pull/756)에서 확인 가능함  
  오늘 저녁에는 오픈소스 생태계 내 다른 **Ed25519 구현체**들을 모두 점검해, 동일한 검증 누락이 있는지 확인해볼 예정임
  - 몇몇 라이브러리에서 아예 검증 로직이 빠져 있음을 발견했음  
    하지만 위에서 언급된 취약점처럼 **잘못된 방식으로 구현된 사례**는 없었음  
    내가 이메일을 보내지 않았다면, 아마 [ianix의 Ed25519 배포 목록](https://ianix.com/pub/ed25519-deployment.html)에 없거나, 내가 놓쳤거나, 혹은 안전한 구현일 가능성이 높음
  - 오픈소스에 기여해줘서 고맙다는 말을 전하고 싶음

- 지난 4개월 동안 **Lean4용 sodium 바인딩**을 개발 중임  
  이제 **Ristretto255** 단계에 도달했는데, 왜 저자가 이 기술에 열광하는지 이해하게 되었음  
  Ristretto는 Curve25519 위에서 임의의 다항식을 구성할 수 있는 정교한 API로, 실험하는 과정이 정말 즐거움  
  혹시 저자가 이 글을 본다면, 진심으로 감사의 말을 전하고 싶음
  - 혹시 이 프로젝트의 **공개 저장소**가 있는지 궁금함

- Libsodium의 목표는 저수준 함수가 아니라 **고수준 API**를 제공하는 것이었음  
  사용자는 내부 알고리즘을 몰라도 되도록 설계되었지만, 시간이 지나면서 점점 저수준 함수들을 직접 사용하는 사례가 늘어남  
  결국 Libsodium이 **알고리즘 툴킷**처럼 쓰이게 되었음  
  중요한 점은 사용자가 원하는 방향을 인식하고, 프로젝트를 특정 방식으로만 강요하지 않는 것임  
  일부 프로젝트는 이런 점에서 독단적으로 변하며 실패를 겪음
  - 흥미로운 지적임. 하지만 반대로 **사용자가 원한다고 생각하는 것**과 실제로 필요한 것이 다를 수도 있음  
    비전문가가 암호학적 원시 함수를 직접 사용하는 것은 위험함  
    Libsodium은 사용자가 스스로를 위험에 빠뜨리지 않도록 설계되었음  
    라이브러리는 **잘못된 사용이 불가능하도록 만드는 것**이 이상적임  
    관련 글로 [“If You're Typing The Letters A-E-S Into Your Code, You're Doing It Wrong”](https://people.eecs.berkeley.edu/~daw/teaching/cs261-f12/misc/if.html)을 추천함
  - 모든 내부 함수를 API 계약으로 간주하면, 거의 모든 변경이 **호환성 깨짐**으로 이어짐  
    따라서 일부 기능을 private 또는 internal로 제한하는 것이 맞는 선택일 때가 많음  
    Libsodium이 그 경계를 잘 잡았는지는 확신할 수 없지만, 균형이 중요함
  - 예전에 **CeeFIT**이라는 C++ 테스트 프레임워크를 만들었는데, 컴파일 타임에 fixture를 등록하는 방식이 자랑스러웠음  
    그런데 일부 사용자가 이를 **배치 실행기**처럼 사용하더라  
    그들의 요구를 지원하기 위해 몇 가지 버그를 수정했음  
    결국 사용자가 있다는 사실 자체가 기뻤음

- 이번 버그는 미묘하지만 중요한 **암호 검증 오류**임  
  “유효한지 확인”이라는 단순한 검사가 실제로는 매우 복잡함  
  소수 차수 부분군 밖의 점을 허용하면, 즉각적인 취약점이 없어 보여도 상위 계층의 가정을 무너뜨릴 수 있음  
  또한 저수준 원시 함수는 의도보다 훨씬 널리 재사용되므로, 작은 검증 누락이 **큰 파급력**을 가질 수 있음
  - 다만 **X25519**와 **Ed25519**는 애초에 이런 검증이 필요 없도록 설계되었음  
    Curve25519 위에서 더 복잡한 프로토콜을 만들 때만 부분군 문제가 생김  
    그래서 나는 가능한 한 모든 점을 소수 차수 부분군으로 다시 사상함  
    **Monocypher**에는 이런 고급 함수들이 있음  
    예를 들어 `crypto_x25519_dirty_fast()`나 `crypto_elligator_map()` 같은 함수들임  
    이런 “dirty” 함수는 전체 곡선을 덮는 공개키를 생성해, 무작위성과 구분되지 않게 함  
    이후 X25519 키 교환 시에도 동일한 공유 비밀을 얻을 수 있음  
    이는 **DJB의 설계 덕분**으로, 공개키가 비정상적이어도 공유 비밀이 소수 차수 부분군으로 사상됨  
    결국 Ristretto는 이런 재사상이 불가능한 경우에만 필요함  
    물론 소수 차수 그룹 추상화는 유용하지만, 그런 프로토콜을 설계할 수 있는 사람이라면 비자명한 cofactor를 다루는 것도 가능해야 함

- 대기업에 근무한다면 **Frank**를 회사 차원에서 후원하는 것을 고려해보길 권함
  - 나는 **Apple**에 근무하지만, Frank가 누구인지 모르겠고, 후원 절차도 모름  
    설령 안다고 해도 회사 계좌가 아니라 **내 개인 돈**으로 후원해야 할 것 같음

- **libnacl**도 영향을 받는지 궁금함  
  나는 매일 libnacl로 컴파일된 소프트웨어를 쓰지만, “libsodium”으로 컴파일된 것은 없음

- 정말 훌륭한 라이브러리임  
  **Frank Denis**에게 감사의 마음을 전함
