The JavaScript/WASM build can be created using a copy of the SQLite Encryption Extension (SEE), but doing so comes with some caveats:
This project does not provide pre-built WASM SEE builds. Users requiring SEE builds will have to create the build themselves (see instructions below). Similarly, there are no npm packages (or similar) for such builds (and the SEE license prohibits such distribution), so clients using SEE will have to do so the old-fashioned way, with vanilla JS and no package manager.
SEE's license is at odds with distribution of SQLite via client-side WASM. The official stance is that it is acceptable for an SEE licensee to host an SEE-capable WASM build within a private/intranet-only application within their organization, but may not host an SEE WASM build on a public-facing site or to organizations which have themselves not licensed SEE. Note that "server-side" WASM builds are unaffected by the SEE license but this page specifically covers browser-side WASM usage.
Only encryption options which do not require third-party library dependencies can be used here. In short, that means that clients are restricted to the
sqlite3-see.c
source file, as opposed to one of the othersqlite3-see-XYZ.c
variants.There is no way in JavaScript to reliably hide SEE encryption keys. Any user who loads an SEE-capable site can freely inspect the JavaScript code and other assets. The only way to ensure that encryption keys remain secret is to require that end users enter them manually (noting that browser-side password managers will helpfully offer to save them).
Encryption is arguably redundant for the persistent storage options because the underlying data are locked away in browser-specific storage which is illegible even to the browser's user. The argument could be made that anyone with direct access to a given user's login and browser can read the content, but the counter-argument of "physical access trumps all security measures" also applies (and see the above note about password managers). Encryption is unnecessary in the non-persistent storage modes because the databases exist only in memory. SEE specifically does not encrypt in-memory or temporary databases, and the non-persistent storage options are actually in-memory databases which are accessed via (transient) filesystem-like paths.
Creating an SEE-capable WASM Build
Building the SQLite WASM package requires a Linux system with the Emscripten tools installed. Instructions for installing those tools can be found in the canonical sqlite source tree.
With those installed, creating the SEE bundle is as easy as doing the following from the top-most directory of a checked-out copy of the SQLite canonical source tree:
$ ./configure --enable-all # or preferred flags
$ cd ext/wasm
$ . /path/to/emsdk_env.sh # part of the Emscripten tools
$ make sqlite3.c=/path/to/sqlite3-see.c # needs to be an absolute path
The resulting build artifacts can all be found in the jswasm
subdirectory. The build time, of course, varies wildly depending on
the system. A mid-range x64 machine typically runs it in about 45
seconds.
For users who exclusively, and repeatedly, create SEE-capable builds,
the above can be simplified somewhat by placing a copy of, or symlink
to, sqlite3-see.c
in the top-most directory of the build tree:
$ ln -s /path/to/sqlite3-see.c . # only needed once
$ ./configure --enable-all # or preferred flags
$ cd ext/wasm
$ . /path/to/emsdk_env.sh # part of the Emscripten tools
$ make
Note that the build may be parallelized using the -j#
flag to
make
, where #
is the number of parallel make
instances to run.
The longest-running parts of the build do not benefit from that,
however, so setting #
to be arbitrarily high will not speed up the
build significantly1.
Assuming all goes well, the output of the build will start with something like:
$ make
using emcc version [3.1.57]
This is an SEE build.
...
If that "SEE" line (or something equivalent) does not appear, the build is not SEE-capable. It is also possible to inspect the resulting JS sources to determine whether it's an SEE build:
$ grep -w sqlite3_key_v2 jswasm/sqlite3.js
If that produces any output then the resulting build is SEE-capable.
When alternating between SEE- and non-SEE builds, it is necessary to
run make clean
between each build, otherwise the build may either
outright fail or silently fail to include the SEE APIs.
Using the SEE Build
The SEE build is used identically to the main distribution, but also
includes the various sqlite3 API functions related to encryption, such
as sqlite3_key_v2()
. Those functions are not required for using
encryption, as each such API is also accessible via pragmas, as
documented in the SEE docs. The existence of the SEE-specific
functions in a JS/WASM build can be used to distinguish it from a
non-SEE build.
As of version 3.46, the oo1 API supports SEE in the
form of an optional argument to the
constructors of the DB
class and its
subclasses.
- ^
For long and boring technical reasons involving
how
sqlite3.wasm
needs to be built.