궁금한 주제를 찾아보세요

비트코인, 스테이블코인, 온체인 데이터처럼 주제로 검색하세요.

다시 읽을 이야기

저장한 글은 이 브라우저에만 보관됩니다.

해설기술·생태계

EVM ecrecover 사용 시 서명 가변성과 도메인 분리를 확인하는 이유

ecrecover가 high-s도 받아들이는 경계와 low-s·v·zero address·nonce·chain·contract domain 검증을 permit 사례로 설명합니다.

난이도 중급주제 카테고리와 개념 밀도 기준검토 정보AI 보조 초안 · 출처 목록 제공 · 주장별 대조 진행 중
여러 서명 표현이 검증 문턱으로 모이고 잘못된 문맥의 경로는 막히는 서명 검증 그림
주제의 이해를 돕기 위해 imagegen으로 제작한 AI 생성 개념 일러스트
먼저 읽는 핵심

Transaction의 low-s 규칙이 ecrecover 입력에 자동 적용되지는 않습니다.
복구 성공은 signer 식별일 뿐 message 의미와 재사용 방지는 별도입니다.
도메인·nonce·deadline과 서명 bytes 중복 처리 정책을 함께 설계합니다.

ecrecover는 32바이트 digest와 v·r·s로 Ethereum address를 복구하지만 서명이 누구의 어떤 행위를 어느 chain·contract에서 승인했는지 판단하지 않습니다. EIP-2는 transaction signature의 high-s를 무효화했지만 ecrecover precompile은 과거 서명 호환을 위해 high-s도 계속 받습니다. Contract는 s가 secp256k1 order의 절반 이하인지, v가 허용 형식인지, 복구 주소가 zero가 아닌지 확인해야 합니다. 여기에 EIP-191·712 prefix, chainId, verifying contract, action parameters, nonce와 deadline을 digest에 묶어 replay 범위를 제한해야 합니다.

같은 의미의 ECDSA 서명이 둘일 수 있습니다

secp256k1 ECDSA에서 유효한 (r,s)에 대해 (r,n-s)와 반대 recovery parity도 같은 공개키를 복구할 수 있습니다. 서명 bytes가 다르므로 signature hash를 사용한 unique key나 ‘이 bytes는 아직 안 썼다’는 mapping은 우회될 수 있습니다. 권한의 핵심 replay key는 message nonce와 signer여야 합니다.

EIP-2 Homestead 규칙은 Ethereum transaction의 s가 n/2보다 크면 invalid로 만들었지만 ecrecover precompile은 변경하지 않았습니다. Old Bitcoin signatures 같은 용도를 보존하기 위해서입니다. 따라서 wallet이 항상 canonical signature를 만든다는 가정 대신 contract 경계에서 low-s를 검사합니다.

ecrecover는 암호학적 복구 함수이지 승인 정책 함수가 아닙니다. 복구된 주소 앞뒤의 메시지 문맥은 계약이 직접 검증해야 합니다.

JOBCOIN 해설

VISUAL GUIDE키 보관과 거래 서명
보호된 개인키로 거래에 서명하고 노드가 서명을 검증하는 개념도
그림과 함께 짚어볼 본문 내용

그림은 이 주제의 공통 개념을 단순화한 설명입니다. 아래 항목에서 이 글의 구체적인 조건과 예외를 함께 읽어보세요.

  1. 같은 의미의 ECDSA 서명이 둘일 수 있습니다

    secp256k1 ECDSA에서 유효한 (r,s)에 대해 (r,n-s)와 반대 recovery parity도 같은 공개키를 복구할 수 있습니다.

  2. v·r·s와 실패 결과를 모두 검증합니다

    Solidity ecrecover는 오류 시 address(0)를 반환합니다.

  3. Permit 예제로 digest 범위를 점검합니다

    Owner가 spender에게 100 token allowance 를 주는 off-chain signature를 만든다고 하겠습니다.

AI로 제작한 개념도 · 실제 가격·거래 내역·통계가 아닙니다.

v·r·s와 실패 결과를 모두 검증합니다

Solidity ecrecover는 오류 시 address(0)를 반환합니다. Zero address가 role mapping에서 허용되거나 signer 입력과 우연히 같아지는 로직이면 실패가 승인으로 바뀔 수 있어 recovered != address(0)을 먼저 확인합니다. r·s range와 lower-half s, v가 27·28인지 또는 library가 0·1을 정규화하는지 명시합니다.

EIP-2098 compact signature처럼 parity가 s의 최상위 bit에 들어가는 형식도 있으므로 64바이트·65바이트 parser를 섞지 않습니다. Transaction의 EIP-155 v 값과 message signature v를 같은 방식으로 해석하면 chain id 산식이 잘못 적용될 수 있습니다.

서명 검증 층별 질문
검사 막는 문제 누락 시 결과
low-s·v range ECDSA 가변 표현 다른 bytes 재사용
zero address 복구 실패 실패를 signer로 오인
domain prefix 다른 서명 종류 혼용 transaction·message 혼동
chain·contract cross-domain replay 다른 배포에서 재사용
nonce·deadline 시간·횟수 replay 같은 승인 반복 실행

Permit 예제로 digest 범위를 점검합니다

Owner가 spender에게 100 token allowance를 주는 off-chain signature를 만든다고 하겠습니다. Digest에는 owner, spender, value뿐 아니라 현재 nonce와 deadline, domain의 chainId와 verifyingContract가 들어가야 합니다. Contract는 recovered signer가 owner인지 확인하고 nonce를 소비한 뒤 allowance를 갱신합니다.

Value만 서명하면 공격자는 다른 spender나 contract에 서명을 붙일 수 있습니다. Nonce를 포함해도 state를 증가시키기 전에 token hook 같은 외부 호출을 하면 재진입으로 같은 nonce가 재사용될 수 있습니다. Signature 검증, nonce effect, interaction 순서를 하나의 state transition으로 봅니다.

  • 서명 scheme과 prefix byte를 고정합니다.
  • Typed fields와 type hash를 test vector로 검산합니다.
  • s lower-half·v 형식·zero address를 검사합니다.
  • Chain id·verifying contract·nonce·deadline을 포함합니다.
  • Nonce를 외부 호출 전에 소비하고 event를 남깁니다.

EIP-191은 의도하지 않은 Ethereum transaction을 막습니다

EIP-191 signed data는 0x19 뒤 version byte와 version-specific data, payload 구조를 사용합니다. 첫 0x19는 서명 데이터가 유효한 RLP Ethereum transaction이 되지 않게 합니다. Version 0은 intended validator address를 넣고 version 0x45는 personal_sign 계열 prefix에 사용됩니다.

Prefix가 있다는 사실만으로 application domain이 충분하지는 않습니다. 두 contract가 같은 payload와 validator 규칙을 공유하면 replay가 가능할 수 있습니다. EIP-712 domain separator 또는 protocol 고유 domain을 사용하고 proxy upgrade에서 verifying contract와 chain fork 처리 정책을 문서화합니다.

서명 bytes보다 승인 상태를 감사합니다

운영 로그에는 raw signature 전체보다 signer, digest, nonce, action과 transaction hash를 연결해 남깁니다. Signature를 unique ID로 쓰지 않고 message digest·signer·nonce의 소비 상태를 기준으로 중복 실행을 막습니다. 개인키나 미공개 승인 payload는 로그에 남기지 않습니다.

Test vector는 정상 low-s, 대응 high-s, 잘못된 v, zero recovery, 다른 chain id·contract, 만료와 nonce 재사용을 포함합니다. Frontend가 보여 준 문구와 contract가 hash한 bytes가 같은지 독립 구현으로 비교해야 합니다.

자주 묻는 질문

Ethereum transaction이 low-s이면 contract 서명도 자동 low-s인가요?

아닙니다. EIP-2의 transaction 유효성 규칙과 ecrecover precompile 입력 검사는 다르므로 contract가 직접 확인해야 합니다.

ecrecover가 zero address를 반환하면 signer가 0인 건가요?

복구 실패일 수 있습니다. 유효 signer로 취급하지 말고 명시적으로 거부해야 합니다.

Nonce만 넣으면 replay가 모두 막히나요?

같은 contract 내 반복은 줄이지만 다른 chain·contract 재사용을 막으려면 domain도 digest에 포함해야 합니다.

더 깊이 읽기

본문에서 다룬 개념과 확인 절차를 다음 글에서 이어서 살펴보세요.

참고한 원문 자료

자료 확인 기준일 2026.09.27
  1. EIP-2: Homestead Hard-fork Changeseips.ethereum.org
  2. ERC-191: Signed Data Standardeips.ethereum.org
자료 대조 기록과 확인 범위
출처 수집
원문 링크 2개 제공
핵심 주장 대조
완료 근거가 아직 기록되지 않았습니다.
분야 전문가 검수
별도 완료 기록이 없습니다.

원문 링크와 자료 확인일은 글 전체의 주장 대조나 전문가 검수 완료를 뜻하지 않습니다. 별도 확인이 필요한 절차는 원문의 적용 대상과 최신 안내를 함께 확인해 주세요.

AI 활용 안내

이 글은 초안 구성과 자료 정리에 AI를 활용했습니다. 글에 표시된 출처와 기준일을 함께 확인해 주세요. 별도 검토 정보가 없다면 전문가 검수를 뜻하지 않습니다.

이해를 위한 정보 콘텐츠

이 글은 특정 자산의 매수·매도 또는 수익을 권유하지 않습니다. 자료의 발표 시점과 이후 변경 사항을 함께 확인해 주세요.

편집 원칙 보기 →이 기사 정정 제보 →