跳到主要内容

1 篇博文 含有标签「Seal」

查看所有标签

使用 @mysten/seal 构建去中心化加密:开发者教程

· 阅读需 14 分钟
Dora Noda
Software Engineer

隐私正在成为公共基础设施。在 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}`);
}
}

资源和后续步骤

官方文档

社区和支持

  • Sui Discord: 加入 #seal 频道获得社区支持
  • GitHub Issues: 报告错误和请求功能
  • 开发者论坛: Sui 社区论坛进行讨论

要探索的高级主题

  1. 自定义访问策略:使用 Move 合约构建复杂的授权逻辑
  2. 跨链集成:将 Seal 与其他区块链网络一起使用
  3. 企业密钥管理:设置您自己的密钥服务器基础设施
  4. 审计和合规:为受监管环境实施日志记录和监控

示例应用程序

  • 安全聊天应用:使用 Seal 的端到端加密消息传递
  • 文档管理:具有访问控制的企业文档共享
  • 数字版权管理:具有使用策略的内容分发
  • 隐私保护分析:加密数据处理工作流

结论

Seal 代表了朝着使隐私和加密成为 Web3 中基础设施级关注点的根本转变。通过结合基于身份的加密、门限安全和可编程访问控制,它为开发者提供了构建真正安全和去中心化应用程序的强大工具。

使用 Seal 构建的主要优势包括:

  • 无单点故障:分布式密钥服务器消除了中央权威
  • 可编程安全:基于智能合约的访问策略提供灵活的授权
  • 开发者友好:TypeScript SDK 与现有的 Web3 工具无缝集成
  • 存储无关:与 Walrus、IPFS 或任何存储解决方案配合使用
  • 生产就绪:由 Mysten Labs 构建,具有企业安全标准

无论您是在保护用户数据、实施订阅模型还是构建复杂的多方应用程序,Seal 都提供了您需要的加密原语和访问控制基础设施,让您可以放心地构建。

今天就开始构建,加入越来越多的开发者生态系统,让隐私成为公共基础设施的基本组成部分。


准备开始构建了吗? 安装 @mysten/seal 并开始尝试本教程中的示例。去中心化网络正在等待将隐私和安全放在首位的应用程序。