EIP-155 단순 재전송 공격 방지 (Simple replay attack protection)

최종 확정 · 보안·프라이버시 · 원문 상태 Final · 2016-10-14 작성

트랜잭션 서명에 체인 고유 번호(체인 ID)를 포함해 한 체인에서 서명한 트랜잭션을 다른 체인에 그대로 다시 제출해도 통하지 않게 만듭니다.

왜 필요한가

이 EIP 이전의 트랜잭션 서명은 논스, 가스 가격, 가스 한도, 수신 주소, 금액, 데이터라는 6개 요소만 해시해서 만들었습니다. 서명 어디에도 어느 체인을 위한 트랜잭션인지 담기지 않았습니다. 그래서 이더리움 메인넷에서 보낸 서명 트랜잭션을 누군가 이더리움 클래식(ETC)이나 Morden 테스트넷 같은 다른 체인에 그대로 복사해 제출하면, 그 체인에서도 유효한 트랜잭션으로 처리될 수 있었습니다. 이것이 재전송 공격(replay attack)입니다. 사용자가 메인넷에서 한 송금이 본인 의사와 무관하게 다른 체인에서도 똑같이 실행될 수 있는 문제입니다. EIP-155는 서명할 데이터에 체인마다 다른 번호인 체인 ID(chain ID)를 넣어 서명이 특정 체인에서만 유효하도록 묶습니다. 원문은 이더리움에서는 동작하지만 ETC나 Morden 테스트넷에서는 동작하지 않는 트랜잭션을 보낼 방법을 제공한다고 설명하고 ETC와 미래의 테스트넷·컨소시엄 체인들도 각자 고유한 체인 ID로 이 방식을 채택하라고 권장합니다.

무엇이 바뀌나

지금

EIP-155 이후

누구에게 영향이 있나

심층 설명

서명 데이터가 6개에서 9개 요소로 바뀝니다

block.number >= FORK_BLKNUM이고 CHAIN_ID가 있으면, 서명용 트랜잭션 해시를 계산할 때 기존 6개 RLP 요소 (nonce, gasprice, startgas, to, value, data) 대신 9개 RLP 요소 (nonce, gasprice, startgas, to, value, data, chainid, 0, 0)를 해시해야 합니다(SHOULD). 뒤에 붙는 chainid, 0, 0은 서명 데이터에만 들어가고 실제 전송되는 트랜잭션 필드가 늘어나는 것은 아닙니다. 체인 ID가 해시에 들어가므로 같은 내용의 트랜잭션이라도 체인 ID가 다르면 서명 해시가 달라집니다.

v 값에 체인 ID를 인코딩합니다

9개 요소를 해시해 서명했다면 v는 반드시(MUST) {0,1} + CHAIN_ID * 2 + 35로 설정합니다. 여기서 {0,1}은 secp256k1 서명 과정에서 r이 x 값인 곡선 점의 y 값 패리티입니다. 메인넷(CHAIN_ID = 1)에서는 v가 37 또는 38이 됩니다. 6개 요소만 해시하는 기존 방식을 택했다면 v는 이전처럼 {0,1} + 27로 둡니다. 즉 v 값만 보고도 어떤 방식으로, 어느 체인을 위해 서명했는지 알 수 있습니다.

복구 규칙과 하위 호환

block.number >= FORK_BLKNUM이고 v = CHAIN_ID * 2 + 35 또는 v = CHAIN_ID * 2 + 36이면, 서명자 주소를 복구할 때도 6개가 아니라 9개 RLP 요소를 해시합니다. v = 27, 28을 쓰는 기존 서명 방식은 계속 유효하며 이전과 같은 규칙으로 동작합니다. 새 방식이 SHOULD(권장)로 규정되어 있어 강제 전환이 아니라 점진적 이행이 가능하도록 설계되어 있습니다.

적용 시점과 파라미터

이 EIP는 Spurious Dragon 하드포크(EIP-607)에 포함되어 FORK_BLKNUM = 2,675,000 블록부터 적용됩니다. 메인넷의 CHAIN_ID는 1입니다. 원문의 체인 ID 목록에는 Morden(2, 사용 중단)과 Expanse 메인넷(2), Ropsten(3), Rinkeby(4), Goerli(5), Kovan(42), Geth 사설 체인 기본값(1337)이 실려 있고 더 많은 체인 ID는 chainid.network와 ethereum-lists/chains 저장소에서 확인하고 등록할 수 있습니다.

원문 예시로 보는 실제 값

nonce = 9, gasprice = 20 * 10**9, startgas = 21000, to = 0x3535...3535, value = 10**18, data 빈 값인 트랜잭션의 서명 데이터는 0xec098504a817c800825208943535...018080이고 서명 해시는 0xdaf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53입니다. 개인키 0x4646...4646으로 서명하면 v는 27이 아닌 37이 나옵니다. r, s 값과 최종 서명된 트랜잭션 바이트도 원문 Example 절에 그대로 실려 있습니다.

다른 체인들의 채택을 권장합니다

원문 Rationale은 이 방식이 이더리움에서는 동작하지만 ETC나 Morden 테스트넷에서는 동작하지 않는 트랜잭션을 보낼 수단이 된다고 설명합니다. ETC에는 CHAIN_ID를 다른 값으로 바꿔 이 EIP를 채택하라고 권장하고 미래의 모든 테스트넷, 컨소시엄 체인, 대체 이더리움 체인에도 각자 고유한 값으로 채택하기를 권장합니다. 이 EIP의 상태는 Final로, 명세가 확정되어 더 바뀌지 않습니다.

EIP 원문 · ← EIPs