ERC-7627 온체인 보안 메시징 프로토콜 (Secure Messaging Protocol)

Final · 기타 · 2024-02-19 작성

사용자가 체인 위에 공개키를 등록하고 상대의 공개키로 암호화한 메시지를 주소로 보내는 종단간 암호화(end-to-end encryption) 메시징의 공통 인터페이스를 정의합니다.

왜 필요한가

블록 생성이 1초 미만으로 빨라진 레이어 2(Layer 2) 체인이 등장하고 계정 추상화(account abstraction)가 도입되면서 체인 위에서 실시간 소통과 온라인 채팅을 제공하는 분산 앱이 늘어날 토대가 마련되었습니다. 그런데 암호화된 메시지를 주고받는 공통 규격이 없으면 앱마다 공개키를 등록하는 방식, 메시지를 보내는 함수, 대화를 구분하는 방법이 제각각이 됩니다. 이러면 한 앱에서 보낸 메시지를 다른 앱이 읽거나 표시하기 어렵고 스마트 컨트랙트에 암호화 통신을 붙이려는 개발자도 매번 새로 설계해야 합니다. 이 표준은 사용자 등록과 메시지 전송 기능을 하나의 인터페이스로 통일해 컨트랙트에 암호화 통신을 쉽게 통합하게 하고 플랫폼 사이에서 메시지가 매끄럽게 오가는 상호운용성을 만드는 것을 목표로 합니다.

구현해야 하는 것

심층 설명

PublicKey 구조체와 알고리즘 열거형

공개키는 PublicKey 구조체로 표현합니다. public_key(키 값 바이트), valid_before(uint64 형식의 유효 기한), algorithm(사용 알고리즘) 세 필드로 구성됩니다. 알고리즘은 PublicKeyAlgorithm 열거형으로 지정하며 ECDSA, ED25519, X25519 세 가지를 정의합니다. 키는 bytes32 형식의 키 인덱스(_keyIndex)로 구분하므로 한 사용자가 여러 개의 키를 인덱스별로 관리할 수 있습니다. 이렇게 알고리즘 열거형과 사용자 정보 구조체를 표준에 포함해 다양한 암호화 알고리즘과 사용자 정보 관리를 지원하고 메시징 시스템의 유연성과 확장성을 높이는 것이 명세의 목표입니다.

updatePublicKey, 본인만 갱신하는 키 등록

updatePublicKey(bytes32 _keyIndex, PublicKey memory _publicKey)는 호출자(msg.sender)의 공개키를 지정한 인덱스에 저장하고 PublicKeyUpdated 이벤트를 발생시킵니다. 설계상 주소의 소유자만 자신의 공개키를 갱신할 수 있습니다. 이 제한이 종단간 암호화의 무결성을 지키는 핵심입니다. 다른 사람이 키를 바꿔치기할 수 없으므로, 등록된 공개키로 암호화한 메시지는 의도한 수신자만 복호화해 읽을 수 있습니다.

sendMessage와 세션 ID 기반 대화 구성

sendMessage(address _to, bytes32 _keyIndex, bytes32 _sessionId, bytes calldata _encryptedMessage)는 수신자 주소로 암호화된 메시지를 보냅니다. 메시지 내용은 전송 시 수신자의 공개키로 암호화해야 하며, _keyIndex는 암호화에 사용한 공개키의 인덱스를 가리킵니다. _sessionId는 통신의 세션 ID로, 임의로 정한 세션 ID를 사용해 여러 메시지를 하나의 대화로 묶을 수 있습니다. 이 기능은 분산 앱 안에서 토론을 정리하고 관리하는 데 핵심적이며 사용자에게 일관되고 구조화된 메시징 경험을 제공합니다.

이벤트를 통한 오프체인 연동

메시지가 전송되면 MessageSent 이벤트가, 공개키가 갱신되면 PublicKeyUpdated 이벤트가 발생합니다. MessageSent는 발신자(from), 수신자(to), 키 인덱스(keyIndex)를 인덱스된 파라미터로 담고 세션 ID와 암호화된 메시지 본문을 함께 기록합니다. 오프체인 분산 앱은 이 이벤트를 구독해 최신 메시지와 키 갱신을 쉽게 추적하고 표시할 수 있어 실시간 반응성과 사용자 상호작용이 좋아집니다. 이벤트 정의는 컨트랙트의 관찰 가능성과 감사 가능성을 높이려는 명세 목표이기도 합니다.

참조 구현의 저장 구조

참조 구현은 공개키를 mapping(address => mapping(bytes32 => PublicKey)) public pk로 저장합니다. 사용자 주소와 고유 키 인덱스의 2단 매핑이므로 주소마다 여러 키를 둘 수 있습니다. updatePublicKey는 pk[msg.sender][_keyIndex]에 새 키를 기록하고 getUserPublicKey는 해당 슬롯을 그대로 돌려줍니다. sendMessage는 메시지를 컨트랙트 상태에 저장하지 않고 MessageSent 이벤트만 발생시키는 방식으로 구현되어 있어 메시지 본문은 이벤트 로그로 남습니다.

쓸 때 주의할 점

ERC 원문 · ← ERCs