Construindo Criptografia Descentralizada com @mysten/seal: Tutorial para Desenvolvedores
A privacidade está se tornando infraestrutura pública. Em 2025, desenvolvedores precisam de ferramentas que tornem a criptografia tão fácil quanto armazenar dados. O Seal da Mysten Labs oferece exatamente isso—gerenciamento descentralizado de segredos com controle de acesso onchain. Este tutorial te ensinará como construir aplicações Web3 seguras usando criptografia baseada em identidade, segurança threshold e políticas de acesso programáveis.
Introdução: Por que o Seal Importa para Web3
Aplicações cloud tradicionais dependem de sistemas centralizados de gerenciamento de chaves onde um único provedor controla o acesso aos dados criptografados. Embora conveniente, isso cria pontos únicos perigosos de falha. Se o provedor for comprometido, ficar offline ou decidir restringir o acesso, seus dados se tornam inacessíveis ou vulneráveis.
Seal muda completamente esse paradigma. Construído pela Mysten Labs para a blockchain Sui, Seal é um serviço de gerenciamento descentralizado de segredos (DSM) que possibilita:
- Criptografia baseada em identidade onde o conteúdo é protegido antes de deixar seu ambiente
- Criptografia threshold que distribui acesso às chaves entre múltiplos nós independentes
- Controle de acesso onchain com time locks, token-gating e lógica de autorização customizada
- Design agnóstico de armazenamento que funciona com Walrus, IPFS ou qualquer solução de armazenamento
Seja construindo aplicações de mensagens seguras, plataformas de conteúdo restrito por tokens ou transferências de ativos com time lock, Seal fornece as primitivas criptográficas e infraestrutura de controle de acesso que você precisa.
Primeiros Passos
Pré-requisitos
Antes de mergulhar, certifique-se de ter:
- Node.js 18+ instalado
- Familiaridade básica com TypeScript/JavaScript
- Uma carteira Sui para testes (como Sui Wallet)
- Entendimento de conceitos blockchain
Instalação
Instale o SDK Seal via npm:
npm install @mysten/seal
Você também vai querer o SDK Sui para interações blockchain:
npm install @mysten/sui
Configuração do Projeto
Crie um novo projeto e inicialize-o:
mkdir seal-tutorial
cd seal-tutorial
npm init -y
npm install @mysten/seal @mysten/sui typescript @types/node
Crie uma configuração TypeScript simples:
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Conceitos Fundamentais: Como o Seal Funciona
Antes de escrever código, vamos entender a arquitetura do Seal:
1. Criptografia Baseada em Identidade (IBE)
Diferente da criptografia tradicional onde você criptografa para uma chave pública, IBE permite criptografar para uma identidade (como um endereço de email ou endereço Sui). O destinatário só pode descriptografar se conseguir provar que controla essa identidade.
2. Criptografia Threshold
Em vez de confiar em um único servidor de chaves, Seal usa esquemas t-of-n threshold. Você pode configurar 3-de-5 servidores de chaves, significando que qualquer 3 servidores podem cooperar para fornecer chaves de descriptografia, mas 2 ou menos não conseguem.
3. Controle de Acesso Onchain
Políticas de acesso são aplicadas por smart contracts da Sui. Antes que um servidor de chaves forneça chaves de descriptografia, ele verifica se o solicitante atende aos requisitos da política onchain (propriedade de tokens, restrições de tempo, etc.).
4. Rede de Servidores de Chaves
Servidores de chaves distribuídos validam políticas de acesso e geram chaves de descriptografia. Esses servidores são operados por diferentes partes para garantir que não haja um único ponto de controle.
Implementação Básica: Sua Primeira Aplicação Seal
Vamos construir uma aplicação simples que criptografa dados sensíveis e controla o acesso através de políticas blockchain da Sui.
Passo 1: Inicializar o Cliente Seal
// src/seal-client.ts
import { SealClient } from '@mysten/seal';
import { SuiClient } from '@mysten/sui/client';
export async function createSealClient() {
// Inicializar cliente Sui para testnet
const suiClient = new SuiClient({
url: 'https://fullnode.testnet.sui.io'
});
// Configurar cliente Seal com servidores de chaves da testnet
const sealClient = new SealClient({
suiClient,
keyServers: [
'https://keyserver1.seal-testnet.com',
'https://keyserver2.seal-testnet.com',
'https://keyserver3.seal-testnet.com'
],
threshold: 2, // threshold 2-de-3
network: 'testnet'
});
return { sealClient, suiClient };
}
Passo 2: Criptografia/Descriptografia Simples
// src/basic-encryption.ts
import { createSealClient } from './seal-client';
async function basicExample() {
const { sealClient } = await createSealClient();
// Dados para criptografar
const sensitiveData = "Esta é minha mensagem secreta!";
const recipientAddress = "0x742d35cc6d4c0c08c0f9bf3c9b2b6c64b3b4f5c6d7e8f9a0b1c2d3e4f5a6b7c8";
try {
// Criptografar dados para um endereço Sui específico
const encryptedData = await sealClient.encrypt({
data: Buffer.from(sensitiveData, 'utf-8'),
recipientId: recipientAddress,
// Opcional: adicionar metadados
metadata: {
contentType: 'text/plain',
timestamp: Date.now()
}
});
console.log('Dados criptografados:', {
ciphertext: encryptedData.ciphertext.toString('base64'),
encryptionId: encryptedData.encryptionId
});
// Depois, descriptografar os dados (requer autorização adequada)
const decryptedData = await sealClient.decrypt({
ciphertext: encryptedData.ciphertext,
encryptionId: encryptedData.encryptionId,
recipientId: recipientAddress
});
console.log('Dados descriptografados:', decryptedData.toString('utf-8'));
} catch (error) {
console.error('Falha na criptografia/descriptografia:', error);
}
}
basicExample();
Controle de Acesso com Smart Contracts da Sui
O verdadeiro poder do Seal vem do controle de acesso programável. Vamos criar um exemplo de criptografia com time lock onde os dados só podem ser descriptografados após um tempo específico.
Passo 1: Implementar Contrato de Controle de Acesso
Primeiro, precisamos de um smart contract Move que define nossa política de acesso:
// 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
}
}
Passo 2: Integrar com 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();
// Criar política de acesso na Sui
const txb = new TransactionBlock();
const unlockTime = Date.now() + 60000; // Desbloquear em 1 minuto
const authorizedUser = "0x742d35cc6d4c0c08c0f9bf3c9b2b6c64b3b4f5c6d7e8f9a0b1c2d3e4f5a6b7c8";
txb.moveCall({
target: 'time_lock::policy::create_time_lock',
arguments: [
txb.pure(unlockTime),
txb.pure(authorizedUser)
]
});
// Executar transação para criar política
const result = await suiClient.signAndExecuteTransactionBlock({
transactionBlock: txb,
signer: yourKeypair, // Seu keypair Sui
});
const policyId = result.objectChanges?.find(
change => change.type === 'created'
)?.objectId;
// Agora criptografar com esta política
const sensitiveData = "Isso será desbloqueado em 1 minuto!";
const encryptedData = await sealClient.encrypt({
data: Buffer.from(sensitiveData, 'utf-8'),
recipientId: authorizedUser,
accessPolicy: {
policyId,
policyType: 'time_lock'
}
});
console.log('Dados com time lock criados. Tente descriptografar após 1 minuto.');
return {
encryptedData,
policyId,
unlockTime
};
}
Exemplos Práticos
Exemplo 1: Aplicação de Mensagens Seguras
// 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()
}
});
// Armazenar mensagem criptografada em armazenamento descentralizado (Walrus)
return this.storeOnWalrus(encryptedMessage);
}
async readMessage(encryptionId: string, recipientKeypair: any) {
// Recuperar do armazenamento
const encryptedData = await this.retrieveFromWalrus(encryptionId);
// Descriptografar com 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) {
// Integração com armazenamento Walrus
// Isso faria upload dos dados criptografados para Walrus
// e retornaria o blob ID para recuperação
}
private async retrieveFromWalrus(blobId: string) {
// Recuperar dados criptografados do Walrus usando blob ID
}
}
Exemplo 2: Plataforma de Conteúdo com Token-Gating
// 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
) {
// Criar política de propriedade de NFT
const accessPolicy = await this.createNftPolicy(
requiredNftCollection,
creatorKeypair
);
// Criptografar conteúdo com requisito de acesso por NFT
const encryptedContent = await this.sealClient.encrypt({
data: Buffer.from(content, 'utf-8'),
recipientId: 'nft_holders', // Destinatário especial para portadores de NFT
accessPolicy: {
policyId: accessPolicy.policyId,
policyType: 'nft_ownership'
}
});
return {
contentId: encryptedContent.encryptionId,
accessPolicy: accessPolicy.policyId
};
}
async accessGatedContent(
contentId: string,
userAddress: string,
userKeypair: any
) {
// Verificar propriedade de NFT primeiro
const hasAccess = await this.verifyNftOwnership(
userAddress,
contentId
);
if (!hasAccess) {
throw new Error('Acesso negado: NFT necessário não encontrado');
}
// Descriptografar conteúdo
const decryptedContent = await this.sealClient.decrypt({
encryptionId: contentId,
recipientId: userAddress
});
return decryptedContent.toString('utf-8');
}
private async createNftPolicy(collection: string, creator: any) {
// Criar contrato Move que verifica propriedade de NFT
// Retorna ID do objeto de política
}
private async verifyNftOwnership(user: string, contentId: string) {
// Verificar se usuário possui NFT necessário
// Consultar Sui para propriedade de NFT
}
}
Exemplo 3: Transferência de Ativos com Time Lock
// 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();
// Criar política de time lock na Sui
const timeLockPolicy = await createTimeLockPolicy(
unlockTimestamp,
recipientAddress,
senderKeypair,
suiClient
);
// Criptografar dados de transferência de ativo
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(`Ativo bloqueado até ${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'));
// Processar a transferência de ativo
console.log('Transferência de ativo desbloqueada:', transferData);
return transferData;
} catch (error) {
console.error('Transferência ainda não desbloqueada ou acesso negado:', error);
throw error;
}
}