메시지 서명: ‘지갑으로 로그인’이 실제로 증명하는 것

·5분 읽기·작성자: SSP Editorial Team
SSP Academy 표지: 메시지 서명과 지갑으로 로그인

메시지 서명: ‘지갑으로 로그인’이 실제로 증명하는 것

언젠가는 어떤 사이트가 트랜잭션을 보내는 대신 “메시지에 서명해 달라”고 요청하게 됩니다. 가스비도 없고, 온체인 확인도 없으며, 내역에도 아무것도 남지 않습니다. 무해하게 느껴지고, 실제로도 대부분은 무해합니다. 하지만 서명이란 여러분의 키가 무언가를 보증하는 것이며, 매번 던져 볼 가치가 있는 질문은 간단합니다. 무엇을 보증하는가?

서명이 증명하는 것

디지털 서명이 증명하는 것은 단 하나입니다. 특정 개인 키를 통제하는 사람이 특정 데이터에 동의했다는 사실입니다. 누구나 여러분의 공개 주소로 이를 검증할 수 있으며, 그 과정에서 키에 대해서는 아무것도 알 수 없습니다.

그래서 서명은 코인 전송을 훨씬 넘어서는 쓸모가 있습니다. 사이트는 수수료를 받지 않고도 여러분이 어떤 주소의 소유자임을 확인할 수 있습니다. 개발자는 특정 릴리스를 자신이 배포했음을 증명할 수 있습니다. 노드 운영자는 어떤 서버가 자신의 것임을 증명할 수 있습니다. 이 중 어느 것도 블록체인을 건드리지 않으며, 모두 같은 보장에 기반합니다. 바로 그 키가 정확히 이 바이트들에 서명했다는 것입니다.

함정은 ‘정확히 이 바이트들’이라는 부분에 있습니다. 서명에는 의도가 담기지 않습니다. 여러분이 로그인한다고 생각했는지, 결제를 승인한다고 생각했는지 서명은 알지 못합니다. 서명은 여러분의 키를 데이터에 묶을 뿐이며, 그 서명을 가진 사람은 데이터가 허용하는 모든 용도로 그것을 사용할 수 있습니다.

‘지갑으로 로그인’

가장 흔히 보게 될 메시지는 로그인입니다. 사이트는 비밀번호 대신 텍스트 한 조각을 보내고, 여러분이 거기에 서명하면, 사이트는 여러분의 주소로 서명을 확인합니다. 일치하면 로그인됩니다.

잘 만든 로그인 메시지는 작은 계약서처럼 읽히며, 이더리움의 표준 형식(EIP-4361, 흔히 SIWE, 즉 ‘이더리움으로 로그인’이라고 부름)은 그 내용을 다음과 같이 명시합니다.

  • 요청하는 도메인 — 주소창에 표시된 사이트와 일치해야 합니다.
  • 로그인하는 주소.
  • 평이한 말로 된 문구, 예를 들어 “Example에 로그인”.
  • 논스(nonce) — 서명이 나중에 재사용되지 않도록 하는 일회용 무작위 값.
  • 발행 시각과 만료 시각 — 오래된 서명이 효력을 잃도록 합니다.

이 모든 항목이 갖춰져 있고 서로 일치한다면, 로그인 서명은 위험이 낮습니다. 한 사이트에서 세션을 열어 줄 뿐 그 이상은 아닙니다. 메시지 속 도메인이 지금 접속한 사이트와 일치하지 않는다면 멈추세요. 그 불일치야말로 여러분의 서명을 다른 곳에서 재사용하려는 피싱 페이지가 만들어 내는 모습입니다.

돈을 움직이는 서명

‘가스비가 없으니 무해하다’는 생각이 무너지는 곳이 바로 여기입니다. 몇몇 종류의 오프체인 서명은 나중에 다른 사람이 제출해 여러분의 자금을 옮길 수 있습니다.

  • 토큰 퍼밋(permit). 많은 토큰은 온체인 승인 대신 서명으로 지출 권한을 부여할 수 있게 해 줍니다. 권한을 받은 쪽이 이를 제출하면 허용된 금액까지 전송할 수 있습니다. 여러분 입장에서는 그저 메시지에 서명한 것처럼 보였을 뿐입니다. 이름만 다를 뿐 모든 면에서 승인입니다.
  • 마켓플레이스 주문. 서명된 등록 매물과 제안은 이를 가진 누구나 여러분이 서명한 조건으로 체결할 수 있습니다. 악성 사이트가 여러분 대신 채워 넣은 조건도 포함해서요.
  • 원시 해시 서명. 일부 구식 방법은 읽을 수 있는 내용도 없고 ‘단순한 메시지’임을 표시하는 접두사도 없는 임의의 32바이트 해시에 서명합니다. 해시는 실제 트랜잭션의 지문일 수 있습니다. 읽을 수 없는 해시에 서명하는 것은 가장 순수한 형태의 블라인드 서명입니다.

여기서 나오는 규칙은 짧습니다. 무엇에 서명하는지 읽을 수 없다면, 그것이 무엇을 허가하는지도 알 수 없습니다.

서명 요청을 읽는 방법

어떤 메시지든 승인하기 전에 같은 네 가지 질문을 점검하세요.

  1. 누가 요청하는가? 요청한 사이트가 원래 사용하려던 사이트와 같은지 확인하세요.
  2. 어떤 주소, 어떤 네트워크인가? 예상과 다른 주소나 체인에 대한 요청은 경고 신호입니다.
  3. 읽을 수 있는가? 이해할 수 있는 평문이라면 괜찮습니다. 16진수, 해시, 설명 없는 긴 JSON은 전혀 다른 이야기입니다.
  4. 누군가에게 무엇을 허용하게 되는가? 로그인, 소유권 증명 — 괜찮습니다. 지출, 등록, 전송, 승인 — 트랜잭션처럼 다루세요. 실제로 그것이 트랜잭션이니까요.

SSP가 보여 주는 것

WalletConnect로 연결된 dApp이 SSP에 메시지 서명을 요청하면, 요청 화면에는 요청한 사이트, 주소와 네트워크, 그리고 메시지 자체가 표시됩니다. 16진수로 인코딩된 메시지는 먼저 읽을 수 있는 텍스트로 디코딩되며, 원시 바이트는 확인하고 싶을 때 펼쳐 볼 수 있는 영역에 들어 있습니다.

일반 텍스트 메시지에는 이더리움 표준 ‘서명된 메시지’ 접두사가 붙습니다. 이 접두사는 해당 데이터를 트랜잭션이 아닌 메시지로 표시하므로 트랜잭션으로 재사용될 수 없습니다. 구조화된 타입 데이터 요청은 승인하기 전에 원시 내용 전체를 보여 줍니다.

SSP의 모든 작업과 마찬가지로, 지갑에서 하는 메시지 서명에도 두 키가 모두 필요합니다. SSP Wallet에서 승인한 뒤 SSP Key에서 확인합니다. 이 두 번째 단계는 별도의 기기에서 이루어지는 진짜 ‘두 번째 확인’이며, 그렇게 활용할 가치가 있습니다.

SSP가 할 수 없는 일은 사이트가 서명으로 무엇을 하려는지 알려 주는 것입니다. SSP는 데이터를 충실하게 보여 줍니다. 그것을 읽는 것은 여전히 여러분의 몫입니다.

솔직한 요약

메시지 서명은 아무것도 지출하지 않고 키로 무언가를 증명하는 방법이며, 대부분의 경우 보이는 그대로 무해합니다. 예외는 지출, 등록, 전송을 허가하는 서명이며, 이런 서명은 읽어 보기 전까지는 똑같아 보이는 경우가 많습니다.

그러니 읽으세요. 도메인, 주소, 체인, 내용을 확인하세요. 이해하는 것에만 서명하고, 읽을 수 없는 것은 모두 ‘아니요’로 취급하세요.

이 글 공유하기

관련 글