ECDSA의 한계
•
서명의 가변성 문제
◦
같은 메시지에 대한 서명값은 항상 두 개 (s, N-s)가 존재한다.
▪
N-s 는 모듈러 연산에서 -s와 같다. (N=11, s=3 인 경우 8과 11-3은 같다)
▪
따라서 우리가 알던 서명 검증식은
▪
이렇게 바뀐다.
▪
하지만 우리는 R의 x좌표만 서명으로 사용하기 때문에 R과 -R을 구분할 수 없다.
◦
개인키를 잘 모른다 하더라도 누구든 유효한 서명값을 만들어낼 수 있다.
•
서명의 가변길이 문제
◦
ECDSA의 서명 길이는 r, s 작은 수가 나오는 경우 패딩(0 채우기)를 강제하지 않는다.
30 06 ; SEQUENCE, length = 6
02 01 01 ; r = 1 (1 byte)
02 01 01 ; s = 1 (1 byte)
Python
복사
◦
따라서 r, s의 길이를 표현하는 것이 필요하다.
◦
서명이 없는 상태에서 수수료율 예측이 어렵다.
•
다중서명의 프라이버시 문제
◦
ECDSA를 사용하면 다중서명 주소라는 것 자체가 노출된다.
◦
P2WPKH 는 20바이트이고, P2WSH는 32바이트이다.
•
k (임시개인키)의 취약함 (BIP-340 적용)
◦
k에 어떤 수나 사용할 수 있게 됨으로써, 어떤 수를 선택하느냐에 따라 안전하지 않을 수 있다.
•
비선형구조의 한계
◦
선형구조면 f(d₁) + f(d₂) = f(d₁ + d₂)를 만족해야 한다.
◦
ECDSA의 서명
◦
두 서명의 합은 부분들의 합으로 표현이 어렵다.
▪
에서
▪
일단 가 성립하지 않음
◦
따라서 두 개 이상의 서명을 묶어서 처리할 수 없다. (예: 다중서명)
슈노르 서명의 해결책
•
서명의 가변성 문제
◦
슈노르 서명의 검증 식은 다음과 같다.
◦
여기서 s를 N-s 로 바꾸면 검증에 실패한다.
◦
r의 y좌표를 항상 짝수로 유지한다. (만약 홀수가 추출되면 k를 N-k로 바꾼다)
•
서명의 가변 길이 문제
◦
서명의 길이를 r, s 각각 32바이트로 고정한다.
◦
만약 길이가 짧은 경우 패딩(0을 채움)을 한다.
r (Rₓ):
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 01 (32 bytes)
Python
복사
◦
별도의 길이 표현이 필요하지 않다.
•
다중서명 프라이버시의 문제
◦
탭루트의 주소는 변형 공개키를 활용하며 다중 서명은 여러 공개키를 선형으로 조합하여 사용하므로 단일 서명과 길이가 같다.
탭루트는 공개키의 해시가 아닌 공개키를 그대로 쓴다.
→ 그럼 p2pkh에서 공개키를 UTXO에서 감추는 노력이 무의미해질까?
•
무의미해졌다. 그러나 커뮤니티는 이렇게 판단했다.
•
공개키 해시를 통해 UTXO 단계에서 공개키를 은닉하는 전략은, Taproot 도입 시점의 위협모델 재평가 결과 보안상 결정적 이점을 제공하지 않는 것으로 판단되었다.
•
P2PKH 설계 당시에는 공개키 장기 노출에 대한 암호학적 불확실성이 컸으나, 장기간의 실전 운영 결과 공개키 노출 자체가 현실적인 공격 벡터로 작동하지 않음이 확인되었다.
•
공개키 노출이라는 잠재적·이론적 위험보다, 실제로 반복 관측된 서명 가변성, 스크립트 및 멀티시그 프라이버시 누수, 합의 복잡성(다중서명, 스크립트 공개, 파싱의 복잡성 등) 문제를 더 시급한 위협으로 평가했다.
•
최악의 가정을 지연시키는 방어보다는, 당장 시스템의 안정성과 프라이버시를 저해하는 명확한 공격 표면을 제거하는 데 초점을 맞춘 설계적 전환의 결과다.
•
k (임시개인키)의 취약함
◦
ECDSA는 k값을 임의로 정할 수 있었지만, 슈노르에서는 해시를 필수로 사용해야 한다.
◦
256비트의 난수를 통해 k를 추출하여 낮은 k가 발생할 확률이 희박하다.
항목 | ECDSA (RFC6979) | Schnorr (BIP340) |
k 생성 | 결정론적 (HMAC) | 결정론적 (tagged hash) |
aux 난수 | 없음 | 있음 (권장) |
parity 보정 | 없음 | 있음 (짝수만 사용) |
공개키 입력 | 없음 | 포함 (P_x) |
구조적 안전성 | 보통 | 더 강함 |
•
비선형구조의 한계
◦
슈노르 서명의 가장 큰 특징은 여러개의 서명을 효율적으로 검증할 수 있다는 점이다.
◦
ECDSA는 모든 서명을 각각 검증하여야 한다.
◦
슈노르 서명은 서명값을 모두 더하는 방식으로 한 번에 검증할 수 있다.
슈노르 서명 메커니즘
•
기호
◦
곡선: secp256k1
◦
생성자: G
◦
곡선 차수: n
◦
개인키: d ∈ [1, n−1]
◦
공개키: P = d·G (짝수만, 홀수인 경우 d=n-d)
◦
메시지: m (보통 32바이트 sighash)
•
서명 준비
◦
nonce k 생성 (hash 사용)
◦
R = kG (짝수만, 홀수인 경우 k=n-k)
▪
t=d⊕taggedHash(”BIP0340/aux”, aux)
▪
k=taggedHash(”BIP0340/nonce”, t || P_x || m)
taggedHash란?
•
H_tag(m) = SHA256( SHA256(tag) || SHA256(tag) || m )
•
해시의 용도를 명확히 분리(domain separation)하기 위해 정의된 해시 방식
◦
challenge e 생성 (메시지를 해시로 변형)
▪
e=taggedHash(”BIP0340/challenge” || R_x || P_x || m)
•
서명 구하기
•
서명 검증
•
ECDSA 와 비교
구분 | ECDSA | Schnorr |
서명 공식 | s = k⁻¹(z + r·d) | s = k + e·d |
역원 | 필요 | 없음 |
선형성 | 없음 | 있음 |
집계 가능 | 불가 | 가능 |
서명 길이 | 가변 | 고정 64B |
•
다중서명(MuSig) 절차
1.
공개키 집계 (계수 계산 후 키를 집계함)
2.
각자 nonce k 생성 후
•
MuSig (BIP-340 미적용)
◦
각자 랜덤 k 생성 후 R을 구한다.
◦
R을 taggedHash하여 각 commit 을 구한다.
◦
commit 을 먼저 전송한 뒤에 R을 구한다. (나는 이 k를 쓸거고, 나중에 바꾸지 않겠다.)
◦
3번의 교환 (commit, R, s)이 필요하다.
•
MuSig2 (BIP-340 적용)
◦
k의 방법을 미리 결정한다.
◦
commit을 교환할 필요가 없어서 2회 교환으로 충분하다.
3.
R 추출 후 집계
4.
공통 challenge 계산
5.
challenge를 통해 각자 서명 계산
6.
서명의 합 계산
7.
서명 제출

