Создание децентрализованного шифрования с @mysten/seal: Руководство для разработчиков
Конфиденциальность становится общественной инфраструктурой. В 2025 году разработчикам нужны инструменты, которые сделают шифрование таким же простым, как хранение данных. Seal от Mysten Labs предоставляет именно это — децентрализованное управление секретами с контролем доступа в блокчейне. Это руководство научит вас создавать безопасные Web3-приложения, используя шифрование на основе идентификаторов, пороговую безопасность и программируемые политики доступа.
Введение: Почему Seal важен для Web3
Традиционные облачные приложения полагаются на централизованные системы управления ключами, где один провайдер контролирует доступ к зашифрованным данным. Хотя это удобно, это создает опасные единые точки отказа. Если провайдер скомпрометирован, отключается или решает ограничить доступ, ваши данные становятся недоступными или уязвимыми.
Seal полностью меняет эту парадигму. Разработанный Mysten Labs для блокчейна Sui, Seal — это децентрализованный сервис управления секретами (DSM), который обеспечивает:
- Шифрование на основе идентификаторов, при котором контент защищается до того, как покинет вашу среду
- Пороговое шифрование, которое распределяет доступ к ключам между несколькими независимыми узлами
- Контроль доступа в блокчейне с временными блокировками, токен-гейтингом и настраиваемой логикой авторизации
- Независимый от хранилища дизайн, который работает с Walrus, IPFS или любым другим решением для хранения
Независимо от того, создаете ли вы безопасные приложения для обмена сообщениями, платформы с ограниченным доступом к контенту или переводы активов с временной блокировкой, Seal предоставляет необходимые криптографические примитивы и инфраструктуру контроля доступа.
Начало работы
Предварительные требования
Прежде чем приступить к работе, убедитесь, что у вас есть:
- Установленный Node.js 18+
- Базовое знакомство с TypeScript/JavaScript
- Кошелек Sui для тестирования (например, Sui Wallet)
- Понимание концепций блокчейна
Установка
Установите SDK Seal через npm:
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-из-n пороговые схемы. Вы можете настроить 3 из 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() {
// Initialize Sui client for testnet
const suiClient = new SuiClient({
url: "https://fullnode.testnet.sui.io",
});
// Configure Seal client with testnet key servers
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 threshold
network: "testnet",
});
return { sealClient, suiClient };
}
Шаг 2: Простое шифрование/дешифрование
// src/basic-encryption.ts
import { createSealClient } from "./seal-client";
async function basicExample() {
const { sealClient } = await createSealClient();
// Data to encrypt
const sensitiveData = "This is my secret message!";
const recipientAddress =
"0x742d35cc6d4c0c08c0f9bf3c9b2b6c64b3b4f5c6d7e8f9a0b1c2d3e4f5a6b7c8";
try {
// Encrypt data for a specific Sui address
const encryptedData = await sealClient.encrypt({
data: Buffer.from(sensitiveData, "utf-8"),
recipientId: recipientAddress,
// Optional: add metadata
metadata: {
contentType: "text/plain",
timestamp: Date.now(),
},
});
console.log("Encrypted data:", {
ciphertext: encryptedData.ciphertext.toString("base64"),
encryptionId: encryptedData.encryptionId,
});
// Later, decrypt the data (requires proper authorization)
const decryptedData = await sealClient.decrypt({
ciphertext: encryptedData.ciphertext,
encryptionId: encryptedData.encryptionId,
recipientId: recipientAddress,
});
console.log("Decrypted data:", decryptedData.toString("utf-8"));
} catch (error) {
console.error("Encryption/decryption failed:", 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();
// Create access policy on Sui
const txb = new TransactionBlock();
const unlockTime = Date.now() + 60000; // Unlock in 1 minute
const authorizedUser =
"0x742d35cc6d4c0c08c0f9bf3c9b2b6c64b3b4f5c6d7e8f9a0b1c2d3e4f5a6b7c8";
txb.moveCall({
target: "time_lock::policy::create_time_lock",
arguments: [txb.pure(unlockTime), txb.pure(authorizedUser)],
});
// Execute transaction to create policy
const result = await suiClient.signAndExecuteTransactionBlock({
transactionBlock: txb,
signer: yourKeypair, // Your Sui keypair
});
const policyId = result.objectChanges?.find(
(change) => change.type === "created",
)?.objectId;
// Now encrypt with this policy
const sensitiveData = "This will unlock in 1 minute!";
const encryptedData = await sealClient.encrypt({
data: Buffer.from(sensitiveData, "utf-8"),
recipientId: authorizedUser,
accessPolicy: {
policyId,
policyType: "time_lock",
},
});
console.log("Time-locked data created. Try decrypting after 1 minute.");
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(),
},
});
// Store encrypted message on decentralized storage (Walrus)
return this.storeOnWalrus(encryptedMessage);
}
async readMessage(encryptionId: string, recipientKeypair: any) {
// Retrieve from storage
const encryptedData = await this.retrieveFromWalrus(encryptionId);
// Decrypt with 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) {
// Integration with Walrus storage
// This would upload the encrypted data to Walrus
// and return the blob ID for retrieval
}
private async retrieveFromWalrus(blobId: string) {
// Retrieve encrypted data from Walrus using blob ID
}
}
Пример 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,
) {
// Create NFT ownership policy
const accessPolicy = await this.createNftPolicy(
requiredNftCollection,
creatorKeypair,
);
// Encrypt content with NFT access requirement
const encryptedContent = await this.sealClient.encrypt({
data: Buffer.from(content, "utf-8"),
recipientId: "nft_holders", // Special recipient for NFT holders
accessPolicy: {
policyId: accessPolicy.policyId,
policyType: "nft_ownership",
},
});
return {
contentId: encryptedContent.encryptionId,
accessPolicy: accessPolicy.policyId,
};
}
async accessGatedContent(
contentId: string,
userAddress: string,
userKeypair: any,
) {
// Verify NFT ownership first
const hasAccess = await this.verifyNftOwnership(userAddress, contentId);
if (!hasAccess) {
throw new Error("Access denied: Required NFT not found");
}
// Decrypt content
const decryptedContent = await this.sealClient.decrypt({
encryptionId: contentId,
recipientId: userAddress,
});
return decryptedContent.toString("utf-8");
}
private async createNftPolicy(collection: string, creator: any) {
// Create Move contract that checks NFT ownership
// Returns policy object ID
}
private async verifyNftOwnership(user: string, contentId: string) {
// Check if user owns required NFT
// Query Sui for NFT ownership
}
}
Пример 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();
// Create time-lock policy on Sui
const timeLockPolicy = await createTimeLockPolicy(
unlockTimestamp,
recipientAddress,
senderKeypair,
suiClient,
);
// Encrypt asset transfer data
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(`Asset locked until ${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"));
// Process the asset transfer
console.log("Asset transfer unlocked:", transferData);
return transferData;
} catch (error) {
console.error("Transfer not yet unlocked or access denied:", error);
throw error;
}
}