Sign in to access your cloud library. EPUB contents are encrypted in your browser before upload. Your randomly generated account key is stored in your private bucket and fetched after sign-in, so there is no separate passphrase.
0 books
Deriving AES-256-GCM key via PBKDF2...
Client-Side Encryption
Your Library is Empty
Sign in to your cloud account, then upload any local .epub file or generate a sample book to test the reader.
Book Title
Decrypted in RAM
Progress Synced
100%
Storage Backend & Supabase Setup
Connect your own Supabase project or use Local IndexedDB Demo Mode.
Supabase schema and security policies (run in SQL Editor)
-- CipherFolio schema. Run once in the Supabase SQL Editor.
create table if not exists public.encrypted_books (
id uuid primary key,
user_id uuid not null references auth.users(id) on delete cascade,
storage_path text not null unique,
encrypted_meta text,
encrypted_cover text,
title text,
author text,
cover_data text,
file_size_bytes bigint not null default 0,
cfi_progress text not null default '',
progress_percent numeric(5,2) not null default 0
check (progress_percent >= 0 and progress_percent <= 100),
updated_at timestamptz not null default now()
);
-- Safe upgrades for projects that already have an earlier CipherFolio table.
-- Legacy encrypted rows remain in place; new rows use title/author/cover_data.
alter table public.encrypted_books alter column encrypted_meta drop not null;
alter table public.encrypted_books add column if not exists title text;
alter table public.encrypted_books add column if not exists author text;
alter table public.encrypted_books add column if not exists cover_data text;
alter table public.encrypted_books add column if not exists encrypted_cover text;
alter table public.encrypted_books add column if not exists cfi_progress text not null default '';
alter table public.encrypted_books add column if not exists progress_percent numeric(5,2) not null default 0;
alter table public.encrypted_books add column if not exists updated_at timestamptz not null default now();
alter table public.encrypted_books enable row level security;
drop policy if exists "Users manage own encrypted books" on public.encrypted_books;
create policy "Users manage own encrypted books"
on public.encrypted_books for all to authenticated
using (auth.uid() = user_id)
with check (auth.uid() = user_id);
grant select, insert, update, delete on public.encrypted_books to authenticated;
insert into storage.buckets (id, name, public, file_size_limit)
values ('encrypted-epubs', 'encrypted-epubs', false, 524288000)
on conflict (id) do update set public = false;
drop policy if exists "Users access own encrypted blobs" on storage.objects;
create policy "Users access own encrypted blobs"
on storage.objects for all to authenticated
using (
bucket_id = 'encrypted-epubs'
and (storage.foldername(name))[1] = auth.uid()::text
)
with check (
bucket_id = 'encrypted-epubs'
and (storage.foldername(name))[1] = auth.uid()::text
);
Supabase Vault Account
Signed in as
Your EPUBs are encrypted in your browser. A random account key is stored in your private Supabase bucket and retrieved automatically after sign-in. No separate passphrase is needed.