使用 @mysten/seal 构建去中心化加密:开发者教程
隐私正在成为公共基础设施。在 2025 年,开发者需要让加密变得如存储数据一样简单的工具。Mysten Labs 的 Seal 正好提供了这样的解决方案——具有链上访问控制的去中心化密钥管理。本教程将教你如何使用基于身份的加密、门限安全和可编程访问策略构建安全的 Web3 应用程序。
简介:为什么 Seal 对 Web3 很重要
传统的云应用程序依赖于中心化的密钥管理系统,其中单一提供商控制对加密数据的访问。虽然方便,但这创造了危险的单点故障。如果提供商被攻击、离线或决定限制访问,你的数据将变得无法访问或易受攻击。
Seal 完全改变了这种模式。由 Mysten Labs 为 Sui 区块链构建,Seal 是一个去中心化密钥管理(DSM)服务,支持:
- 基于身份的加密,内容在离开你的环境之前就受到保护
- 门限加密,将密钥访问分布在多个独立节点上
- 链上访问控制,具有时间锁、代币门控和自定义授权逻辑
- 存储无关设计,可与 Walrus、IPFS 或任何存储解决方案配合使用
无论你是在构建安全消息应用程序、门控内容平台还是时间锁定资产转移,Seal 都提供了你需要的加密原语和访问控制基础设施。
开始使用
前提条件
在深入学习之前,确保你具有:
- 安装了 Node.js 18+
- 对 TypeScript/JavaScript 的基本了解
- 用于测试的 Sui 钱包(如 Sui Wallet)
- 对区块链概念的理解
安装
通过 npm 安装 Seal SDK:
npm install @mysten/seal
你还需要 Sui SDK 进行区块链交互:
npm install @mysten/sui
项目设置
创建一个新项目并初始化它:
mkdir seal-tutorial
cd seal-tutorial
npm init -y
npm install @mysten/seal @mysten/sui typescript @types/node
创建一个简单的 TypeScript 配置:
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
核心概念:Seal 的工作原理
在编写代码之前,让我们了解 Seal 的架构:
1. 基于身份的加密 (IBE)
与传统的加密方式不同(你加密到公钥),IBE 让你加密到一个身份(如电子邮件地址或 Sui 地址)。接收者只有在能够证明他们控制该身份时才能解密。
2. 门限加密
Seal 使用 t-of-n 门限方案,而不是信任单个密钥服务器。你可以配置 3-of-5 密钥服务器,这意味着任何 3 个服务器可以合作提供解密密钥,但 2 个或更少的服务器不能。
3. 链上访问控制
访问策略由 Sui 智能合约强制执行。在密钥服务器提供解密密钥之前,它会验证请求者是否满足链上策略要求(代币所有权、时间约束等)。
4. 密钥服务器网络
分布式密钥服务器验证访问策略并生成解密密钥。这些服务器由不同的方运营,以确保没有单一控制点。
基本实现:你的第一个 Seal 应用程序
让我们构建一个简单的应用程序,它加密敏感数据并通过 Sui 区块链策略控制访问。
步骤 1:初始化 Seal 客户端
// src/seal-client.ts
import { SealClient } from '@mysten/seal';
import { SuiClient } from '@mysten/sui/client';
export async function createSealClient() {
// 为测试网初始化 Sui 客户端
const suiClient = new SuiClient({
url: 'https://fullnode.testnet.sui.io'
});
// 使用测试网密钥服务器配置 Seal 客户端
const sealClient = new SealClient({
suiClient,
keyServers: [
'https://keyserver1.seal-testnet.com',
'https://keyserver2.seal-testnet.com',
'https://keyserver3.seal-testnet.com'
],
threshold: 2, // 2-of-3 门 限
network: 'testnet'
});
return { sealClient, suiClient };
}
步骤 2:简单加密/解密
// src/basic-encryption.ts
import { createSealClient } from './seal-client';
async function basicExample() {
const { sealClient } = await createSealClient();
// 要加密的数据
const sensitiveData = "这是我的秘密消息!";
const recipientAddress = "0x742d35cc6d4c0c08c0f9bf3c9b2b6c64b3b4f5c6d7e8f9a0b1c2d3e4f5a6b7c8";
try {
// 为特定的 Sui 地址加密数据
const encryptedData = await sealClient.encrypt({
data: Buffer.from(sensitiveData, 'utf-8'),
recipientId: recipientAddress,
// 可选:添加元数据
metadata: {
contentType: 'text/plain',
timestamp: Date.now()
}
});
console.log('加密数据:', {
ciphertext: encryptedData.ciphertext.toString('base64'),
encryptionId: encryptedData.encryptionId
});
// 稍后,解密数据(需要适当的授权)
const decryptedData = await sealClient.decrypt({
ciphertext: encryptedData.ciphertext,
encryptionId: encryptedData.encryptionId,
recipientId: recipientAddress
});
console.log('解密数据:', decryptedData.toString('utf-8'));
} catch (error) {
console.error('加密/解密失败:', error);
}
}
basicExample();
使用 Sui 智能合约的访问控制
Seal 的真正威力来自可编程访问控制。让我们创建一个时间锁定加密示例,其中数据只能在特定时间后解密。
步骤 1:部署访问控制合约
首先,我们需要一个定义访问策略的 Move 智能合约:
// contracts/time_lock.move
module time_lock::policy {
use sui::clock::{Self, Clock};
use sui::object::{Self, UID};
use sui::tx_context::{Self, TxContext};
public struct TimeLockPolicy has key, store {
id: UID,
unlock_time: u64,
authorized_user: address,
}
public fun create_time_lock(
unlock_time: u64,
authorized_user: address,
ctx: &mut TxContext
): TimeLockPolicy {
TimeLockPolicy {
id: object::new(ctx),
unlock_time,
authorized_user,
}
}
public fun can_decrypt(
policy: &TimeLockPolicy,
user: address,
clock: &Clock
): bool {
let current_time = clock::timestamp_ms(clock);
policy.authorized_user == user && current_time >= policy.unlock_time
}
}
步骤 2:与 Seal 集成
// src/time-locked-encryption.ts
import { createSealClient } from './seal-client';
import { TransactionBlock } from '@mysten/sui/transactions';
async function createTimeLocked() {
const { sealClient, suiClient } = await createSealClient();
// 在 Sui 上创建访问策略
const txb = new TransactionBlock();
const unlockTime = Date.now() + 60000; // 1分钟后解锁
const authorizedUser = "0x742d35cc6d4c0c08c0f9bf3c9b2b6c64b3b4f5c6d7e8f9a0b1c2d3e4f5a6b7c8";
txb.moveCall({
target: 'time_lock::policy::create_time_lock',
arguments: [
txb.pure(unlockTime),
txb.pure(authorizedUser)
]
});
// 执行交易创建策略
const result = await suiClient.signAndExecuteTransactionBlock({
transactionBlock: txb,
signer: yourKeypair, // 你的 Sui 密钥对
});
const policyId = result.objectChanges?.find(
change => change.type === 'created'
)?.objectId;
// 现在使用此策略加密
const sensitiveData = "这将在1分钟后解锁!";
const encryptedData = await sealClient.encrypt({
data: Buffer.from(sensitiveData, 'utf-8'),
recipientId: authorizedUser,
accessPolicy: {
policyId,
policyType: 'time_lock'
}
});
console.log('时间锁定数据已创建。请在1分钟后尝试解密。');
return {
encryptedData,
policyId,
unlockTime
};
}
实际示例
示例 1:安全消息应用程序
// src/secure-messaging.ts
import { createSealClient } from './seal-client';
class SecureMessenger {
private sealClient: any;
constructor(sealClient: any) {
this.sealClient = sealClient;
}
async sendMessage(
message: string,
recipientAddress: string,
senderKeypair: any
) {
const messageData = {
content: message,
timestamp: Date.now(),
sender: senderKeypair.toSuiAddress(),
messageId: crypto.randomUUID()
};
const encryptedMessage = await this.sealClient.encrypt({
data: Buffer.from(JSON.stringify(messageData), 'utf-8'),
recipientId: recipientAddress,
metadata: {
type: 'secure_message',
sender: senderKeypair.toSuiAddress()
}
});
// 将加密消息存储在去中心化存储(Walrus)上
return this.storeOnWalrus(encryptedMessage);
}
async readMessage(encryptionId: string, recipientKeypair: any) {
// 从存储中检索
const encryptedData = await this.retrieveFromWalrus(encryptionId);
// 使用 Seal 解密
const decryptedData = await this.sealClient.decrypt({
ciphertext: encryptedData.ciphertext,
encryptionId: encryptedData.encryptionId,
recipientId: recipientKeypair.toSuiAddress()
});
return JSON.parse(decryptedData.toString('utf-8'));
}
private async storeOnWalrus(data: any) {
// 与 Walrus 存储的集成
// 这将把加密数据上传到 Walrus
// 并返回用于检索的 blob ID
}
private async retrieveFromWalrus(blobId: string) {
// 使用 blob ID 从 Walrus 检索加密数据
}
}
示例 2:代币门控内容平台
// src/gated-content.ts
import { createSealClient } from './seal-client';
class ContentGating {
private sealClient: any;
private suiClient: any;
constructor(sealClient: any, suiClient: any) {
this.sealClient = sealClient;
this.suiClient = suiClient;
}
async createGatedContent(
content: string,
requiredNftCollection: string,
creatorKeypair: any
) {
// 创建 NFT 所有权策略
const accessPolicy = await this.createNftPolicy(
requiredNftCollection,
creatorKeypair
);
// 使用 NFT 访问要求加密内容
const encryptedContent = await this.sealClient.encrypt({
data: Buffer.from(content, 'utf-8'),
recipientId: 'nft_holders', // NFT 持有者的特殊接收 者
accessPolicy: {
policyId: accessPolicy.policyId,
policyType: 'nft_ownership'
}
});
return {
contentId: encryptedContent.encryptionId,
accessPolicy: accessPolicy.policyId
};
}
async accessGatedContent(
contentId: string,
userAddress: string,
userKeypair: any
) {
// 首先验证 NFT 所有权
const hasAccess = await this.verifyNftOwnership(
userAddress,
contentId
);
if (!hasAccess) {
throw new Error('访问被拒绝:未找到所需的 NFT');
}
// 解密内容
const decryptedContent = await this.sealClient.decrypt({
encryptionId: contentId,
recipientId: userAddress
});
return decryptedContent.toString('utf-8');
}
private async createNftPolicy(collection: string, creator: any) {
// 创建检查 NFT 所有权的 Move 合约
// 返回策略对象 ID
}
private async verifyNftOwnership(user: string, contentId: string) {
// 检查用户是否拥有所需的 NFT
// 查询 Sui 的 NFT 所有权
}
}
示例 3:时间锁定资产转移
// src/time-locked-transfer.ts
import { createSealClient } from './seal-client';
async function createTimeLockTransfer(
assetData: any,
recipientAddress: string,
unlockTimestamp: number,
senderKeypair: any
) {
const { sealClient, suiClient } = await createSealClient();
// 在 Sui 上创建时间锁定策略
const timeLockPolicy = await createTimeLockPolicy(
unlockTimestamp,
recipientAddress,
senderKeypair,
suiClient
);
// 加密资产转移数据
const transferData = {
asset: assetData,
recipient: recipientAddress,
unlockTime: unlockTimestamp,
transferId: crypto.randomUUID()
};
const encryptedTransfer = await sealClient.encrypt({
data: Buffer.from(JSON.stringify(transferData), 'utf-8'),
recipientId: recipientAddress,
accessPolicy: {
policyId: timeLockPolicy.policyId,
policyType: 'time_lock'
}
});
console.log(`资产锁定至 ${new Date(unlockTimestamp)}`);
return {
transferId: encryptedTransfer.encryptionId,
unlockTime: unlockTimestamp,
policyId: timeLockPolicy.policyId
};
}
async function claimTimeLockTransfer(
transferId: string,
recipientKeypair: any
) {
const { sealClient } = await createSealClient();
try {
const decryptedData = await sealClient.decrypt({
encryptionId: transferId,
recipientId: recipientKeypair.toSuiAddress()
});
const transferData = JSON.parse(decryptedData.toString('utf-8'));
// 处理资产转移
console.log('资产转移已解锁:', transferData);
return transferData;
} catch (error) {
console.error('转移尚未解锁或访问被拒绝:', error);
throw error;
}
}
与 Walrus 去中心化存储的集成
Seal 与 Sui 的去中心化存储解决方案 Walrus 无缝协作。以下是如何集成两者:
// src/walrus-integration.ts
import { createSealClient } from './seal-client';
class SealWalrusIntegration {
private sealClient: any;
private walrusClient: any;
constructor(sealClient: any, walrusClient: any) {
this.sealClient = sealClient;
this.walrusClient = walrusClient;
}
async storeEncryptedData(
data: Buffer,
recipientAddress: string,
accessPolicy?: any
) {
// 使用 Seal 加密
const encryptedData = await this.sealClient.encrypt({
data,
recipientId: recipientAddress,
accessPolicy
});
// 在 Walrus 上存储加密数据
const blobId = await this.walrusClient.store(
encryptedData.ciphertext
);
// 返回包含 Seal 和 Walrus 信息的引用
return {
blobId,
encryptionId: encryptedData.encryptionId,
accessPolicy: encryptedData.accessPolicy
};
}
async retrieveAndDecrypt(
blobId: string,
encryptionId: string,
userKeypair: any
) {
// 从 Walrus 检索
const encryptedData = await this.walrusClient.retrieve(blobId);
// 使用 Seal 解密
const decryptedData = await this.sealClient.decrypt({
ciphertext: encryptedData,
encryptionId,
recipientId: userKeypair.toSuiAddress()
});
return decryptedData;
}
}
// 使用示例
async function walrusExample() {
const { sealClient } = await createSealClient();
const walrusClient = new WalrusClient('https://walrus-testnet.sui.io');
const integration = new SealWalrusIntegration(sealClient, walrusClient);
const fileData = Buffer.from('重要文档内容');
const recipientAddress = '0x...';
// 存储加密数据
const result = await integration.storeEncryptedData(
fileData,
recipientAddress
);
console.log('已存储,Blob ID:', result.blobId);
// 稍后,检索并解密
const decrypted = await integration.retrieveAndDecrypt(
result.blobId,
result.encryptionId,
recipientKeypair
);
console.log('检索到的数据:', decrypted.toString());
}
门限加密高级配置
对于生产应用程序,你需要配置具有多个密钥服务器的自定义门限加密:
// src/advanced-threshold.ts
import { SealClient } from '@mysten/seal';
async function setupProductionSeal() {
// 配置多个独立的密钥服务器
const keyServers = [
'https://keyserver-1.your-org.com',
'https://keyserver-2.partner-org.com',
'https://keyserver-3.third-party.com',
'https://keyserver-4.backup-provider.com',
'https://keyserver-5.fallback.com'
];
const sealClient = new SealClient({
keyServers,
threshold: 3, // 3-of-5 门限
network: 'mainnet',
// 高级选项
retryAttempts: 3,
timeoutMs: 10000,
backupKeyServers: [
'https://backup-1.emergency.com',
'https://backup-2.emergency.com'
]
});
return sealClient;
}
async function robustEncryption() {
const sealClient = await setupProductionSeal();
const criticalData = "关键任务加密数据";
// 以高安全保证进行加密
const encrypted = await sealClient.encrypt({
data: Buffer.from(criticalData, 'utf-8'),
recipientId: '0x...',
// 要求所有5个服务器以获得最大安全性
customThreshold: 5,
// 添加冗余
redundancy: 2,
accessPolicy: {
// 多因子要求
requirements: ['nft_ownership', 'time_lock', 'multisig_approval']
}
});
return encrypted;
}
安全最佳实践
1. 密钥管理
// src/security-practices.ts
// 正确:使用安全的密钥派生
import { generateKeypair } from '@mysten/sui/cryptography/ed25519';
const keypair = generateKeypair();
// 正确:安全地存储密钥(使用环境变量的示例)
const keypair = Ed25519Keypair.fromSecretKey(
process.env.PRIVATE_KEY
);
// 错误:永远不要硬编码密钥
const badKeypair = Ed25519Keypair.fromSecretKey(
"hardcoded-secret-key-12345" // 不要这样做!
);
2. 访问策略验证
// 在加密前始终验证访问策略
async function secureEncrypt(data: Buffer, recipient: string) {
const { sealClient } = await createSealClient();
// 验证接收者地址
if (!isValidSuiAddress(recipient)) {
throw new Error('无效的接收者地址');
}
// 检查策略是否存在且有效
const policy = await validateAccessPolicy(policyId);
if (!policy.isValid) {
throw new Error('无效的访问策略');
}
return sealClient.encrypt({
data,
recipientId: recipient,
accessPolicy: policy
});
}
3. 错误处理和回退机制
// 健壮的错误处理
async function resilientDecrypt(encryptionId: string, userKeypair: any) {
const { sealClient } = await createSealClient();
try {
return await sealClient.decrypt({
encryptionId,
recipientId: userKeypair.toSuiAddress()
});
} catch (error) {
if (error.code === 'ACCESS_DENIED') {
throw new Error('访问被拒绝:请检查你的权限');
} else if (error.code === 'KEY_SERVER_UNAVAILABLE') {
// 尝试使用备份配置
return await retryWithBackupServers(encryptionId, userKeypair);
} else if (error.code === 'THRESHOLD_NOT_MET') {
throw new Error('可用的密钥服务器不足');
} else {
throw new Error(`解密失败:${error.message}`);
}
}
}
4. 数据验证
// 在加密前验证数据
function validateDataForEncryption(data: Buffer): boolean {
// 检查大小限制
if (data.length > 1024 * 1024) { // 1MB 限制
throw new Error('数据太大,无法加密');
}
// 检查敏感模式(可选)
const dataStr = data.toString();
if (containsSensitivePatterns(dataStr)) {
console.warn('警告:数据包含潜在的敏感模式');
}
return true;
}
性能优化
1. 批处理操作
// 批量多个加密以提高效率
async function batchEncrypt(dataItems: Buffer[], recipients: string[]) {
const { sealClient } = await createSealClient();
const promises = dataItems.map((data, index) =>
sealClient.encrypt({
data,
recipientId: recipients[index]
})
);
return Promise.all(promises);
}
2. 缓存密钥服务器响应
// 缓存密钥服务器会话以减少延迟
class OptimizedSealClient {
private sessionCache = new Map();
async encryptWithCaching(data: Buffer, recipient: string) {
let session = this.sessionCache.get(recipient);
if (!session || this.isSessionExpired(session)) {
session = await this.createNewSession(recipient);
this.sessionCache.set(recipient, session);
}
return this.encryptWithSession(data, session);
}
}
测试你的 Seal 集成
单元测试
// tests/seal-integration.test.ts
import { describe, it, expect } from 'jest';
import { createSealClient } from '../src/seal-client';
describe('Seal 集成', () => {
it('应该成功加密和解密数据', async () => {
const { sealClient } = await createSealClient();
const testData = Buffer.from('测试消息');
const recipient = '0x742d35cc6d4c0c08c0f9bf3c9b2b6c64b3b4f5c6d7e8f9a0b1c2d3e4f5a6b7c8';
const encrypted = await sealClient.encrypt({
data: testData,
recipientId: recipient
});
expect(encrypted.encryptionId).toBeDefined();
expect(encrypted.ciphertext).toBeDefined();
const decrypted = await sealClient.decrypt({
ciphertext: encrypted.ciphertext,
encryptionId: encrypted.encryptionId,
recipientId: recipient
});
expect(decrypted.toString()).toBe('测试消息');
});
it('应该强制执行访问控制策略', async () => {
// 测试未授权用户无法解密
const { sealClient } = await createSealClient();
const encrypted = await sealClient.encrypt({
data: Buffer.from('秘密'),
recipientId: 'authorized-user'
});
await expect(
sealClient.decrypt({
ciphertext: encrypted.ciphertext,
encryptionId: encrypted.encryptionId,
recipientId: 'unauthorized-user'
})
).rejects.toThrow('访问被拒绝');
});
});
部署到生产环境
环境配置
// config/production.ts
export const productionConfig = {
keyServers: [
process.env.KEY_SERVER_1,
process.env.KEY_SERVER_2,
process.env.KEY_SERVER_3,
process.env.KEY_SERVER_4,
process.env.KEY_SERVER_5
],
threshold: 3,
network: 'mainnet',
suiRpc: process.env.SUI_RPC_URL,
walrusGateway: process.env.WALRUS_GATEWAY,
// 安全设置
maxDataSize: 1024 * 1024, // 1MB
sessionTimeout: 3600000, // 1小时
retryAttempts: 3
};
监控和日志记录
// utils/monitoring.ts
export class SealMonitoring {
static logEncryption(encryptionId: string, recipient: string) {
console.log(`[SEAL] 为 ${recipient} 加密数据 ${encryptionId}`);
// 发送到你的监控服务
}
static logDecryption(encryptionId: string, success: boolean) {
console.log(`[SEAL] 解密 ${encryptionId}:${success ? '成功' : '失败'}`);
}
static logKeyServerHealth(serverUrl: string, status: string) {
console.log(`[SEAL] 密钥服务器 ${serverUrl}:${status}`);
}
}
资源和后续步骤
官方文档
- Seal 文档: https://seal-docs.wal.app/
- GitHub 仓库: https://github.com/MystenLabs/seal
- Sui 文档: https://docs.sui.io/
- Walrus 文档: https://docs.wal.app/
社区和支持
- Sui Discord: 加入 #seal 频道获得社区支持
- GitHub Issues: 报告错误和请求功能
- 开发者论坛: Sui 社区论坛进行讨论
要探索的高级主题
- 自定义访问策略:使用 Move 合约构建复杂的授权逻辑
- 跨链集成:将 Seal 与其他区块链网络一起使用
- 企业密钥管理:设置你自己的密钥服务器基础设施
- 审计和合规:为受监管环境实施日志记录和监控
示例应用程序
- 安全聊天应用:使用 Seal 的端到端加密消息传递
- 文档管理:具有访问控制的企业文档共享
- 数字版权管理:具有使用策略的内容分 发
- 隐私保护分析:加密数据处理工作流
结论
Seal 代表了朝着使隐私和加密成为 Web3 中基础设施级关注点的根本转变。通过结合基于身份的加密、门限安全和可编程访问控制,它为开发者提供了构建真正安全和去中心化应用程序的强大工具。
使用 Seal 构建的主要优势包括:
- 无单点故障:分布式密钥服务器消除了中央权威
- 可编程安全:基于智能合约的访问策略提供灵活的授权
- 开发者友好:TypeScript SDK 与现有的 Web3 工具无缝集成
- 存储无关:与 Walrus、IPFS 或任何存储解决方案配合使用
- 生产就绪:由 Mysten Labs 构建,具有企业安全标准
无论你是在保护用户数据、实施订阅模型还是构建复杂的多方应用程序,Seal 都提供了你需要的加密原语和访问控制基础设施,让你可以放心地构建。
今天就开始构建,加入越来越多的开发者生态系统,让隐私成为公共基础设施的基本组成部分。
准备开始构建了吗? 安装 @mysten/seal 并开始尝试本教程中的示例。去中心化网络正在等待将隐私和安全放在首位的应用程序。