zkLogin技术详解:使用OAuth凭据实现无缝Sui交易

·

zkLogin是Sui区块链的核心原语之一,它允许用户使用熟悉的OAuth凭据(如Google、Facebook或Twitch账户)直接在Sui地址上发送交易,而无需公开关联Web2身份与链上活动。这一创新方案既简化了用户体验,又保障了隐私和安全。

设计目标与核心优势

zkLogin在设计时充分考虑了以下关键目标:

兼容的OpenID提供商

目前支持或正在审核的OpenID提供商包括:

提供商是否支持DevnetTestnetMainnet
Facebook
Google
Twitch
Slack
Kakao
Apple

多个主流提供商(如Microsoft、Amazon、WeChat等)目前处于审核阶段,未来将逐步扩展支持范围。

集成指南:实现zkLogin功能

集成zkLogin的钱包或前端应用需要遵循以下高级流程:

  1. 创建临时密钥对
  2. 引导用户完成包含临时公钥随机数的OAuth登录流程
  3. 获取JWT令牌后生成零知识证明
  4. 基于JWT令牌获取唯一用户盐值
  5. 使用临时私钥签署交易
  6. 提交包含临时签名和零知识证明的交易

安装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令牌

  1. 生成临时密钥对(遵循传统钱包相同流程)
  2. 设置密钥对过期时间(当前或未来时期)
  3. 组装包含客户端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的整数。管理选项包括:

盐值服务示例请求:

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采用多重安全机制保障用户资产和隐私:

隐私方面,默认情况下OAuth标识符与Sui地址无关联,JWT令牌不会上链,敏感字段在证明生成时作为私有输入处理。

常见问题

zkLogin与传统钱包有何不同?

传统钱包要求用户管理助记词和私钥,而zkLogin只需临时密钥存储和OAuth登录流程。遗忘临时密钥不会导致资金损失,用户可随时重新登录生成新密钥。

OAuth账户被盗怎么办?

zkLogin采用双因素验证,攻击者仅获取OAuth凭证无法访问zkLogin地址,还需要单独获取盐值。

失去OAuth访问权限会丢失资金吗?

是的,必须能登录OAuth账户生成当前JWT才能使用zkLogin。建议通过提供商密码重置流程恢复访问,或使用多重签名增加恢复选项。

zkLogin地址会变化吗?

地址从subissauduser_salt派生。使用相同提供商登录相同钱包时地址不变,但更换提供商或钱包会导致地址变化。

每笔交易都需要新证明吗?

不需要。证明在临时密钥对过期前一直有效,可缓存并使用相同密钥签署多个交易。

移动设备是否支持?

zkLogin是Sui原生功能,任何Sui开发者都可在移动应用中使用。

技术原理深度解析

zkLogin协议基于以下核心要素:

  1. JWT令牌:包含用户定义随机数字段的OAuth提供商签名负载
  2. 临时密钥对:会话期间签署交易,消除用户记忆需求
  3. 零知识证明:基于JWT令牌生成,隐藏隐私敏感字段
  4. 地址派生:从OAuth标识符、提供商信息和用户盐值派生,而非公钥

zkLogin代表了Web2与Web3身份融合的重要创新,通过密码学原语实现了既用户友好又安全可靠的区块链交互体验。随着更多身份提供商的加入和生态系统的成熟,zkLogin有望成为下一代区块链应用的标准身份入口。