EIP-7951 secp256r1 서명 검증 프리컴파일 (Precompile for secp256r1 Curve Support)

최종 확정 · EVM·실행 · 원문 상태 Final · 2025-05-27 작성

스마트폰 보안칩이나 웹오튼 기기가 쓰는 secp256r1(P-256) 곡선의 전자서명을 검증하는 프리컴파일 P256VERIFY를 주소 0x100에 추가합니다. L2에 배포된 RIP-7212의 보안 결함을 고친 명세입니다.

왜 필요한가

지금 이더리움이 기본으로 검증할 수 있는 서명은 secp256k1 곡선 하나뿐입니다. 그런데 아이폰의 시큐어 엔클레이브(Apple Secure Enclave), 안드로이드 키스토어, 지문이나 얼굴 인식으로 로그인하는 FIDO2/웹오튼(WebAuthn) 기기 같은 현대 보안 하드웨어는 대부분 다른 곡선인 secp256r1(P-256)로 키를 만들고 서명합니다. 이 서명을 이더리움에서 검증하려면 지금은 비용이 지나치게 크거나 사실상 불가능합니다. 여러 L2는 이미 RIP-7212라는 규격으로 이 기능을 제공하지만 거기에서 합의 실패로 이어질 수 있는 치명적 보안 결함 두 가지가 발견되었습니다. 이 EIP는 RIP-7212와 같은 인터페이스를 유지하면서 결함을 고친 명세이고 기기에 내장된 키로 바로 서명하는 지갑이나 다중 인증 같은 계정 추상화 활용을 가능하게 합니다.

무엇이 바뀌나

지금

EIP-7951 이후

누구에게 영향이 있나

심층 설명

프리컴파일 주소와 가스 비용

주소 0x100에 P256VERIFY 프리컴파일을 추가하며 가스 비용은 6900입니다. 이 값은 기존 ECRECOVER 프리컴파일(3000가스)과의 벤치마크로 정했는데, 실제 R1 검증이 ECRECOVER보다 상당히 느린 것으로 나타나 6900가스로 올렸습니다. 이 비용은 RIP-7212(3450가스)와 달라 L2와의 가스 호환성은 유지하지 않지만 실제 구현 벤치마크에 더 가깝습니다. 또 프리컴파일은 어떤 경우에도 리버트해서는 안 되며 입력이 잘못되거나 검증이 실패해도 성공했을 때와 같은 양의 가스를 소모하고 빈 값을 반환해야 합니다.

입출력 형식과 인코딩

입력은 정확히 160바이트로, 메시지 해시 h, 서명 성분 r과 s, 공개키 x좌표 qx와 y좌표 qy를 각각 32바이트씩 이어 붙인 것입니다. 모든 값은 부호 없는 정수의 빅엔디언 인코딩입니다. 체 원소는 반드시 체 모듈러스 p보다 작아야 하고 스칼라는 부분군 차수 n 이하일 필요가 없습니다. 곡선 위의 점은 x, y 좌표를 이어 붙인 64바이트로 표현하며 (0, 0)은 secp256r1 곡선 위의 점이 아니므로 64바이트의 0을 무한원점 인코딩으로 약속합니다. 출력은 서명이 유효하면 32바이트(0x00...01)이고 실패하면 0바이트(빈 값)입니다.

다섯 가지 입력 검증

프리컴파일은 다음 검사를 모두 수행하고 하나라도 실패하면 빈 값을 반환해야 합니다. 1) 입력 길이가 정확히 160바이트인지, 2) r과 s가 모두 0 < r < n, 0 < s < n을 만족하는지, 3) qx와 qy가 모두 0 ≤ qx < p, 0 ≤ qy < p를 만족하는지, 4) 점 (qx, qy)가 곡선 방정식 qy^2 ≡ qx^3 + a*qx + b (mod p)를 만족하는지, 5) 점 (qx, qy)가 무한원점 (0, 0)이 아닌지입니다. 유효한 체 원소나 점의 인코딩이 될 수 없는 입력에도 반드시 빈 값(실패)을 반환합니다.

검증 알고리즘

입력 검증을 통과하면 ECDSA 검증을 수행합니다. 먼저 s1 = s^(-1) (mod n)을 구하고 서명 때 쓰인 랜덤 점을 R' = (h * s1) * G + (r * s1) * (qx, qy)로 복원합니다. R'이 무한원점이면 실패입니다. R'의 x좌표 r'을 꺼내 r' ≡ r (mod n)이면 유효한 서명으로 32바이트 1을 반환하고 아니면 빈 값을 반환합니다. 비교를 단순 동일성(r' == r)이 아니라 mod n으로 하는 이유는 R'의 x좌표가 곡선 차수 n을 넘는 경우까지 ECDSA 표준에 맞게 처리하기 위해서입니다.

RIP-7212의 보안 결함 수정과 호환성

이 EIP는 RIP-7212의 치명적 취약점 두 가지를 고칩니다. 첫째, RIP-7212는 복원한 점 R'이 무한원점인지 검사하지 않았습니다. 이 경우 검증 결과가 하부 구현이 무한원점을 다루는 방식에 따라 달라지는 비결정적 동작이 생길 수 있고 합의 실패로 이어질 수 있습니다. 둘째, 비교를 r' == r에서 r' ≡ r (mod n)으로 바로잡았습니다. 인터페이스는 RIP-7212와 같습니다. 같은 주소(0x100), 같은 입력 형식(160바이트), 같은 출력 형식(32바이트), 같은 반환값이며 가스 비용만 3450에서 6900으로 다릅니다. 보안 수정은 원래 검증에 실패했어야 할 가장자리 사례에만 영향을 주므로 올바르게 구현된 기존 호출자에게는 투명하고 기존의 유효한 사용 사례를 깨지 않습니다.

복구가 아닌 검증을 택한 이유

ECRECOVER처럼 서명에서 공개키를 복구하는 방식 대신 서명을 직접 검증하는 방식을 택했습니다. 하드웨어와 소프트웨어의 secp256r1 구현 대부분이 서명을 직접 검증하고 NIST FIPS 186-5 표준도 복구가 아닌 검증을 규정하며 이 곡선에서는 검증이 복구보다 효율적이고 기존 하드웨어 구현이 검증 인터페이스를 제공하기 때문입니다. 따라서 호출자는 공개키 좌표 qx, qy를 입력에 함께 넣어야 합니다.

보안 고려사항과 진행 현황

secp256r1은 이더리움이 이미 쓰는 secp256k1과 동등한 약 128비트 보안 수준을 제공하며 NIST SP 800-186으로 표준화되어 폭넓은 암호학적 분석을 거쳤고 RIP-7212 형태로 여러 L2에 배포되어 왔습니다. 다만 NIST FIPS 186-5 기준으로 secp256r1 ECDSA 서명은 비가변성이 요구되지 않으므로, 비가변성이 필요한 애플리케이션은 응용 계층에서 추가 검사를 구현해야 합니다. 프리컴파일이 모든 연산을 상수 시간 알고리즘으로 수행할 필요는 없다고 명시합니다. 원문 상태는 Final이며 08.29 AMA #14에서 논의되었고 결정은 없었습니다.

EIP 원문 · ← EIPs