Kyunghoon
Notes

Blockchain / Sep 27, 2026 / 17 min

Distributed Key Generation: 전체 Private Key를 한곳에 만들지 않는 방법

Distributed Key Generation이 전체 private key를 한곳에 만들지 않는 원리와 VSS·Complaint 흐름, production state와 restart recovery 문제를 정리한다.

DKGThreshold CryptographyDistributed SystemsBlockchainSRE

Cryptography에서 Durable State와 Restart Recovery까지

Private key 하나가 자산이나 validator 권한 전체를 제어한다면, 운영자는 결국 그 key를 어디에 둘지 결정해야 한다. Application memory에 둘 수도 있고, offline storage나 HSM에 보관할 수도 있다. 보관 장치를 강화하면 탈취 가능성은 낮아지지만, 완성된 key를 가진 지점이 집중된 trust boundary라는 사실은 남는다.

그렇다면 처음부터 전체 private key를 한곳에 만들지 않을 수는 없을까?

Distributed Key Generation(DKG)은 여러 participant가 하나의 protocol에 참여해 공동 public key와 각자의 secret share를 만드는 과정이다. 정상 protocol 경로에서는 완성된 private key를 한 participant의 memory에 materialize하지 않는다. 이후 participant들은 secret share로 partial signature를 만들고, threshold를 충족했을 때 하나의 결과를 조합할 수 있다.

Traditional Key Generation

        Private Key K
             │
             ▼
       Single Trust Boundary


Distributed Key Generation

  A ─┐
  B ─┼── DKG ──→ Public Key PK
  C ─┘
  │   │   │
 S_A S_B S_C

하지만 DKG가 신뢰 자체를 제거하는 것은 아니다. 공격자가 threshold 이상의 share weight를 장악하면 공동 signing authority도 장악할 수 있다.

반대로 정상 participant가 충분히 online 상태를 유지하지 못하면 threshold를 충족하지 못해 protocol이 진행되지 않는다. 즉 하나의 key custodian을 신뢰하던 구조가, 여러 participant의 보안과 가용성을 함께 가정하는 구조로 바뀐다.

그리고 production에서 DKG는 암호학만의 문제가 아니다. participant set, message delivery, timeout, terminal state, secret-share storage, restart recovery가 함께 맞아야 한다.

범위: 이하의 수식과 그림은 흐름을 설명하기 위해 participant의 weight가 모두 같고 participant당 하나의 share를 가진다고 단순화한다. 실제 protocol은 scheme과 구현에 따라 phase, complaint 처리, threshold 표현이 다르며, Sui randomness DKG는 validator voting weight를 반영한다.


1. 왜 key를 만든 뒤 나누는 것만으로는 부족한가

가장 단순한 signing service는 private key K를 불러와 message에 서명한다.

Application
    │
    ▼
Private Key K
    │
    ▼
Sign(message)
    │
    ▼
Signature

HSM이나 Secure Enclave는 key export를 어렵게 하고 사용 정책을 적용할 수 있다. 이는 중요한 방어 수단이다. 다만 완성된 K를 사용하는 하나의 component가 cryptographic authority의 중심이라는 구조는 바뀌지 않는다.

이를 피하기 위해 하나의 trusted dealer가 먼저 K를 생성한 다음 secret sharing으로 나눌 수도 있다.

Trusted Dealer

K 생성
  │
  ├── S_A
  ├── S_B
  └── S_C

이 방법에서는 share를 배포하기 전에 dealer가 전체 K를 알 수 있다. dealer의 memory, random number generator, 로그 또는 배포 과정이 손상되면 분산 보관의 장점도 약해진다.

DKG는 순서를 바꾼다. K를 먼저 만든 뒤 나누는 것이 아니라, 각 participant의 contribution을 합쳐 distributed key material을 만든다. 따라서 보안 가정이 지켜지는 동안 어느 한 participant도 혼자 전체 secret을 결정하거나 알 수 없다.


2. DKG는 무엇을 만드는가

Shamir Secret Sharing이란

Shamir Secret Sharing은 하나의 secret을 polynomial을 이용해 여러 share로 나누는 방법이다. Secret은 polynomial의 상수항(x = 0일 때의 값)에 두고, 각 participant에게 서로 다른 x에서 계산한 값을 share로 나눠준다.

가장 단순한 2-of-3 구성을 생각해보자. 세 participant 중 두 명의 share가 있어야 secret을 계산할 수 있는 구성이다.

f(x) = K + ax

K   = f(0)
S_A = f(1)
S_B = f(2)
S_C = f(3)

위 식은 직선을 나타낸다. 직선은 서로 다른 점 두 개가 있으면 결정할 수 있지만, 점 하나만으로는 어느 직선인지 결정할 수 없다. 따라서 participant 한 명은 자신의 share 하나만으로 K를 계산할 수 없지만, 두 participant의 share가 모이면 interpolation으로 f(0)을 구할 수 있다.

Shamir Secret Sharing에는 하나의 dealer가 secret과 polynomial을 만드는 구조가 남아 있다. DKG는 각 participant가 자신의 polynomial contribution을 만들고 이를 결합함으로써, 한 명의 trusted dealer가 전체 secret을 먼저 알게 되는 문제를 피한다.

하나의 logical key와 여러 secret share

A, B, C가 DKG에 참여한다고 하자. 각 participant는 자신의 secret polynomial을 만든다.

A: f_A(x)
B: f_B(x)
C: f_C(x)

세 contribution의 합을 하나의 polynomial로 생각할 수 있다.

F(x) = f_A(x) + f_B(x) + f_C(x)

개념적인 전체 secret은 F(x)의 상수항이다.

K = F(0)

각 participant는 서로 다른 지점의 값을 자신의 final secret share로 가진다.

S_A = F(1)
S_B = F(2)
S_C = F(3)

따라서 다음 관계가 중요하다.

S_A ≠ K
S_B ≠ K
S_C ≠ K

S_A, S_B, S_C는 private-key 파일을 물리적으로 잘라놓은 byte 조각이 아니다. 각각은 같은 polynomial에 연결된 수학적 share다. 한 participant의 share만 보고 K를 계산할 수는 없지만, 사용하는 secret-sharing scheme의 threshold 이상 share가 모이면 interpolation을 통해 secret을 reconstruct할 수 있다.

DKG의 목표는 K가 수학적으로 존재하지 않게 만드는 것이 아니다. 정상적인 생성과 사용 과정에서 전체 K를 한곳에 만들 필요를 없애는 것이다.

Public key는 어떻게 생기는가

각 participant가 만든 polynomial의 상수항은 그 participant가 DKG에 제공하는 secret contribution이다. A, B, C의 secret contribution을 각각 k_A, k_B, k_C라고 해보자.

여기서 k_A는 A의 polynomial 상수항이고, S_A는 모든 participant가 A에게 보낸 contribution을 합친 final secret share다. 둘은 서로 다른 값이다.

A의 secret contribution: k_A
B의 secret contribution: k_B
C의 secret contribution: k_C

세 secret contribution을 모두 더한 결과가 개념적인 공동 secret K가 된다.

K = k_A + k_B + k_C

하지만 participant들은 k_A, k_B, k_C를 서로에게 공개하지 않는다. 대신 각 secret contribution에 대응하는 공개값을 하나씩 계산한다.

k_A ──→ C_A
k_B ──→ C_B
k_C ──→ C_C

이처럼 secret contribution으로부터 만든 공개된 검증값을 commitment라고 한다. 공개된 값만 보고 원래 secret contribution을 되돌리는 것은 현실적으로 어렵지만, commitment끼리는 결합할 수 있다.

C_A
+ C_B
+ C_C
─────
  PK

Secret contribution의 합이 공동 secret K가 되는 것처럼, 각 secret contribution에 대응하는 commitment를 결합한 결과는 K에 대응하는 공동 public key PK가 된다. 따라서 어느 participant도 전체 K를 알거나 한곳에 만들지 않으면서, 누구나 사용할 수 있는 공동 public key PK는 계산할 수 있다.

Polynomial의 나머지 부분에 대응하는 commitment들은 각 receiver가 받은 share가 sender의 polynomial과 일치하는지 검증하는 데 사용된다. 이것이 다음 절에서 살펴볼 VSS의 역할이다.


3. Message에서 final share까지

DKG participant들은 secret polynomial 자체를 서로 보내지 않는다. 각 receiver를 위한 share와 그 share의 정합성을 확인할 public 정보가 필요하다. 이후 사용할 Sui case와 연결하기 위해, 이 절에서는 Mysten Labs의 fastcrypto DKG 구현을 구체적인 예로 사용한다.

구현의 첫 DKG Message는 개념적으로 다음 정보를 담는다.

Message
├── sender
├── VSS commitment / public polynomial
└── encrypted shares
    ├── receiver A용
    ├── receiver B용
    └── receiver C용

3.1 Contribution과 receiver별 share

A는 f_A(x)를 만든 뒤 각 receiver에 대응하는 값을 계산한다.

f_A(1) ──→ A용 share
f_A(2) ──→ B용 share
f_A(3) ──→ C용 share

Receiver별 share는 해당 receiver만 읽을 수 있도록 암호화되어 전달된다. B가 받는 것은 A의 polynomial 전체가 아니라 자신의 final share를 구성할 한 contribution이다. B는 다른 receiver에게 전달된 plaintext share를 알 필요가 없다.

3.2 VSS는 무엇을 검증하는가

암호화만으로는 sender가 올바른 값을 보냈다는 사실을 보장하지 못한다. 악의적이거나 고장 난 A가 B와 C에게 서로 모순되는 share를 보낼 수 있기 때문이다.

Verifiable Secret Sharing(VSS)은 이 문제를 다룬다. A는 secret polynomial을 숨긴 채 public commitment를 함께 보낸다. B는 자신의 share를 복호화한 뒤 다음을 확인한다.

내가 받은 share가 sender가 commitment한 polynomial과 일치하는가?

Encrypted share 수신
        ↓
Receiver가 자신의 share 복호화
        ↓
Public commitment와 검증
        ↓
    valid / invalid

즉 VSS는 secret을 공개하는 장치가 아니라, 숨겨진 secret으로부터 일관된 share가 생성됐는지 검증하는 장치다.

3.3 Confirmation과 complaint

Participant는 받은 Message들을 검증한 뒤 다음 phase의 Confirmation을 만든다. fastcrypto 구현에서 Confirmation은 sender와 complaint 정보를 포함한다. 유효한 complaint가 확인되면 accused participant의 contribution을 제외할 수 있고, 유효하지 않은 complaint를 낸 participant도 처리 대상이 될 수 있다. 정확한 제외 규칙과 종료 조건은 사용하는 DKG scheme 및 구현에 따라 달라진다.

Message 수집
    ↓
Share 복호화와 VSS 검증
    ↓
Confirmation / complaint 교환
    ↓
유효 contribution 집합 확정

예를 들어 A가 B에게 잘못된 share를 보냈다고 하자.

A가 B에게 잘못된 share 전송
        ↓
B가 A에 대한 complaint 제출
        ↓
다른 participant가 A의 Message와 commitment를 기준으로 complaint 검증
        ↓
complaint가 유효하면 A의 contribution 제외

Complaint는 단순한 application error log가 아니다. 악의적 contribution을 식별하고 모든 정상 participant가 같은 qualified set에 도달하기 위한 protocol message다.

3.4 Final secret share 계산

A의 final share는 한 sender에게 받은 값 하나가 아니다. 유효한 participant contribution을 모두 합친 결과다.

A 자신의 contribution
+ B가 A에게 보낸 contribution
+ C가 A에게 보낸 contribution
              │
              ▼
             S_A

B와 C도 같은 qualified contribution 집합을 사용해 S_B, S_C를 계산한다. 이 과정을 마치면 하나의 공동 PK와 서로 다른 secret share가 만들어진다.

                  PK
                  │
          ┌───────┼───────┐
          │       │       │
         S_A     S_B     S_C
          │       │       │
          A       B       C

4. DKG 이후의 정상 경로는 key reconstruction이 아니다

DKG는 transaction을 서명하거나 random value를 만드는 마지막 단계가 아니다. 이후 threshold operation이 사용할 key material을 준비하는 단계다.

Threshold Signature Scheme(TSS)는 여러 participant가 각자의 secret share를 사용해 하나의 signature를 공동 생성하는 방식이다. 정상적인 signing 과정에서는 전체 private key를 한곳에 reconstruct하지 않는다.

DKG와 TSS는 같은 protocol이 아니라 서로 다른 단계를 담당한다.

DKG
└── 공동 public key와 participant별 secret share 생성

TSS
└── 생성된 secret share를 사용해 signature 공동 생성

즉 DKG는 key material을 준비하는 setup 단계이고, TSS는 그 key material을 실제로 사용하는 operation 단계다.

정상적인 threshold signing 경로는 다음과 같다.

S_A ──→ partial signature σ_A
S_B ──→ partial signature σ_B
S_C ──→ partial signature σ_C
                  │
                  ▼
         Signature Combination
                  │
                  ▼
            Final Signature σ

이 경로에서는 K를 먼저 reconstruct한 다음 Sign(K)를 실행하지 않는다. 각 participant가 자신의 share로 partial signature를 만들고, 충분한 partial signature를 조합한다.

반면 secret reconstruction은 별도의 경로다.

Threshold 이상의 shares
          │
          ▼
Interpolation / Reconstruction
          │
          ▼
          K

Shamir 계열 share에서는 threshold 이상의 share가 모이면 K를 reconstruct할 수 있다. 다른 scheme에서도 threshold 이상을 장악한 집단은 적어도 signing authority를 행사할 수 있다. 따라서 다음 두 문장을 분리해야 한다.

  • 정상 operation: full key를 reconstruct하지 않고 threshold operation을 수행한다.
  • 보안 가정: 공격자가 threshold에 도달하면 scheme에 따라 secret reconstruction 또는 signing authority 장악이 가능하다.

Randomness beacon도 이 위에 올라가는 응용이다. 예를 들어 Sui는 epoch 시작 시 DKG로 key shares를 만들고, 해당 epoch의 randomness round에서 partial signature를 모아 randomness를 생성한다. DKG를 매 transaction마다 반복하는 구조가 아니다. 자세한 설계는 Sui의 native randomness 설명에서 확인할 수 있다.

Epoch Start
    ↓
DKG: key material 준비
    ↓
Round 0: partial signatures → R_0
Round 1: partial signatures → R_1
Round 2: partial signatures → R_2

여기서도 역할을 구분해야 한다. DKG는 randomness 자체가 아니라 randomness protocol이 사용할 distributed key material을 만든다.


5. Production DKG는 stateful distributed system이다

수식만 보면 DKG의 핵심은 polynomial, commitment, threshold처럼 보인다. 실제 system에서는 어떤 participant가 어느 protocol instance의 어느 phase에 있는지, 실패가 확정됐는지, restart 후 무엇을 복원해야 하는지가 함께 중요하다.

Cryptography
├── Secret sharing
├── VSS
├── Complaint verification
└── Threshold operation

Distributed System
├── Participant set and weight
├── Message delivery and ordering
├── Timeout
├── Durable terminal state
├── Secret-share storage
├── Restart recovery
├── Downstream queue
└── Reconfiguration

Participant set과 threshold

모든 participant는 같은 protocol instance, member identity, public key, weight, threshold, protocol version을 기준으로 계산해야 한다. 서로 다른 participant set을 사용하면 같은 PK와 qualified set에 도달한다는 전제가 깨진다.

Threshold도 단순한 node 수가 아닐 수 있다. Weighted protocol에서는 실제 조건이 3개 node 중 2개가 아니라 필요한 total weight 이상이다. 따라서 운영자는 살아 있는 process 수뿐 아니라 usable weight를 봐야 한다.

Timeout과 terminal state

일부 participant가 message를 보내지 않거나 valid weight가 부족하면 protocol은 영원히 기다릴 수 없다. 구현은 timeout이나 protocol-specific round 조건을 사용해 FAILED를 결정할 수 있다.

PENDING
  ├── SUCCESS
  └── FAILED

여기서 FAILED는 process가 예기치 않게 죽었다는 뜻과 다르다. protocol이 더 진행될 수 없다고 판단한 정상적인 terminal state일 수 있다. 따라서 success output만 저장하고 failure를 “output 없음”으로 표현하면 restart 후 PENDING과 FAILED를 구분할 수 없다.

Durable state와 restart

Durable state는 process memory의 상태와 같은 의미를 표현해야 한다.

Runtime: DKG = FAILED
Storage: terminal record 없음
             │
             ▼ restart
Recovery: PENDING인지 FAILED인지 판단 불가

이 원칙은 DKG에만 해당하지 않는다. state machine이 PENDING, SUCCESS, FAILED를 구분한다면 persistent model도 필요한 상태 공간을 표현해야 한다. 저장 시점과 downstream side effect의 순서도 함께 정의해야 한다.

Secret-share storage

DKG가 끝나면 각 participant의 secret share는 장기적인 private key material이 된다. 전체 key가 없다는 이유로 share의 보호 수준을 낮출 수는 없다. encryption at rest, access control, backup, rotation, memory exposure, deletion policy를 고려해야 하며, backup이 오히려 threshold 이상의 share를 한곳에 모으지 않는지도 확인해야 한다.

Downstream dependency와 reconfiguration

DKG의 결과를 기다리는 queue나 epoch transition이 있다면 실패 처리도 downstream까지 전파되어야 한다.

DKG SUCCESS ──→ downstream work execute
DKG FAILED  ──→ downstream work cancel / fallback

두 terminal state 중 어느 것도 복원하지 못하면 work는 execute도 cancel도 되지 않은 채 남을 수 있다. 그리고 reconfiguration이 그 queue의 drain을 기다린다면 local state 복원 문제가 system-wide liveness 문제로 커질 수 있다.

그렇다면 왜 모든 system이 DKG를 사용하지 않는가

DKG는 single key holder에 집중된 위험을 줄이는 대신 participant 사이의 network coordination을 필요로 한다. 초기 DKG와 participant 구성이 바뀔 때의 resharing에는 여러 차례 message를 교환해야 한다. Threshold signing에서도 충분한 participant weight가 online 상태여야 하므로 signing latency와 availability dependency가 늘어난다.

Participant 변경이나 share 손실이 발생하면 key rotation, backup, recovery 절차도 함께 설계해야 한다. 특히 잘못된 backup 정책은 분산된 share를 다시 한곳에 모아 threshold security를 약화할 수 있다. 따라서 보호할 authority의 가치와 threat model이 이러한 운영 복잡도를 정당화할 때 DKG를 선택하는 것이 적절하다.


6. Case Study: Sui 2026 Mainnet Halt

이제 일반적인 원리가 실제 장애에서 어떻게 연결됐는지 살펴보자. Sui의 공식 postmortem에 따르면 2026년 5월 28일부터 29일까지 세 차례 outage가 있었다. 앞선 두 장애는 gas 관련 bug였고, 여기서 다루는 세 번째 장애는 validator restart 이후 드러난 randomness DKG persistence 문제였다.

정상적으로는 failure도 queue를 끝내야 한다

Sui는 epoch마다 randomness를 위한 DKG를 수행한다. 정상적으로 완료되면 secret shares를 사용해 randomness round를 진행한다. 필요한 participation을 확보하지 못해 DKG가 실패하면 해당 epoch의 randomness를 disable하고, randomness를 기다리는 transaction을 cancel하는 경로로 가야 한다.

                  DKG
           ┌───────┴───────┐
           │               │
        SUCCESS          FAILED
           │               │
        Execute           Cancel
           └───────┬───────┘
                   ▼
               Queue Drain

즉 failure는 복구를 방해하는 예외가 아니라 queue를 terminal state로 이동시키는 데 필요한 정보다.

Runtime은 실패를 알았지만 storage는 표현하지 못했다

장애 당시 mainnet-v1.72.3의 per-epoch storage schema는 성공한 output을 저장하는 형태였다.

dkg_output: DBMap<u64, dkg_v1::Output<PkG, EncG>>

Row가 있으면 success output을 읽을 수 있지만, row가 없을 때는 두 의미가 겹친다.

아직 terminal outcome이 기록되지 않음
                vs
DKG가 FAILED로 끝남

Process가 살아 있는 동안 runtime은 failure verdict를 알고 있었다. 그러나 그 verdict가 durable하게 저장되지 않은 상태에서 validator들이 restart하자 FAILED를 복원할 수 없었다. 그 결과 paused randomness transaction은 실행할 수도, failure 경로로 cancel할 수도 없었다. Queue가 drain되지 않으면서 이를 기다리던 end-of-epoch transition도 진행되지 못했고, network liveness가 멈췄다.

DKG FAILED
    ↓
Failure verdict persistence 누락
    ↓
Validator restart
    ↓
FAILED 복원 불가
    ↓
Randomness queue: execute 불가 / cancel 불가
    ↓
Queue drain 대기
    ↓
Epoch reconfiguration 정지
    ↓
Network halt

Persistent model이 runtime state를 표현하도록 바뀌었다

현재 main branch의 schema는 stored value 자체가 success와 failure를 구분한다.

dkg_output_v2: DBMap<u64, Option<dkg_v1::Output<PkG, EncG>>>

Storage read error는 별도로 처리됐다고 가정하고 row lookup의 value만 보면, 중첩된 Option은 다음 세 상태를 표현한다.

get() == None
→ DB row가 없음
→ terminal outcome이 아직 기록되지 않음

get() == Some(Some(output))
→ SUCCESS

get() == Some(None)
→ FAILED

Source comment도 stored None이 DKG failure 완료를 뜻한다고 명시한다. 공식 postmortem에 따르면 수정은 DKG status를 restart 이후에도 복원할 수 있게 저장하고, stuck epoch을 coordinated하게 종료할 recovery mechanism을 추가하는 방향으로 이루어졌다.

이 장애의 핵심은 threshold cryptography가 깨졌다는 것이 아니다. Runtime state machine의 전체 상태 공간을 persistent model이 표현하지 못했고, 그 불일치가 restart, queue, reconfiguration 순서로 전파됐다는 것이다.

일반화할 수 있는 교훈: failure가 downstream의 진행 여부를 결정한다면 failure verdict도 success output과 같은 수준의 durable state여야 한다.


7. 운영 관점에서 무엇을 확인해야 하는가

Production DKG를 운영할 때는 “DKG가 성공했는가?” 하나만으로 부족하다. 현재 phase와 usable weight, terminal state의 persistence, downstream backlog를 함께 봐야 장애 전파 지점을 찾을 수 있다.

확인 영역물어야 할 질문이상 상태가 의미하는 것
Participant set모든 node가 같은 member, weight, threshold, version을 보는가?서로 다른 protocol instance 또는 qualified set을 계산할 수 있음
Participation현재 valid message·confirmation weight가 얼마인가?process 수가 충분해 보여도 threshold를 충족하지 못할 수 있음
Protocol phasePENDING, complaint 처리, terminal state 중 어디인가?단순한 지연과 종료된 failure를 구분해야 함
Durable stateSUCCESS와 FAILED가 모두 storage에 기록됐는가?restart 후 runtime 판단을 재현하지 못할 수 있음
Secret share올바른 epoch 또는 key version의 share가 load됐는가?이전 key material 사용 또는 operation 불가 가능성
Downstream work대기 queue의 depth와 oldest age가 증가하는가?DKG 상태가 execute/cancel 경로로 전달되지 않을 수 있음
Reconfiguration어느 barrier가 어떤 queue나 terminal state를 기다리는가?local stall이 global liveness로 전파되는 경로를 보여줌
Restart recoveryrestart 전후에 같은 logical state로 복원되는가?memory와 durable state model의 불일치 가능성

이 표는 필요한 observability의 의미를 설명한다. 실제 metric, log field, admin API의 이름과 제공 여부는 구현 및 version별로 확인해야 한다. 존재하지 않는 signal을 있다고 가정해서는 안 된다.

실험 제안

다음 항목은 이 글에서 직접 수행한 실험 결과가 아니라, 격리된 test environment에서 검증해볼 fault-injection 시나리오다.

  1. FAILED 결정 직전과 persistence 직후에 process를 각각 종료하고 restart한다.
    • 예상 결과: persistence 이후 restart에서는 동일한 terminal state가 복원되어야 한다.
  2. DKG success와 failure 양쪽에서 restart를 수행한다.
    • 예상 결과: success output뿐 아니라 failure verdict도 downstream component에 같은 의미로 전달되어야 한다.
  3. Old schema에서 new schema로 migration한 storage를 load한다.
    • 예상 결과: row 부재와 explicit failure가 혼동되지 않아야 한다.
  4. Online node 수는 많지만 usable weight가 threshold보다 낮은 상태를 만든다.
    • 예상 결과: 단순 node count가 아니라 weight 조건에 따라 protocol이 진행 또는 실패해야 한다.
  5. DKG failure 이후 downstream queue가 drain되는지 관찰한다.
    • 예상 결과: 대기 work가 정의된 cancel 또는 fallback terminal state로 이동하고 reconfiguration barrier를 영구히 막지 않아야 한다.

실제 관측 결과를 기록할 때는 예상 결과와 분리하고, 실행한 version, configuration, fault timing을 함께 남겨야 한다.


8. DKG Use Cases

Sui randomness는 DKG의 한 사례일 뿐이다. DKG가 직접 제공하는 것은 특정 business operation이 아니라, 여러 participant에 분산된 key material이다.

Use caseDKG가 직접 제공하는 것이후 별도 protocol이 하는 일
Randomness Beaconrandomness protocol용 distributed key sharesround별 partial output을 조합해 randomness 생성
Distributed Validatorvalidator threshold signing sharesvalidator duty에 대한 공동 signature 생성
DKG-based Threshold Custodysigning authority의 초기 distributed key materialpolicy, approval, recovery를 거쳐 transaction 서명
Cross-chain Signing외부 chain용 signing shares외부 chain transaction의 threshold signature 생성
Agentic Paymentagent와 policy signer 사이의 분산 signing 기반authorization, budget, idempotency, settlement 처리

Obol Charon의 DKG는 Ethereum validator key shares를 여러 operator가 생성하는 사례다. Threshold Network의 tBTC wallet signing은 signer group이 외부 Bitcoin wallet의 signing authority를 공동으로 행사하는 구조를 보여준다. ICP chain-key cryptography는 threshold BLS와 threshold ECDSA·Schnorr를 이용해 subnet이 full private key를 정상 경로에서 reconstruct하지 않고 signature를 만드는 사례다.

Potential Architecture: Agentic Payment

AI agent에게 blockchain 결제 권한을 줄 때 runtime에 전체 private key를 넣는 설계는 agent compromise와 wallet compromise를 같은 failure domain에 둔다. DKG와 TSS를 적용하면 agent와 별도 policy signer가 share를 보유하고, 정책을 통과한 payment intent에 대해서만 함께 서명하는 구조를 고려할 수 있다.

여기서 DKG와 TSS가 agent 자체의 판단을 신뢰할 수 있게 만드는 것은 아니다. 만약 threshold signer들이 agent가 생성한 모든 요청에 자동으로 참여한다면, authorization 관점에서는 agent가 단일 signing key를 가진 것과 큰 차이가 없다. DKG/TSS가 주로 줄이는 위험은 key exfiltration과 single signer compromise다.

Agent의 잘못된 판단이나 prompt injection으로 발생한 결제를 제한하려면 threshold signer 중 적어도 하나가 agent와 독립적인 policy를 적용하거나, smart account의 spending limit, allowlist, session capability 같은 별도의 authorization mechanism이 필요하다.

DKG / TSS
→ Who controls the signing key?

Policy / Capability
→ What may the agent sign?

Settlement
→ Did the payment actually complete?
Agent Runtime
    │
    ▼
Payment Intent
    │
    ▼
Policy Check ──→ reject
    │ approve
    ▼
Threshold Signing
    │
    ▼
Transaction Submission

여기서 DKG가 해결하는 범위는 distributed signing key의 초기 생성이다. Recipient allowlist, amount limit, duplicate payment 방지, transaction submission, settlement 확인, recovery는 별도의 system 설계가 필요하다.

이 구조는 제안 가능한 architecture이지, 이 글에서 배포하거나 runtime으로 검증한 구현 사례가 아니다. Agentic Payment에 적용하려면 사용하는 chain의 signature scheme, signer 가용성, recovery 정책, policy bypass 가능성을 별도로 검증해야 한다.


9. DKG Flow Overview

DKG를 이해할 때는 세 층을 분리한 뒤 다시 연결하면 좋다.

1. Key Establishment

Participant contributions
        ↓
Message / VSS / Complaint
        ↓
Secret Shares + Public Key


2. Threshold Operation

Secret Shares
        ↓
Partial Operations
        ↓
Signature / Randomness / Decryption


3. Production Lifecycle

Participant set + Network + Timeout
        ↓
Durable terminal state
        ↓
Restart recovery
        ↓
Queue / Reconfiguration

첫 번째 층의 cryptography가 안전해도 두 번째 층의 threshold 가정이 깨지면 authority가 장악될 수 있다. 두 층이 모두 올바르더라도 세 번째 층에서 failure state를 잃으면 liveness가 멈출 수 있다.

핵심은 다음과 같다.

  • DKG는 private key 파일을 만든 뒤 byte 조각으로 나누는 과정이 아니다.
  • 각 participant의 contribution으로 하나의 logical key와 여러 secret share를 만든다.
  • VSS와 complaint는 secret을 공개하지 않으면서 contribution의 정합성을 검증한다.
  • 정상 threshold operation은 full key reconstruction과 다른 경로다.
  • DKG는 trust를 없애지 않고 보안·가용성 가정을 threshold와 participant set으로 이동시킨다.
  • Production에서는 FAILED도 success output만큼 중요한 durable state다.
  • DKG subsystem의 local failure는 queue와 reconfiguration을 통해 전체 service의 liveness 문제로 전파될 수 있다.

이해 확인 질문

  1. Trusted dealer가 key를 생성한 뒤 share로 나누는 방식과 DKG의 핵심 차이는 무엇인가?
  2. VSS commitment는 secret polynomial을 공개하지 않으면서 무엇을 검증하게 해주는가?
  3. 정상적인 threshold signing과 full private key reconstruction은 어떤 점에서 다른가?
  4. DKG의 FAILED 상태를 durable storage에 남기지 않으면 restart 후 어떤 모호성이 생기는가?
  5. Sui 사례에서 local DKG state 복원 문제가 어떤 순서로 network liveness 문제까지 전파됐는가?

References