# Encryption and Decryption Process with Seal SDK and Walrus

The system uses Seal SDK for threshold encryption and Walrus for decentralized storage, enabling secure document sharing where only authorized parties (government addresses or registered users) can decrypt documents.\
\
Architecture Components\
\
1\. Smart Contract (Move)

```rust
The government_whitelist module manages access control:
move/// Check access policy for Seal decryption
fun check_policy(caller: address, encryption_id: vector<u8>, whitelist: &GovWhitelist): bool {
    // Check if the encryption_id has the right prefix (whitelist id)
    let prefix = object::uid_to_bytes(&whitelist.id);
    let mut i = 0;
    if (vector::length(&prefix) > vector::length(&encryption_id)) {
        return false
    };
    while (i < vector::length(&prefix)) {
        if (*vector::borrow(&prefix, i) != *vector::borrow(&encryption_id, i)) {
            return false
        };
        i = i + 1;
    };

    // Check if caller is government address (can access any document)
    if (table::contains(&whitelist.government_addresses, caller)) {
        return true
    };
    
    // Check if caller is a registered user
    if (table::contains(&whitelist.registered_users, caller)) {
        return true
    };
    
    false
}

/// Seal approval function - called by Seal network to verify access
entry fun seal_approve(
    encryption_id: vector<u8>,
    whitelist: &GovWhitelist,
    ctx: &TxContext
) {
    let caller = tx_context::sender(ctx);
    assert!(check_policy(caller, encryption_id, whitelist), ENoAccess);
}
```

\\

2. Encryption Process (encryptionService.ts)\\

   ```tsx
   Step 1: Generate Encryption ID
   The encryption ID format is [whitelist_id][random_nonce]:
   typescript// Generate encryption ID with whitelist prefix
   const nonce = crypto.getRandomValues(new Uint8Array(5));
   const policyObjectBytes = fromHex(GOVERNMENT_WHITELIST_ID);
   const encryptionId = toHex(new Uint8Array([...policyObjectBytes, ...nonce]));

   console.log('🔑 Generated Encryption ID:', encryptionId);
   console.log('📄 Encryption ID format: [whitelist_id][nonce]');
   Step 2: Initialize Seal Client
   typescriptconst serverObjectIds = [
     '0x73d05d62c18d9374e3ea529e8e0ed6161da1a141a94d3f76ae3fe4e99356db75',
     '0xf5d14a81a982144ae441cd7d64b09027f116a468bd36e7eca494f750591623c8',
     '0x6068c0acb197dddbacd4746a9de7f025b2ed5a5b6c1b1ab44dade4426d141da2',
     '0x5466b7df5c15b508678d51496ada8afab0d6f70a01c10613123382b1b8131007'
   ];

   const sealClient = new SealClient({
     suiClient: SUI_CLIENT,
     serverConfigs: serverObjectIds.map((id) => ({
       objectId: id,
       weight: 1,
     })),
     verifyKeyServers: false,
   });
   Step 3: Encrypt Document
   typescript// Convert file to ArrayBuffer
   const arrayBuffer = await file.arrayBuffer();
   const fileData = new Uint8Array(arrayBuffer);

   // Encrypt with Seal using threshold encryption
   const { encryptedObject: encryptedBytes } = await sealClient.encrypt({
     threshold: 2,  // Requires 2 key servers to decrypt
     packageId: PACKAGE_ID,
     id: encryptionId,
     data: fileData,
   });

   console.log('✅ Document encrypted successfully');
   console.log('📦 Encrypted data size:', encryptedBytes.length, 'bytes');
   Step 4: Upload to Walrus
   typescriptconst WALRUS_PUBLISHER_URL = 'http://68.183.40.65:3111';
   const NUM_EPOCH = 1;

   // Upload encrypted data to Walrus
   const url = ${WALRUS_PUBLISHER_URL}/v1/blobs?epochs=${NUM_EPOCH};
   const response = await fetch(url, {
     method: 'PUT',
     body: encryptedBytes,
   });

   if (response.status === 200) {
     const result = await response.json();
     
     // Extract blob information
     let blobId: string;
     let suiRef: string;
     
     if ('alreadyCertified' in result) {
       blobId = result.alreadyCertified.blobId;
       suiRef = result.alreadyCertified.event.txDigest;
     } else if ('newlyCreated' in result) {
       blobId = result.newlyCreated.blobObject.blobId;
       suiRef = result.newlyCreated.blobObject.id;
     }
     
     console.log('🆔 Blob ID:', blobId);
     console.log('🔗 Sui Reference:', suiRef);
   }
   ```

\\

3. Decryption Process (decryptionService.ts)\\

   ```typescript
   Step 1: Create Session Key
   typescriptconst TTL_MIN = 10;
   const sessionKey = new SessionKey({
     address: governmentAddress,
     packageId: PACKAGE_ID,
     ttlMin: TTL_MIN,
   });

   // Get user to sign personal message for authentication
   signPersonalMessage(
     {
       message: sessionKey.getPersonalMessage(),
     },
     {
       onSuccess: async (result) => {
         await sessionKey.setPersonalMessageSignature(result.signature);
         // Proceed with decryption...
       }
     }
   );
   Step 2: Create Move Call Constructor
   typescriptconst createMoveCallConstructor = (whitelistId: string): MoveCallConstructor => {
     return (tx: Transaction, encryptionId: string) => {
       tx.moveCall({
         target: ${PACKAGE_ID}::government_whitelist::seal_approve,
         arguments: [
           tx.pure.vector('u8', fromHex(encryptionId)),
           tx.object(whitelistId)
         ],
       });
     };
   };
   Step 3: Download from Walrus
   typescriptconst reliableAggregators = [
     'https://aggregator.walrus-testnet.walrus.space',
     'https://wal-aggregator-testnet.staketab.org',
     'https://aggregator.walrus.banansen.dev',
     'https://sui-walrus-tn-aggregator.bwarelabs.com'
   ];

   // Download encrypted file with retry logic
   for (const aggregatorBase of reliableAggregators) {
     try {
       const aggregatorUrl = ${aggregatorBase}/v1/blobs/${blobId};
       const response = await fetch(aggregatorUrl, { 
         signal: controller.signal,
         mode: 'cors'
       });
       
       if (response.ok) {
         const encryptedData = await response.arrayBuffer();
         console.log(✅ Successfully downloaded from ${aggregatorBase});
         break;
       }
     } catch (err) {
       console.log(Failed from ${aggregatorBase}:, err);
       continue;
     }
   }
   Step 4: Decrypt with Seal
   typescript// Convert downloaded data to Uint8Array
   const encryptedBytes = new Uint8Array(encryptedData);

   // Decrypt using Seal SDK with session key
   const decryptedData = await sealClient.decrypt({
     encryptedObject: encryptedBytes,
     sessionKey,
     moveCallConstructor,
     id: encryptionId, // Must match the encryption ID used during encryption
   });

   console.log('✅ Decryption successful');

   // Create blob URL for display
   const blob = new Blob([decryptedData], { type: 'image/jpeg' });
   const url = URL.createObjectURL(blob);
   ```
