담당자가 바뀌어도 같은 MPC 지갑을 유지할 수 있을까
기관의 지갑을 관리하던 담당자 한 명이 다른 부서로 이동한다. 새 담당자를 넣으려면 지갑도 새로 만들어야 할까? 고객에게 알려 준 입금 주소와 이미 보유한 자산까지 옮겨야 한다면, 인사 변경 하나가 자산 이전 작업으로 커진다.
MPC 지갑에서는 공동으로 사용하는 키를 유지하면서, 그 키를 사용하는 참여자들의 비밀 자료를 새로 나눌 수 있다. 이를 키 조각 재분배, resharing이라고 부른다. 같은 공개키를 유지하면서 서명에 참여할 사람과 그 사람이 보관할 자료를 바꾸는 것이 이번 글의 목표다.
세 명 중 두 명이 필요한 지갑에서 P3를 P4로 바꾸는 예제로 원리를 살펴보자. 비밀값을 한곳에 복원하지 않는 계산과, 새 조각을 실제 운영에 적용하는 절차를 나누어 보아야 한다.
1. 담당자를 바꿔도 토큰은 옮기지 않는다
주소 A에는 토큰 T 90개, 주소 B에는 T 10개가 있다. MPC 공동 서명을 설명한 1편에서 A가 B에게 10개를 보낸 뒤의 상태다. 이 글부터 읽는다면, A의 서명 권한을 P1·P2·P3 세 참여자가 나누어 갖고 그중 두 명이 협력해야 서명할 수 있다고 이해하면 된다. 이를 2-of-3이라고 쓴다. 필요한 최소 인원은 , 전체 인원은 이다.
이번에는 P1과 P2가 기존 자료를 사용할 수 있고, P3 대신 P4가 앞으로 참여하게 된다고 하자. P1·P2·P4 역시 세 명 중 두 명이 필요한 조건을 유지한다. P1 같은 참여자 이름과 A 같은 블록체인 주소는 다른 종류의 식별자다. 담당자가 바뀐다고 계정 주소의 이름이 바뀌는 것은 아니다.
| 항목 | 교체 전 | 교체 후 목표 |
|---|---|---|
| 참여자 | P1·P2·P3 | P1·P2·P4 |
| 최소 참여 | 2명 | 2명 |
| 지갑 주소 | A | A |
| T 잔액 | A90 / B10 | A90 / B10 |
T의 소수 자릿수는 0이고, 발행·소각·토큰 전송 수수료·동시 거래는 없다는 가정을 유지한다. 이번 작업은 새 토큰 전송을 제출하지 않는다. 재분배 자체는 온체인 잔액을 바꾸지 않으며, 이번 재분배로 발생한 온체인 거래 수수료도 없다. 통신과 연산에 드는 서비스 운영 비용과는 구별한다.
2. 기존 두 조각이 새 조각의 출발점이 된다
작은 수로 원리를 보자. 모든 계산은 17로 나눈 나머지, 즉 로 한다. 이는 실제 지갑의 키나 보안 강도를 재현하는 값이 아니다. 독자가 관계를 볼 수 있도록 비밀값도 공개하는 설명용 예제다.
기존 비밀값은 , 기존 분산 다항식은 다음과 같다.
여기서 는 참여자에게 부여한 계산 좌표다. 기존 P1·P2·P3의 좌표를 각각 1·2·3으로 두면, 세 조각은 , , 다. 각 참여자는 자기 조각만 보관하며, 비밀은 다항식의 상수항인 에 해당한다.
P1과 P2를 골랐을 때 원래 비밀과의 관계는 다음처럼 쓸 수 있다.
계수 2와 은 두 좌표에서 상수항을 구하는 보간 가중치다. 핵심은 이 식의 오른쪽을 한 서버로 가져와 실제로 합치지 않아도 된다는 데 있다. P1은 자기 조각에 2를 곱하고, P2는 자기 조각에 을 곱하면 된다.
각자는 자신이 맡을 값 또는 를 안다. 두 값의 합이 5라는 관계는 있지만, 그 합을 전달받아 보관하는 역할은 만들지 않는다. 대신 각자가 맡은 값을 새 참여자들에게 다시 나누는 것으로 이어 간다.
이 출발점에는 기존 키에 대한 권한이 필요하다. 이 예제에서 P1 한 명의 조각만 남았다면, P4가 새로 접속했다는 이유로 부족한 두 번째 조각이 생기지는 않는다. 재분배는 필요한 기존 자료를 가진 참여자들이 협력하는 방법이지, 잃어버린 모든 비밀을 주소에서 되찾는 방법이 아니다.
3. 자기 몫을 다시 나누고, 받는 쪽에서 합친다
P1은 16을 상수항으로 하는 새 일차식을 만들고, P2는 6을 상수항으로 하는 새 일차식을 만든다. 새 기울기는 각각 무작위로 뽑는다. 계산을 보여 주기 위해 이번에는 4와 3이 나왔다고 하자.
는 새 조각을 받을 참여자의 좌표다. 여기서는 새 집합 P1·P2·P4에 각각 1·2·4를 사용한다. 이 좌표와 사람 이름의 연결은 설명을 위한 선택이며, 제품 내부의 참여자 번호나 저장 순서와 같다는 뜻은 아니다.
P1은 새 참여자마다 를 계산해 그 참여자에게만 전달한다. P2도 를 전달한다. 같은 사람이 보내는 역할과 받는 역할을 겸할 수 있으므로, P1은 자신이 받을 을 로컬에서 계산하고 P2에게서 을 받는다. P4는 기존 조각이 없어도 두 사람에게서 자신을 위한 값을 받을 수 있다.
P4의 계산을 먼저 보자.
P4가 받은 것은 P1의 기존 조각 8과 P2의 기존 조각 11이 아니다. 자기 좌표에 맞추어 새로 나눈 두 값 15와 1이다. P4는 이 둘을 합쳐 자신의 새 조각 16을 얻는다. 여기서 프라임 기호가 붙은 는 재분배 뒤의 조각을 뜻한다.
같은 계산을 새 참여자 셋에게 적용하면 다음과 같다. 표의 모든 수는 17로 나눈 나머지다.
| 받는 참여자 | P1의 값 | P2의 값 | 새 조각 |
|---|---|---|---|
| P1 | 3 | 9 | 12 |
| P2 | 7 | 12 | 2 |
| P4 | 15 | 1 | 16 |
P4만 새 자료를 받는 것이 아니라 P1과 P2의 자료도 바뀐다. 기존 사람을 유지한다는 것과 그 사람이 기존 조각을 계속 쓴다는 것은 다른 일이다. 이 예제에서는 P1의 8이 12로, P2의 11이 2로 바뀌고 P4가 새 조각 16을 갖는다.
기존 조각을 다시 분산하고 수신자가 보간 가중치를 적용하는 재분배는 Desmedt·Jajodia의 연구에서 다룬다. 위 예제는 그 가중치를 보내기 전에 적용한 형태다. 가중치를 적용하는 위치를 옮겨도 선형 관계는 같지만, 이 간단한 계산만으로 악의적 참여자를 다루는 전체 프로토콜이 완성되는 것은 아니다.
4. 조각은 바뀌는데 공개키는 왜 같을까
새 참여자들이 받은 값은 두 일차식을 합친 다항식 위에 놓인다. 설명을 위해 그 전체 식을 라고 쓰면 다음과 같다.
기존 식은 , 새 식은 다. 기울기와 각 좌표의 값은 달라졌지만, 좌표 0의 값은 둘 다 5다. 이 전체 식도 설명을 위한 표현이지, 실제 서버가 두 다항식의 비밀 계수를 모으라는 지시가 아니다.
새로 들어온 P4를 포함한 P2·P4의 조각으로 관계를 확인해 보자. 좌표가 2와 4일 때 상수항을 구하는 가중치는 다시 2와 이다.
두 새 조각으로 같은 비밀값에 대응하는 계산이 가능하다. P1·P2나 P1·P4를 선택해도 같은 결과를 얻는다. 이 보간은 조각의 관계를 확인하려는 계산이며, 다음 거래에 서명할 때 개인키 5를 실제로 복원한다는 뜻은 아니다. 그때는 새 조각으로 임계값 서명 프로토콜을 수행한다.
실제 ECDSA에서 비밀 스칼라를 , 곡선 기준점을 라고 하면 공동 공개키는 다. 재분배가 같은 를 보존하면 공개키 도 그대로다. 같은 네트워크에서 같은 공개키로 EVM 주소를 계산하므로 A도 유지된다. 작은 수 17은 이 관계를 설명하기 위한 것이며 secp256k1의 실제 계산 범위는 훨씬 크다.
하지만 결과에 “같은 공개키”라는 문자열을 적었다고 계산이 검증되지는 않는다. 예를 들어 P1이 수신자마다 서로 다른 다항식에 해당하는 값을 보냈다면, 새 조각들이 하나의 유효한 분산 관계를 이루지 못할 수 있다. 상수항이 기존 키에 제대로 연결됐는지와, 수신자들이 받은 값이 약속한 다항식에 맞는지를 함께 다뤄야 한다. 검증 가능한 재분배 연구는 이 두 연결을 검사하는 문제를 설명한다.
공개키·주소 비교와 프로토콜의 증명 검증은 서로 보완하는 역할이다. 앞의 숫자 예제에서는 참여자들이 계산을 정직하게 따랐다고 가정했다. 실제 구현에는 인증된 참여자 연결, 값의 일관성을 확인하는 증명과 오류 처리가 필요하며, 블로그의 덧셈 표는 그 모든 보안 조건을 대신하지 않는다.
5. 조각 갱신과 새 참여자에게 주는 재분배
같은 참여자들의 조각만 새롭게 만드는 refresh도 있다. 전형적인 원리는 상수항이 0인 무작위 다항식을 기존 식에 더하는 것이다. 그 추가 다항식을 라고 하면 다음 관계를 만족한다.
여기서 는 비밀값 계산에 사용하는 소수다. 실제로는 여러 참여자가 만드는 무작위 기여를 합쳐 갱신할 수 있다. 기존 조각에 각 좌표의 추가분을 더하므로 조각은 달라지고 비밀은 유지된다. 주기적인 비밀 조각 갱신 연구가 다루는 기본 방향이다.
그런데 P4는 기존 조각 를 보관하고 있지 않다. 상수항 0인 추가분 만 보냈다고 P4에게 새 조각 전체가 생기지는 않는다. 새 참여자 집합을 만들려면 기존 키에 대한 충분한 권한을 가진 쪽에서 그 집합으로 유효한 자료를 이전하는 과정이 더 필요하다.
이번 예제는 기존 조각에 0의 조각을 더하라는 갱신식으로 끝내지 않고, P1·P2의 가중 조각을 P1·P2·P4에게 다시 나누는 과정을 보여 줬다. 두 방법 모두 비밀을 유지할 수 있지만, 필요한 입력과 전달 과정이 다르다. 또한 처음 새로운 비밀값을 정하는 분산 키 생성, DKG와도 다르다. 여기서는 기존 키를 유지하는 것이 제약 조건이다.
6. BXB는 이전 역할과 새 역할을 따로 실행한다
BXB에서 확인한 것은 복구가 필요한 키를 대상으로 하는 사용자 참여형 경로다.
이 경로는 기존 참여자가 가진 자료를 바탕으로 새 참여자 집합에 재분배하는 절차를 연결한다.
암호 계산 모듈은 tss-lib v3.0.0의 secp256k1 재분배 API를 사용한다.
앞의 일차식 예제가 라이브러리의 모든 연산과 라운드를 재현한 것은 아니며, 공개키를 보존하는 이유를 설명하는 모델이다.
복구에 참여할 기존 집합과 새 조각을 받을 집합은 서로 다르다. 이번 사례에서는 기존 P1·P2가 자료를 제공하고, 새 P1·P2·P4가 결과를 받는다. 구현도 기존 집합에만 속하는 역할, 새 집합에만 속하는 역할, 양쪽에 속하는 역할을 구분한다. P1과 P2처럼 겹치는 참여자는 기존 자료를 사용하는 계산과 새 자료를 받는 계산에 각각 참여한다. P4는 기존 자료 없이 새 자료를 받는 쪽에 참여한다. 기존 자료를 제공하는 두 명만 준비되면 전체 교체가 끝나는 것은 아니다. 확장 프로그램은 기존 집합에서 필요한 수의 참여자를 선택하고, 새 집합은 전원이 준비된 뒤 계산을 시작한다. 따라서 이 사례에서 P3는 빠질 수 있지만 새 집합의 P4까지 빠진 채 교체를 마칠 수는 없다.
암호 모듈은 기존 참여자 수가 기존 threshold + 1에 못 미치면 설정을 거절한다.
여기서 라이브러리의 threshold는 최소 인원보다 1 작은 값이다. 2-of-3은 threshold=1이므로 기존 두 명이 필요하다.
서비스의 사용자 참여형 복구 경로는 이번처럼 전체 인원과 최소 참여 조건을 유지하는 범위를 기준으로 한다.
라이브러리가 받는 매개변수가 더 넓다고 해서 제품의 임의 인원·정족수 변경까지 확인된 것은 아니다.
프로토콜이 끝나면 새 조각을 받은 참여자에게 저장 자료와 공동 공개키·주소가 결과로 나온다. 이 저장 자료는 표에 적은 정수 하나보다 크다. 이후 서명에 필요한 비밀 조각과 보조 자료, 참여자에 대응하는 정보가 들어 있다. 계속 남는 P1·P2도 새 결과를 보관해야 하므로, 예전 파일을 그대로 두고 명단에서 P3의 이름만 P4로 바꾸는 작업으로 대체할 수 없다.
코드에는 2-of-3과 3-of-5에서 재분배 전후 EVM 주소를 비교하고 새 자료로 서명 세션을 진행하는 테스트가 있다. 이는 주소 보존과 다음 서명으로의 연결을 검사하는 근거다. 다만 이 글의 P3→P4 사례를 실제 지갑으로 실행하거나 거래를 체인에 보내 얻은 결과는 아니다.
7. 새 조각에는 새 보관 기록이 따라야 한다
재분배 계산이 성공해도, 다음 서명에서 서로 다른 세대의 자료를 고르면 문제가 남는다. P1은 새 조각 12를 읽고 P2는 예전 조각 11을 읽는 상황을 생각해 보자. 둘은 서로 다른 다항식의 점이다. 이를 같은 세대의 두 조각인 것처럼 계산하면, 이 예제에서는 이 되어 목표인 5와 다르다.
그래서 키 조각의 버전은 단순한 화면 표시가 아니다. 어느 지갑의 어떤 참여자 집합으로 만든 자료를 지금 사용해야 하는지를 구분하는 운영 정보다. 새 조각 자체와 함께 참여자 목록, 자신의 위치, 공동 공개키·주소가 일관되게 연결돼야 한다. 같은 주소 A를 계속 쓴다는 이유로 어느 시기의 조각이나 섞어 쓸 수 있는 것은 아니다.
BXB의 확장 프로그램은 결과의 주소, 새 참여자 목록과 버전을 새 자료에 연결해 저장한다. 이 복구 저장 경로는 비밀번호로 자료를 암호화해 같은 지갑 식별자의 로컬 기록을 갱신한 다음 서버에 완료를 보고한다. 서버는 새 멤버 전원이 완료를 보고했을 때 새 버전을 활성화하고 이전 버전의 멤버를 운영상 사용할 수 없는 상태로 바꾼다. 이후 서명은 새 참여자 목록에 맞는 자료를 사용해야 한다.
완료 처리에는 전달된 공동 공개키를 기존 공개키와 비교하는 경로도 있다. 그러나 공개키를 비교하는 일과 서버가 모든 참여자의 비밀 조각을 받아 독립적으로 검증하는 일은 다르다. 서버의 상태 전환을 프로토콜 검증이나 각 장치의 보관 결과 확인을 대신하는 것으로 이해해서는 안 된다. 누가 새 자료를 받았는지, 어떤 버전으로 전환했는지, 새 참여자와 공동 계산이 가능한지를 확인하는 일까지 있어야 “담당자 교체가 끝났다”는 운영 판단에 도달할 수 있다.
개별 장치의 저장과 서버가 관리하는 진행 상태는 같은 순간에 끝난다고 가정할 수 없다. 새 참여자가 결과를 받기 전에 연결이 끊겼거나 보관에 실패했다면, 성공 메시지 하나로 전체 전환을 완료 처리해서는 안 된다. 각 참여자의 결과와 현재 보관 상태를 확인하고, 필요한 재시작이나 복구 절차를 정해야 한다. 이 설명은 모든 장치와 서버가 한 번에 갱신되는 원자적 저장을 약속하는 것이 아니다.
새 조각으로 서명할 수 있는지 확인하는 일도 토큰 전송과는 별개다. 프로토콜 테스트나 별도 검증용 메시지로 서명을 점검할 수 있지만, 그 결과가 실제 송금의 실행 영수증은 아니다. 이번 글의 범위에서는 새 거래를 제출하지 않으므로 A90/B10을 계속 유지한다.
8. 이전 조각이 남아 있다면 이전 권한도 살펴야 한다
P3를 새 참여자 명단에서 뺐으니, P3가 보관한 모든 비밀 자료가 자동으로 쓸모없어졌다고 생각하기 쉽다. 하지만 이 재분배는 비밀값 자체를 바꾸지 않았다. 예전 P1·P2의 조각 8과 11을 누군가 함께 보관하고 있다면, 예전 관계 은 여전히 성립한다.
과거 한 세대의 정족수만큼 자료가 남아 있으면, 새 버전 번호가 그것을 암호학적으로 무효화하지 않는다. 시스템이 예전 버전의 요청을 받지 않는 것과, 예전 비밀 자료로 키를 사용할 능력이 사라지는 것은 다른 문제다. 같은 공개키의 유효한 서명을 받는 체인은 기관 내부의 담당자 명단 변경만으로 서명을 구별하지 않는다.
그렇다고 P3 한 명의 예전 조각만으로 2-of-3 조건을 넘을 수 있다는 뜻은 아니다. 어떤 시기의 자료가 얼마나 남았는지, 과거 정족수의 자료가 한곳에 모이거나 공모에 사용될 수 있는지가 중요하다. 참여자 교체에는 기존 장치와 백업의 보관·폐기 정책, 계정 접근 권한 회수, 진행 중인 서명 세션 처리가 함께 따라야 한다. 갱신과 재분배의 보안 논의에서 이전 자료의 삭제 가정을 따로 두는 이유도 여기에 있다. Desmedt·Jajodia의 재분배 연구도 이전 자료의 삭제 조건을 별도로 다룬다.
주소를 유지하는 편의와 이미 노출된 키의 권한을 없애는 목표가 언제나 같은 방법으로 해결되지는 않는다. 기존 정족수의 비밀 자료가 외부에 남았다고 의심되는 상황을, 정상적인 담당자 교체와 같은 완료 기준으로 처리해서는 안 된다. 그때는 같은 키를 유지할 것인지부터 다시 판단해야 한다.
이번 정상 사례의 결과는 새 지갑에 자산을 옮긴 것이 아니다. P1·P2·P4가 새 자료로 같은 A의 서명 권한을 나누어 갖고, 토큰은 A90/B10으로 남는다. 이를 가능하게 하는 것은 이름표 교체가 아니라 기존 키와 연결된 재분배 계산이다. 그리고 그 계산을 운영으로 완성하는 것은 새 보관본의 일치, 다음 공동 서명의 준비, 이전 자료의 처리다. 새 참여자들이 실제로 다음 서명을 시작하려면 메시지를 같은 세션 안에서 주고받는 통신도 이어져야 한다.