zkLogin是Sui区块链的核心原语之一,它允许用户使用熟悉的OAuth凭据(如Google、Facebook或Twitch账户)直接在Sui地址上发送交易,而无需公开关联Web2身份与链上活动。这一创新方案既简化了用户体验,又保障了隐私和安全。
设计目标与核心优势
zkLogin在设计时充分考虑了以下关键目标:
- 简化入门流程:通过OAuth登录流程消除处理加密密钥或记忆助记词的摩擦
- 自我托管:交易需用户通过标准OAuth流程批准,提供商无法代表用户操作
- 增强安全性:采用双因素验证方案,需要最近OAuth登录凭据和独立管理的盐值
- 隐私保护:零知识证明技术防止第三方将Sui地址与OAuth标识符关联
- 身份可验证性:用户可选择验证用于派生地址的OAuth标识符,建立可验证链上身份
- 无缝集成:作为Sui原生签名方案,与赞助交易和多重签名等功能完美兼容
- 严格审计:代码经过两家零知识专业公司的独立安全审计
兼容的OpenID提供商
目前支持或正在审核的OpenID提供商包括:
| 提供商 | 是否支持 | Devnet | Testnet | Mainnet |
|---|---|---|---|---|
| 是 | 是 | 是 | 是 | |
| 是 | 是 | 是 | 是 | |
| Twitch | 是 | 是 | 是 | 是 |
| Slack | 是 | 是 | 否 | 否 |
| Kakao | 是 | 是 | 否 | 否 |
| Apple | 是 | 是 | 否 | 否 |
多个主流提供商(如Microsoft、Amazon、WeChat等)目前处于审核阶段,未来将逐步扩展支持范围。
集成指南:实现zkLogin功能
集成zkLogin的钱包或前端应用需要遵循以下高级流程:
- 创建临时密钥对
- 引导用户完成包含临时公钥随机数的OAuth登录流程
- 获取JWT令牌后生成零知识证明
- 基于JWT令牌获取唯一用户盐值
- 使用临时私钥签署交易
- 提交包含临时签名和零知识证明的交易
安装zkLogin TypeScript SDK
npm install @mysten/zklogin
# 使用最新实验版本
npm install @mysten/zklogin@experimental配置OpenID提供商开发者账户
当前支持Google、Facebook和Twitch,更多提供商将陆续启用。以下是构建测试登录URL的示例代码:
const REDIRECT_URI = '';
const params = new URLSearchParams({
client_id: $CLIENT_ID,
redirect_uri: $REDIRECT_URL,
response_type: 'id_token',
scope: 'openid',
nonce: nonce,
});
const loginURL = `https://accounts.google.com/o/oauth2/v2/auth?${params}`;每个提供商都需要配置客户端ID和重定向URL,具体步骤因平台而异。
技术实现细节
获取JWT令牌
- 生成临时密钥对(遵循传统钱包相同流程)
- 设置密钥对过期时间(当前或未来时期)
- 组装包含客户端ID、重定向URL和随机数的OAuth URL
import { generateNonce, generateRandomness } from '@mysten/zklogin';
const FULLNODE_URL = 'https://fullnode.devnet.sui.io';
const suiClient = new SuiClient({ url: FULLNODE_URL });
const { epoch, epochDurationMs, epochStartTimestampMs } = await suiClient.getLatestSuiSystemState();
const maxEpoch = Number(epoch) + 2;
const ephemeralKeyPair = new Ed25519Keypair();
const randomness = generateRandomness();
const nonce = generateNonce(ephemeralKeyPair.getPublicKey(), maxEpoch, randomness);用户盐值管理
用户盐值在计算zkLogin Sui地址时使用,必须是16字节值或小于2^128的整数。管理选项包括:
- 客户端管理:用户输入或浏览器存储(需考虑跨设备同步)
- 后端服务:通过验证JWT令牌一致返回唯一盐值
盐值服务示例请求:
curl -X POST https://salt.api.mystenlabs.com/get_salt \
-H 'Content-Type: application/json' \
-d '{"token": "$JWT_TOKEN"}'获取零知识证明
生成扩展临时公钥作为ZKP输入:
import { getExtendedEphemeralPublicKey } from '@mysten/zklogin';
const extendedEphemeralPublicKey = getExtendedEphemeralPublicKey(ephemeralKeyPair.getPublicKey());建议使用专用后端服务生成ZK证明,避免客户端资源消耗。可选择Mysten Labs维护的服务或自建服务。
组装签名并提交交易
import { genAddressSeed, getZkLoginSignature } from "@mysten/zklogin";
// 使用临时私钥签署交易
const { bytes, signature: userSignature } = await txb.sign({
client,
signer: ephemeralKeyPair,
});
// 生成地址种子和zkLogin签名
const addressSeed = genAddressSeed(BigInt(userSalt!), "sub", decodedJwt.sub, decodedJwt.aud).toString();
const zkLoginSignature = getZkLoginSignature({
inputs: { ...partialZkLoginSignature, addressSeed },
maxEpoch,
userSignature,
});
// 执行交易
client.executeTransactionBlock({
transactionBlock: bytes,
signature: zkLoginSignature,
});安全与隐私考量
zkLogin采用多重安全机制保障用户资产和隐私:
- JWT令牌:受客户端ID限制防止钓鱼攻击,泄漏不会导致资金损失
- 用户盐值:泄漏仅可能导致OAuth标识符与地址关联,不影响资金控制
- 临时私钥:具有生命周期限制,泄漏需要同时获取用户盐和ZK证明才构成威胁
- 零知识证明:单独获取无法创建有效交易
隐私方面,默认情况下OAuth标识符与Sui地址无关联,JWT令牌不会上链,敏感字段在证明生成时作为私有输入处理。
常见问题
zkLogin与传统钱包有何不同?
传统钱包要求用户管理助记词和私钥,而zkLogin只需临时密钥存储和OAuth登录流程。遗忘临时密钥不会导致资金损失,用户可随时重新登录生成新密钥。
OAuth账户被盗怎么办?
zkLogin采用双因素验证,攻击者仅获取OAuth凭证无法访问zkLogin地址,还需要单独获取盐值。
失去OAuth访问权限会丢失资金吗?
是的,必须能登录OAuth账户生成当前JWT才能使用zkLogin。建议通过提供商密码重置流程恢复访问,或使用多重签名增加恢复选项。
zkLogin地址会变化吗?
地址从sub、iss、aud和user_salt派生。使用相同提供商登录相同钱包时地址不变,但更换提供商或钱包会导致地址变化。
每笔交易都需要新证明吗?
不需要。证明在临时密钥对过期前一直有效,可缓存并使用相同密钥签署多个交易。
移动设备是否支持?
zkLogin是Sui原生功能,任何Sui开发者都可在移动应用中使用。
技术原理深度解析
zkLogin协议基于以下核心要素:
- JWT令牌:包含用户定义随机数字段的OAuth提供商签名负载
- 临时密钥对:会话期间签署交易,消除用户记忆需求
- 零知识证明:基于JWT令牌生成,隐藏隐私敏感字段
- 地址派生:从OAuth标识符、提供商信息和用户盐值派生,而非公钥
zkLogin代表了Web2与Web3身份融合的重要创新,通过密码学原语实现了既用户友好又安全可靠的区块链交互体验。随着更多身份提供商的加入和生态系统的成熟,zkLogin有望成为下一代区块链应用的标准身份入口。