Skip to content

chemonoworld/schnorr-proof

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔐 Schnorr Proof

Zero-Knowledge Schnorr Proof 구현체 — Rust로 작성된 가장 간단한 형태의 타원곡선 기반 영지식 증명

*** 학습 및 세미나 공유 목적이니 절대 프로덕션에 사용하지 마세요.

Rust License secp256k1


📖 개요

Schnorr Proof는 비밀 키를 공개하지 않고도 해당 키를 알고 있음을 증명할 수 있는 영지식 증명(Zero-Knowledge Proof) 입니다.

이 프로젝트는 암호학적 기초 원리를 직접 구현하여 학습하고, 실제 Bitcoin/Ethereum에서 사용되는 서명 알고리즘의 동작 원리를 이해하기 위해 개발되었습니다. (PDAO 세미나 공유 용도)


🧮 수학적 배경

Schnorr 서명 스키마

Setup:
  G = Generator Point (타원곡선 상의 기준점)
  x = Private Key (비밀 키)
  P = x·G (Public Key, 공개 키)

Signature Generation:
  1. k ← random()                    # 랜덤 nonce 생성
  2. R = k·G                         # Commitment
  3. e = H(m)                        # Challenge (메시지 해시)
  4. s = k + e·x                     # Response
  
  σ = (R, s)                         # 서명

Verification:
  s·G ?= R + e·P                     # 검증 방정식

⚠️ Note: 이 구현에서는 학습 목적으로 단순화된 e = H(m) 방식을 사용합니다.
실제 BIP-340에서는 e = H(R || P || m) 형태의 Fiat-Shamir 변환을 사용합니다.

왜 이것이 영지식인가?

  • Completeness: 정직한 증명자는 항상 검증을 통과
  • Soundness: 비밀 키 없이는 유효한 증명 생성 불가능
  • Zero-Knowledge: 검증 과정에서 비밀 키 x에 대한 정보가 노출되지 않음

🏗️ 아키텍처

schnorr_proof/
├── src/
│   ├── lib.rs        # 라이브러리 진입점 및 테스트
│   ├── zkp.rs        # Schnorr 증명 핵심 구현
│   └── compat.rs     # 타원곡선 추상화 레이어
└── Cargo.toml

핵심 컴포넌트

모듈 설명
ECCurve 다양한 타원곡선을 지원하기 위한 추상화 트레이트
SchnorrProof<C> 제네릭 Schnorr 증명 구조체
k256_impl secp256k1 곡선 구현체

💻 사용 예시

Non-Interactive Schnorr Proof

use schnorr_proof::{SchnorrProof, ECCurve};
use k256::{Scalar, Secp256k1, ProjectivePoint};

// 1. 키 쌍 생성
let private_key = Scalar::generate_biased(&mut rand::thread_rng());
let public_key = (ProjectivePoint::GENERATOR * private_key).to_affine();

// 2. 챌린지 생성 (메시지 해시)
let message = b"Hello, PDAO!";
let challenge = scalar_hash(message);

// 3. 서명 생성
let proof = SchnorrProof::<Secp256k1>::create_signature(
    private_key,
    challenge,
    &mut rand::thread_rng(),
);

// 4. 검증
assert!(proof.verify(public_key, challenge));

BIP-340 호환 Schnorr 서명

use k256::schnorr::{SigningKey, VerifyingKey};

// BIP-340은 짝수 y 좌표를 요구
let affine = public_key.to_affine();
if affine.y_is_odd().into() {
    private_key = -private_key;  // y 좌표 정규화
}

let signing_key = SigningKey::from(SecretKey::from_bytes(&private_key.to_bytes())?);
let signature = signing_key.sign_raw(message, &aux_rand)?;

// 검증
let verifying_key = VerifyingKey::try_from(public_key)?;
verifying_key.verify_raw(message, &signature)?;

🔬 구현 상세

제네릭 타원곡선 지원

pub trait ECCurve: PrimeCurve + CurveArithmetic {
    const NAME: &'static [u8];
    const BITS: usize;
    
    fn generator() -> Self::ProjectivePoint;
    fn sample_scalar_constant_time<R: CryptoRngCore>(r: &mut R) -> Self::Scalar;
}

이 추상화를 통해 secp256k1 외에도 다른 곡선(secp256r1 등)으로 쉽게 확장 가능합니다.

상수 시간 연산

fn sample_scalar_constant_time<R: CryptoRngCore>(r: &mut R) -> Self::Scalar {
    let mut data = [0u8; 64];
    r.fill_bytes(&mut data);
    <Self::Scalar as Reduce<U512>>::reduce_bytes(&data.into())
}

사이드 채널 공격 방지를 위해 상수 시간(constant-time) 연산을 사용합니다.


🛠️ 기술 스택

  • Language: Rust 2021 Edition
  • Elliptic Curve: elliptic-curve 0.13.8
  • secp256k1: k256 0.13.4
  • Hashing: SHA-256 (sha2)
  • Serialization: Serde

🧪 테스트 실행

# 모든 테스트 실행
cargo test

# 특정 테스트 실행 (상세 출력)
cargo test test_schnorr_signature -- --nocapture

📚 참고 자료


📝 License

MIT License © 2024

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages