Installation

Install Bao with the right tool for your programming language.

pip install baolib
go get github.com/stregato/bao/lib
dart pub add bao
dart run bao:bootstrap
# Add to pom.xml or build.gradle
# Dependency details available on Maven Central

Basic Example: File Sharing

Alice and Bob want to share files securely. Here’s how it works step by step.

Step 1: Create Identities

Each person generates a private/public key pair to secure their communications.

from baolib import *

# Alice creates her identity
alice, alice_secret = newKeyPair()
print(f"Alice's public ID: {alice}")

# Bob creates his identity
bob, bob_secret = newKeyPair()
print(f"Bob's public ID: {bob}")
package main

import (
  "fmt"
  "github.com/stregato/bao/lib"
)

func main() {
  // Alice creates her identity
  alice, aliceSecret := lib.NewKeyPair()
  fmt.Println("Alice's public ID:", alice)

  // Bob creates his identity
  bob, bobSecret := lib.NewKeyPair()
  fmt.Println("Bob's public ID:", bob)
}
import 'package:bao/bao.dart';

void main() {
  // Alice creates her identity
  final (alice, aliceSecret) = newKeyPair();
  print('Alice public ID: $alice');

  // Bob creates his identity
  final (bob, bobSecret) = newKeyPair();
  print('Bob public ID: $bob');
}
import ink.francesco.bao.*;

public class QuickStart {
  public static void main(String[] args) {
    // Alice creates her identity
    var aliceKeyPair = IDs.newKeyPair();
    var alice = aliceKeyPair.publicID();
    var aliceSecret = aliceKeyPair.privateID();
    System.out.println("Alice's public ID: " + alice);

    // Bob creates his identity
    var bobKeyPair = IDs.newKeyPair();
    var bob = bobKeyPair.publicID();
    var bobSecret = bobKeyPair.privateID();
    System.out.println("Bob's public ID: " + bob);
  }
}

Step 2: Alice’s Side - Create Vault and Write

Alice sets up storage, creates a vault, grants Bob access, and writes a file.

from baolib import *
from pathlib import Path
import tempfile

# Configure cloud storage
store_config = {
    'type': 's3',
    'id': 'my-vault',
    's3': {
        'bucket': 'my-bucket',
        'endpoint': 's3.amazonaws.com',
        'prefix': 'bao',
        'auth': {
            'accessKeyId': 'your-key-id',
            'secretAccessKey': 'your-secret'
        }
    }
}
store = Store(store_config)

# Create a database for Alice's vault
db_alice = DB('sqlite3', 'alice_vault.db')

# Alice creates a vault (she already has alice and alice_secret from Step 1)
vault_alice = Vault.create(Vault.users, alice_secret, store, db_alice)

# Alice grants Bob access to her vault
vault_alice.sync_access(0, AccessChange(bob, Access.read_write))
print("Bob now has access to Alice's vault")

# Alice creates a file to share
tmp_file = Path(tempfile.mkdtemp()) / "message.txt"
tmp_file.write_text("Hello Bob! This is Alice.")

# Alice writes the file to the vault
file_info = vault_alice.write('shared/message.txt', src=str(tmp_file))
vault_alice.wait_files([file_info.id])
print(f"File written: {file_info.name}")
package main

import (
  "fmt"
  "os"
  "path/filepath"
  "github.com/stregato/bao/lib"
  "github.com/stregato/bao/lib/vault"
)

func main() {
  // Configure cloud storage
  store, err := lib.OpenStore(lib.StoreConfig{
    Type: "s3",
    Id:   "my-vault",
    S3: lib.S3Config{
      Bucket:   "my-bucket",
      Endpoint: "s3.amazonaws.com",
      Prefix:   "bao",
      Auth: lib.S3Auth{
        AccessKeyId:     "your-key-id",
        SecretAccessKey: "your-secret",
      },
    },
  })
  if err != nil {
    panic(err)
  }

  // Create a database for Alice's vault
  dbAlice, err := lib.OpenDB("sqlite3", "alice_vault.db", "")
  if err != nil {
    panic(err)
  }

  // Alice creates a vault (she already has alice and aliceSecret from Step 1)
  vaultAlice, err := vault.Create(vault.Users, aliceSecret, store, dbAlice, vault.Config{})
  if err != nil {
    panic(err)
  }

  // Alice grants Bob access to her vault
  err = vaultAlice.SyncAccess(0, vault.AccessChange{
    UserId: bob,
    Access: vault.ReadWrite,
  })
  if err != nil {
    panic(err)
  }
  fmt.Println("Bob now has access to Alice's vault")

  // Alice creates a file to share
  tmpDir := os.TempDir()
  tmpFile := filepath.Join(tmpDir, "message.txt")
  err = os.WriteFile(tmpFile, []byte("Hello Bob! This is Alice."), 0o600)
  if err != nil {
    panic(err)
  }

  // Alice writes the file to the vault
  fileInfo, err := vaultAlice.Write("shared/message.txt", tmpFile, nil, 0, nil)
  if err != nil {
    panic(err)
  }
  fmt.Println("File written:", fileInfo.Name)
}
import 'dart:io';
import 'package:bao/bao.dart';

void main() async {
  // Configure cloud storage
  final storeConfig = StoreConfig.s3(
    id: 'my-vault',
    bucket: 'my-bucket',
    endpoint: 's3.amazonaws.com',
    prefix: 'bao',
    accessKeyId: 'your-key-id',
    secretAccessKey: 'your-secret',
  );
  final store = await Store.open(storeConfig);

  // Create a database for Alice's vault
  final dbAlice = DB('alice_vault.db');

  // Alice creates a vault (she already has alice and aliceSecret from Step 1)
  final vaultAlice = await Vault.create(
    Vault.users,
    aliceSecret,
    store,
    dbAlice,
  );

  // Alice grants Bob access to her vault
  await vaultAlice.syncAccess(0, [
    AccessChange(userId: bob, access: AccessLevel.readWrite),
  ]);
  print('Bob now has access to Alice\'s vault');

  // Alice creates a file to share
  final tmpDir = Directory.systemTemp;
  final tmpFile = File('${tmpDir.path}/message.txt');
  await tmpFile.writeAsString('Hello Bob! This is Alice.');

  // Alice writes the file to the vault
  final fileInfo = await vaultAlice.write(
    'shared/message.txt',
    src: tmpFile.path,
  );
  print('File written: ${fileInfo.name}');
}
import ink.francesco.bao.*;
import java.nio.file.Files;
import java.nio.file.Path;

public class QuickStart {
  public static void main(String[] args) throws Exception {
    // Configure cloud storage
    var storeConfig = StoreConfig.s3(
      "my-vault",
      "s3.amazonaws.com",
      "us-east-1",
      "my-bucket",
      "bao",
      "your-key-id",
      "your-secret"
    );
    var store = Store.open(storeConfig);

    // Create a database for Alice's vault
    var dbAlice = new DB("alice_vault.db");

    // Alice creates a vault (she already has alice and aliceSecret from Step 1)
    var vaultAlice = Vault.create(
      Vault.USERS,
      aliceSecret,
      store,
      dbAlice
    );

    // Alice grants Bob access to her vault
    vaultAlice.syncAccess(0, new AccessChange[]{
      new AccessChange(bob, AccessLevel.READ_WRITE)
    });
    System.out.println("Bob now has access to Alice's vault");

    // Alice creates a file to share
    Path tmpFile = Files.createTempFile("message", ".txt");
    Files.writeString(tmpFile, "Hello Bob! This is Alice.");

    // Alice writes the file to the vault
    var fileInfo = vaultAlice.write("shared/message.txt", tmpFile.toString());
    System.out.println("File written: " + fileInfo.name);
  }
}

Step 3: Bob’s Side - Open Vault and Read

Bob opens Alice’s vault and reads the file she wrote.

from baolib import *
from pathlib import Path
import tempfile

# Use the same store configuration as Alice
store_config = {
    'type': 's3',
    'id': 'my-vault',
    's3': {
        'bucket': 'my-bucket',
        'endpoint': 's3.amazonaws.com',
        'prefix': 'bao',
        'auth': {
            'accessKeyId': 'your-key-id',
            'secretAccessKey': 'your-secret'
        }
    }
}
store = Store(store_config)

# Create a database for Bob's vault
db_bob = DB('sqlite3', 'bob_vault.db')

# Bob opens Alice's vault using Alice's public ID
# (bob and bob_secret are from Step 1, alice is Alice's public ID from Step 1)
vault_bob = Vault.open(Vault.users, bob_secret, alice, store, db_bob)

# Bob reads the file Alice wrote
out_file = Path(tempfile.mkdtemp()) / "received.txt"
vault_bob.read('shared/message.txt', str(out_file))

# Bob reads and displays the content
content = out_file.read_text()
print(f"Bob received: {content}")
package main

import (
  "fmt"
  "os"
  "path/filepath"
  "github.com/stregato/bao/lib"
  "github.com/stregato/bao/lib/vault"
)

func main() {
  // Use the same store configuration as Alice
  store, err := lib.OpenStore(lib.StoreConfig{
    Type: "s3",
    Id:   "my-vault",
    S3: lib.S3Config{
      Bucket:   "my-bucket",
      Endpoint: "s3.amazonaws.com",
      Prefix:   "bao",
      Auth: lib.S3Auth{
        AccessKeyId:     "your-key-id",
        SecretAccessKey: "your-secret",
      },
    },
  })
  if err != nil {
    panic(err)
  }

  // Create a database for Bob's vault
  dbBob, err := lib.OpenDB("sqlite3", "bob_vault.db", "")
  if err != nil {
    panic(err)
  }

  // Bob opens Alice's vault using Alice's public ID
  // (bob and bobSecret are from Step 1, alice is Alice's public ID from Step 1)
  vaultBob, err := vault.Open(vault.Users, bobSecret, alice, store, dbBob)
  if err != nil {
    panic(err)
  }

  // Bob reads the file Alice wrote
  tmpDir := os.TempDir()
  outFile := filepath.Join(tmpDir, "received.txt")
  _, err = vaultBob.Read("shared/message.txt", outFile, 0, nil)
  if err != nil {
    panic(err)
  }

  // Bob reads and displays the content
  content, err := os.ReadFile(outFile)
  if err != nil {
    panic(err)
  }
  fmt.Println("Bob received:", string(content))
}
import 'dart:io';
import 'package:bao/bao.dart';

void main() async {
  // Use the same store configuration as Alice
  final storeConfig = StoreConfig.s3(
    id: 'my-vault',
    bucket: 'my-bucket',
    endpoint: 's3.amazonaws.com',
    prefix: 'bao',
    accessKeyId: 'your-key-id',
    secretAccessKey: 'your-secret',
  );
  final store = await Store.open(storeConfig);

  // Create a database for Bob's vault
  final dbBob = DB('bob_vault.db');

  // Bob opens Alice's vault using Alice's public ID
  // (bob and bobSecret are from Step 1, alice is Alice's public ID from Step 1)
  final vaultBob = await Vault.open(
    Vault.users,
    bobSecret,
    alice,
    store,
    dbBob,
  );

  // Bob reads the file Alice wrote
  final tmpDir = Directory.systemTemp;
  final outFile = File('${tmpDir.path}/received.txt');
  await vaultBob.read('shared/message.txt', outFile.path);

  // Bob reads and displays the content
  final content = await outFile.readAsString();
  print('Bob received: $content');
}
import ink.francesco.bao.*;
import java.nio.file.Files;
import java.nio.file.Path;

public class QuickStart {
  public static void main(String[] args) throws Exception {
    // Use the same store configuration as Alice
    var storeConfig = StoreConfig.s3(
      "my-vault",
      "s3.amazonaws.com",
      "us-east-1",
      "my-bucket",
      "bao",
      "your-key-id",
      "your-secret"
    );
    var store = Store.open(storeConfig);

    // Create a database for Bob's vault
    var dbBob = new DB("bob_vault.db");

    // Bob opens Alice's vault using Alice's public ID
    // (bob and bobSecret are from Step 1, alice is Alice's public ID from Step 1)
    var vaultBob = Vault.open(
      Vault.USERS,
      bobSecret,
      alice,
      store,
      dbBob
    );

    // Bob reads the file Alice wrote
    Path outFile = Files.createTempFile("received", ".txt");
    vaultBob.read("shared/message.txt", outFile.toString());

    // Bob reads and displays the content
    String content = Files.readString(outFile);
    System.out.println("Bob received: " + content);
  }
}

Learn More

This quick start shows the basics of creating identities, vaults, and sharing files between two users. For comprehensive documentation including:

See the complete guide.