Skip to main content

Verify Passport Offline

Overview

Verify a Passport and its delegations without network connectivity. Cryptographic verification happens locally using public keys and signatures—no API calls, no latency, no dependency on HUMΛN's infrastructure.

Why Offline Verification?

  • Zero Latency: Verification is instant (milliseconds, not seconds)
  • High Availability: Works even if HUMΛN's servers are down
  • Privacy: No network calls means no metadata leakage
  • Edge Computing: Perfect for IoT, mobile, and distributed systems
  • Compliance: Meet data residency requirements (data never leaves device)
  • Resilience: Continue operating during network outages

Think of it like: Checking a driver's license by looking at the hologram—you don't need to call the DMV to know it's authentic.

How Offline Verification Works

HUMΛN Passports use cryptographic proofs that can be verified without contacting a server:

  1. Public Key Infrastructure (PKI): Every Passport has a public/private key pair
  2. Signatures: Actions are signed with the private key
  3. Local Verification: Anyone with the public key can verify the signature
  4. Revocation Lists (CRLs): Downloaded periodically (optional) to check for revoked Passports

SDK Examples

typescript:TypeScript
```typescript
import { HumanOS } from '@human/sdk';

async function verifyPassportOffline(
  passportContainer: PassportContainer
) {
  try {
    // Verify cryptographic signature (no network required)
    const isValid = await HumanOS.Passport.verifyOffline({
      passportContainer: passportContainer,
      checkRevocation: false, // Skip network call for revocation check
    });
    
    if (!isValid) {
      throw new Error('Invalid Passport signature');
    }
    
    console.log(`✓ Passport verified offline: ${passportContainer.did}`);
    console.log(`  Issued by: ${passportContainer.issuer}`);
    console.log(`  Valid until: ${passportContainer.expiresAt}`);
    
    return isValid;
  } catch (error) {
    console.error("Offline verification failed:", error);
    throw error;
  }
}

// Example: Verify at edge device with no network
const passportData = {
  did: "did:human:alice-smith",
  publicKey: "0x7b3f9a2c...",
  signature: "0x9d4e1f8a...",
  issuer: "did:human:root-ca",
  expiresAt: "2027-01-10T00:00:00Z"
};

const isValid = await verifyPassportOffline(passportData);
```

python:Python
```python
from human_sdk import HumanOS

async def verify_passport_offline(
    passport_container: PassportContainer
):
    try:
        # Verify cryptographic signature (no network required)
        is_valid = await HumanOS.Passport.verify_offline(
            passport_container=passport_container,
            check_revocation=False  # Skip network call for revocation check
        )
        
        if not is_valid:
            raise Exception('Invalid Passport signature')
        
        print(f"✓ Passport verified offline: {passport_container.did}")
        print(f"  Issued by: {passport_container.issuer}")
        print(f"  Valid until: {passport_container.expires_at}")
        
        return is_valid
    except Exception as error:
        print(f"Offline verification failed: {error}")
        raise

# Example: Verify at edge device with no network
passport_data = {
    'did': 'did:human:alice-smith',
    'public_key': '0x7b3f9a2c...',
    'signature': '0x9d4e1f8a...',
    'issuer': 'did:human:root-ca',
    'expires_at': '2027-01-10T00:00:00Z'
}

# is_valid = await verify_passport_offline(passport_data)
```

go:Go
```go
package main

import (
    "fmt"
    "time"
    "github.com/human/sdk-go/humanos"
)

func verifyPassportOffline(passport *humanos.PassportContainer) (bool, error) {
    // Verify cryptographic signature (no network required)
    isValid, err := humanos.Passport.VerifyOffline(&humanos.VerifyOfflineRequest{
        PassportContainer: passport,
        CheckRevocation: false, // Skip network call
    })
    if err != nil {
        return false, fmt.Errorf("offline verification failed: %w", err)
    }
    
    if !isValid {
        return false, fmt.Errorf("invalid passport signature")
    }
    
    fmt.Printf("✓ Passport verified offline: %s\n", passport.DID)
    fmt.Printf("  Issued by: %s\n", passport.Issuer)
    fmt.Printf("  Valid until: %s\n", passport.ExpiresAt)
    
    return isValid, nil
}

// Example usage:
// passportData := &humanos.PassportContainer{
//     DID: "did:human:alice-smith",
//     PublicKey: "0x7b3f9a2c...",
//     Signature: "0x9d4e1f8a...",
//     Issuer: "did:human:root-ca",
//     ExpiresAt: time.Now().Add(365 * 24 * time.Hour),
// }
// isValid, err := verifyPassportOffline(passportData)
```

Verify Delegation Offline

Delegations can also be verified without network connectivity.

typescript:TypeScript
```typescript
async function verifyDelegationOffline(
  delegation: Delegation,
  action: string
) {
  // 1. Verify delegation signature
  const isValidSignature = await HumanOS.Passport.verifySignature({
    data: delegation,
    signature: delegation.signature,
    publicKey: delegation.grantorPublicKey
  });
  
  if (!isValidSignature) {
    throw new Error('Invalid delegation signature');
  }
  
  // 2. Check expiration (local time check, no network)
  const now = Date.now();
  const expiresAt = new Date(delegation.constraints.validUntil).getTime();
  
  if (now > expiresAt) {
    throw new Error('Delegation expired');
  }
  
  // 3. Check scope
  if (!delegation.scopes.includes(action)) {
    throw new Error(`Action '${action}' not authorized`);
  }
  
  console.log('✓ Delegation verified offline');
  console.log(`  Grantor: ${delegation.grantorDid}`);
  console.log(`  Delegatee: ${delegation.delegateeDid}`);
  console.log(`  Action '${action}' authorized`);
  
  return true;
}

// Example: IoT device verifies agent can control it
const delegation = {
  grantorDid: "did:human:alice-smith",
  delegateeDid: "did:human:agent:home-automation",
  scopes: ["iot:control:thermostat"],
  constraints: {
    validUntil: "2026-01-11T00:00:00Z"
  },
  signature: "0x9d4e1f8a...",
  grantorPublicKey: "0x7b3f9a2c..."
};

await verifyDelegationOffline(delegation, "iot:control:thermostat");
```

python:Python
```python
async def verify_delegation_offline(
    delegation: Delegation,
    action: str
):
    # 1. Verify delegation signature
    is_valid_signature = await HumanOS.Passport.verify_signature(
        data=delegation,
        signature=delegation.signature,
        public_key=delegation.grantor_public_key
    )
    
    if not is_valid_signature:
        raise Exception('Invalid delegation signature')
    
    # 2. Check expiration (local time check, no network)
    now = datetime.now()
    expires_at = datetime.fromisoformat(delegation.constraints.valid_until)
    
    if now > expires_at:
        raise Exception('Delegation expired')
    
    # 3. Check scope
    if action not in delegation.scopes:
        raise Exception(f"Action '{action}' not authorized")
    
    print('✓ Delegation verified offline')
    print(f"  Grantor: {delegation.grantor_did}")
    print(f"  Delegatee: {delegation.delegatee_did}")
    print(f"  Action '{action}' authorized")
    
    return True

# Example: IoT device verifies agent can control it
delegation = {
    'grantor_did': 'did:human:alice-smith',
    'delegatee_did': 'did:human:agent:home-automation',
    'scopes': ['iot:control:thermostat'],
    'constraints': {
        'valid_until': '2026-01-11T00:00:00Z'
    },
    'signature': '0x9d4e1f8a...',
    'grantor_public_key': '0x7b3f9a2c...'
}

# await verify_delegation_offline(delegation, 'iot:control:thermostat')
```

Use Cases

1. IoT & Edge Devices

Scenario: Smart home device verifies agent authority without internet connectivity.

typescript:TypeScript
```typescript
// Thermostat with intermittent connectivity
class SmartThermostat {
  async setTemperature(
    newTemp: number,
    agentPassport: PassportContainer,
    delegation: Delegation
  ) {
    // Verify offline (no network required)
    const isValidPassport = await HumanOS.Passport.verifyOffline({
      passportContainer: agentPassport,
      checkRevocation: false // Device may be offline
    });
    
    if (!isValidPassport) {
      throw new Error('Agent Passport verification failed');
    }
    
    // Verify delegation offline
    await this.verifyDelegationOffline(delegation, 'iot:control:thermostat');
    
    // Authorization confirmed - execute action
    this.temperature = newTemp;
    console.log(`✓ Temperature set to ${newTemp}°F by ${delegation.delegateeDid}`);
    
    // Log will sync to cloud when connectivity returns
    await this.logAction({
      action: 'set_temperature',
      agent: delegation.delegateeDid,
      value: newTemp,
      verified: 'offline',
      timestamp: Date.now()
    });
  }
}
```

python:Python
```python
# Thermostat with intermittent connectivity
class SmartThermostat:
    async def set_temperature(
        self,
        new_temp: float,
        agent_passport: PassportContainer,
        delegation: Delegation
    ):
        # Verify offline (no network required)
        is_valid_passport = await HumanOS.Passport.verify_offline(
            passport_container=agent_passport,
            check_revocation=False  # Device may be offline
        )
        
        if not is_valid_passport:
            raise Exception('Agent Passport verification failed')
        
        # Verify delegation offline
        await self.verify_delegation_offline(delegation, 'iot:control:thermostat')
        
        # Authorization confirmed - execute action
        self.temperature = new_temp
        print(f"✓ Temperature set to {new_temp}°F by {delegation.delegatee_did}")
        
        # Log will sync to cloud when connectivity returns
        await self.log_action({
            'action': 'set_temperature',
            'agent': delegation.delegatee_did,
            'value': new_temp,
            'verified': 'offline',
            'timestamp': datetime.now().isoformat()
        })
```

2. Mobile Apps with Spotty Connectivity

Scenario: Mobile app verifies user identity without network access.

typescript:TypeScript
```typescript
// Mobile app during airplane mode
async function unlockApp(userPassport: PassportContainer) {
  try {
    // Verify passport offline
    const isValid = await HumanOS.Passport.verifyOffline({
      passportContainer: userPassport,
      checkRevocation: false // No network available
    });
    
    if (!isValid) {
      throw new Error('Invalid Passport');
    }
    
    // Check expiration locally
    const now = Date.now();
    const expiresAt = new Date(userPassport.expiresAt).getTime();
    
    if (now > expiresAt) {
      throw new Error('Passport expired - please renew online');
    }
    
    console.log('✓ User authenticated offline');
    return { authenticated: true, did: userPassport.did };
    
  } catch (error) {
    console.log('✗ Offline authentication failed - network required');
    return { authenticated: false, requiresNetwork: true };
  }
}
```

python:Python
```python
# Mobile app during airplane mode
async def unlock_app(user_passport: PassportContainer):
    try:
        # Verify passport offline
        is_valid = await HumanOS.Passport.verify_offline(
            passport_container=user_passport,
            check_revocation=False  # No network available
        )
        
        if not is_valid:
            raise Exception('Invalid Passport')
        
        # Check expiration locally
        now = datetime.now()
        expires_at = datetime.fromisoformat(user_passport.expires_at)
        
        if now > expires_at:
            raise Exception('Passport expired - please renew online')
        
        print('✓ User authenticated offline')
        return {'authenticated': True, 'did': user_passport.did}
        
    except Exception as error:
        print('✗ Offline authentication failed - network required')
        return {'authenticated': False, 'requires_network': True}
```

3. High-Security Environments

Scenario: Air-gapped system verifies credentials without external connectivity.

typescript:TypeScript
```typescript
// Air-gapped secure facility
async function grantAccess(
  employeePassport: PassportContainer,
  accessDelegation: Delegation,
  facilityId: string
) {
  // CRITICAL: No network access allowed in this environment
  
  // 1. Verify Passport offline
  const passportValid = await HumanOS.Passport.verifyOffline({
    passportContainer: employeePassport,
    checkRevocation: false, // Use local CRL (Certificate Revocation List)
    crlCache: await loadLocalCRL() // Pre-downloaded revocation list
  });
  
  if (!passportValid) {
    await securityAlert('Invalid Passport presented');
    return { access: 'denied', reason: 'invalid_passport' };
  }
  
  // 2. Verify delegation for facility access
  const hasAccess = accessDelegation.scopes.includes(`facility:enter:${facilityId}`);
  
  if (!hasAccess) {
    await securityAlert('Unauthorized facility access attempt');
    return { access: 'denied', reason: 'insufficient_scope' };
  }
  
  // 3. Check local revocation list
  const isRevoked = await checkLocalCRL(employeePassport.did);
  
  if (isRevoked) {
    await securityAlert('Revoked credential presented');
    return { access: 'denied', reason: 'credential_revoked' };
  }
  
  console.log('✓ Access granted (verified offline)');
  return { access: 'granted', did: employeePassport.did };
}
```

python:Python
```python
# Air-gapped secure facility
async def grant_access(
    employee_passport: PassportContainer,
    access_delegation: Delegation,
    facility_id: str
):
    # CRITICAL: No network access allowed in this environment
    
    # 1. Verify Passport offline
    passport_valid = await HumanOS.Passport.verify_offline(
        passport_container=employee_passport,
        check_revocation=False,  # Use local CRL
        crl_cache=await load_local_crl()  # Pre-downloaded revocation list
    )
    
    if not passport_valid:
        await security_alert('Invalid Passport presented')
        return {'access': 'denied', 'reason': 'invalid_passport'}
    
    # 2. Verify delegation for facility access
    has_access = f'facility:enter:{facility_id}' in access_delegation.scopes
    
    if not has_access:
        await security_alert('Unauthorized facility access attempt')
        return {'access': 'denied', 'reason': 'insufficient_scope'}
    
    # 3. Check local revocation list
    is_revoked = await check_local_crl(employee_passport.did)
    
    if is_revoked:
        await security_alert('Revoked credential presented')
        return {'access': 'denied', 'reason': 'credential_revoked'}
    
    print('✓ Access granted (verified offline)')
    return {'access': 'granted', 'did': employee_passport.did}
```

Hybrid Approach: Offline with Periodic Sync

Best practice is verify offline, sync periodically:

typescript:TypeScript
```typescript
class OfflineVerifier {
  private crlCache: Set<string> = new Set(); // Revoked DIDs
  private lastSync: number = 0;
  private SYNC_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
  
  async verify(passport: PassportContainer): Promise<boolean> {
    // 1. Always verify signature offline (fast, no network)
    const isValidSignature = await HumanOS.Passport.verifyOffline({
      passportContainer: passport,
      checkRevocation: false
    });
    
    if (!isValidSignature) {
      return false;
    }
    
    // 2. Check local CRL cache
    if (this.crlCache.has(passport.did)) {
      console.log('✗ Passport revoked (local cache)');
      return false;
    }
    
    // 3. Sync CRL if stale (opportunistic, doesn't block)
    if (Date.now() - this.lastSync > this.SYNC_INTERVAL) {
      this.syncCRLInBackground();
    }
    
    return true;
  }
  
  private async syncCRLInBackground() {
    try {
      const crl = await HumanOS.Passport.downloadCRL();
      this.crlCache = new Set(crl.revokedDIDs);
      this.lastSync = Date.now();
      console.log(`✓ CRL synced: ${crl.revokedDIDs.length} revoked DIDs`);
    } catch (error) {
      // Network error - continue with stale cache
      console.log('CRL sync failed, using cached data');
    }
  }
}
```

python:Python
```python
class OfflineVerifier:
    def __init__(self):
        self.crl_cache: set = set()  # Revoked DIDs
        self.last_sync: float = 0
        self.SYNC_INTERVAL = 24 * 60 * 60  # 24 hours
    
    async def verify(self, passport: PassportContainer) -> bool:
        # 1. Always verify signature offline (fast, no network)
        is_valid_signature = await HumanOS.Passport.verify_offline(
            passport_container=passport,
            check_revocation=False
        )
        
        if not is_valid_signature:
            return False
        
        # 2. Check local CRL cache
        if passport.did in self.crl_cache:
            print('✗ Passport revoked (local cache)')
            return False
        
        # 3. Sync CRL if stale (opportunistic, doesn't block)
        if time.time() - self.last_sync > self.SYNC_INTERVAL:
            asyncio.create_task(self.sync_crl_in_background())
        
        return True
    
    async def sync_crl_in_background(self):
        try:
            crl = await HumanOS.Passport.download_crl()
            self.crl_cache = set(crl.revoked_dids)
            self.last_sync = time.time()
            print(f"✓ CRL synced: {len(crl.revoked_dids)} revoked DIDs")
        except Exception as error:
            # Network error - continue with stale cache
            print('CRL sync failed, using cached data')
```

Security Considerations

DO:

  • Verify signatures locally for speed and privacy
  • Cache Certificate Revocation Lists (CRLs) and sync periodically
  • Check expiration dates locally (no network required)
  • Use offline verification for latency-critical operations
  • Log verification events for audit trails

DON'T:

  • Skip revocation checks entirely (use cached CRLs)
  • Trust expired Passports (always check expiresAt locally)
  • Rely solely on offline verification for high-security scenarios (combine with periodic online checks)
  • Ignore signature validation errors (they indicate tampering)

Performance

Offline verification is orders of magnitude faster than online verification:

Verification Type Latency Network Required
Offline (signature only) ~5ms ❌ No
Offline + CRL check (cached) ~10ms ❌ No
Online (full verification) ~200ms ✅ Yes
smartphone:Edge IoT Devices|Verify sensor data signatures without network access in remote locations
bot:Autonomous Vehicles|Authenticate control commands offline for safety-critical operations
building:Air-Gapped Systems|Verify identities in secure facilities without external connectivity
zap:High-Frequency Trading|Sub-millisecond verification for financial transactions
do:Download and cache revocation lists (CRLs) periodically when online
do:Use time-bounded verification with expiry timestamps
do:Validate full certificate chains for trust verification
do:Implement fallback to online verification when critical
dont:Trust stale CRLs beyond their validity period
dont:Skip signature verification to save processing time
dont:Store private keys on verification-only devices
dont:Assume offline verification is sufficient for all use cases

Next Steps


See Also

← All patterns