zkLogin
zkLogin은 두 항목을 공개적으로 연결하지 않고 OAuth credential을 사용하여 Sui address에서 transaction을 전송할 수 있게 해주는 Sui primitive 기능이다.
zkLogin은 다음과 같은 목표로 설계되었다:
- Streamlined onboarding: zkLogin은 암호 키를 다루거나 니모닉을 기억할 필요를 제거하여, 익숙한 OAuth 로그인 흐름을 사용해 Sui에서 거래할 수 있게 한다.
- Self-custody: zkLogin transaction은 표준 OAuth 로그인 프로세스를 통한 사용자 승인이 필요하다. OAuth 제공자는 사용자를 대신하여 거래할 수 없다.
- Security: zkLogin은 2요소 인증 방식이다. Transaction을 전송하려면 최근 OAuth 로그인에서 발급된 credential과 OAuth 제공자가 관리하지 않는 salt 모두 필요하다. OAuth 계정을 탈취한 공격자라도 salt까지 탈취하지 않는 한 사용자의 Sui address에서 거래할 수 없다.
- Privacy: 영지식 증명은 제3자가 Sui address를 그 주소에 대응하는 OAuth 식별자와 연결하는 것을 방지한다.
- Optional verified identity: 사용자는 특정 Sui address를 도출하는 데 사용된 OAuth 식별자를 검증하도록 선택할 수 있다. 이는 검증 가능한 온체인 신원 레이어의 기반을 마련한다.
- Accessibility: zkLogin은 Sui’s cryptography agility 덕분에 여러 네이티브 Sui 서명 방식 중 하나이다. 이는 sponsored transactions와 multisig 같은 다른 Sui primitive 기능과 통합된다.
- Rigor: zkLogin의 코드는 영지식에 특화된 두 업체에 의해 독립적으로 audited되었다. Common reference string 생성을 위한 공개 zkLogin ceremony에는 100명 이상이 기여했다.
애플리케이션이나 지갑에 zkLogin을 통합하려는 빌더라면 zkLogin integration guide를 참고한다.
영지식 증명이 생성되는 방식과 Sui가 zkLogin transaction을 검증하는 방법을 포함하여 zkLogin이 어떻게 동작하는지 알아보려면 how zkLogin works를 참고한다.
zkLogin의 보안 모델과 프라이버시 고려 사항에 대한 정보는 security and privacy를 참고한다.
자주 묻는 질문은 FAQ section을 참고한다.
OpenID providers
The following table lists the OpenID providers that can support zkLogin or are currently being reviewed to determine whether they can support zkLogin.
| Provider | Can support? | Devnet | Testnet | Mainnet |
|---|---|---|---|---|
| Yes | Yes | Yes | Yes | |
| Yes | Yes | Yes | Yes | |
| Twitch | Yes | Yes | Yes | Yes |
| Apple | Yes | Yes | Yes | Yes |
| Slack | Yes | Yes | No | No |
| Kakao | Yes | Yes | No | No |
| Microsoft | Yes | Yes | No | No |
| AWS (Tenant)* | Yes | Yes | Yes | Yes |
| Karrier One | Yes | Yes | Yes | Yes |
| Credenza3 | Yes | Yes | Yes | Yes |
| RedBull | Under review | No | No | No |
| Amazon | Under review | No | No | No |
| Under review | No | No | No | |
| Auth0 | Under review | No | No | No |
| Okta | Under review | No | No | No |
- Sui supports AWS (Tenant) but the provider is enabled per tenant. Contact us for more information.
How zkLogin works
큰 틀에서, zkLogin 프로토콜은 다음과 같이 동작한다:
- JWT는 OAuth 제공자가 서명한 payload이며 nonce라는 사용자 정의 필드를 포함한다. zkLogin은 nonce를 공개 키와 만료 epoch로 정의하여 the OpenID Connect OAuth flow를 사용한다.
- 지갑은 nonce에 정의된 임시 공개 키가 있는 임시 키 쌍을 저장한다. 임시 개인 키는 짧은 세션 동안 transaction에 서명한다. Groth16 영지식 증명은 민감한 필드를 숨기는 JWT로부터 생성된다.
- Transaction은 임시 서명과 영지식 증명을 포함하여 온체인에 제출된다. Sui authorities는 임시 서명과 증명을 검증한 후 transaction을 실행한다.
- 공개 키를 기반으로 Sui address를 도출하는 대신 zkLogin address는
sub(사용자 식별자),iss(제공자),aud(어플리케이션), 그리고user_salt(OAuth 식별자를 온체인 address와 분리하는 값)로부터 도출된다.
The complete zkLogin flow

(Step 0) zkLogin은 zkSNARK 인스턴스화를 위해 Groth16을 사용하며, 이는 회로에 연결된 common reference string(CRS)을 필요로 한다. Ceremony는 CRS를 생성하며 이 CRS는 증명 서비스의 증명 키와 Sui authorities의 검증 키를 생성하는 데 사용된다. 자세한 내용은 ceremony를 참고한다.
(Step 1-3) 사용자는 nonce를 포함하는 JWT를 얻기 위해 OpenID provider(OP)에 로그인한다. 사용자는 임시 키 쌍 (eph_sk, eph_pk)를 생성하고 eph_pk, 만료 시간(max_epoch), 그리고 randomness(jwt_randomness)를 nonce에 포함한다. 로그인 후 JWT는 애플리케이션의 redirect URL에 나타난다.
(Step 4-5) 애플리케이션 프런트엔드는 JWT를 salt service로 보낸다. 서비스는 iss, aud, 그리고 sub를 기반으로 고유한 user_salt를 반환한다.
(Step 6-7) 사용자는 JWT, 사용자 salt, 임시 공개 키, JWT randomness, 그리고 key claim 이름(예: sub)을 증명 서비스로 보낸다. 증명 서비스는 다음에 해당하는 영지식 증명을 생성한다:
- Nonce가 올바르게 도출되었음을 확인한다.
- Key claim 값이 해당 JWT 필드와 일치함을 확인한다.
- JWT에 대한 제공자의 RSA 서명을 검증한다.
- Address가 key claim과 user salt와 일관됨을 확인한다.
(Step 8) 애플리케이션은 iss, aud, 그리고 sub를 기반으로 사용자 address를 계산한다.
(Step 9-10) 사용자는 임시 개인 키로 transaction에 서명하고 임시 서명, ZK proof, 기타 입력과 함께 이를 Sui에 제출한다.
(After Step 10) Sui authorities는 제공자의 JWKs(합의에 의해 저장됨)와 임시 서명을 대조해 ZK proof를 검증한다.
Entities
-
Application frontend: 이는 zkLogin을 지원하는 지갑 또는 프런트엔드 애플리케이션을 나타낸다. 이 프런트엔드는 임시 개인 키를 저장하고 사용자가 OAuth 로그인 흐름을 완료하도록 안내하며 zkLogin transaction을 생성하고 서명하는 책임을 진다.
-
Salt Backup Service: 이는 고유 사용자별 salt를 반환하는 백엔드 서비스이다. salt를 유지하는 다른 전략은 zkLogin Integration Guide를 참고한다.
-
ZK Proving Service: 이는 JWT, JWT randomness, user salt, max epoch를 기반으로 ZK proof를 생성하는 백엔드 서비스이다. 이 증명은 zkLogin transaction을 위한 임시 서명과 함께 온체인에 제출된다.
Address definition
Address는 다음 입력에 기반하여 계산된다:
-
The address flag: zkLogin address를 위한
zk_login_flag = 0x05이다. 이는 crypto agility에 정의된 서명 방식의 domain separator 역할을 한다. -
kc_name_F = hashBytesToField(kc_name, maxKCNameLen): Key claim의 이름으로, 예를 들자면sub이다. 바이트 시퀀스는hashBytesToField(아래에 정의됨)를 사용해 BN254의 field element로 매핑된다. -
kc_value_F = hashBytesToField(kc_value, maxKCValueLen):hashBytesToField를 사용해 매핑된 key claim의 값이다. -
aud_F = hashBytesToField(aud, maxAudValueLen): relying party(RP) 식별자이다. definition을 참고한다. -
iss: OpenID Provider(OP) 식별자이다. definition을 참고한다. -
user_salt: OAuth 식별자를 온체인 address와 분리하기 위해 도입된 값이다.
마지막으로 addr_seed = Poseidon_BN254(kc_name_F, kc_value_F, aud_F, Poseidon_BN254(user_salt)인 경우 zk_login_address = Blake2b_256(zk_login_flag, iss_L, iss, addr_seed)를 도출한다.
Terminology and notations
프로토콜 세부 정의와 함께 spec에 정의된 관련 OpenID 용어와 해당 개념들이 zkLogin에서 어떻게 사용되는지 알아보려면 아래를 참고한다.
OpenID provider (OP)
최종 사용자를 인증하고 인증 이벤트 및 최종 사용자에 대한 클레임을 RP에 제공할 수 있는 OAuth 2.0 authorization server이다. 이는 JWT payload의 iss 필드에서 식별된다. 현재 zkLogin이 지원하는 엔티티는 table of available OPs에서 확인한다.
Relying party (RP) or client
OpenID 제공자로부터 최종 사용자 인증과 클레임이 필요한 OAuth 2.0 client 애플리케이션이다. 이는 개발자가 애플리케이션을 생성할 때 OP에 의해 할당된다. 이는 JWT payload의 aud 필드에서 식별된다. 이는 zkLogin이 활성화된 모든 지갑 또는 애플리케이션을 의미한다.
Subject identifier (sub)
Issuer 내에서 최종 사용자에 대해 로컬하게 유일하며 재할당되지 않는 식별자로 RP가 사용하도록 의도 되었다. Sui는 사용자 address를 도출하기 위한 key claim으로 이를 사용한다.
JSON Web Key (JWK)
OP에 대한 공개 키 집합을 나타내는 JSON 데이터 구조이다. 공개 endpoint(예: https://www.googleapis.com/oauth2/v3/certs)에 질의하여 제공자의 kid에 해당하는 유효한 공개 키를 검색할 수 있다. JWT 헤더의 kid와 일치하면 JWT는 payload와 해당 JWK에 대해 검증될 수 있다. Sui에서는 모든 authorities가 JWK endpoint를 독립적으로 호출하고, 모든 지원되는 제공자에 대한 JWK 최신 뷰를 프로토콜 업그레이드 동안 업데이트한다. JWK의 정확성은 validator stake의 정족수(2f+1)에 의해 보장된다.
JSON Web Token (JWT)
사용자가 OAuth 로그인 흐름을 완료한 후 JWT는 RP로의 redirect URI에 포함된다(https://redirect.com?id_token=$JWT_TOKEN 처럼). JWT는 header, payload, 그리고 signature를 포함한다. 서명은 jwt_message = header + . + payload와 kid에 의해 식별되는 해당 메세지의 JWK와 대조해 검증되는 RSA 서명이다. payload는 여러 claim으로 구성된 이름-값 쌍 형태의 JSON을 포함한다. zkLogin 프로토콜과 관련된 특정 클레임은 아래를 참고한다.
Header
| Name | Example Value | Usage |
|---|---|---|
| alg | RS256 | zkLogin은 RS256(RSA + SHA-256)만 지원한다. |
| kid | c3afe7a9bda46bae6ef97e46c95cda48912e5979 | JWT를 검증하는 데 사용되어야 하는 JWK를 식별한다. |
| typ | JWT | zkLogin은 JWT만 지원한다. |
Payload
| Name | Example Value | Usage |
|---|---|---|
| iss | https://accounts.google.com | OAuth 제공자에 할당된 고유 식별자이다. |
| aud | 575519200000-msop9ep45u2uo98hapqmngv8d8000000.apps.googleusercontent.com | OAuth 제공자가 relying party에 할당한 고유 식별자이다. |
| nonce | hTPpgF7XAKbW37rEUS6pEVZqmoI | Relying party가 설정하는 값이다. zkLogin가 활성화된 지갑은 이를 임시 공개 키, 만료 시간, randomness의 해시값으로 설정해야 한다. |
| sub | 110463452167303000000 | 사용자에게 할당된 고유 식별자이다. |
zkLogin transaction의 경우 iat와 exp 클레임(타임스탬프)는 사용되지 않는다. 대신 nonce가 만료 시간을 지정한다.
Key claim
sub 또는 email과 같이 사용자 address를 도출하는 데 사용되는 claim은 key claim이라 한다. 당연히, 한 번 설정된 후 다시 변경되지 않는 claim을 사용하는 것이 이상적이다. zkLogin은 현재 sub를 key claim으로 지원하는데 이는 OpenID 규격이 제공자가 이 식별자를 변경하지 못하도록 요구하기 때문이다. 이는 향후 email, 사용자 이름 등으로 확장될 수 있다.
Notations
(eph_sk, eph_pk): 임시 키 쌍은 임시 서명을 생성하는 데 사용되는 private/공개 키 쌍을 의미한다. 서명 메커니즘은 전통적인 transaction 서명과 동일하지만 짧은 세션 동안만 저장되고 새로운 OAuth 세션에서 갱신될 수 있으므로 일시적이다. 임시 공개 키는 nonce를 계산하는 데 사용된다.nonce: JWT payload에 포함되는 애플리케이션 정의 필드로, 임시 공개 키, JWT randomness, 최대 epoch(Sui에서 정의한 만료 epoch)의 해시값으로 계산된다. 구체적으로, zkLogin과 호환되는 nonce는nonce = ToBase64URL(Poseidon_BN254([ext_eph_pk_bigint / 2^128, ext_eph_pk_bigint % 2^128, max_epoch, jwt_randomness]).to_bytes()[len - 20..])로 전달되어야 하는데 여기서ext_eph_pk_bigint는ext_eph_pk의 BigInt 표현이다.ext_eph_pk: 임시 공개 키의 바이트 표현(flag || eph_pk)이다. 크기는 서명 방식 선택에 따라 달라진다(플래그로 표시되며 Signatures에 정의됨).user_salt: OAuth 식별자를 온체인 address와 분리하기 위해 도입된 값이다.max_epoch: JWT가 만료되는 epoch이다. 이는 Sui에서 사용되는 u64이다.kc_name: Key claim 이름으로, 예시로는sub가 있다.kc_value: Key claim 값으로, 예시로는110463452167303000000가 있다.hashBytesToField(str, maxLen): Poseidon 해시를 사용하여 ASCII 문자열을 필드 요소 로 해싱한다.
Ceremony
OAuth 아티팩트의 프라이버시를 보호하기 위해 아티팩트 소유에 대한 영지식 증명이 제공된다. zkLogin은 영지식 증명을 인스턴스화하기 위해 Groth16 zkSNARK을 사용하는데 이는 증명 크기와 검증 효율성 측면에서 가장 효율적인 범용 zkSNARK이기 때문이다.
그러나 Groth16은 신뢰할 수 있는 주체에 의해 설정되는 특정 계산 전용 common reference string(CRS)을 필요로 한다. zkLogin이 고가치 transaction의 안전한 보호와 중요한 smart contract의 무결성을 보장할 것으로 기대되는 만큼, 시스템의 보안을 단일 엔티티의 정직성에 의존할 수 없다. 따라서 zkLogin 회로의 CRS를 생성하기 위해서는, 많은 참여자 중 소수의 정직성을 가정하여 보안을 확보하는 프로토콜을 실행하는 것이 중요하다.
What is the ceremony?
Sui zkLogin 세레모니는 다양한 참여자 그룹이 이 CRS를 생성하기 위해 수행하는 본질적으로 암호학적 다자 계산(MPC)이다. 우리는 Bowe, Gabizon, Miers가 기술한 MPC 프로토콜 MMORPG를 따른다. 프로토콜은 대략 두 단계로 진행된다. 첫 번째 단계는 타원 곡선 원소의 지수에서 비밀 값 tau의 거듭제곱 수열을 생성한다. 이 단계는 회로에 종속되지 않으므로 기존 커뮤니티가 기여한 perpetual powers of tau의 결과를 채택했다. 우리의 세레모니는 zkLogin 회로에 특화된 두 번째 단계였다.
MMORPG 프로토콜은 순차적인 프로토콜로, 사전 동기화나 정해진 순서 없이도 무제한의 참여자가 순서대로 참여할 수 있게 한다. 각 참여자는 이전 참여자가 생성한 결과물을 다운로드하고, 자신의 엔트로피를 생성한 뒤 그것을 전달받은 결과 위에 덧씌워 자신의 기여 값을 만든 후, 이를 다음 참여자에게 전달해야 한다. 적어도 한 명의 참여자가 프로토콜을 성실히 따르고 강한 엔트로피를 생성하며 이를 신뢰성 있게 폐기하면 이 프로토콜은 보안을 보장한다.
How was the ceremony performed?
우리는 다양한 배경과 소속을 가진 100명 이상의 사람들에게 초대장을 보냈다: Sui validators, 암호학자, Web3 전문가, 세계적 학자, 비즈니스 리더. 우리는 세레모니를 2023년 9월 12–18일에 진행하도록 계획했지만 고정된 슬롯 없이 참여자가 원할 때 참가할 수 있도록 허용했다.
MPC가 순차적이므로 각 기여자는 이전 기여자의 작업이 끝날 때까지 기다려 이전 기여물을 수신하고 MPC 단계를 수행해 자신의 기여물을 생성해야 했다. 이러한 구조로 인해, 우리는 먼저 참여한 사람들이 작업을 완료하는 동안 뒤에 합류한 참여자들이 대기할 수 있도록 대기열을 마련하였다. 참가자 인증을 위해 각자에게 고유한 활성화 코드를 보냈다. 활성화 코드는 서명 키 쌍의 비밀 키였으며, 이중 목적을 가졌다: 이는 코디네이션 서버가 참가자의 이메일을 기여물과 연관시키고 해당 공개 키로 기여물을 검증할 수 있게 한다.
참가자는 기여에 대한 두 가지 옵션이 있었다: 브라우저 또는 도커. 브라우저 옵션은 모든 것이 브라우저에서 이루어지므로 더 사용자 친화적이었다. 도커 옵션은 도커 설정이 필요하지만 더 투명하다—Dockerfile과 기여자 소스 코드가 오픈소스이고 전체 프로세스를 검증할 수 있다. 또한 브라우저 옵션은 snarkjs를, 도커 옵션은 Kobi's implementation을 사용한다. 이는 소프트웨어 다양성을 제공하며 기여자는 그들이 신뢰하는 방법으로 기여하도록 선택할 수 있었다. 추가로 참가자는 임의의 텍스트를 입력하거나 커서를 임의로 움직여 엔트로피를 생성할 수 있었다.
zkLogin 회로와 세레모니 클라이언트 code는 오픈소스로 공개 되었고 해당 링크는 세레모니 전에 검토할 수 있도록 참가자들에게 제공되었다. 추가로 우리는 이 개발자 문서와 zkSecurity의 회로에 대한 audit report도 게시했다. 우리는 1단계에서 perpetual powers of tau로부터 회로에 종속되지 않는 challenge #0081(80건의 커뮤니티 기여로 생성됨)을 채택했다. 우리는 편향성을 제거하기 위해 epoch #3298000에서 Drand 랜덤 비콘의 결과물을 적용했다. 2단계에서 우리의 세레모니에는 111건의 기여가 있었고 브라우저 82건, 도커 29건이었다. 마지막으로 기여의 편향을 제거하기 위해 epoch #3320606에서 Drand 랜덤 비콘의 결과물을 적용했다. 모든 중간 파일은 1단계는 here, 2단계는 here의 지침을 따라 재현할 수 있다.
Finalization
최종 CRS와 모든 참여자의 기여에 대한 전사본은 공개 저장소에서 확인할 수 있다. 기여자들은 자신이 작업하던 이전 기여의 해시값과, 자신의 기여가 반영된 이후의 결과 해시값을 화면에 표시된 형태로 확인하고 이메일로도 전달받았다. 기여자들은 이 해시값들을 세레모니 사이트에 공개된 전사본과 비교할 수 있다. 또한 누구나 해시값이 올바르게 계산되었고 각 기여가 최종 파라미터에 적절히 반영되었음을 확인할 수 있다.
결국 최종 CRS는 증명 키와 검증 키를 생성하는 데 사용되었다. 증명 키는 zkLogin을 위한 영지식 증명을 생성하는 데 사용되며 ZK 증명 서비스에 저장된다. 검증 키는 Sui에서 zkLogin transaction을 검증하는 데 사용되는 validator 소프트웨어(release 1.10.1의 프로토콜 버전 25)의 일부로 deployed되었다.
Security and privacy
다음 섹션에서는 모든 zkLogin 아티팩트, 그들의 보안 가정, 그리고 유실 또는 노출 시의 결과를 살펴본다.
JWT
JWT의 유효성은 피싱 공격을 방지하기 위해 클라이언트 ID (aud) 범위로 제한된다. 증명에 대한 동일 출처 정책은 악성 애플리케이션을 위해 얻어진 JWT가 zkLogin에 사용되는 것을 방지한다. 클라이언트 ID용 JWT는 redirect URL을 통해 애플리케이션 프런트엔드로 직접 전송된다. 이러한 토큰은 보통 사용자 이름과 이메일 같은 민감한 정보를 포함하므로, 특정 클라이언트 ID에 대해 유출된 JWT는 사용자 프라이버시를 훼손할 수 있다. 더 나아가 백엔드 salt 서버가 사용자 salt 관리를 담당하는 경우, JWT가 사용자의 salt를 가져오기 위해 악용될 가능성이 있으며, 이는 추가적인 위험을 초래한다.
하지만 해당 임시 개인 키가 안전한 이상, JWT 유출이 곧바로 자금 손실을 의미하지는 않는다.
User salt
zkLogin 지갑에 접근하려면 사용자 salt가 필요하다. 이 값은 ZK proof 생성과 zkLogin address 도출 모두에 필수적이다.
사용자 salt의 유출은 자금 손실을 의미하지는 않지만, 공격자가 사용자의 주체 식별자(예: sub)를 Sui address와 연관지을 수 있게 한다. 이는 pairwise 또는 공개 주체 식별자 사용 여부에 따라 문제가 될 수 있다. 특히 pairwise ID를 사용하는 경우(예: Facebook) 주체 식별자가 RP마다 고유하므로 문제가 없다. 그러나 공개 재사용 ID(예: Google, Twitch)의 경우 전역 고유 sub 값이 사용자를 식별하는 데 사용될 수 있다.
Ephemeral private key
임시 개인 키의 수명은 유효한 ZK proof 생성을 위해 nonce에 지정된 최대 epoch에 연관 되어 있다. 만약 그것이 분실되더라도, 새로운 ephemeral 개인 키를 생성하여 트랜잭션 서명에 사용할 수 있으며, 새로운 nonce를 사용해 새로 생성된 ZK proof가 함께 제공된다. 그러나 임시 개인 키가 탈취된 경우, 자금을 이동시키려면 사용자 salt와 유효한 ZK proof를 확보해야 한다.
Proof
증명 자체를 획득하는 것만으로는 유효한 zkLogin transaction을 생성할 수 없으며 transaction에 대한 임시 서명도 필요하다.
Privacy
기본적으로 OAuth 주체 식별자(예: sub)와 Sui address 사 이에는 연관이 없다. 이것이 사용자 salt의 목적이다. JWT는 기본적으로 온체인에 게시되지 않는다. 공개되는 값에는 iss, aud, kid가 포함되어 공개 입력 해시값을 계산할 수 있으며, sub와 같은 민감한 필드는 증명 생성 시 private input으로 사용된다.
ZK 증명 서비스와 salt service(운영되는 경우)는 사용자 salt와 JWT를 알고 있으므로 사용자 신원을 연결할 수 있지만, 두 서비스는 설계상 stateless하다.
향후 사용자는 온체인에서 Sui address와 연결된 OAuth 신원을 검증하도록 선택할 수 있다.
FAQ
zkLogin은 어떤 제공자들과 호환되나요?
zkLogin은 OAuth 2.0 프레임워크 위에 구축된 OpenID Connect와 연동되는 제공자들을 지원할 수 있다. 이는 OAuth 2.0과 호환되는 제공자 중 일부에 해당한다. 활성화된 모든 제공자는 latest table를 참고한다. 기타 호환되는 제공자들도 향후 프로토콜 업그레이드를 통해 활성화될 예정이다.