//go:build libsqlite3 && sqlcipher // +build libsqlite3,sqlcipher package sqlite3 import ( "database/sql" "net/url" "os" "testing" ) const sqlCipherTestRawKey = "x'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'" func requireSQLCipher(t *testing.T, db *sql.DB) { t.Helper() var version string if err := db.QueryRow("PRAGMA cipher_version").Scan(&version); err != nil || version == "" { t.Fatalf("SQLCipher is required for this test; link it with -tags libsqlite3: %v", err) } } func TestSQLCipherKeyDSN(t *testing.T) { filename := TempFilename(t) defer os.Remove(filename) dsn := "file:" + filename + "?_key=" + url.QueryEscape(sqlCipherTestRawKey) db, err := sql.Open("sqlite3", dsn) if err != nil { t.Fatal(err) } requireSQLCipher(t, db) if _, err := db.Exec("CREATE TABLE test (value TEXT)"); err != nil { t.Fatal(err) } if _, err := db.Exec("INSERT INTO test VALUES ('encrypted')"); err != nil { t.Fatal(err) } if err := db.Close(); err != nil { t.Fatal(err) } db, err = sql.Open("sqlite3", dsn) if err != nil { t.Fatal(err) } var value string if err := db.QueryRow("SELECT value FROM test").Scan(&value); err != nil { t.Fatal(err) } if value != "encrypted" { t.Fatalf("value = %q; want encrypted", value) } if err := db.Close(); err != nil { t.Fatal(err) } for _, key := range []string{ "x'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'", "", } { db, err = sql.Open("sqlite3", "file:"+filename+"?_key="+url.QueryEscape(key)) if err != nil { t.Fatal(err) } var count int err = db.QueryRow("SELECT count(*) FROM test").Scan(&count) db.Close() if err == nil { t.Errorf("reading encrypted database with key %q succeeded", key) } } } func TestSQLCipherKeyAbsentPreservesSQLiteBehavior(t *testing.T) { filename := TempFilename(t) defer os.Remove(filename) db, err := sql.Open("sqlite3", filename) if err != nil { t.Fatal(err) } defer db.Close() if _, err := db.Exec("CREATE TABLE test (value TEXT)"); err != nil { t.Fatal(err) } if _, err := db.Exec("INSERT INTO test VALUES ('plain')"); err != nil { t.Fatal(err) } var value string if err := db.QueryRow("SELECT value FROM test").Scan(&value); err != nil { t.Fatal(err) } if value != "plain" { t.Fatalf("value = %q; want plain", value) } }