Threshold Signature Scheme

#cryptography #blockchain #mpc #tss #math

Original presentation by Jinwoo Lee on Nov 7, 2024

1. Elliptic Curve over Finite Field

Elliptic Curve

y2=x3+ax+by^2 = x^3 + ax + b

1.1. secp256k1 Elliptic Curve

y2(modp)=x3+7(modp)y^2 \pmod p = x^3 + 7 \pmod p

Finite Field (유한체)

유한체 위에 있으므로 유한체를 정의하기 위한 prime number pp가 필요합니다.

p=225623229282726241p = 2^{256}-2^{32}-2^9-2^8-2^7-2^6-2^4-1 0,1,2,...,p10, 1, 2, ..., p - 1

1.2. Cyclic Group (순환군)

정의

Group (군)의 성질:

  1. 닫혀있음 (Closure): 연산 결과가 항상 군 안에 존재.
  2. 결합 법칙 (Associativity): (a+b)+c=a+(b+c)(a+b)+c = a+(b+c).
  3. 항등원 (Identity): a+0=aa+0 = a.
  4. 역원 (Invertibility): a+(a)=0a+(-a) = 0.

Order (위수)

하나의 Base Point로 시작해서 + 연산을 계속하다 보면 다시 처음의 Base Point로 돌아오게 됩니다. 이때 처음으로 돌아오는 연산 횟수 nn을 순환군의 Order(위수)라고 부릅니다.

왜 순환군인가? 유한체에 대한 타원곡선 위의 임의의 점을 Base Point GG로 잡고 연산을 정의하면 순환군을 이룹니다. 이때 순환군의 위수 nnpp와 다를 수 있습니다.

타원곡선 연산 시 주의할 점

1.3. 무한원점 & 타원곡선 덧셈 연산

Elliptic Curve Addition

Base Point GG \rightarrow 타원곡선 위의 점 (xg,yg)(x_g, y_g)에 대해 Private Key xx만큼 덧셈 연산을 하여 Public Key를 얻을 수 있습니다.

P=xGP = xG

Base Point에 대해 xx만큼 덧셈을 하는 것은 쉽지만, P,GP, G로부터 xx를 알아내는 것은 수학적으로 매우 어렵다고 알려져 있습니다 (Discrete Logarithm Problem).


2. Digital Signature using Elliptic Curves

2.1. Create Signature

Given Key Pair: PP (Public), xx (Secret) where 1<x<n1 < x < n.

  1. Random Nonce kk 생성: 1<k<n1 < k < n

  2. Point RR 계산: R=kG,r=RxR = kG, \quad r = R_x

  3. Signature (r,s)(r, s) 생성: s=k1(m+rx)(modn)s = k^{-1}(m + rx) \pmod n (mm: message hash, k1k^{-1}: inverse of kk)

2.2. Verify Signature

ss에 대한 수식을 변형하여 검증합니다.

k=s1(m+rx)k = s^{-1}(m + rx)

양변에 GG를 곱하고 R=kG,P=xGR=kG, P=xG를 대입합니다:

R=s1mG+s1rPR = s^{-1}mG + s^{-1}rP
  1. 좌변 RR은 서명 (r,s)(r,s)rr로부터 얻을 수 있습니다.
  2. 우변은 m,s,r,P,Gm, s, r, P, G를 대입하여 계산합니다.
  3. 좌우변의 xx좌표가 같음을 보이면 검증 완료입니다.

Note: secp256k1recovery 메서드를 지원하여, 서명과 메시지만으로 Public Key를 복구할 수 있습니다. 이를 위해 서명에 v 값을 포함합니다.


3. TSS (Threshold Signature Scheme)

3.1. Schnorr Signature

Create & Verify

  1. 난수 kkRR 값 계산: R=kGR = kG
  2. Challenge cc 계산: c=H(RM)c = H(R \parallel M)
  3. 서명 ss 계산: sschnorr=(k+cx)(modn)s_{schnorr} = (k + cx) \pmod n

서명 결과: (R,s)(R, s)

Verification

sG=(k+cx)G=R+cPsG = (k + cx)G = R + cP

좌변(sGsG)과 우변(R+cPR + cP)이 같음을 확인합니다.

Advantage

3.2. Cryptographic Architecture of TSS

과정을 3단계로 나누어 살펴봅시다.

1) Sharing Secret and Nonce

  1. Secret Key Sharing: MPC 참여자가 비밀키 xx를 SSS로 나눠가집니다.

    x=ixiλi,Pi=xiGx = \sum_i x_i \lambda_i, \quad P_i = x_iG
  2. Nonce Sharing: Nonce kk는 나누는 것이 아니라, 각자 난수 kik_i를 생성한 후 합치는 방식입니다.

    k=ikiλik = \sum_i k_i \lambda_i

2) Create Partial Signature (ri,sir_i, s_i)

각 참여자는 자신의 파편으로 부분 서명을 생성합니다.

Ri=kiGR_i = k_iG si=ki+cxi(modn)s_i = k_i + c x_i \pmod n

3) Aggregate Partial Signatures

부분 서명들을 합쳐(Interpolation) 하나의 서명을 만듭니다.

s=isiλi=k+cxs = \sum_i s_i \lambda_i = k + cx

4) Verify Complete Signature

sG=(R+cP)sG = (R + cP)

외부에서는 이것이 단일 서명인지, MPC 서명인지 구분할 수 없습니다.


4. Code Example

mpc-cmp Schnorr ZK Proof implementation (pseudo-C code):

#include "crypto/zero_knowledge_proof/schnorr.h"

// 슈노르 ZK Proof 생성
static zero_knowledge_proof_status schnorr_zkp_generate_impl(...)
{
    // 1. R = kG
    status = algebra->generator_mul(algebra, &proof->R, &k);

    // 2. Challenge c = H(prover_id || R || public_data)
    SHA256_Init(&sha_ctx);
    SHA256_Update(&sha_ctx, prover_id, id_len);
    SHA256_Update(&sha_ctx, proof->R, sizeof(proof->R));
    SHA256_Update(&sha_ctx, *public_data, sizeof(elliptic_curve256_point_t));
    SHA256_Final(c, &sha_ctx);

    // 3. s = k - c * x
    status = algebra->mul_scalars(algebra, &c, secret, secret_size, c, sizeof(c));
    status = algebra->sub_scalars(algebra, &proof->s, k, sizeof(k), c, sizeof(c));

    return ZKP_SUCCESS;
}