zkLogin이란?
zkLogin은 두 항목을 공개적으로 연결하지 않고 OAuth credential을 사용하여 Sui address에서 transaction을 전송할 수 있게 해주는 Sui primitive 기능이다.
zkLogin은 다음과 같은 목표로 설계되었다:
- Streamlined onboarding: zkLogin은 익숙한 OAuth login flow를 사용해 Sui에서 transaction할 수 있게 하여 cryptographic key를 다루거나 mnemonic을 기억할 필요를 없앤다.
- Self-custody: zkLogin transaction은 표준 OAuth login process를 통한 사용 자 승인을 요구한다. OAuth provider는 사용자를 대신해 transaction할 수 없다.
- Security: zkLogin은 two-factor authentication scheme이다. transaction을 전송하려면 최근 OAuth login의 credential과 OAuth provider가 관리하지 않는 salt가 모두 필요하다. OAuth account를 탈취한 공격자라도 salt까지 탈취하지 않는 한 사용자의 Sui address에서 transaction할 수 없다.
- Privacy: zero-knowledge proof는 제3자가 Sui address를 그에 대응하는 OAuth identifier와 연결하는 것을 방지한다.
- Optional verified identity: 특정 Sui address를 도출하는 데 사용된 OAuth identifier를 검증하도록 선택할 수 있다. 이는 검증 가능한 온체인 identity layer의 기반을 만든다.
- Accessibility: zkLogin은 sponsored transaction과 다중 서명(multisig) 같은 다른 Sui primitive와 통합된다.
- Rigor: zkLogin의 코드는 zero-knowledge를 전문으로 하는 두 회사가 독립적으로 audited했다. common reference string 생성을 위한 공개 zkLogin ceremony에는 100명이 넘는 참여자의 기여가 포함되었다.
zkLogin이 Sui에 가져오는 핵심 차별점은 다음과 같다:
-
Native support in Sui: blockchain agnostic한 다른 솔루션과 달리, zkLogin은 Sui 전용으로 배포된다. 이는 zkLogin transaction이 다중 서명 및 sponsored transaction과 매끄럽게 결합될 수 있음을 뜻한다.
-
Self-custodial without additional trust: Sui는 JWT의 nonce field를 활용해 ephemeral public key를 commit하므로, 어떤 trusted party와도 persistent private key management가 필요 없다. JWK 자체도 어떤 source of authority를 신뢰하지 않고 validator의 stake 정족수가 합의한 oracle이다.
-
Full privacy: 온체인에 제출할 것은 zero-knowledge proof와 ephemeral signature 외에는 없다.
-
Compatible with existing identity providers: zkLogin은 OpenID Connect를 채택한 provider와 호환되므로 OAuth provider 자체 외의 중간 identity issuer나 verifier를 신뢰할 필요가 없다.
애플리케이션이나 wallet에 zkLogin을 통합하려는 builder라면 zkLogin 통합을 참고한다.
OpenID provider 설정
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.
용어와 표기
이 섹션은 the OpenID specification에 정의된 관련 OpenID 용어와 zkLogin에서의 사용 방식을 설명하고, 프로토콜 세부사항에 대한 정의를 함께 제공한다.
OpenID provider(OP) 설명
OpenID provider는 최종 사용자를 인증하고 인증 이벤트와 최종 사용자에 대한 claim을 relying party에 제공할 수 있는 OAuth 2.0 authorization server이다.
이는 JSON web token payload의 iss field에서 식별된다.
zkLogin이 현재 지원하는 엔티티는 사용 가능한 OP 표를 확인한다.
Relying party (RP) 또는 client
relying party는 OpenID provider로부터 최종 사용자 인증과 claim이 필요한 OAuth 2.0 client application이다.
이는 애플리케이션을 생성할 때 OP가 할당한다.
이는 JWT payload의 aud field에서 식별되며 zkLogin enabled wallet 또는 application을 의미한다.
Subject identifier(sub) 설명
subject identifier는 issuer 내에서 최종 사용자에 대해 로컬하게 유일한 식별자이며 RP가 소비하도록 의도된 값이다. Sui는 이를 사용자 address를 도출하는 key claim으로 사용한다.
JSON Web Key(JWK) 설명
JSON Web Key는 OP에 대한 public key 집합을 나타내는 JSON data structure이다.
공개 endpoint(예: https://www.googleapis.com/oauth2/v3/certs)를 질의하면 provider의 kid에 대응하는 유효한 public key를 검색할 수 있다.
JWT header의 kid와 일치하면 JWT는 payload와 대응 JWK에 대해 검증될 수 있다.
Sui에서는 모든 authority가 JWK endpoint를 독립적으로 호출하고, 지원되는 모든 provider에 대한 최신 JWK view는 protocol upgrade 중에 업데이트 된다.
JWK의 정확성은 validator stake의 정족수(2f+1)에 의해 보장된다.
JSON Web Token(JWT) 설명
JSON Web Token은 OAuth login flow를 완료한 뒤 RP로 가는 redirect URI 안에 있다(https://redirect.com?id_token=$JWT_TOKEN처럼).
JWT는 header, payload, signature를 포함한다.
signature는 jwt_message = header + . + payload와 kid로 식별되는 그 JWK에 대해 검증되는 RSA signature이다.
payload는 여러 claim으로 구성된 name-value pair 형태의 JSON을 담는다.
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 provider에 할당된 고유 식별자이다. |
aud | 575519200000-msop9ep45u2uo98hapqmngv8d8000000.apps.googleusercontent.com | OAuth provider가 relying party에 할당한 고유 식별자이다. |
nonce | hTPpgF7XAKbW37rEUS6pEVZqmoI | relying party가 설정하는 값이 다. zkLogin enabled wallet는 이를 ephemeral public key, expiry time, randomness의 해시로 설정해야 한다. |
sub | 110463452167303000000 | 사용자에게 할당된 고유 식별자이다. |
zkLogin transaction의 경우 iat와 exp claim(timestamp)은 사용되지 않는다.
대신 nonce가 expiry time을 지정한다.
Key claim 설명
sub 또는 email처럼 address를 도출하는 데 사용되는 claim이 key claim이다.
당연히 한 번 설정된 후 다시 변경되지 않는 claim을 사용하는 것이 이상적이다.
zkLogin은 현재 OpenID specification이 provider가 이 identifier를 변경하지 못하게 요구하기 때문에 sub를 key claim으로 지원한다.
Notation 표기
-
(eph_sk, eph_pk): ephemeral signature를 생성하는 데 사용되는 private/public key pair이다. 서명 메커니즘은 전통적인 transaction 서명과 같지만, 짧은 session 동안만 저장되고 새 OAuth session에서 갱신될 수 있기 때문에 ephemeral하다. ephemeral public key는nonce계산에 사용된다. -
nonce: JWT payload에 포함된 application-defined field이며, ephemeral public key, JWT randomness, maximum epoch(Sui가 정의한 expiry 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: ephemeral public key(flag || eph_pk)의 byte 표현이다. 크기는 signature scheme 선택에 따라 달라진다(flag로 표시되며 서명에 정의된다). -
user_salt: OAuth identifier를 온체인 address와 분리하기 위해 도입된 값이다. -
max_epoch: JWT가 만료되는 epoch이다. 이는 Sui에서 사용하는u64이다. -
kc_name: key claim 이름이며, 예를 들면sub이다. -
kc_value: key claim 값이며, 예를 들면110463452167303000000이다. -
hashBytesToField(str, maxLen): Poseidon hash를 사용해 ASCII string을 field element로 해싱한다.
Entity 구성
-
Application frontend: zkLogin을 지원하는 wallet 또는 frontend application을 말한다. frontend는 ephemeral private key 저장, OAuth login flow 유도, zkLogin transaction 생성 및 서명을 담당한다.
-
Salt backup service: 고유 사용자별 salt 를 반환하는 backend service이다. salt를 유지하는 다른 전략은 zkLogin 통합을 참조한다.
-
Zero-knowledge proving service: JWT, JWT randomness, user salt, max epoch에 기반한 zero-knowledge proof를 생성하는 backend service이다. 이 proof는 zkLogin transaction을 위한 ephemeral signature와 함께 온체인에 제출된다.
zkLogin 작동 방식
high level에서 zkLogin protocol은 다음과 같이 동작한다:
-
JWT는 nonce라는 사용자 정의 field를 포함하는 OAuth provider의 signed payload이다. zkLogin은 nonce를 public key와 expiry epoch로 정의하여 the OpenID Connect OAuth flow를 사용한다.
-
wallet는 nonce에 정의되는 ephemeral key pair를 저장한다. ephemeral private key는 짧은 session 동안 transaction에 서명한다. Groth16 zero-knowledge proof는 JWT에서 생성되며 민감한 field를 숨긴다.
-
transaction은 ephemeral signature와 zero-knowledge proof와 함께 온체인에 제출된다. Sui authority는 ephemeral signature와 proof를 검증한 뒤 transaction을 실행한다.
-
public key에 기반해 Sui address를 도출하는 대신, zkLogin address는
sub(user identifier),iss(provider),aud(application),user_salt(OAuth identifier를 온체인 address와 분리하는 값)로부터 도출된다.

Step 0: zkLogin은 zkSNARK instance 생성을 위해 Groth16을 사용하며, circuit에 연결된 common reference string(CRS)이 필요하다.
ceremony는 proving service의 proving key와 Sui authority의 verifying key를 생성하는 데 사용되는 CRS를 생성한다.
Steps 1-3: OpenID provider(OP)에 login해 nonce가 포함된 JWT를 얻는다.
ephemeral key pair (eph_sk, eph_pk)를 생성하고 eph_pk, expiry time(max_epoch), randomness(jwt_randomness)를 nonce에 포함한다.
login 후 JWT는 application의 redirect URL에 나타난다.
Steps 4-5: Application frontend가 JWT를 salt service로 보낸다. Service는 iss, aud, sub를 기반으로 unique user_salt를 반환한다.
Steps 6-7: JWT, user salt, ephemeral public key, JWT randomness, key claim name(예: sub)을 proving service로 보낸다.
proving service는 다음을 증명하는 zero-knowledge proof를 생성한다:
- nonce가 올바르게 도출되었음을 확인한다.
- key claim 값이 대응되는 JWT field와 일치함을 확인한다.
- provider의 JWT에 대한 RSA signature를 검증한다.
- address가 key claim과 user salt와 일관됨을 확인한다.
Step 8: Application이 iss, aud, sub를 기반으로 address를 계산한다.
Steps 9-10: Ephemeral private key로 transaction에 sign하고 ephemeral signature, ZK proof, 기타 input과 함께 Sui에 submit한다.
Step 10 이후 Sui authority는 provider의 JWK(합의에 의해 저장됨)와 ephemeral signature를 대조해 ZK proof를 검증한다.
Address definition 정의
address는 다음 입력으로 계산된다:
-
The address flag: zkLogin address에 대한
zk_login_flag = 0x05이다. 이는 domain separator 역할을 한다. -
kc_name_F = hashBytesToField(kc_name, maxKCNameLen): key claim의 이름이며, 예를 들어sub이다. byte sequence는hashBytesToField(아래 정의)를 사용해 BN254의 field element로 매핑된다. -
kc_value_F = hashBytesToField(kc_value, maxKCValueLen):hashBytesToField로 매핑된 key claim의 값이다. -
aud_F = hashBytesToField(aud, maxAudValueLen): relying party(RP) identifier이다. -
iss: OpenID Provider(OP) identifier이다. -
user_salt: OAuth identifier를 온체인 address와 분리하기 위해 도입된 값이다.
마지막으로 Sui는 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)를 도출한다.
Ceremony 절차
OAuth artifact의 프라이버시를 보존하기 위해 소유에 대한 zero-knowledge proof가 제공된다. zkLogin은 proof 크기와 검증 효율성 측면에서 가장 효율적인 범용 zkSNARK이기 때문에 zero-knowledge proof를 인스턴스화하기 위해 Groth16 zkSNARK를 사용한다.
그러나 Groth16은 trusted party가 설정해야 하는 계산별 common reference string(CRS)을 필요로 한다. zkLogin은 고가치 transaction의 안전한 보관과 중요한 smart contract의 무결성을 보장할 것으로 기대되므로, 시스템 보안을 단일 엔티티의 정직성에 기반할 수 없다. 따라서 zkLogin 회로용 CRS를 생성하려면 많은 참여자 중 소수의 정직성을 가정하는 protocol을 실행하는 것이 중요하다.
Sui zkLogin ceremony는 다양한 참여자 그룹이 CRS를 생성하기 위해 수행하는 cryptographic multi-party computation(MPC)이다. ceremony는 Bowe, Gabizon, Miers가 설명한 MMORPG MPC protocol을 따른다. protocol은 2단계로 진행된다. 첫 번째 단계는 타원 곡선 원소의 지수에서 비밀 값 tau의 거듭제곱 수열을 만든다. 이 단계는 회로와 무관하므로 ceremony는 기존 커뮤니티 기여 perpetual powers of tau의 결과를 채택한다. 현재 ceremony는 zkLogin 회로에 특화된 두 번째 단계이다.
MMORPG protocol은 순차적 protocol이므로 사전 동기화나 순서 지정 없이도 무제한의 참여자가 순차적으로 참여할 수 있다. 각 참여자는 이전 참여자의 출력을 다운로드하고, 자신의 entropy를 생성한 뒤 받은 결과 위에 덧씌워 자신의 기여를 만들고, 이를 다음 참여자에게 전달해야 한다. 이 protocol은 최소 1명의 참여자가 protocol을 성실히 따르고 강한 entropy를 생성해 신뢰성 있게 폐기하면 보안을 보장한다.