PEP 644 – OpenSSL 1.1.1 이상 요구
- Author:
- Christian Heimes <christian at python.org>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Created:
- 27-Oct-2020
- Python-Version:
- 3.10
- Post-History:
- 27-Oct-2020, 03-Mar-2021, 17-Mar-2021, 17-Apr-2021
- Resolution:
- Python-Dev message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 CPython의 표준 라이브러리가 OpenSSL 1.1.1 LTS 이상만 지원하도록 제안합니다. 수명이 종료된 OpenSSL 버전, 호환되지 않는 포크, 그리고 기타 TLS 라이브러리에 대한 지원은 중단합니다.
동기
Python은 hashlib, hmac, ssl 모듈에서 OpenSSL을 사용합니다. OpenSSL은 암호화 프리미티브의 빠른 구현과 X.509 인증서 처리를 포함한 완전한 TLS 스택을 제공합니다. ssl 모듈은 urllib 같은 표준 라이브러리 모듈과 urllib3 같은 서드파티 모듈이 인터넷 프로토콜의 보안 변형을 구현하는 데 사용됩니다. pip는 PyPI에서 패키지를 안전하게 내려받기 위해 ssl 모듈을 사용합니다. ssl 모듈의 OpenSSL 바인딩에 버그가 있으면 심각한 보안 문제로 이어질 수 있습니다.
시간이 흐르면서 OpenSSL의 공개 API는 발전하고 변경되었습니다. 버전 1.0.2에서는 호스트 이름을 검증하고 대조하는 새로운 API가 도입되었습니다. OpenSSL 1.1.0에서는 내부 구조체를 불투명하게 만들고, 구조체 멤버에 직접 접근하는 방식을 대체하는 새로운 API를 도입했습니다. 버전 3.0.0에서는 암호화 알고리즘을 코어에서 프로바이더로 옮기는 내부 재구성으로 인해 더 많은 API가 폐지 예정이 될 것입니다. LibreSSL과 BoringSSL 같은 포크는 서로 다른 방향으로 갈라졌습니다.
현재 Python 버전 3.6부터 3.9까지는 OpenSSL 1.0.2, 1.1.0, 1.1.1과 호환됩니다. Python은 대체로 LibreSSL >= 2.7.1에서도 동작하지만, 일부 기능이 빠져 있고 일부 테스트가 실패합니다.
제한된 자원과 시간 때문에 여러 버전과 포크를 지원하면서 정확성까지 테스트하고 검증하는 일은 점점 더 어려워지고 있습니다. 호환되지 않는 여러 API 외에도 빌드 시점 플래그, 배포판별 패치, 로컬 암호화 정책 설정이 있어 가능한 조합의 수가 매우 많아집니다. 반면에 Python 코어 팀에는 TLS와 OpenSSL 내부 구조에 정통한 도메인 전문가가 몇 명밖에 없으며, 그중 활발히 활동하는 유지 관리자는 그보다도 적습니다.
OpenSSL 1.1.1을 요구하면 대다수 사용자에게 더 나은 경험을 제공하고 유지 보수 부담을 줄일 수 있으며, 그만큼 확보한 자원을 새로운 기능 구현에 쓸 수 있습니다. 사용자는 새로운 기능이 존재하고 동작이 일관된다는 점을 신뢰할 수 있게 되며, 결과적으로 더 견고한 경험을 얻게 됩니다.
영향
OpenSSL 1.1.1은 지원되는 거의 모든 플랫폼과 배포판에서 기본으로 쓰이는 OpenSSL 변형이자 버전입니다. 또한 업스트림에서 여전히 보안 지원을 받는 유일한 버전이기도 합니다 [9].
이번 폐지로 영향을 받는 macOS 및 Windows 사용자는 없습니다. python.org 설치 프로그램과 Conda 같은 대체 배포판은 최신 OpenSSL 버전을 함께 제공합니다.
2020년 10월 기준 DistroWatch [1] 자료에 따르면, 현재 대부분의 BSD 및 Linux 배포판도 OpenSSL 1.1.1을 탑재하고 있습니다. 장기 지원(LTS) 배포판과 엔터프라이즈 배포판의 일부 오래된 릴리스는 이전 버전의 OpenSSL이나 LibreSSL을 사용합니다. Python 3.10이 정식 출시될 무렵에는 이들 배포판 중 여럿이 수명 종료나 일반 지원 종료에 도달했거나, LibreSSL에서 OpenSSL로 전환했을 것입니다.
다른 소프트웨어들도 OpenSSL 1.0.2 지원을 중단했습니다. 예를 들어, PyCA cryptography 3.2(2020-10-25)는 OpenSSL 1.0.2와의 호환성을 제거했습니다.
OpenSSL 1.0.2 LTS
출시: 2015-02 지원 종료: 2019-12
OpenSSL 1.0.2에서 호스트 이름 검증, ALPN 지원, 타원 곡선이 추가되었습니다.
- CentOS 7 (EOL 2024-06)
- Debian 8 Jessie (EOL 2020-07)
- Linux Mint 18.3 (EOL 2021-04)
- RHEL 7 (전체 지원 종료 2019-08, 유지 보수 2 지원 종료 2024-06)
- SUSE Enterprise Linux 12-SP5 (일반 지원 종료 2024-10)
- Ubuntu 16.04 LTS / Xenial (일반 지원 종료 2021-04)
OpenSSL 1.1.0
출시: 2016-08 지원 종료: 2019-09
OpenSSL 1.1.0에서는 안전하지 않은 암호를 기본적으로 제거하거나 비활성화했으며, ChaCha20-Poly1305, BLAKE2(기본 기능), X25519, CT 지원이 추가되었습니다. 대부분의 구조체가 불투명(opaque) 구조체로 바뀌었고 새로운 API가 도입되었습니다. OpenSSL 1.1.0은 1.0.2와 API가 호환되지 않습니다.
- Debian 9 Stretch (보안 지원 종료 2020-07, LTS 2022-06까지)
- Ubuntu 18.04 LTS / Bionic (일반 지원 종료 2023-04)
OpenSSL 1.1.1 LTS
출시: 2018-08 지원 종료: 2023-09 (예정)
OpenSSL 1.1.1에서 TLS 1.3, SHA-3, X448, Ed448이 추가되었습니다.
- Alpine (2018년에 OpenSSL로 복귀 [4])
- Arch Linux 최신 버전
- CentOS 8.0+
- Debian 10 Buster
- Debian 11 Bullseye (출시 예정 2021-06)
- Fedora 29+
- FreeBSD 11.3+
- Gentoo Linux stable (2021년 1월에 대안이던 LibreSSL 지원 중단 [10])
- HardenedBSD (2018년에 OpenSSL로 복귀 [3])
- Linux Mint 19.3+
- macOS (python.org 설치 프로그램)
- NetBSD 8.2+
- openSUSE 15.2+
- RHEL 8.0+
- Slackware current
- SUSE Enterprise Linux 15-SP2
- Ubuntu 18.10+
- Ubuntu 20.04 LTS / Focal
- VoidLinux (2021년 3월에 OpenSSL로 다시 전환 [5])
- Windows (python.org 설치 프로그램, Conda)
주요 CI 제공업체는 OpenSSL 1.1.1이 포함된 이미지를 제공합니다.
- AppVeyor (
Ubuntu2004이미지 사용 시) - CircleCI (최신
cimg/base:stable또는cimg/base:stable-20.04사용 시) - GitHub Actions (
runs-on: ubuntu-20.04사용 시) - Giblab CI (Debian Stretch, Ubuntu Focal, CentOS 8, RHEL 8 또는 Fedora 러너 사용 시)
- Packit
- TravisCI (
dist: focal사용 시) - Zuul
OpenSSL 3.0.0
릴리스: 해당 없음 (2021년 중후반 예정)
OpenSSL 3.0.0은 현재 개발 중입니다. 주요 변경 사항으로는 Apache License 2.0으로의 라이선스 변경과 암호화 알고리즘 제공자를 위한 새로운 API가 있습니다. 대부분의 변경 사항은 내부 리팩터링이며 공개 API에는 영향을 주지 않습니다. [8]
LibreSSL
생성: 2014-04 (OpenSSL 1.0.1g에서 포크됨)
- DragonFly BSD
- Hyperbola GNU/Linux-libre
- OpenBSD
- OpenELEC (개발 중단)
- TrueOS (개발 중단)
FreeBSD와 OPNsense 같은 일부 배포판도 OpenSSL 대신 LibreSSL을 비표준 TLS 라이브러리로 제공합니다. Gentoo는 호환성 문제와 부족한 테스트를 이유로 2021년 1월에 OpenSSL의 대안으로 제공하던 LibreSSL을 중단했습니다 [10].
OpenBSD 포트에는 security/openssl/1.1 포트가 있으며, 이 포트는 “[…] LibReSSL과 호환되도록 만들 수 없는 애플리케이션을 지원하기 위해 존재합니다”라고 문서화되어 있습니다 [7]. OpenBSD는 이 패키지를 사용하여 제대로 동작하는 ssl 모듈을 제공할 수 있습니다.
BoringSSL
생성: 2014-06
BoringSSL은 Google이 OpenSSL을 포크한 것입니다. 일반적인 용도로 만들어진 것이 아니므로 Python에서는 지원하지 않습니다. API나 ABI의 안정성은 보장되지 않습니다. BoringSSL의 벤더링된 사본은 Chrome/Chromium 브라우저, Android, Apple 플랫폼에서 사용됩니다 [6].
이점
TLS 1.3
OpenSSL 1.1.1에서 새로운 TLS 1.3 버전 지원이 도입되었습니다. TLS 프로토콜의 최신 버전은 이전 버전보다 핸드셰이크가 빠르고 더 안전합니다.
스레드 및 fork 안전성
1.1.0c 릴리스부터 OpenSSL은 fork와 스레드에 대해 완전히 안전합니다. 이제 바인딩은 멀티스레딩을 지원하기 위해 별도의 우회책이나 추가 콜백을 둘 필요가 없습니다.
SHA-3
OpenSSL은 1.1.0부터 SHA-3 및 SHAKE 구현을 함께 제공합니다. Python의 내장 SHA-3 지원은 참조 구현을 기반으로 합니다. 내부 _sha3 코드는 상당히 크며, 이를 빌드한 공유 라이브러리는 0.5 MB에 가깝습니다. Python은 내장 구현을 제거하고 그 대신 OpenSSL의 libcrypto에 의존할 수 있습니다.
지금까지 LibreSSL 업스트림 개발진은 SHA-3 지원 추가를 거부해 왔습니다. [2]
호환성
OpenSSL 다운스트림 패치와 옵션
OpenSSL에는 OPENSSL_NO_* 매크로 형태의 구성 및 빌드 시점 옵션이 70개 넘게 있습니다. 그중 약 60개 옵션은 암호화 알고리즘이나 TLS 버전 같은 기능의 포함 여부에 영향을 줍니다. 일부 배포판은 패치를 적용하여 설정을 변경합니다. 또한 보안 수준, 암호 스위트, TLS 버전 범위, 서명 알고리즘 같은 설정의 기본값은 OpenSSL 구성 파일에서 지정할 수 있습니다.
Python 코어 팀에는 가능한 모든 조합을 테스트할 자원이 부족합니다. 이 PEP는 Python이 표준 기능이 활성화된 OpenSSL 빌드만 지원할 것을 제안합니다. 벤더는 OPENSSL_NO_TLS1_1_METHOD 같은 빌드 시점 옵션이나 MinProtocol = TLSv1.2 같은 OpenSSL 구성 옵션을 사용하여 폐기되었거나 안전하지 않은 알고리즘과 TLS 버전을 비활성화해야 합니다.
Python은 OpenSSL이 다음을 갖추고 빌드되었다고 가정합니다
- MD5, SHA-1, SHA-2 계열, SHA-3/SHAKE 계열, BLAKE2 같은 hashlib의 기본 알고리즘
- TLS 1.2 및 TLS 1.3 프로토콜
- TLS 1.2 및 1.3을 위한 현행 키 합의, 서명, 암호화 알고리즘(ECDH, RSA, ECDSA, Curve25519, AES, Poly1309-ChaCha20, …)
- 스레딩, 파일 I/O, 소켓 I/O, 오류 메시지
취약한 알고리즘(MD5, SHA-1 서명)과 짧은 키(RSA < 2024비트)는 런타임에 비활성화될 수 있습니다. FIPS와 같은 암호화 정책이 알고리즘을 비활성화한 경우에도 해당 알고리즘이 차단될 수 있습니다. 이 PEP는 새로운 기능과 취약점 대응책을 위한 여지를 남기기 위해 의도적으로 더 구체적으로 규정하지 않습니다. 대략적인 기준으로, Python은 PyPI에 연결할 수 있어야 하며 테스트 스위트를 통과해야 합니다.
LibreSSL 지원
LibreSSL은 OpenSSL의 포크입니다. 이 포크는 heartbleed 취약점을 계기로 2014년에 OpenBSD 팀 구성원들이 OpenSSL 1.0.1g에서 분기하여 만들었습니다. 출범 이후 문제가 있거나 안전하지 않다고 판단된 여러 기능이 제거 또는 대체되었으며(SSL 2.0, SSL 3.0, 개선된 CPRNG), OpenSSL과 BoringSSL로부터 백포트된 기능도 있습니다.
현재 LibreSSL은 OpenSSL 1.1.1과 API가 완전히 호환되지는 않습니다. 최신 릴리스인 LibreSSL 3.3.2에는 누락된 기능이 있으며 일부 경우에는 다르게 동작합니다. 언급할 만한 누락되었거나 호환되지 않는 기능은 다음과 같습니다
- SHA-3, SHAKE, BLAKE2
SSL_CERT_*환경 변수- 보안 수준 API
- 세션 처리 API
- 키 로깅 API
- 검증된 인증서 체인 API
- OPENSSL_VERSION 매크로
이 PEP는 Python에서 LibreSSL 관련 우회 코드를 모두 제거할 것을 제안했습니다. 앞으로 Python은 configure 및 컴파일 시점 검사를 통해 LibreSSL 지원을 적극적으로 막지는 않을 것입니다. 그러나 Python은 사소하지 않은 우회 코드를 추가하거나 테스트를 비활성화하는 패치도 받아들이지 않을 것입니다.
BoringSSL
현재 BoringSSL을 지원할 계획은 없습니다.
기각된 아이디어
지원되는 OpenSSL 버전의 공식화
이 PEP는 OpenSSL 버전이 지원되는 조건에 관한 공식적인 규칙과 조건을 제시하지 않습니다.
일반적으로 Python은 널리 사용되며 공식적으로 지원되는 OpenSSL 버전과 호환되는 것을 목표로 합니다. Python의 패치 릴리스는 OpenSSL의 새로운 메이저 릴리스와 호환되지 않을 수 있습니다. 사용자는 Python의 새로운 메이저 또는 마이너 릴리스가 수명이 종료된 OpenSSL 버전에서 동작할 것이라고 기대해서는 안 됩니다. Python 코어 개발팀은 적절하다고 판단하는 경우 새로운 릴리스를 위한 수정 사항을 백포트하거나 EOL된 릴리스와의 호환성을 연장할 수 있습니다.
OpenSSL의 새로운 ABI 안정성 및 LTS 정책 [9]도 도움이 될 것입니다.
OpenSSL 1.1.0 지원 유지
Debian 9 (Stretch)와의 호환성을 위해 OpenSSL 1.1.0 지원을 유지하자는 제안이 있었습니다. 이 제안은 코드 정리와 테스트를 복잡하게 만들 것이므로 기각되었습니다. Stretch는 이미 정규 보안 지원이 종료되었으며 장기 지원 종료도 얼마 남지 않았습니다. Python 3.10 최종 릴리스 시점에는 Debian Buster와 Debian Bullseye를 사용할 수 있을 것입니다.
대신 Python 3.10에는 사용자 정의 OpenSSL 빌드를 더 쉽게 사용할 수 있도록 추가 문서와 새 configure 옵션 --with-openssl-rpath=auto가 제공될 것입니다 [11].
하위 호환성
Python 3.10은 OpenSSL 1.0.2나 LibreSSL을 사용하는 플랫폼에서 TLS/SSL과 빠른 해싱을 더 이상 지원하지 않습니다. 이 PEP의 첫 초안은 Linux 배포판 제작자나 CI 제공 업체 같은 벤더가 계획을 세울 시간을 충분히 가질 수 있도록 3.10 릴리스 주기 초반에 공개되었습니다.
Python이 내부에 보유한 Keccak 코드 패키지의 사본과 내부 _sha3 모듈은 제거됩니다. 이를 통해 소스 코드 크기는 약 280kB, 코드 크기는 약 0.5MB 줄어들 것입니다. hashlib은 OpenSSL의 SHA-3 구현에만 의존하게 될 것입니다. OpenSSL 없이는 SHA-3와 SHAKE를 더 이상 사용할 수 없습니다.
고지 사항 및 특별한 감사의 말
이 PEP의 저자는 OpenSSL 프로젝트의 기여자이며, OpenSSL을 사용하는 주요 Linux 배포판 업체에 고용되어 있습니다.
초안을 검토하고 피드백을 주신 Alex Gaynor, Gregory P. Smith, Nathaniel J. Smith, Paul Kehrer, Seth Larson에게 감사드립니다.
참고 문헌
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.