컨텐츠 바로가기

10.05 (토)

세상에서 가장 쉬운 영지식증명 라이브러리, 조크라테스

댓글 첫 댓글을 작성해보세요
주소복사가 완료되었습니다
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


조크라테스는 영지식증명을 이더리움에서 사용하기 쉽도록 구현한 라이브러리다. 영지식증명이란 증명자가 민감한 데이터를 직접 드러내지 않고도 해당 내용이 유효함을 증명하는 기술이다. 영지식증명은 검증에 필요한 데이터를 최소한만 요구해 최소지식증명이라고도 불린다. 조크라테스는 특히 영지식증명에 입문하는 개발자에게 좋은 가이드로 평가받고 있는데 사용시 영지식증명의 작동 방식을 코드를 통해 알 수 있기 때문이다.

이번 사용기는 맥OS 하이 시에라를 기준으로 조크라테스 공식 튜토리얼을 참고해 작성했다. 디펜던시 파일 에러를 막기 위해 도커를 통해 조크라테스를 설치했다. 튜토리얼을 진행하려면 컴퓨터에 도커를 먼저 설치해야 한다.


튜토리얼 60초 요약

튜토리얼에 사용한 코드는 해시값을 출력하는 함수다. 함수에 a라는 값을 넣으면 b라는 해시값이 출력된다. 증명자는 a라는 값이 b라는 문제의 답임을 자신이 증명하고 싶다. 
조크라테스에서는 해당 해시 함수를 R1CS와 같은 특수한 산술 회로로 컴파일한다. 이때 다항식의 단일 사칙연산을 기준으로 수학적으로 코드를 쪼개 한줄씩 나눈다. 예를 들어 y=x^3라는 함수는 in=x*x, y=in*x, ~out=y+1로 나뉘며 각각을 게이트라고 부른다. 실제로 해시 함수의 경우 과정상 무수히 많은 게이트로 쪼개질 수 있다.
이렇게 생성된 산술 회로에 증명자가 실제 답(a)을 입력하고 영지식 증명(프루프)을 생성한다. 프루프에는 암호화된 변수값이 몇 개 들어간다. 증명자는 프루프에 담긴 암호화된 값들을 검증자에게 건네 공개한다. 이는 0x2f24c17e6570124badc8처럼 본래의 a값을 추측하기 매우 힘든 암호화 된 값이다. 검증자는 이값을 토대로 검산을 수행한다. 검산에 오류가 없다면 증명자의 주장은 참이다.

이 과정에서 문제의 답인 원본 a값은 공개될 일이 전혀 없다. 검증 자체도 여러 단계가 필요없다. 이더리움의 스마트 컨트랙트에서 단번에 이뤄진다.

1. 영지식증명을 생성하기 위한 준비작업

준비 단계에서는 조크라테스를 설치하고 예시 코드를 토대로 입력값과 결과값인 키밸류 쌍을 도출해본다. 

먼저 조크라테스를 설치할 디렉토리를 생성한다. 도커를 통해 조크라테스를 설치한다. $docker run -v $PWD:/home/zokrates/code -ti zokrates/zokrates /bin/bash 를 입력해 도커 이미지를 다운로드하고 컨테이너를 현재 작업 폴더에서 실행한다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


현재 작업폴더에 해시를 만들어주는 코드를 간단하게 붙여넣는다. 코드는 다음과 같다. hashexample.code라는 이름으로 저장한다.

import "hashes/sha256/512bitPacked.code" as sha256packed

def main(private field a, private field b, private field c, private field d) -> (field[2]):

    h = sha256packed([a, b, c, d])

    return h
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


그리고 난 후 코드를 컴파일한다. $./zokrates compile -i code/hashexample.code

컴파일하면 다음과 같은 산술 코드를 얻는다. 이는 R1CS 회로로 변환된 코드다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


이렇게 컴파일 된 값은 out.code라는 파일로 저장된다. 파일은 7MB로 본래의 코드보다 훨씬 큰 용량을 차지한다.

위트니스 파일을 만든다. 위트니스는 컴파일된 out.code에 입력 변수를 넣어 얻는 값으로 문제 코드의 결과값에 해당한다. $./zokrates compute-witness -a 0 0 0 5
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


0 0 0 5라는 값을 입력했고 결과값은 두개로 나눠져 출력됐다. 하나는 ~out_1=65303172752238645975888084098459749904, 다른 하나는 ~out_0=263561599766550617289250058199814760685이다. 코드의 결과값은 이를 각각 16진수로 변환하고 붙인 값이다. 결과값은 256비트지만 조크라테스에서는 최대 254비트까지만 담을 수 있기 때문에 두개 변수로 나눠져 출력된 것이다. 0 0 0 5를 넣은 코드의 실제 결과값은 0xc6481e22c5ff4164af680b8cfaa5e8ed3120eeff89c4f307c4a6faaae059ce10다. 

2. 검증자 빅터 컨테이너 실행

빅터는 페기가 제출한 값이 맞는지 검증하는 검증자며 페기는 빅터에게 자신이 답을 알고 있다고 주장하는 증명자다. 튜토리얼을 통해 증명자, 검증자가 주체별로 영지식증명을 어떻게 다루는지 확인할 수 있다. 빅터와 페기는 도커를 사용해 컨테이너로 각각 구현된다. 컨테이너는 쉽게 말해 애플리케이션이 사는 집과 같다. 빅터 컨테이너는 빅터 컴퓨터, 페기 컨테이너는 페기 컴퓨터라고 생각하면 된다. 

증명자인 페기는 0 0 0 5라는 입력값을 문제에 넣으면 결과값으로 0xc6481e22c5ff4164af680b8cfaa5e8ed3120eeff89c4f307c4a6faaae059ce10를 얻는다는 사실을 안다. 하지만 0 0 0 5라는 입력값을 검증자인 빅터에게 공개하고 싶지 않다. 0 0 0 5는 “열려라 참깨”처럼 외부로 노출되면 안 되는 비밀 주문이기 때문이다. 상황은 복잡하지만 이를 해결하는 증명-검증 로직은 간단하다. 페기는 그 자체로는 아무것도 추측할 수 없는 암호화된 값을 만들어서 빅터에게 건네준다. 이는 페기가 문제에 답을 올바르게 넣어서 풀었다는 행위에 대한 기록이다. 빅터가 페기가 건네 준 영지식을 회로에 넣고 검산한 뒤 결과가 올바르면 빅터는 페기가 본래 문제에 대한 답을 알고 있다고 쳐준다. 

먼저 본래의 코드를 입력값을 토대로 정해진 결과값과 비교하는 코드로 변경한다. 본래의 코드는 입력변수에 따라 해시값을 각각 출력해줬지만 변경된 코드는 입력값이 코드에 지정된 함수값을 출력하는지 그저 확인하는 코드다. 변경된 코드는 마치 자물쇠와 같다. 입력값에 따라 성공하면 1을 출력하고 열리며 틀리면 실패할 뿐이다. 빅터와 페기 모두는 이렇게 변경된 코드를 문제지처럼 공유한다. 코드는 빔에디터를 통해 수정했다.

import "hashes/sha256/512bitPacked.code" as sha256packed

def main(private field a, private field b, private field c, private field d) -> (field):

    h = sha256packed([a, b, c, d])

    h[0] == 263561599766550617289250058199814760685

    h[1] == 65303172752238645975888084098459749904

    return 1
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


이제 빅터 컨테이너를 실행한다. 탭을 하나 추가로 열고 도커를 통해 현위치($PWD)에 설치해 실행한다. $docker run -v $PWD:/home/zokrates/code --name victor -ti zokrates/zokrates /bin/bash 
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


빅터 컨테이너에서 수정된 코드를 컴파일해 변경된 내용을 반영한다. $./zokrates compile -i code/hashexample.code
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


컨스트레인트(로직 게이트) 수가 56985개인 산술회로로 컴파일됐다. 이렇게 컴파일된 코드는 out.code로 출력됐다.

빅터는 컨테이너에서 영지식증명을 주고받기 위한 셋업을 시작한다. $./zokrates setup 셋업과정에서는 일회성 폐기물인 톡식 웨이스트가 생성된다. verifiation.key 파일과 proving.key 파일이 그것이다. proving.key는 증명을 생성하는데 쓰이고 verification.key는 컨트랙트를 생성하는데 사용된다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


셋업 과정은 지캐시 등 프로젝트에서 트러스티드 셋업이라고도 한다. 트러스티드 셋업은 증명자인 페기와 검증자인 빅터 간 암호화 통신을 수행하기 위한 약속과도 같다. proving.key와 verification.key가 유출되면 연산해보지 않고도 영지식 검증을 통과할 수 있는 영지식 증명을 만들어낼 수 있어 보안상 주의가 필요하다.

조크라테스 라이브러리의 핵심 기능은 주어진 문제에 답 대신 영지식을 입력해 참거짓을 판별해주는 솔리디티 코드를 뽑아내 준다는 것이다. 빅터 컨테이너에서 $./zokrates export-verifier 명령어를 사용하면 out.code를 토대로 verifier.sol 파일을 만들어준다. 이는 이더리움에 배포할 수 있는 컨트랙트 소스 파일이다. 영지식의 검증은 빅터가 이 verifier.sol 파일로 생성한 컨트랙트에서 실행된다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


verifier.sol 파일이 생성된 모습.

3.증명자, 페기 컨테이너 실행

터미널에 새로운 탭을 하나 더 열고 도커 명령어를 통해 페기 컨테이너를 시작한다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


페기는 증명을 만들어서 빅터에게 제출해야 하는데 아무렇게나 만들 수는 없다. 수행하기 위한 준비물이 필요하다. 준비물은 검증자인 빅터가 건네주는 프루빙키다. 페기는 프루빙 키를 토대로 프루프를 만들어야 한다. 조크라테스는 영지식증명 기술 중 지케이스나크(zk-SNARK)에 기반해 구동된다. 프루빙 키는 지케이스나크를 셋업하는데 필요한 일회성 비밀값(톡식 웨이스트)의 일종이다.

빅터에서 페기에게 프루빙키 키를 복사하는 건 직접 할 수 없고 호스트 컨테이너를 경유해 복사해준다. 빅터는 호스트 컨테이너로, 호스트 컨테이너는 페기에게 프루빙키를 복사한다. 페기에게 프루빙키가 전달된 모습. $docker cp victor:/home/zokrates/proving.key ./

$docker cp ./proving.key peggy:/home/zokrates
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


페기 컨테이너에서도 빅터 컨테이너와 마찬가지로 코드를 다시 컴파일한다. 빅터와 페기 컨테이너는 같은 디렉토리($PWD)에 위치하기에 hashexample.code 파일을 별도 수정할 필요는 없이 바로 컴파일한다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


그결과 페기 컨테이너에서도 out.code가 만들어진다. 

이제 페기는 위트니스 파일을 생성한다. $./zokrates compute-witness -a 0 0 0 5 위트니스는 페기의 입력값을 토대로 자물쇠가 실제로 열렸는지를 표시해준다. 즉 위트니스는 문제를 실제로 풀어냈다는 행위를 나타내는 파일이다. 코드에 명시된 대로 참일 경우 1을 출력하고, 만약 답이 틀릴 경우 작업은 실패한다. 
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


위트니스를 생성하는데는 입력값이 필요하다. 페기는 0 0 0 5라는 입력값을 넣어 위트니스를 생성했다. 페기는 성공해 1이라는 값을 얻었다. 위트니스 파일이 성공적으로 생성됐다.

페기는 생성된 위트니스 파일을 토대로 프루프(영지식증명)를 생성한다. $./zokrates generate-proof 프루프 파일인 proof.json 내부에는 영지식 증거들을 포함하고 있다. 이같은 변수들을 빅터가 배포한 솔리디티 컨트랙트에 입력하면 해당 컨트랙트는 페기가 올바른 답을 입력했는지 즉각 판별해준다. proof.json 프루프가 생성된 모습. 
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


4. 리믹스 브라우저에서 검증 컨트랙트를 배포하고 검증하기

조크라테스는 검증자 컨트랙트를 만들어주는 라이브러리다. 빅터 컨테이너에서 솔리디티 파일을 열어서 복사한다. 간단하게 $cat 명령어를 사용하면 된다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


이같이 출력된 코드를 리믹스 브라우저에 올리고 0.5.0버전의 컴파일러를 선택해 컴파일 한다. 리믹스 브라우저에서 자바스크립트 가상머신(VM)을 선택하고 컨트랙트를 배포한다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


페기는 프루프를 cat 명령어를 통해 열어 암호화 값들을 빅터의 컨트랙트에 넣는다. 
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


verifyTx부분에 a,b,c, 인풋값 이렇게 하나하나씩 복사-붙여넣기 한다. 빅터의 컨트랙트는 입력된 값이 유효한지 검산을 수행한다. 결과가 참이면 빅터는 페기가 문제에 대한 답을 알고 있다고 검증한다.
매일경제

<이미지를 클릭하시면 크게 보실 수 있습니다>


리믹스 창 하단에 event에 verified로 표시되며 페기의 증명이 올바름을 알 수 있다. 페기가 문제를 알맞게 풀었음을 이 스마트 컨트랙트가 검증했다. 즉 페기는 문제를 푸는 답을 알고 있고 실제로도 풀었다는 행위를 빅터로부터 인정받게 된 셈이다.

송무복 온더 연구원은 “영지식증명을 만드는데 필요한 산술회로인 컨스트레인트를 직접 만드는 과정은 복잡하고 영지식증명을 내부적으로 모두 이해해야 가능하다. 하지만 조크라테스 라이브러리를 사용하면 영지식 증명에 대한 내부적인 이해 없이도 컨스트레인트를 작성하고 검증 컨트랙트까지 배포할 수 있어 매우 편리하다"고 강조했다. 다만 그는 “조크라테스에서 제공하는 프로그래밍 언어 자체가 254비트 까지만 표현할 수 있는 등 기존 프로그래밍 언어와 비교했을때 기능이 상당히 제한돼 있고 내부적으로 지원하는 라이브러리도 적은 편이 단점”이라고 말했다.

기사 작성에 기여하고 검토한 송무복 연구원은 블록체인 연구개발 기업인 온더에서 토카막 프로토콜의 컴퓨테이션 챌린지를 연구, 개발하고 있다.

[강민승 D.STREET(디스트리트) 기자]

[ⓒ 매일경제 & mk.co.kr, 무단전재 및 재배포 금지]
기사가 속한 카테고리는 언론사가 분류합니다.
언론사는 한 기사를 두 개 이상의 카테고리로 분류할 수 있습니다.