Skip to content

Access Control Module

The access_control module provides cryptographic access control for encrypted documents without storing keys on-chain. It uses commitment-based access management that automatically transfers with token ownership.

Overview

Access control ensures that only token owners can access encrypted documents. The system:

  • Never stores encryption keys on-chain
  • Uses cryptographic commitments instead
  • Automatically transfers access with token ownership
  • Emits events for off-chain key distribution

Key Structures

AccessRegistry

Shared registry for access records:

public struct AccessRegistry has key {
    id: UID,
    records: Table<address, AccessRecord>,  // Maps token address to access record
    total_records: u64,
}

AccessRecord

Access control record:

public struct AccessRecord has store {
    token_address: address,
    key_commitment: vector<u8>,             // Commitment to encryption key
    blob_id: String,                       // Walrus blob ID reference
    version_index: u64,                    // Document version index
    created_at: u64,
    updated_at: u64,
}

AccessProof

Proof of ownership for access verification:

public struct AccessProof has store {
    token_address: address,
    owner: address,
    timestamp: u64,
}

Main Functions

register_access()

Register access control with key commitment:

public entry fun register_access(
    registry: &mut AccessRegistry,
    token_address: address,
    key_commitment: vector<u8>,
    blob_id: String,
    version_index: u64,
    ctx: &mut TxContext
)

Parameters:

  • registry: Mutable reference to AccessRegistry
  • token_address: Address of RWA token
  • key_commitment: Cryptographic commitment to encryption key
  • blob_id: Walrus blob ID
  • version_index: Document version index
  • ctx: Transaction context

Effects:

  • Creates AccessRecord
  • Increments total_records
  • Emits AccessRecordCreated event

verify_and_grant_access()

Verify token ownership and grant access:

public fun verify_and_grant_access(
    registry: &AccessRegistry,
    token: &RwaToken,
    token_address: address
): AccessProof

Requirements:

  • Caller must own the RWA token
  • Access record must exist

Returns: AccessProof struct

Effects:

  • Verifies ownership on-chain
  • Emits AccessGranted event
  • Off-chain systems can monitor events to distribute keys

get_access_record()

Read access record details:

public fun get_access_record(
    registry: &AccessRegistry,
    token_address: address
): AccessRecord

Returns: AccessRecord if exists

Key Commitment Scheme

The key commitment is computed as:

key_commitment = hash(secret || blob_id || version_index)

Where:

  • secret: Secret value known only to document issuer
  • blob_id: Walrus blob ID (public)
  • version_index: Document version (public)

Access Flow

Registration Flow

  1. Issuer encrypts document with key
  2. Computes key commitment
  3. Registers commitment on-chain
  4. Stores encrypted key off-chain (indexer/backend)
  5. Key encrypted with token owner's public key

Access Flow

  1. Token owner calls verify_and_grant_access()
  2. Smart contract verifies ownership
  3. Smart contract emits AccessGranted event
  4. Off-chain system monitors event
  5. Off-chain system retrieves encrypted key
  6. Key decrypted and provided to owner

Transfer Flow

  1. Token transferred to new owner
  2. New owner calls verify_and_grant_access()
  3. Event emitted with new owner address
  4. Off-chain system updates key encryption
  5. New owner receives access

Events

AccessRecordCreated

public struct AccessRecordCreated has copy, drop {
    token_address: address,
    key_commitment: vector<u8>,
    blob_id: String,
    timestamp: u64,
}

AccessGranted

public struct AccessGranted has copy, drop {
    token_address: address,
    owner: address,
    timestamp: u64,
}

Security Model

On-Chain

  • Commitments Only: No keys stored on-chain
  • Ownership Verification: Smart contract verifies token ownership
  • Event-Based: Events trigger off-chain key distribution

Off-Chain

  • Key Storage: Encrypted keys stored off-chain
  • Event Monitoring: Indexer monitors AccessGranted events
  • Key Encryption: Keys encrypted per owner
  • Access Control: Only verified owners receive keys

Integration with Vault

Access control integrates with both vault modules:

Regular Vault

// Vault stores access_key in DocumentVersion
// Access control provides additional layer
// Key commitment can be verified against vault

ZK Vault

// ZK vault stores encrypted access_key
// Access control provides ownership verification
// ZK proofs can prove ownership without revealing

Usage Examples

Register Access

sui client call \
  --package <PACKAGE_ID> \
  --module access_control \
  --function register_access \
  --args <REGISTRY_ID> <TOKEN_ADDRESS> "[<KEY_COMMITMENT>]" "<BLOB_ID>" 0 \
  --gas-budget 10000000

Verify and Grant Access

const tx = new TransactionBlock();
tx.moveCall({
  target: `${PACKAGE_ID}::access_control::verify_and_grant_access`,
  arguments: [
    tx.object(ACCESS_REGISTRY_ID),
    tx.object(tokenId),
    tx.pure.address(tokenAddress),
  ],
});
await suiClient.signAndExecuteTransactionBlock({
  signer: keypair,
  transactionBlock: tx,
});

Event Monitoring

Off-chain systems should monitor AccessGranted events:

const events = await suiClient.subscribeEvent({
  filter: {
    Package: PACKAGE_ID,
  },
  onMessage: (event) => {
    if (event.type === 'AccessGranted') {
      // Retrieve encrypted key
      // Decrypt for owner
      // Provide access
    }
  },
});

Benefits

Security

  • Keys never exposed on-chain
  • Ownership verified cryptographically
  • Commitment prevents key reconstruction

Flexibility

  • Works with any encryption scheme
  • Compatible with ZK proofs
  • Supports multiple access patterns

Automation

  • Automatic transfer with ownership
  • Event-based key distribution
  • No manual key management

Best Practices

  1. Secret Management: Store secrets securely off-chain
  2. Commitment Strength: Use cryptographically secure hash functions
  3. Event Monitoring: Reliable off-chain event monitoring
  4. Key Encryption: Encrypt keys per owner
  5. Access Logging: Log all access grants for audit

Comparison with Direct Key Storage

ApproachOn-Chain KeysAccess Control Module
Key StorageStored directlyCommitment only
PrivacyLowerHigher
FlexibilityLimitedHigh
ComplexitySimpleMore complex
Off-Chain RequiredNoYes (for key distribution)

Next Steps