Skip to main content

Command Palette

Search for a command to run...

EP 3: Walrus และ Seal เข้ารหัสข้อมูล สำหรับเนื้อหาสุดพิเศษ

ปูพื้นฐานระบบจัดการข้อมูลลับบน Sui ด้วย Seal และ Walrus

Updated
3 min read
EP 3: Walrus และ Seal เข้ารหัสข้อมูล สำหรับเนื้อหาสุดพิเศษ

สวัสดีครับ หายไปกันไปนาน 2-3 สัปดาห์ สาเหตุนั้นมีเพียงหนึ่งเดียวนั้นก็คือ งานเยอะจ้า ไม่รู้จะเยอะไปไหน ไม่ไหวจะเคลีย บทความเลยดองไว้สะนานเลย วันนี้กลับมาต่อกันละนะ ไม่แน่ใจว่าลืมกันไปแล้วยังกับ 2 EP ก่อนหน้านั้น

ไปทบทวนกันก่อนนะ สำหรับ EP นี้เราจะไปต่อกันที่การนำ Seal มาใช้ในการเข้าหรัสข้อมูลของเรานั้นเอง ซึ่งอย่างที่รู้กันว่า Blockchain ทุกคนสามารถเข้าถึงและตรวจสอบได้ แต่กลายเป็นปัญหาใหญ่สำหรับแอปพลิเคชันที่ต้องจัดการข้อมูลที่ละเอียดอ่อน เช่น ข้อความส่วนตัว, ข้อมูลที่เป็นกรรมสิทธิ์, หรือ คอนเทนต์ลับ ของเรา! ถ้าทุกคนเห็นได้หมด ก็ไม่ Exclusive อะดิ

นี่แหละคือที่มาของ Seal ที่เราสามารถสร้างความเป็นส่วนตัว (Privacy) และการควบคุมการเข้าถึง (Access Control) บน Sui network ได้


Seal คืออะไร?

Seal คือ Decentralized Secrets Management (DSM) ที่ช่วยให้นักพัฒนาจัดการข้อมูลลับ (Secrets) ที่ถูกเข้ารหัสไว้ได้อย่างปลอดภัย โดยใช้ Key Servers บนเครือข่าย Sui Network เพื่อกำหนดและบังคับใช้นโยบายการเข้าถึงข้อมูลลับแบบ Trust-Minimized

Seal ออกแบบมาเพื่อให้:

  • ได้ Privacy แบบเดิม: เหมือนระบบเข้ารหัสข้อมูลทั่วไป

  • ได้ Security แบบ Web3: ไม่มี single point of failure, ตรวจสอบได้, trust-minimized

  • สร้าง dApps ที่ยังคงความ Private ได้ บนระบบ Decentralized เต็มรูปแบบ

พูดง่าย ๆ คือ Seal = ความลับ + Decentralized + ควบคุมสิทธิ์ด้วย Smart Contract

ซึ่งด้วยความสามารถของ Seal นักพัฒนาก็จะสามารถสร้าง dApps ที่ยังมีความเป็นส่วนตัวของผู้ใช้ได้โดยไม่ต้องทิ้งความเป็น Decentralized ไปนั้นเอง

ภาพการทำงานของ Seal SDK

ทำไมต้องใช้ Seal + Walrus คู่กัน?

ระบบหน้าที่
Sealเข้ารหัสข้อมูลลับ + บังคับนโยบายผู้เข้าถึง
Walrusเก็บ payload ที่เข้ารหัสแบบ decentralized

พอละไปลุยกันเลยดีกว่า ไปเขียนโค๊ดกันเถอะ

เริ่มต้นใช้งาน Seal SDK

  1. ติดตั้ง Seal SDK

    ต้องติดตั้ง Seal SDK ก่อนเริ่มใช้งานนะ

     npm install @mysten/seal
    
  2. จากนั้นแก้ไขไฟล์ index.ts ของเราเพื่อเพิ่ม SealClient และตั้งค่า Public Key Servers สำหรับ Testnet นอกจากนี้เราจะสร้าง keypair เพิ่มอีกหนึ่งคู่สำหรับจำลองเป็น "ผู้รับ" คอนเทนต์ของเรา:

     // index.ts (เพิ่มโค้ดส่วนนี้)
     import { SealClient, SessionKey, EncryptedObject } from "@mysten/seal";
     import { Transaction } from "@mysten/sui/transactions";
     import { fromHex } from "@mysten/sui/utils";
    
     // Public key server object IDs สำหรับ Sui Testnet (นี่คือ Key Servers ที่จะช่วยจัดการกุญแจ)
     const KEY_SERVER_LIST_TESTNET = [
       "0x73d05d62c18d9374e3ea529e8e0ed6161da1a141a94d3f76ae3fe4e99356db75",
       "0xf5d14a81a982144ae441cd7d64b09027f116a468bd36e7eca494f750591623c8",
     ];
    
     // NOTE: แทนที่ด้วย Package ID ของ Smart Contract Move ที่เราจะ deploy ในอนาคต
     // ตอนนี้อาจจะยังไม่มี ก็ใช้ '0x...' ไปก่อนได้
     const PACKAGE_ID = "0x...";
    
     // ... โค้ดส่วน main() 
     async function main() {
     // สร้าง SealClient ของเรา
       const sealClient = new SealClient({
         suiClient: suiClient,
         serverConfigs: KEY_SERVER_LIST_TESTNET.map((id) => ({
           objectId: id,
           weight: 1,
         })),
         verifyKeyServers: true, // ตรวจสอบความถูกต้องของ Key Servers
       });
     }
    
  3. สร้าง ฟังก์ชัน ในการเข้ารหัสข้อมูล

     async function sendSecretMessage(params: { secret: string; recipient: string; sender: Ed25519Keypair; suiClient: SuiClient; walrusClient: any; sealClient: SealClient }): Promise<string> {
         const { secret, recipient, sender, suiClient, walrusClient, sealClient } = params;
    
         console.log(`\nกำลังเข้ารหัสคอนเทนต์ลับสำหรับ ${recipient}...`);
         const placeholderPolicyId = "0x" + "0".repeat(64);
    
         const { encryptedObject } = await sealClient.encrypt({
             threshold: 2,
             packageId: PACKAGE_ID,
             id: placeholderPolicyId,
             data: new TextEncoder().encode(secret),
         });
    
         console.log("กำลังอัปโหลดข้อมูลที่เข้ารหัสไป Walrus...");
         const walrusFile = WalrusFile.from({ contents: encryptedObject });
         const writeResult = await walrusClient.walrus.writeFiles({
             files: [walrusFile],
             signer: sender,
             epochs: 1,
             deletable: false,
         });
    
         const blobId = writeResult[0]?.blobId;
         if (!blobId) throw new Error("Failed to upload encrypted blob to Walrus");
    
         console.log(`Blob ที่เข้ารหัสถูกจัดเก็บแล้ว. Blob ID: ${blobId}`);
    
         console.log("กำลังสร้าง SecretMessage Policy Object บนเชน...");
         const tx = new Transaction();
         tx.moveCall({
             target: `${PACKAGE_ID}::message::create_secret_message`,
             arguments: [tx.pure.address(recipient), tx.pure.string(blobId)],
         });
         const result = await suiClient.signAndExecuteTransaction({
             signer: sender,
             transaction: tx,
             options: { showObjectChanges: true },
         });
         const created = result.objectChanges?.find((c) => c.type === "created" && "objectId" in c && c.objectType.includes("secret_message::message::SecretMessage"));
         if (!created || !("objectId" in created)) {
             throw new Error("SecretMessage object was not created");
         }
         return created.objectId;
     }
    
  4. เมื่อต้องการเรียกใช้งานเราสามารถเพิ่ม ฟังก์ชัน ในการใช้งานดังนี้

     async function main() {
      ...
      ...
      ...
      const secret = "My super secret message for you ❤️";
      const policyObjectId = await sendSecretMessage({
         secret,
         recipient,
         sender: keypair,
         suiClient,
         walrusClient,
         sealClient,
       });
       console.log(`✅ SecretMessage policy object id: ${policyObjectId}`);
     }
    

    สำหรับ recipient นั้นคือ address ของผู้รับนั้นเอง เราสามารถกำหนดได้เลยนะว่าจะส่งไปยัง address ไหน

เรียบร้อบ เราได้ฟังก์ชั่น ในการส่งข้อความเเบบเข้ารหัสไปยังปลายทางแล้วครับ แต่บอกไว้ก่อนเลยตัวอย่างโค๊ดชุดนี้ยังทำงานไม่ได้นะ :P เเน่ละสิ เพราะยังไม่ได้เขียน Move Smart Contract เลยนิ ทำให้เรายังไม่มี Package ID นั้นเอง ถ้านำไปทดสอบและ เรียกใช้งาน มันจะเเสดงข้อความ Error ทันที รอติดตาม EP นะ เราจะไปเขียน Move Smart Contract กัน