서명 페이지 직접 호스팅

Vela는 승인 전에 모든 거래를 해독하고, 그 작업은 진짜입니다. 다만 그 작업을 하는 것은 그 거래를 만든 바로 그 앱입니다. 앱이나 앱이 당신에게 도달하는 경로가 변조되면, 하나를 보여 주고 다른 것에 서명하게 만들 수 있습니다. 바이비트에서 벌어진 일이 정확히 그것입니다.

서명 페이지는 그것을 둘로 쪼개기 위해 존재합니다. 거래는 한 곳에서 오고, 확인과 서명은 당신이 통제하는 다른 곳에서 일어납니다.

그것이 무엇인가

저장소의 app-web/clearsigning이라는 폴더 하나이며, 웹 페이지이자 Chrome 확장입니다. 순수한 HTML·CSS·자바스크립트뿐, 프레임워크도 번들러도 빌드 단계도 의존성도 없고, 자체 네트워크 요청도 없습니다.

서명 요청을 받아도 함께 온 요약을 믿지 않습니다. 원시 거래를 받아 calldata를 스스로 다시 해독하고, 그 서명이 실제로 무엇을 허용하는지 당신 앞에 놓은 뒤에야 패스키를 요청합니다.

빌드 단계가 없으므로, 당신이 읽은 파일이 곧 실행되는 파일입니다. 폴더를 저장소와 비교해 보면, 자신이 무엇을 서비스하고 있는지 알 수 있습니다.

어떤 사본이 내 지갑을 위해 서명할 수 있나

패스키는 만들어진 도메인에 묶입니다. 당신의 Vela 키는 getvela.app 아래에 등록되어 있고, 브라우저는 relying party가 getvela.app인 페이지에만 그 키를 제시합니다. 이 한 가지 규칙이, “직접 돌리기” 중 어느 쪽이 당신에게 유용한지를 정합니다.

Chrome 확장으로 — 기존 지갑과 쓰려면 이쪽입니다. 폴더가 어디서 왔든 확장의 relying party는 getvela.app이므로 기존 키로 서명할 수 있고, 실행되는 코드는 당신이 불러와 확인한 그 폴더입니다.

  1. chrome://extensions를 열고 개발자 모드를 켭니다.
  2. 압축해제된 확장 프로그램을 로드app-web/clearsigning 폴더를 고릅니다.
  3. 툴바 아이콘을 누르면 탭에서 페이지가 열립니다.

내 도메인이나 localhost의 페이지로. HTTP(S)로 서비스하면 페이지의 relying party는 그 호스트명이 됩니다. 즉 그 호스트명 아래 등록된 키로는 서명할 수 있지만, getvela.app 아래 등록된 키로는 서명할 수 없습니다. 전체 흐름을 끝까지 시험해 보거나, 데스크톱 플로를 돌리거나, 키를 내 도메인에서 만든 지갑에 서명할 때 알맞습니다. 기존 getvela.app 지갑을 위해 서명하는 방법은 아닙니다.

cd app-web/clearsigning
python3 -m http.server 8080   # → http://localhost:8080

앱 안의 경로는 모두 상대 경로이므로 기존 호스트의 하위 디렉터리에서도 동작합니다. 디스크에서 index.html을 바로 여는 것(file://)은 둘러보기에는 되지만, 오리진이 없으니 relying party도 없고 아무것도 서명할 수 없습니다.

서명 전에 무엇을 하나

  • 거래를 스스로 해독합니다. 그 호출이 무엇을 하고, 누구에게, 얼마인지를 calldata에서 — 배치 안에 중첩된 호출까지 포함해서.
  • 스스로 계산한 다이제스트에만 서명합니다. EIP-191, EIP-712, SafeOp, SafeMessage 다이제스트를 페이지 안에서 계산하고, 지갑이 쓰는 같은 코드인 vela-core와 대조합니다. 계산하지 못한 다이제스트는 서명이 아니라 거부입니다.
  • 요청된 바로 그 거래인지 확인합니다. 사이트가 요청한 호출이 서명되는 오퍼레이션 안에 실제로 들어 있어야 합니다.
  • 무제한 승인을 거부합니다. 경고가 아니라 거부이고, 대신 무엇을 하면 되는지 알려 줍니다.
  • 읽지 못하면 못 읽는다고 말합니다. 책임질 수 없는 친절한 요약을 내놓지 않습니다.
  • 계정의 주소와 아이덴티콘을 보여 주고, 서명을 요청한 쪽이 건넨 받는 사람 이름은 보여 주지 않습니다. 요청자가 조작할 수 있는 것은 빼거나, 그쪽 주장임을 명시합니다.

일부러 없는 것

  • 편집 기능이 없습니다. 요청은 도착한 순간 고정입니다. 서명하거나 하지 않거나 둘 중 하나입니다. 수수료 선택이나 한도 편집은 calldata를 다시 쓰는 일이고, 그것이야말로 이 페이지가 막으려는 병입니다.
  • 키를 만들 수 없습니다. 서명 페이지는 패스키를 만들지 못합니다. 새 키를 만드는 것은 다른 계정을 만드는 일이기 때문입니다.
  • 네트워크 요청이 없습니다. 가져올 것이 없으면 가로챌 것도 없습니다.

요청은 어떻게 도달하나

요청자통로
같은 브라우저 안의 페이지postMessage
같은 브라우저의 페이지에서 확장으로확장 포트
같은 기기의 데스크톱 앱URL 프래그먼트 + 루프백 콜백
휴대폰이나 다른 컴퓨터블루투스 LE(프로토콜 구현 완료, 무선 부분은 실제 기기에서 미검증)

와이어 포맷, 다이제스트, 그리고 화면의 각 항목이 어디서 왔는지 정리한 표는 코드 옆의 PROTOCOL.md에 있습니다.

언제 쓰나

그 계정이 잃으면 속상할 돈을 담기 시작한 날부터 — 그리고 그 뒤로는 모든 서명에. 금액이 클 때만이 아닙니다. 작은 승인 하나로도 계정을 비울 만큼의 권한이 넘어갈 수 있습니다. 특별한 날에만 꺼내는 서명 습관은, 정작 필요한 날에 몸에 붙어 있지 않습니다.