Initial commit
This commit is contained in:
		
						commit
						b10e7b0f5d
					
				
					 22 changed files with 1153 additions and 0 deletions
				
			
		
							
								
								
									
										5
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| build | ||||
| repo/db | ||||
| repo/dists | ||||
| repo/pool | ||||
| *.swp | ||||
							
								
								
									
										73
									
								
								Dockerfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								Dockerfile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| # syntax=docker/dockerfile:1.7 | ||||
| ARG BASE_IMAGE=ubuntu:24.04 | ||||
| FROM ${BASE_IMAGE} AS build | ||||
| 
 | ||||
| ARG DEBIAN_FRONTEND=noninteractive | ||||
| ARG TZ=UTC | ||||
| ARG PHP_VER=8.2 | ||||
| ARG SQLCIPHER_VERSION=4.11.0 | ||||
| 
 | ||||
| ENV TZ=${TZ} PHP_VER=${PHP_VER} SQLCIPHER_VERSION=${SQLCIPHER_VERSION} | ||||
| 
 | ||||
| SHELL ["/bin/bash","-o","pipefail","-c"] | ||||
| 
 | ||||
| # --- Root-only bootstrap: system deps, APT sources, build-deps --- | ||||
| WORKDIR /work | ||||
| COPY scripts/ /scripts/ | ||||
| 
 | ||||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||||
|       apt-transport-https apt-utils autoconf autopkgtest build-essential \ | ||||
|       ca-certificates curl dpkg-dev devscripts debhelper dh-php pkg-php-tools \ | ||||
|       build-essential devscripts debhelper dh-php dpkg-dev \ | ||||
|       git gnupg pkg-config pkg-php-tools \ | ||||
|       libicu-dev libreadline-dev libssl-dev libsqlite3-dev libtool \ | ||||
|       lintian lsb-release tcl-dev | ||||
| 
 | ||||
| # Configure PHP repos & ensure deb-src | ||||
| RUN /bin/bash /scripts/setup-php-sources.sh | ||||
| 
 | ||||
| # Install PHP build-deps for the selected version | ||||
| RUN apt-get update \ | ||||
|  && apt-get build-dep -y php${PHP_VER} | ||||
| 
 | ||||
| # Ensure that autopkgtest works ok, by making sure the 'examples' files are installed | ||||
| # from the deb as part of running the tests, which depend on them being present (they | ||||
| # *are* the tests). | ||||
| RUN rm -f /etc/dpkg/dpkg.cfg.d/docker /etc/dpkg/dpkg.cfg.d/excludes; \ | ||||
|   printf 'path-include=/usr/share/doc/*\n' | tee /etc/dpkg/dpkg.cfg.d/01-include-docs; \ | ||||
|   apt-get update && \ | ||||
|   apt-get -y --no-install-recommends install php${PHP_VER}-cli | ||||
| 
 | ||||
| # Create unprivileged builder and artifact dir | ||||
| RUN useradd -m -u 10001 -s /usr/sbin/nologin builder \ | ||||
|  && install -d -o builder -g builder /work /work/src /dist | ||||
| 
 | ||||
| # --- Unprivileged build from here --- | ||||
| USER builder | ||||
| WORKDIR /work/src | ||||
| RUN git clone --branch v${SQLCIPHER_VERSION} --depth 1 https://github.com/sqlcipher/sqlcipher.git build-sqlcipher && \ | ||||
|   git clone --branch main --depth 1 https://git.mig5.net/mig5/pdo_sqlcipher.git && \ | ||||
|   mkdir php-src && cd php-src && apt-get -y source php${PHP_VER} | ||||
| 
 | ||||
| COPY --chown=builder:builder . . | ||||
| 
 | ||||
| # --- No network from here for the actual build --- | ||||
| RUN --network=none bash -lc '\ | ||||
|   set -euo pipefail && umask 022 && \ | ||||
|   ./scripts/render-debian-files.sh && \ | ||||
|   dpkg-buildpackage -us -uc -b -rfakeroot && \ | ||||
|   . /etc/os-release && lintian -i -E --pedantic --profile "${ID}" --fail-on error ../*.changes' | ||||
| 
 | ||||
| # Run autopkgtest as root (needs to touch /etc/apt) | ||||
| USER root | ||||
| RUN --network=none bash -lc 'set -euo pipefail; \ | ||||
|       pkg=$(ls -1 /work/*.deb | grep -v dbgsym | head -n1); \ | ||||
|       autopkgtest "$pkg" -- null' | ||||
| 
 | ||||
| # Back to unprivileged user | ||||
| USER builder | ||||
| RUN mkdir -p /dist && cp -a ../*.{deb,buildinfo,changes} /dist/ || true | ||||
| 
 | ||||
| # --- Artifacts-only stage --- | ||||
| FROM scratch AS artifact | ||||
| COPY --from=build /dist/ /dist/ | ||||
							
								
								
									
										207
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,207 @@ | |||
| # SQLCipher for PHP `sqlite3` / `pdo_sqlite` (Debian & Ubuntu) | ||||
| 
 | ||||
| This repo contains build scripts and a `reprepro` APT repository for **drop-in replacements** of PHP’s `sqlite3` and `pdo_sqlite` extensions, recompiled against [**SQLCipher**](https://www.zetetic.net/sqlcipher/) (encrypted SQLite). | ||||
| 
 | ||||
| > These packages are intended to **replace** the phpX.Y-sqlite3 from Ondřej Surý’s PHP repo, linked against SQLCipher instead of the stock SQLite library. The driver name itself does not change. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Supported PHP & OS versions | ||||
| 
 | ||||
| * **PHP:** 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 | ||||
| * **OS:** Debian **12 (bookworm)**, Debian **13 (trixie)**, Ubuntu **22.04 (jammy)**, Ubuntu **24.04 (noble)** | ||||
| 
 | ||||
| > **Assumption:** You’re using PHP from [**Ondřej Surý**](https://deb.sury.org) (packages.sury.org / PPA) on both Debian and Ubuntu. If not, you may need to edit the scripts to fetch `apt-get source phpX.Y` differently. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## How I build and test the packages | ||||
| 
 | ||||
| I use Docker to help me build the packages. Sorry if you don't like it, but I find it very convenient for handling different distributions (and also as it allows me some hardening measures, see below). | ||||
| 
 | ||||
| Since this is a security-focused package, consider the following information carefully. | ||||
| 
 | ||||
| I build, test and sign these deb packages **locally** using the following: | ||||
| 
 | ||||
|  * Docker, using the [gvisor/runsc](https://gvisor.dev) hardened runtime. | ||||
|  * The actual compile and deb build steps occur as an **unprivileged** user in the Docker container, with **no network access**. Network access is only enabled to install the dependencies | ||||
|  * My Docker daemon runs inside an ephemeral, disposable [QubesOS](https://qubes-os.org) VM that only has port 80/443 access outbound (for apt repositories and git repo cloning). Qubes is a compartmentalised and reasonably-secure operating system. | ||||
|  * The GPG key that signs the packages is on a Yubikey. The GPG key is accessed by the Qubes VM via a Qubes 'vault' VM across Qubes' backplane - the Qubes VM has no direct access to the key on the filesystem or even to the USB device, except when I'm prompted to sign the package. | ||||
|  * The GPG private key does not exist on the apt repository server or in fact **anywhere** other than on the Yubikey. | ||||
|  * The signing and apt repo preparation for the built and tested .deb packages, happens in a **separate Qubes VM** to the build machine, that has **no network access** at all. | ||||
| 
 | ||||
| I consider this reasonably, perhaps even **quite** secure for my use case - but it's not 100% reproducible and it *does* require network access for brief periods. | ||||
| 
 | ||||
| 
 | ||||
| ## Option 1: use my APT repository | ||||
| 
 | ||||
| I publish the packages I built, in my own apt repository, using the process described above. | ||||
| 
 | ||||
| However, you have no reason to trust me and my apt repository. This repository exists so that you can build the packages yourself instead. See Option 2 for that. | ||||
| 
 | ||||
| ### 1) Add the GPG key (signed-by) | ||||
| 
 | ||||
| ```bash | ||||
| sudo mkdir -p /usr/share/keyrings | ||||
| curl -fsSL https://mig5.net/static/mig5.asc | sudo gpg --dearmor -o /usr/share/keyrings/mig5.gpg | ||||
| ``` | ||||
| 
 | ||||
| My GPG fingerprint is `00AE817C24A10C2540461A9C1D7CDE0234DB458D`. You can also fetch it from https://keys.openpgp.org or search the fingerprint online to confirm it. | ||||
| 
 | ||||
| ### 2) Add the APT source | ||||
| 
 | ||||
| **Debian 12 (bookworm):** | ||||
| 
 | ||||
| ```bash | ||||
| echo "deb [arch=amd64 signed-by=/usr/share/keyrings/mig5.gpg] https://apt.mig5.net bookworm main" | sudo tee /etc/apt/sources.list.d/mig5.list | ||||
| ``` | ||||
| 
 | ||||
| **Debian 13 (trixie):** | ||||
| 
 | ||||
| ```bash | ||||
| echo "deb [arch=amd64 signed-by=/usr/share/keyrings/mig5.gpg] https://apt.mig5.net trixie main" | sudo tee /etc/apt/sources.list.d/mig5.list | ||||
| ``` | ||||
| 
 | ||||
| **Ubuntu 22.04 (jammy):** | ||||
| 
 | ||||
| ```bash | ||||
| echo "deb [arch=amd64 signed-by=/usr/share/keyrings/mig5.gpg] https://apt.mig5.net jammy main" | sudo tee /etc/apt/sources.list.d/mig5.list | ||||
| ``` | ||||
| 
 | ||||
| **Ubuntu 24.04 (noble):** | ||||
| 
 | ||||
| ```bash | ||||
| echo "deb [arch=amd64 signed-by=/usr/share/keyrings/mig5.gpg] https://apt.mig5.net noble main" | sudo tee /etc/apt/sources.list.d/mig5.list | ||||
| ``` | ||||
| 
 | ||||
| ### 3) Update & install | ||||
| 
 | ||||
| ```bash | ||||
| sudo apt update | ||||
| # (example: PHP 8.2) | ||||
| sudo apt install php8.2-sqlcipher | ||||
| ``` | ||||
| 
 | ||||
| > Remember: These packages are built to **replace** `phpX.Y-sqlite3` with a SQLCipher-linked build. | ||||
| 
 | ||||
| ### 4) (Recommended) Pin to prefer this repo for sqlcipher packages | ||||
| 
 | ||||
| Create `/etc/apt/preferences.d/mig5.pref`: | ||||
| 
 | ||||
| ```ini | ||||
| Package: php*-sqlcipher | ||||
| Pin: release o=mig5, l=php-sqlcipher, n=bookworm # adjust to your distro | ||||
| Pin-Priority: 990 | ||||
| ``` | ||||
| 
 | ||||
| Then: | ||||
| 
 | ||||
| ```bash | ||||
| sudo apt update | ||||
| apt-cache policy php8.2-sqlcipher | ||||
| ``` | ||||
| 
 | ||||
| You should see this repo as the selected candidate. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Option 2: Building your own .debs | ||||
| 
 | ||||
| If you’d rather build locally, use `scripts/package.sh` which executes the Docker build process. | ||||
| 
 | ||||
| ```bash | ||||
| ./scripts/package.sh | ||||
| ``` | ||||
| 
 | ||||
| See the top of the script for the matrix of PHP versions and distros to build for. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Using SQLCipher for PHP | ||||
| 
 | ||||
| ```php | ||||
| <?php | ||||
|   try { | ||||
|     $dbh = new PDO("sqlite:/tmp/test.db"); | ||||
|     $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||||
|     $dbh->exec("PRAGMA key = 'super secret passphrase goes here'"); | ||||
|     $dbh->exec("PRAGMA cipher_memory_security = ON"); | ||||
|     $create = "CREATE TABLE IF NOT EXISTS users (name TEXT NOT NULL)"; | ||||
|     $dbh->exec($create); | ||||
|     $insert = "INSERT INTO users(name) VALUES(:name)"; | ||||
|     $stmt = $dbh->prepare($insert); | ||||
|     $stmt->bindValue(":name", "mig5"); | ||||
|     $stmt->execute(); | ||||
|     echo "Last insert ID: " . $dbh->lastInsertId() . "\n"; | ||||
|   } catch (Exception $e) { | ||||
|     echo $e->getMessage(); | ||||
|     exit(1); | ||||
|   } | ||||
| ``` | ||||
| 
 | ||||
| See more documentation on the SQLCipher PRAGMAs at https://www.zetetic.net/sqlcipher/sqlcipher-api/ | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Verifying SQLCipher is actually in use | ||||
| 
 | ||||
| Look at the `tests/test_sqlcipher.php` script. This performs a battery of tests against a database to make sure it looks encrypted with SQLCipher. | ||||
| 
 | ||||
| The test script is used by `autopkgtest` during the build, and can also be found in `/usr/share/doc/phpX.Y-sqlcipher/examples` on a system that has installed the deb package. | ||||
| 
 | ||||
| Another technique: run `hexdump -C` on the created database. It should show totally scrambled content. | ||||
| 
 | ||||
| Another technique would be to try and open it with regular SQLite (don't pass `PRAGMA key` as the first query). It should throw an error that it couldn't open the database. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Notes on compatibility | ||||
| 
 | ||||
| * These are drop-in **replacements** of the distro's official PHP `sqlite3`/`pdo_sqlcipher` extensions, just linked to SQLCipher. | ||||
| * You should still be able to use regular SQLite3 databases with these packages. | ||||
| * You must be on **Ondřej Surý’s PHP packages** to match headers and packaging expectations. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Troubleshooting | ||||
| 
 | ||||
| * **Module not loading?** Check `php -m | grep sqlite` and `php --ri sqlite3`. | ||||
| * **Still using stock SQLite?** Ensure the package came from this repo (`apt-cache policy phpX.Y-sqlite3`). | ||||
| * **Encrypted DB won’t open?** Make sure you’re calling `PRAGMA key` **before** any queries, and that the cipher settings (e.g., `cipher_compatibility`) match the DB’s format. | ||||
| * See the `tests` folder for some sample read/write PHP scripts. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## License | ||||
| 
 | ||||
| SQLCipher, PHP itself and the PHP extensions are licensed under their respective upstream licenses. See `debian/copyright.in` in this repository. | ||||
| 
 | ||||
| My own build scripts (e.g everything that is not part of SQLCipher or PHP themselves, here) are in the public domain. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## No warranty | ||||
| 
 | ||||
| This software and repository are provided **“as is”**, **without warranty of any kind**. You assume **all** risk for installing and using these packages or scripts. No liability is accepted for any form of data loss, security issues, or any other damages, even if they resulted from bugs I introduced. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Acknowledgements | ||||
| 
 | ||||
| This project began as far back as 2013 for [Mydex Data Services CIC](https://mydex.org). Thanks to Mydex for encouraging me to open source the build tooling for others. | ||||
| 
 | ||||
| Thanks to Ondřej Surý for many years of tireless packaging of PHP versions for Debian and Ubuntu. [Please support him!](https://deb.sury.org/#support) | ||||
| 
 | ||||
| Thanks to Zetetic for creating and maintaining SQLCipher, and for keeping it open source for the community. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Contact / issues | ||||
| 
 | ||||
| You can contact me via the contact form at https://mig5.net or on GotoSocial ([@mig5@goto.mig5.net](https://goto.mig5.net/@mig5). | ||||
| 
 | ||||
|  * Are you looking for a contract/freelance sysadmin to help harden and/or maintain your Linux infrastructure, CI/CD workflows or tighten up your security? | ||||
|  * In the US or Europe and need a senior Linux expert to help mentor your internal team, or handle the night shift? | ||||
|  * Need SQLCipher packaged for a different version of PHP or Linux? | ||||
| 
 | ||||
| Good news, that's been my bread and butter since 2007. Please visit [my website](https://mig5.net) to learn more and get in touch. | ||||
							
								
								
									
										6
									
								
								debian/changelog.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								debian/changelog.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| ${PKG} (${PKG_VERSION}) ${DIST_CODENAME}; urgency=medium | ||||
| 
 | ||||
|   * Build sqlite3 and pdo_sqlite against SQLCipher. | ||||
|   * Drop-in replacement for php${PHP_VER}-sqlite3. | ||||
| 
 | ||||
|  -- ${MAINT_NAME} <${MAINT_EMAIL}>  ${DATE_RFC2822} | ||||
							
								
								
									
										45
									
								
								debian/config.m4
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								debian/config.m4
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| dnl $Id$ | ||||
| dnl config.m4 for extension pdo_sqlcipher | ||||
| dnl vim:et:sw=2:ts=2: | ||||
| PHP_ARG_ENABLE(pdo_sqlcipher, whether to enable pdo_sqlcipher support, | ||||
| [  --enable-pdo_sqlcipher  Enable pdo_sqlcipher support]) | ||||
| if test "$PHP_PDO_SQLCIPHER" != "no"; then | ||||
|     if test "$PHP_PDO" = "no" && test "$ext_shared" = "no"; then | ||||
|         AC_MSG_ERROR([PDO is not enabled! Add --enable-pdo to your configure line.]) | ||||
|     fi | ||||
|     AC_MSG_CHECKING([for PDO includes]) | ||||
|     if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then | ||||
|         pdo_inc_path=$abs_srcdir/ext | ||||
|     elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then | ||||
|         pdo_inc_path=$abs_srcdir/ext | ||||
|     elif test -f $phpincludedir/ext/pdo/php_pdo_driver.h; then | ||||
|         pdo_inc_path=$phpincludedir/ext | ||||
|     elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then | ||||
|         pdo_inc_path=$prefix/include/php/ext | ||||
|     elif test -f $prefix/include/php5/ext/pdo/php_pdo_driver.h; then | ||||
|         pdo_inc_path=$prefix/include/php5/ext | ||||
|     elif test -f $prefix/include/php/5.5/php/ext/pdo/php_pdo_driver.h; then | ||||
|         pdo_inc_path=$prefix/include/php/5.5/php/ext | ||||
|     elif test -f $prefix/include/php/5.6/php/ext/pdo/php_pdo_driver.h; then | ||||
|         pdo_inc_path=$prefix/include/php/5.6/php/ext | ||||
|     else | ||||
|         AC_MSG_ERROR([Cannot find php_pdo_driver.h.]) | ||||
|     fi | ||||
|     AC_MSG_RESULT($pdo_inc_path) | ||||
|     php_pdo_sqlcipher_sources_core="pdo_sqlite.c sqlite_driver.c sqlite_statement.c sqlite3.c" | ||||
|     dnl Detect PHP 8.4’s DSN parser unit and compile it if present | ||||
|     AC_MSG_CHECKING([for sqlite_sql_parser.c (PHP 8.4 DSN parser)]) | ||||
|     if test -f "$abs_srcdir/sqlite_sql_parser.c"; then | ||||
|       AC_MSG_RESULT([yes]) | ||||
|       php_pdo_sqlcipher_sources_core="$php_pdo_sqlcipher_sources_core sqlite_sql_parser.c" | ||||
|     else | ||||
|       AC_MSG_RESULT([no]) | ||||
|     fi | ||||
| 
 | ||||
|     PHP_NEW_EXTENSION(pdo_sqlite, $php_pdo_sqlcipher_sources_core, $ext_shared,,-I$pdo_inc_path) | ||||
| 
 | ||||
|     ifdef([PHP_ADD_EXTENSION_DEP], | ||||
|     [ | ||||
|         PHP_ADD_EXTENSION_DEP(pdo_sqlite, pdo) | ||||
|     ]) | ||||
| fi | ||||
							
								
								
									
										28
									
								
								debian/control.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								debian/control.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| Source: ${PKG} | ||||
| Section: php | ||||
| Priority: optional | ||||
| Maintainer: ${MAINT_NAME} <${MAINT_EMAIL}> | ||||
| Standards-Version: 4.7.2 | ||||
| Build-Depends: | ||||
|  debhelper-compat (= 13), | ||||
|  dh-php, | ||||
|  pkg-php-tools, | ||||
|  ${PHP_BIN}-dev, | ||||
|  libssl-dev, | ||||
|  libsqlite3-dev, | ||||
|  autoconf, automake, libtool, git | ||||
| Rules-Requires-Root: no | ||||
| Homepage: https://www.zetetic.net/sqlcipher | ||||
| 
 | ||||
| Package: ${PKG} | ||||
| Architecture: any | ||||
| Depends: | ||||
|  ${misc:Depends}, | ||||
|  ${shlibs:Depends}, | ||||
|  ${php:Depends}, | ||||
| Provides: ${PHP_BIN}-sqlite3, php-sqlite3 | ||||
| Replaces: ${PHP_BIN}-sqlite3, php-sqlite3 | ||||
| Conflicts: ${PHP_BIN}-sqlite3 | ||||
| Description: SQLite3/SQLCipher module for PHP ${PHP_VER} (drop-in replacement) | ||||
|  SQLCipher-enabled build of PHP’s sqlite3 and pdo_sqlite extensions. | ||||
|  Acts as a drop-in replacement for ${PHP_BIN}-sqlite3. | ||||
							
								
								
									
										161
									
								
								debian/copyright.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								debian/copyright.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,161 @@ | |||
| Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ | ||||
| Upstream-Name: php-sqlcipher | ||||
| Source: https://github.com/mig5/php-sqlcipher | ||||
| 
 | ||||
| Files: * | ||||
| License: (SQLCipher) Copyright (c) 2025, ZETETIC LLC | ||||
|  All rights reserved. | ||||
|   | ||||
|  Redistribution and use in source and binary forms, with or without | ||||
|  modification, are permitted provided that the following conditions are met: | ||||
|      * Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|      * Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|      * Neither the name of the ZETETIC LLC nor the | ||||
|        names of its contributors may be used to endorse or promote products | ||||
|        derived from this software without specific prior written permission. | ||||
|   | ||||
|  THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY | ||||
|  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY | ||||
|  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| 
 | ||||
|  Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  of this software and associated documentation files (the "Software"), to deal | ||||
|  in the Software without restriction, including without limitation the rights | ||||
|  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  copies of the Software, and to permit persons to do so, subject to the | ||||
|  following conditions: | ||||
|  . | ||||
|  The above copyright notice and this permission notice shall be included in all | ||||
|  copies or substantial portions of the Software. | ||||
|  . | ||||
|  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  SOFTWARE. | ||||
| 
 | ||||
| License: PHP-3.0 | ||||
|  -------------------------------------------------------------------- | ||||
|                    The PHP License, version 3.0 | ||||
|  Copyright (c) 1999 - 2006 The PHP Group. All rights reserved. | ||||
|  -------------------------------------------------------------------- | ||||
|  . | ||||
|  Redistribution and use in source and binary forms, with or without | ||||
|  modification, is permitted provided that the following conditions | ||||
|  are met: | ||||
|  . | ||||
|    1. Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|  . | ||||
|    2. Redistributions in binary form must reproduce the above copyright | ||||
|       notice, this list of conditions and the following disclaimer in | ||||
|       the documentation and/or other materials provided with the | ||||
|       distribution. | ||||
|  . | ||||
|    3. The name "PHP" must not be used to endorse or promote products | ||||
|       derived from this software without prior written permission. For | ||||
|       written permission, please contact group@php.net. | ||||
|  . | ||||
|    4. Products derived from this software may not be called "PHP", nor | ||||
|       may "PHP" appear in their name, without prior written permission | ||||
|       from group@php.net.  You may indicate that your software works in | ||||
|       conjunction with PHP by saying "Foo for PHP" instead of calling | ||||
|       it "PHP Foo" or "phpfoo" | ||||
|  . | ||||
|    5. The PHP Group may publish revised and/or new versions of the | ||||
|       license from time to time. Each version will be given a | ||||
|       distinguishing version number. | ||||
|       Once covered code has been published under a particular version | ||||
|       of the license, you may always continue to use it under the terms | ||||
|       of that version. You may also choose to use such covered code | ||||
|       under the terms of any subsequent version of the license | ||||
|       published by the PHP Group. No one other than the PHP Group has | ||||
|       the right to modify the terms applicable to covered code created | ||||
|       under this License. | ||||
|  . | ||||
|    6. Redistributions of any form whatsoever must retain the following | ||||
|       acknowledgment: | ||||
|       "This product includes PHP, freely available from | ||||
|       <http://www.php.net/>". | ||||
|  . | ||||
|  THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND | ||||
|  ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||||
|  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||||
|  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE PHP | ||||
|  DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | ||||
|  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
|  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||
|  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
|  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||||
|  OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| 
 | ||||
| License: PHP-3.01 | ||||
|  -------------------------------------------------------------------- | ||||
|                    The PHP License, version 3.01 | ||||
|  Copyright (c) 1999 - 2015 The PHP Group. All rights reserved. | ||||
|  -------------------------------------------------------------------- | ||||
|  . | ||||
|  Redistribution and use in source and binary forms, with or without | ||||
|  modification, is permitted provided that the following conditions | ||||
|  are met: | ||||
|  . | ||||
|    1. Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|  . | ||||
|    2. Redistributions in binary form must reproduce the above copyright | ||||
|       notice, this list of conditions and the following disclaimer in | ||||
|       the documentation and/or other materials provided with the | ||||
|       distribution. | ||||
|  . | ||||
|    3. The name "PHP" must not be used to endorse or promote products | ||||
|       derived from this software without prior written permission. For | ||||
|       written permission, please contact group@php.net. | ||||
|  . | ||||
|    4. Products derived from this software may not be called "PHP", nor | ||||
|       may "PHP" appear in their name, without prior written permission | ||||
|       from group@php.net.  You may indicate that your software works in | ||||
|       conjunction with PHP by saying "Foo for PHP" instead of calling | ||||
|       it "PHP Foo" or "phpfoo" | ||||
|  . | ||||
|    5. The PHP Group may publish revised and/or new versions of the | ||||
|       license from time to time. Each version will be given a | ||||
|       distinguishing version number. | ||||
|       Once covered code has been published under a particular version | ||||
|       of the license, you may always continue to use it under the terms | ||||
|       of that version. You may also choose to use such covered code | ||||
|       under the terms of any subsequent version of the license | ||||
|       published by the PHP Group. No one other than the PHP Group has | ||||
|       the right to modify the terms applicable to covered code created | ||||
|       under this License. | ||||
|  . | ||||
|    6. Redistributions of any form whatsoever must retain the following | ||||
|       acknowledgment: | ||||
|       "This product includes PHP software, freely available from | ||||
|       <http://www.php.net/software/>". | ||||
|  . | ||||
|  THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND | ||||
|  ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||||
|  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||||
|  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE PHP | ||||
|  DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | ||||
|  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
|  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||
|  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
|  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||||
|  OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										1
									
								
								debian/pdo_sqlite.ini
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/pdo_sqlite.ini
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| extension=pdo_sqlite | ||||
							
								
								
									
										1
									
								
								debian/pkg.examples.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/pkg.examples.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| tests/test_sqlcipher.php | ||||
							
								
								
									
										2
									
								
								debian/pkg.php.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								debian/pkg.php.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| mod debian/sqlite3.ini | ||||
| mod debian/pdo_sqlite.ini | ||||
							
								
								
									
										126
									
								
								debian/rules
									
										
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										126
									
								
								debian/rules
									
										
									
									
										vendored
									
									
										Executable file
									
								
							|  | @ -0,0 +1,126 @@ | |||
| #!/usr/bin/make -f | ||||
| 
 | ||||
| # Keep dh defaults, but the actual builds pass explicit flags | ||||
| export DEB_BUILD_MAINT_OPTIONS = hardening=+all | ||||
| export DEB_CFLAGS_MAINT_APPEND = -O2 -fPIC | ||||
| 
 | ||||
| # Match the shell script layout: build in-tree and use .libs directly | ||||
| SQLCIPHER_SRC_DIR := $(CURDIR)/build-sqlcipher | ||||
| export SQLITE_LIBS                = $(SQLCIPHER_SRC_DIR)/.libs/ | ||||
| export SQLCIPHER_LIBDIR_ARG       = $(SQLITE_LIBS)sqlite3.o | ||||
| export STANDARD_SQLCIPHER_CFLAGS  = -DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -DSQLITE_MAX_VARIABLE_NUMBER=250000 -DSQLITE_EXTRA_INIT=sqlcipher_extra_init -DSQLITE_EXTRA_SHUTDOWN=sqlcipher_extra_shutdown | ||||
| export STANDARD_SQLCIPHER_LDFLAGS = -lcrypto -L$(SQLITE_LIBS) | ||||
| export SQLITE_CFLAGS              = -I$(SQLCIPHER_SRC_DIR) $(STANDARD_SQLCIPHER_CFLAGS) | ||||
| 
 | ||||
| # Detect PHP version on the build host | ||||
| PHPCONFIG_CANDIDATE := $(shell \ | ||||
|   if ls -1 /usr/bin/php-config[0-9]* >/dev/null 2>&1; then \ | ||||
|     ls -1 /usr/bin/php-config[0-9]* | sed 's#.*/##' | sort -Vr | head -n1; \ | ||||
|   elif command -v php-config >/dev/null 2>&1; then echo php-config; \ | ||||
|   else echo php-config; fi) | ||||
| PHP_VER ?= $(shell $(PHPCONFIG_CANDIDATE) --version 2>/dev/null | awk -F. '{print $$1"."$$2}') | ||||
| PHPCONFIG := $(shell if command -v php-config$(PHP_VER) >/dev/null 2>&1; then echo php-config$(PHP_VER); else echo $(PHPCONFIG_CANDIDATE); fi) | ||||
| PHPIZE    := $(patsubst php-config%,phpize%,$(PHPCONFIG)) | ||||
| 
 | ||||
| # Extension API dir (e.g. 20240924) | ||||
| PHP_API   := $(shell $(PHPCONFIG) --extension-dir | awk -F/ '{print $$NF}') | ||||
| 
 | ||||
| # Binary package name (must match debian/<package>.php) | ||||
| PACKAGE   ?= php$(PHP_VER)-sqlcipher | ||||
| 
 | ||||
| # Final install path (inside package staging tree) | ||||
| EXTDIR     = debian/$(PACKAGE)/usr/lib/php/$(PHP_API) | ||||
| 
 | ||||
| # Markers to persist paths across recipe lines | ||||
| PHP_SRC_MARKER         = .php_src_dir | ||||
| SQLITE3_DIR_MARKER     = .sqlite3_dir | ||||
| PDO_SQLITE_DIR_MARKER  = .pdo_sqlite_dir | ||||
| 
 | ||||
| # Figure out the matching Debian source package from the dev tool that owns php-config | ||||
| PHP_DEV_PKG := $(shell dpkg-query -S $$(command -v $(PHPCONFIG)) 2>/dev/null | cut -d: -f1 | sed 's/:.*//' | head -n1) | ||||
| 
 | ||||
| # PDO sources and build dir | ||||
| PDO_SRC_DIR  := $(CURDIR)/pdo_sqlcipher | ||||
| PDO_BUILD_DIR := $(PDO_SRC_DIR)/build | ||||
| 
 | ||||
| %: | ||||
| 	dh $@ --with php | ||||
| 
 | ||||
| override_dh_auto_build: | ||||
| 	# 1) Build SQLCipher | ||||
| 	cd "$(SQLCIPHER_SRC_DIR)" && env -u DEB_BUILD_MAINT_OPTIONS -u DEB_CFLAGS_MAINT_APPEND \ | ||||
| 		CFLAGS="$(STANDARD_SQLCIPHER_CFLAGS)" \ | ||||
| 		LDFLAGS="-lcrypto" \ | ||||
| 		./configure --with-tempstore=yes | ||||
| 	$(MAKE) -C "$(SQLCIPHER_SRC_DIR)" | ||||
| 
 | ||||
| 	# 2) Check PHP sources are present, set string vars | ||||
| 	@set -eu; \ | ||||
| 	PHP_SRC_DIR=$$(readlink -f $$(ls -dt php-src/*/ | head -n1 | sed 's#/$$##')); \ | ||||
| 	test -d "$$PHP_SRC_DIR" || { echo "Could not locate extracted php$(PHP_VER) source dir"; ls -al php-src; exit 1; }; \ | ||||
| 	printf '%s' "$$PHP_SRC_DIR" > "$(PHP_SRC_MARKER)"; \ | ||||
| 	SQLITE3_DIR=$$(readlink -f $$(find "$$PHP_SRC_DIR" -type d -path '*/ext/sqlite3' | head -n1)); \ | ||||
| 	test -d "$$SQLITE3_DIR" || { echo "ext/sqlite3 not found under $$PHP_SRC_DIR"; find "$$PHP_SRC_DIR" -maxdepth 4 -type d -name sqlite3; exit 1; }; \ | ||||
| 	printf '%s' "$$SQLITE3_DIR" > "$(SQLITE3_DIR_MARKER)"; \ | ||||
| 	PDO_SQLITE_DIR=$$(readlink -f $$(find "$$PHP_SRC_DIR" -type d -path '*/ext/pdo_sqlite' | head -n1)); \ | ||||
| 	test -d "$$PDO_SQLITE_DIR" || { echo "ext/pdo_sqlite not found under $$PHP_SRC_DIR"; exit 1; }; \ | ||||
| 	printf '%s' "$$PDO_SQLITE_DIR" > "$(PDO_SQLITE_DIR_MARKER)" | ||||
| 
 | ||||
| 	# 2a) Prepare ext/sqlite3 (mv config0.m4, phpize, configure, make) | ||||
| 	@set -eu; \ | ||||
| 	SQLITE3_DIR=$$(cat "$(SQLITE3_DIR_MARKER)"); \ | ||||
| 	if [ -f "$$SQLITE3_DIR/config0.m4" ] && [ ! -f "$$SQLITE3_DIR/config.m4" ]; then \ | ||||
| 	  mv "$$SQLITE3_DIR/config0.m4" "$$SQLITE3_DIR/config.m4"; \ | ||||
| 	fi; \ | ||||
| 	cd "$$SQLITE3_DIR" && $(PHPIZE); \ | ||||
| 	cd "$$SQLITE3_DIR" && env -u DEB_BUILD_MAINT_OPTIONS -u DEB_CFLAGS_MAINT_APPEND \ | ||||
| 		CFLAGS="$(STANDARD_SQLCIPHER_CFLAGS)" \ | ||||
| 		LDFLAGS="$(STANDARD_SQLCIPHER_LDFLAGS)" \ | ||||
| 		./configure --libdir="$(SQLCIPHER_LIBDIR_ARG)" --with-php-config="$(PHPCONFIG)" | ||||
| 	$(MAKE) -C "$$(cat "$(SQLITE3_DIR_MARKER)")" | ||||
| 
 | ||||
| 	# Fix the pic_object in sqlite3.lo so it links to sqlcipher's sqlite3.o | ||||
| 	@set -eu; \ | ||||
| 	PHP_SRC_DIR=$$(cat "$(PHP_SRC_MARKER)"); \ | ||||
| 	sed -i "s|pic_object='.libs/sqlite3.o'|pic_object='.libs/sqlite3.o $(SQLCIPHER_SRC_DIR)/sqlite3.o'|g" \ | ||||
| 		"$$PHP_SRC_DIR/ext/sqlite3/sqlite3.lo" | ||||
| 
 | ||||
| 	# Rebuild the sqlite3 extension after the pic_object fix | ||||
| 	$(MAKE) -C "$$(cat "$(SQLITE3_DIR_MARKER)")" | ||||
| 
 | ||||
| 	# 3) Build PDO SQLCipher | ||||
| 	@set -eu; \ | ||||
| 	PDO_SQLITE_DIR=$$(cat "$(PDO_SQLITE_DIR_MARKER)"); \ | ||||
| 	mkdir -p "$(PDO_BUILD_DIR)"; \ | ||||
| 	cp "$$PDO_SQLITE_DIR"/*.c "$$PDO_SQLITE_DIR"/*.h "$(PDO_BUILD_DIR)/"; \ | ||||
| 	# Bring in sqlcipher amalgamation and config for PDO build | ||||
| 	cp "$(SQLCIPHER_SRC_DIR)/sqlite3.c" "$(PDO_BUILD_DIR)/sqlite3.c"; \ | ||||
| 	cp "$(SQLCIPHER_SRC_DIR)/sqlite3.h" "$(PDO_BUILD_DIR)/sqlite3.h"; \ | ||||
| 	cp "$(SQLCIPHER_SRC_DIR)/sqlite_cfg.h" "$(PDO_BUILD_DIR)/config.h"; \ | ||||
| 	sed -i '1i#include "config.h"' "$(PDO_BUILD_DIR)/sqlite3.c"; \ | ||||
| 	cp "$(PDO_SRC_DIR)/config.m4" "$(PDO_BUILD_DIR)/config.m4"; \ | ||||
| 	cd "$(PDO_BUILD_DIR)" && $(PHPIZE) --clean && $(PHPIZE); \ | ||||
| 	cd "$(PDO_BUILD_DIR)" && env -u DEB_BUILD_MAINT_OPTIONS -u DEB_CFLAGS_MAINT_APPEND \ | ||||
| 		CFLAGS="$(STANDARD_SQLCIPHER_CFLAGS)" \ | ||||
| 		LDFLAGS="$(STANDARD_SQLCIPHER_LDFLAGS)" \ | ||||
| 		./configure --libdir="$(SQLCIPHER_LIBDIR_ARG)" --with-php-config="$(PHPCONFIG)" | ||||
| 	$(MAKE) -C "$(PDO_BUILD_DIR)" | ||||
| 
 | ||||
| override_dh_auto_install: | ||||
| 	@set -eu; \ | ||||
| 	SQLITE3_DIR=$$(cat "$(SQLITE3_DIR_MARKER)"); \ | ||||
| 	install -D -m 0644 "$$SQLITE3_DIR/modules/sqlite3.so" "$(EXTDIR)/sqlite3.so"; \ | ||||
| 	install -D -m 0644 "$(PDO_BUILD_DIR)/modules/pdo_sqlite.so" "$(EXTDIR)/pdo_sqlite.so"; \ | ||||
| 	# Install .ini so dh-php can enable them across SAPIs | ||||
| 	install -D -m 0644 debian/sqlite3.ini    "debian/$(PACKAGE)/usr/share/$(PACKAGE)/sqlite3/sqlite3.ini"; \ | ||||
| 	install -D -m 0644 debian/pdo_sqlite.ini "debian/$(PACKAGE)/usr/share/$(PACKAGE)/sqlite3/pdo_sqlite.ini" | ||||
| 
 | ||||
| override_dh_installexamples: | ||||
| 	dh_installexamples --sourcedir=. | ||||
| 
 | ||||
| override_dh_missing: | ||||
| 	dh_missing --fail-missing | ||||
| 
 | ||||
| override_dh_auto_clean: | ||||
| 	rm -rf "$(PHP_SRC_MARKER)" "$(SQLITE3_DIR_MARKER)" "$(PDO_SQLITE_DIR_MARKER)" | ||||
| 
 | ||||
							
								
								
									
										1
									
								
								debian/source/format
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/source/format
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| 3.0 (native) | ||||
							
								
								
									
										1
									
								
								debian/sqlite3.ini
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/sqlite3.ini
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| extension=sqlite3 | ||||
							
								
								
									
										9
									
								
								debian/tests/basic.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								debian/tests/basic.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| #!/bin/sh | ||||
| set -eux | ||||
| 
 | ||||
| # Sanity: modules must be loaded and report info | ||||
| ${PHP_BIN} --ri sqlite3 | ||||
| ${PHP_BIN} --ri pdo_sqlite | ||||
| 
 | ||||
| # Write an encrypted DB | ||||
| ${PHP_BIN} ${DOC_DIR}/examples/test_sqlcipher.php | ||||
							
								
								
									
										3
									
								
								debian/tests/control.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								debian/tests/control.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| Tests: basic | ||||
| Depends: @, ${PHP_BIN}-cli | ||||
| Restrictions: allow-stderr | ||||
							
								
								
									
										35
									
								
								repo/conf/distributions
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								repo/conf/distributions
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| Origin: mig5 | ||||
| Label: php-sqlcipher | ||||
| Suite: stable | ||||
| Codename: trixie | ||||
| Architectures: amd64 | ||||
| Components: main | ||||
| Description: mig5 SQLCipher for PHP packages for Debian 13 (trixie) | ||||
| SignWith: !qubes-gpg-sign | ||||
| 
 | ||||
| Origin: mig5 | ||||
| Label: php-sqlcipher | ||||
| Suite: stable | ||||
| Codename: bookworm | ||||
| Architectures: amd64 | ||||
| Components: main | ||||
| Description: mig5 SQLCipher for PHP packages for Debian 12 (bookworm) | ||||
| SignWith: !qubes-gpg-sign | ||||
| 
 | ||||
| Origin: mig5 | ||||
| Label: php-sqlcipher | ||||
| Suite: stable | ||||
| Codename: noble | ||||
| Architectures: amd64 | ||||
| Components: main | ||||
| Description: mig5 SQLCipher for PHP packages for Ubuntu 24.04 (noble) | ||||
| SignWith: !qubes-gpg-sign | ||||
| 
 | ||||
| Origin: mig5 | ||||
| Label: php-sqlcipher | ||||
| Suite: stable | ||||
| Codename: jammy | ||||
| Architectures: amd64 | ||||
| Components: main | ||||
| Description: mig5 SQLCipher for PHP packages for Ubuntu 22.04 (jammy) | ||||
| SignWith: !qubes-gpg-sign | ||||
							
								
								
									
										39
									
								
								repo/conf/qubes-gpg-sign
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										39
									
								
								repo/conf/qubes-gpg-sign
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| #!/bin/sh | ||||
| set -eu | ||||
| 
 | ||||
| release="$1"                    # file to sign (exists in the repo VM) | ||||
| inrel="${2:-}"                  # path for InRelease.new (may be empty) | ||||
| relgpg="${3:-}"                 # path for Release.gpg.new (may be empty) | ||||
| 
 | ||||
| export QUBES_GPG_DOMAIN="${QUBES_GPG_DOMAIN:-vault}" | ||||
| 
 | ||||
| WRAP="${WRAP:-/usr/bin/qubes-gpg-client-wrapper}" | ||||
| KEY="${REPO_SIGN_KEY:-00AE817C24A10C2540461A9C1D7CDE0234DB458D}" | ||||
| 
 | ||||
| gpgcmd() { | ||||
|   if [ -n "$KEY" ]; then | ||||
|     "$WRAP" --batch --no-tty -u "$KEY" "$@" | ||||
|   else | ||||
|     "$WRAP" --batch --no-tty "$@" | ||||
|   fi | ||||
| } | ||||
| 
 | ||||
| mkout() {                       # write stdout to a tmp next to dst, then mv | ||||
|   dst="$1"; dir="$(dirname "$dst")" | ||||
|   tmp="$(mktemp "$dir/.reprepro.XXXXXX")" | ||||
|   cat >"$tmp" | ||||
|   mv -f "$tmp" "$dst" | ||||
| } | ||||
| 
 | ||||
| [ -r "$release" ] || { echo "error: $release not readable" >&2; exit 1; } | ||||
| umask 022 | ||||
| 
 | ||||
| # InRelease (clearsigned) | ||||
| if [ -n "$inrel" ]; then | ||||
|   gpgcmd --clearsign <"$release" | mkout "$inrel" | ||||
| fi | ||||
| 
 | ||||
| # Release.gpg (detached, armored) | ||||
| if [ -n "$relgpg" ]; then | ||||
|   gpgcmd --armor --detach-sign <"$release" | mkout "$relgpg" | ||||
| fi | ||||
							
								
								
									
										84
									
								
								scripts/package.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										84
									
								
								scripts/package.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,84 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| set -euo pipefail | ||||
| 
 | ||||
| # Space-separated list of PHP major.minor versions to build | ||||
| PHPS="${PHPS:-"7.4 8.0 8.1 8.2 8.3 8.4"}" | ||||
| 
 | ||||
| # Matrix of base images with their distro codenames (image|codename) | ||||
| BASE_MATRIX=( | ||||
|   "debian:13|trixie" | ||||
|   "debian:12|bookworm" | ||||
|   "ubuntu:24.04|noble" | ||||
|   "ubuntu:22.04|jammy" | ||||
| ) | ||||
| 
 | ||||
| # Where to put artifacts on the host | ||||
| OUT_DIR="${OUT_DIR:-"$(cd "$(dirname "$0")/.."; pwd)/build"}" | ||||
| 
 | ||||
| # Docker binary | ||||
| DOCKER_BIN="${DOCKER_BIN:-docker}" | ||||
| 
 | ||||
| # Pass extra args to `docker build` if needed | ||||
| EXTRA_BUILD_ARGS=${EXTRA_BUILD_ARGS:-} | ||||
| 
 | ||||
| export DOCKER_BUILDKIT=1 | ||||
| 
 | ||||
| # Always run from scripts/ so relative paths work the same | ||||
| cd "$(dirname "$0")" | ||||
| 
 | ||||
| # Dockerfile is in parent; use repo root as build context | ||||
| DOCKERFILE="../Dockerfile" | ||||
| CONTEXT=".." | ||||
| 
 | ||||
| mkdir -p "$OUT_DIR" | ||||
| 
 | ||||
| echo "==> Output directory: $OUT_DIR" | ||||
| echo "==> Dockerfile: $DOCKERFILE (context: $CONTEXT)" | ||||
| echo "==> PHP versions: $PHPS" | ||||
| echo "==> Base matrix:" | ||||
| printf '    - %s\n' "${BASE_MATRIX[@]}" | ||||
| 
 | ||||
| for entry in "${BASE_MATRIX[@]}"; do | ||||
|   IFS='|' read -r BASE_IMAGE CODENAME <<<"$entry" | ||||
| 
 | ||||
|   for PHP_VER in $PHPS; do | ||||
|     TAG="pkg-php${PHP_VER}-${CODENAME}" | ||||
|     DEST_DIR="${OUT_DIR}/${CODENAME}/php${PHP_VER}" | ||||
| 
 | ||||
|     echo | ||||
|     echo "==== Building: base=${BASE_IMAGE} (${CODENAME}), php=${PHP_VER} -> tag=${TAG}" | ||||
|     echo "     Artifacts -> ${DEST_DIR}" | ||||
|     mkdir -p "${DEST_DIR}" | ||||
| 
 | ||||
|     # Build the image. | ||||
|     $DOCKER_BIN build \ | ||||
|         -f "${DOCKERFILE}" \ | ||||
|         --build-arg "BASE_IMAGE=${BASE_IMAGE}" \ | ||||
|         --build-arg "PHP_VER=${PHP_VER}" \ | ||||
|         --progress=plain \ | ||||
|         -t "${TAG}" \ | ||||
|         ${EXTRA_BUILD_ARGS} \ | ||||
|         "${CONTEXT}" | ||||
| 
 | ||||
|     # Export /dist/ from the image to the host | ||||
|     CID="$($DOCKER_BIN create "${TAG}" sh -c 'exit 0')" | ||||
| 
 | ||||
|     # Copy artifacts | ||||
|     if ! $DOCKER_BIN cp "${CID}:/dist/." "${DEST_DIR}/"; then | ||||
|       echo "!! No /dist found in image ${TAG}." | ||||
|     else | ||||
|       #find "${DEST_DIR}" -type f ! -name "*.deb" -delete || true | ||||
|       # Sanity check | ||||
|       if compgen -G "${DEST_DIR}/*.deb" >/dev/null; then | ||||
|         echo "==> Collected $(ls -1 "${DEST_DIR}"/*.deb | wc -l | tr -d ' ') .deb files" | ||||
|       else | ||||
|         echo "!! No .deb files found for ${TAG} after copy." | ||||
|       fi | ||||
|     fi | ||||
|   done | ||||
| done | ||||
| 
 | ||||
| echo | ||||
| echo "   Done. All artifacts are under: ${OUT_DIR}" | ||||
| echo "   Structure: build/<codename>/php<version>/*.deb" | ||||
							
								
								
									
										13
									
								
								scripts/publish.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										13
									
								
								scripts/publish.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| set -eoux pipefail | ||||
| 
 | ||||
| OUT_DIR="${OUT_DIR:-"$(cd "$(dirname "$0")/.."; pwd)/build"}" | ||||
| 
 | ||||
| for CODENAME in trixie bookworm noble jammy; do | ||||
|   # feed all .deb for that codename into the repo | ||||
|   if compgen -G "${OUT_DIR}/${CODENAME}/php*/*.deb" >/dev/null 2>&1; then | ||||
|     find "${OUT_DIR}/${CODENAME}" -name '*.deb' -print0 \ | ||||
|       | xargs -0 -n1 reprepro -b repo includedeb "$CODENAME" | ||||
|   fi | ||||
| done | ||||
							
								
								
									
										66
									
								
								scripts/render-debian-files.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										66
									
								
								scripts/render-debian-files.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| set -euo pipefail | ||||
| 
 | ||||
| # ---- Compute variables ---- | ||||
| PHP_VER="${PHP_VER:?set PHP_VER like 7.4|8.0|8.1|8.2|8.3|8.4}" | ||||
| PKG="php${PHP_VER}-sqlcipher" | ||||
| PHP_BIN="php${PHP_VER}" | ||||
| DOC_DIR="/usr/share/doc/${PKG}" | ||||
| 
 | ||||
| # Distro codename | ||||
| if command -v lsb_release >/dev/null 2>&1; then | ||||
|   DIST_CODENAME="${DIST_CODENAME:-$(lsb_release -sc)}" | ||||
| else | ||||
|   . /etc/os-release 2>/dev/null || true | ||||
|   DIST_CODENAME="${DIST_CODENAME:-${VERSION_CODENAME:-unknown}}" | ||||
| fi | ||||
| 
 | ||||
| MAINT_NAME="${MAINT_NAME:-Miguel Jacq}" | ||||
| MAINT_EMAIL="${MAINT_EMAIL:-mig@mig5.net}" | ||||
| DATE_RFC2822="$(date -R)" | ||||
| 
 | ||||
| # Derive package version if not provided | ||||
| if [[ -z "${PKG_VERSION:-}" ]]; then | ||||
|   if command -v "${PHP_BIN}" >/dev/null 2>&1; then | ||||
|     PHP_FULL="$("${PHP_BIN}" -r 'echo PHP_MAJOR_VERSION,".",PHP_MINOR_VERSION,".",PHP_RELEASE_VERSION;')" | ||||
|   else | ||||
|     PHP_FULL="$(dpkg-query -W -f='${Version}\n' "${PHP_BIN}-dev" 2>/dev/null | sed 's/-.*//;q' || echo "${PHP_VER}.0")" | ||||
|   fi | ||||
|   PKG_VERSION="${PHP_FULL}-1+${DIST_CODENAME}" | ||||
| fi | ||||
| 
 | ||||
| # Export everything envsubst must see | ||||
| export PHP_VER PKG PHP_BIN DOC_DIR DIST_CODENAME PKG_VERSION MAINT_NAME MAINT_EMAIL DATE_RFC2822 | ||||
| 
 | ||||
| # Only substitute the vars we care about | ||||
| VARS='${PHP_VER} ${PKG} ${PHP_BIN} ${DOC_DIR} ${DIST_CODENAME} ${PKG_VERSION} ${MAINT_NAME} ${MAINT_EMAIL} ${DATE_RFC2822}' | ||||
| 
 | ||||
| render() { | ||||
|   local src="$1" dst="$2" | ||||
|   [[ -f "$src" ]] || return 0 | ||||
|   # Support both ${VAR} and @VAR@ templates | ||||
|   local tmp; tmp="$(mktemp)" | ||||
|   sed -E 's/@([A-Z0-9_]+)@/\${\1}/g' "$src" > "$tmp" | ||||
|   envsubst "$VARS" < "$tmp" > "$dst" | ||||
|   rm -f "$tmp" | ||||
| } | ||||
| 
 | ||||
| # Render files | ||||
| render debian/changelog.in        debian/changelog | ||||
| render debian/control.in          debian/control | ||||
| render debian/copyright.in        debian/copyright | ||||
| render debian/pkg.examples.in     "debian/${PKG}.examples" | ||||
| render debian/pkg.php.in          "debian/${PKG}.php" | ||||
| mkdir -p debian/tests | ||||
| render debian/tests/control.in    debian/tests/control | ||||
| render debian/tests/basic.in      debian/tests/basic | ||||
| 
 | ||||
| # ---- Self-check: make sure changelog header is valid and no ${...} placeholders remain ---- | ||||
| if [[ -f debian/changelog ]]; then | ||||
|   head -n1 debian/changelog | grep -Eq '^[a-z0-9.+-]+ \([0-9][^)]*\) [^;]+; urgency=' \ | ||||
|     || { echo "ERROR: debian/changelog header invalid:"; sed -n '1,3p' debian/changelog; exit 1; } | ||||
|   ! grep -q '\${[A-Z0-9_]\+}' debian/changelog \ | ||||
|     || { echo "ERROR: Unsubstituted variables remain in debian/changelog"; sed -n '1,8p' debian/changelog; exit 1; } | ||||
| fi | ||||
| 
 | ||||
							
								
								
									
										32
									
								
								scripts/setup-php-sources.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								scripts/setup-php-sources.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| #!/usr/bin/env bash | ||||
| 
 | ||||
| set -euo pipefail | ||||
| 
 | ||||
| . /etc/os-release | ||||
| case "${ID}" in | ||||
|   ubuntu) | ||||
|     apt-get update | ||||
|     apt-get install -y --no-install-recommends software-properties-common | ||||
|     # Adds both deb and deb-src for Ondřej’s PPA | ||||
|     add-apt-repository -y -s ppa:ondrej/php | ||||
|     ;; | ||||
|   debian) | ||||
|     # Official way per deb.sury.org README | ||||
|     curl -fsSL -o /tmp/debsuryorg-archive-keyring.deb \ | ||||
|       https://packages.sury.org/debsuryorg-archive-keyring.deb | ||||
|     # SHA256SUM matches what https://mirrors.dotsrc.org/deb.sury.org/bind-dev/dists/bullseye/main/binary-amd64/Packages shows | ||||
|     echo "d1df4b797498829bb4dbd23de7a88945924a0eac6bce9b6c68e6650c85187f5f /tmp/debsuryorg-archive-keyring.deb" | sha256sum -c - | ||||
|     dpkg -i /tmp/debsuryorg-archive-keyring.deb | ||||
| 
 | ||||
|     codename="$(lsb_release -sc)" | ||||
|     cat >/etc/apt/sources.list.d/php.list <<EOF | ||||
| deb     [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ ${codename} main | ||||
| deb-src [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ ${codename} main | ||||
| EOF | ||||
|     ;; | ||||
|   *) | ||||
|     echo "Unsupported distro ID=${ID}" >&2; exit 2;; | ||||
| esac | ||||
| 
 | ||||
| apt-get update; | ||||
| apt-get install -y --no-install-recommends php${PHP_VER}-dev | ||||
							
								
								
									
										215
									
								
								tests/test_sqlcipher.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								tests/test_sqlcipher.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,215 @@ | |||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| /** | ||||
|  * SQLCipher verification script | ||||
|  * | ||||
|  * WHAT IT CHECKS | ||||
|  *  1) PRAGMA key is correctly applied (and cipher_version is non-empty). | ||||
|  *  2) PRAGMA cipher_integrity_check returns NO ROWS (OK). | ||||
|  *  3) File header is NOT the plain "SQLite format 3\0". | ||||
|  *  4) Inserting a known plaintext marker does NOT make that marker appear in the raw file. | ||||
|  *  5) Opening with a wrong key fails to validate via cipher_integrity_check. | ||||
|  *  6) First-page entropy is high (sanity check). | ||||
|  */ | ||||
| 
 | ||||
| // ---------------------------- Utilities ----------------------------
 | ||||
| 
 | ||||
| function makePrivateTempDir(?string $base = null): string { | ||||
|     $base = $base ?? sys_get_temp_dir(); | ||||
|     $oldUmask = umask(0077); | ||||
|     try { | ||||
|         for ($i = 0; $i < 5; $i++) { | ||||
|             $name = bin2hex(random_bytes(16)); | ||||
|             $dir  = $base . DIRECTORY_SEPARATOR . "php-$name"; | ||||
|             if (@mkdir($dir, 0700)) { | ||||
|                 return realpath($dir) ?: $dir; | ||||
|             } | ||||
|         } | ||||
|         throw new RuntimeException("Could not create a unique temp directory"); | ||||
|     } finally { | ||||
|         umask($oldUmask); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /** Simple pretty assertion helper */ | ||||
| function check(string $label, bool $ok, ?string $detail = null): void { | ||||
|     $prefix = $ok ? "[OK] " : "[FAIL] "; | ||||
|     echo $prefix . $label . ($detail ? " — $detail" : "") . "\n"; | ||||
|     if (!$ok) { | ||||
|         exit(1); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /** Return true if the file begins with the plain SQLite header */ | ||||
| function hasPlainSQLiteHeader(string $path): bool { | ||||
|     $fh = @fopen($path, 'rb'); | ||||
|     if (!$fh) { | ||||
|         throw new RuntimeException("Cannot open $path"); | ||||
|     } | ||||
|     $hdr = fread($fh, 16); | ||||
|     fclose($fh); | ||||
|     return $hdr === "SQLite format 3\0"; | ||||
| } | ||||
| 
 | ||||
| /** Shannon entropy (bits/byte) */ | ||||
| function shannonEntropy(string $bytes): float { | ||||
|     $len = strlen($bytes); | ||||
|     if ($len === 0) return 0.0; | ||||
|     $freq = count_chars($bytes, 1); | ||||
|     $h = 0.0; | ||||
|     foreach ($freq as $n) { | ||||
|         $p = $n / $len; | ||||
|         $h -= $p * log($p, 2); | ||||
|     } | ||||
|     return $h; | ||||
| } | ||||
| 
 | ||||
| /** Read first page (minus the first 16 bytes salt) and estimate entropy */ | ||||
| function firstPageEntropy(string $path, int $pageSize = 4096): float { | ||||
|     $fh = @fopen($path, 'rb'); | ||||
|     if (!$fh) throw new RuntimeException("Cannot open $path"); | ||||
|     $page = fread($fh, $pageSize); | ||||
|     fclose($fh); | ||||
|     if ($page === false || strlen($page) === 0) return 0.0; | ||||
|     // SQLCipher uses first 16 bytes as salt at offset 0
 | ||||
|     $slice = substr($page, 16); | ||||
|     return shannonEntropy($slice); | ||||
| } | ||||
| 
 | ||||
| /** Open PDO with SQLCipher key applied */ | ||||
| function pdoWithKey(string $path, string $passphrase): PDO { | ||||
|     $dbh = new PDO("sqlite:" . $path); | ||||
|     $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||||
|     $dbh->exec("PRAGMA key = " . $dbh->quote($passphrase)); | ||||
|     $dbh->exec("PRAGMA cipher_memory_security = ON"); | ||||
|     return $dbh; | ||||
| } | ||||
| 
 | ||||
| /** Return a single scalar from "PRAGMA xyz;" */ | ||||
| function pragmaOne(PDO $dbh, string $pragma): ?string { | ||||
|     $stmt = $dbh->query("PRAGMA $pragma;"); | ||||
|     $row = $stmt ? $stmt->fetch(PDO::FETCH_NUM) : false; | ||||
|     return $row && isset($row[0]) ? (string)$row[0] : null; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * cipher_integrity_check returns: | ||||
|  *  - zero rows => OK (externally consistent) | ||||
|  *  - one or more rows => errors found (or wrong key) | ||||
|  */ | ||||
| function cipherIntegrityOk(PDO $dbh): bool { | ||||
|     $stmt = $dbh->query("PRAGMA cipher_integrity_check;"); | ||||
|     if (!$stmt) return false;  // query failed -> not OK
 | ||||
|     $row = $stmt->fetch(PDO::FETCH_NUM); | ||||
|     return ($row === false);   // no rows == OK
 | ||||
| } | ||||
| 
 | ||||
| // ---------------------------- Main actions ----------------------------
 | ||||
| 
 | ||||
| function createAndPopulate(string $path, string $passphrase, string $marker): void { | ||||
|     $dbh = pdoWithKey($path, $passphrase); | ||||
| 
 | ||||
|     // Basic SQLCipher sanity: cipher_version should be non-empty
 | ||||
|     $cipherVersion = pragmaOne($dbh, "cipher_version"); | ||||
|     check("cipher_version available", !empty($cipherVersion), $cipherVersion ?? "(empty)"); | ||||
| 
 | ||||
|     // Create table and insert two rows (one is the plaintext 'marker')
 | ||||
|     $dbh->exec("CREATE TABLE IF NOT EXISTS users (name TEXT NOT NULL)"); | ||||
|     $stmt = $dbh->prepare("INSERT INTO users(name) VALUES(:name)"); | ||||
|     $stmt->execute([":name" => "mig5"]); | ||||
|     $stmt->execute([":name" => $marker]); | ||||
| 
 | ||||
|     // Confirm we can read back with the correct key
 | ||||
|     $names = $dbh->query("SELECT name FROM users ORDER BY rowid")->fetchAll(PDO::FETCH_COLUMN, 0); | ||||
|     check("Read back inserted rows", in_array("mig5", $names, true) && in_array($marker, $names, true)); | ||||
| 
 | ||||
|     // Integrity check should be OK (i.e., returns no rows)
 | ||||
|     $ok = cipherIntegrityOk($dbh); | ||||
|     check("cipher_integrity_check", $ok, $ok ? "no rows (OK)" : "reported errors"); | ||||
| 
 | ||||
|     // Capture page_size (for entropy sampling)
 | ||||
|     $pageSize = (int)(pragmaOne($dbh, "page_size") ?? 4096); | ||||
|     $dbh = null; // close
 | ||||
|     // Store page size to a sidecar file so we can read it after closing the DB
 | ||||
|     file_put_contents($path . ".pagesize", (string)$pageSize); | ||||
| } | ||||
| 
 | ||||
| function probeWrongKey(string $path, string $wrongKey): void { | ||||
|     try { | ||||
|         $dbh = pdoWithKey($path, $wrongKey); | ||||
| 
 | ||||
|         // With the wrong key, integrity should NOT be OK (either rows returned or errors)
 | ||||
|         $okWrong = false; | ||||
|         try { | ||||
|             $okWrong = cipherIntegrityOk($dbh); // true means "no rows" => (unexpected)
 | ||||
|         } catch (Throwable $e) { | ||||
|             // Expected scenarios with wrong key can throw; treat as failure (which is good here)
 | ||||
|             $okWrong = false; | ||||
|         } | ||||
| 
 | ||||
|         if ($okWrong) { | ||||
|             check("Wrong key probe (unexpectedly OK)", false); | ||||
|         } else { | ||||
|             check("Wrong key probe (integrity fails as expected)", true); | ||||
|         } | ||||
|     } catch (Throwable $e) { | ||||
|         // Exception creating/using the handle is also acceptable evidence key is wrong
 | ||||
|         check("Wrong key probe (exception on use)", true, get_class($e) . ": " . $e->getMessage()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function scanForPlaintextMarker(string $path, string $marker): void { | ||||
|     $raw = file_get_contents($path); | ||||
|     $found = ($raw !== false) && (strpos($raw, $marker) !== false); | ||||
|     check("Plaintext marker NOT present in raw file", !$found, $found ? "marker leaked to disk" : null); | ||||
| } | ||||
| 
 | ||||
| function headerIsNotPlainSQLite(string $path): void { | ||||
|     $plain = hasPlainSQLiteHeader($path); | ||||
|     check("Header is not plain 'SQLite format 3\\0'", !$plain, $plain ? "found plain SQLite header" : null); | ||||
| } | ||||
| 
 | ||||
| function entropyCheck(string $path): void { | ||||
|     $pageSizePath = $path . ".pagesize"; | ||||
|     $pageSize = 4096; | ||||
|     if (is_file($pageSizePath)) { | ||||
|         $ps = (int)trim((string)file_get_contents($pageSizePath)); | ||||
|         if ($ps > 0) $pageSize = $ps; | ||||
|     } | ||||
|     $H = firstPageEntropy($path, $pageSize); | ||||
|     // Encrypted data typically ~7.8–8.0 bits/byte. Use a lenient threshold.
 | ||||
|     $ok = $H >= 7.5; | ||||
|     check("First-page entropy high (>= 7.5 bits/byte)", $ok, sprintf("H=%.3f (page=%d)", $H, $pageSize)); | ||||
|     @unlink($pageSizePath); | ||||
| } | ||||
| 
 | ||||
| // ---------------------------- Run ----------------------------
 | ||||
| 
 | ||||
| try { | ||||
|     $dir  = makePrivateTempDir(); | ||||
|     $file = $dir . DIRECTORY_SEPARATOR . 'test.db'; | ||||
| 
 | ||||
|     $passphrase = "super-secret-passphrase-for-sqlcipher-pragma"; | ||||
|     $wrongKey   = "definitely-the-wrong-key"; | ||||
|     $marker     = "PLAINTEXT_MARKER_" . bin2hex(random_bytes(8)); | ||||
| 
 | ||||
|     echo "Creating DB at: $file\n"; | ||||
|     createAndPopulate($file, $passphrase, $marker); | ||||
| 
 | ||||
|     headerIsNotPlainSQLite($file); | ||||
|     scanForPlaintextMarker($file, $marker); | ||||
|     probeWrongKey($file, $wrongKey); | ||||
|     entropyCheck($file); | ||||
| 
 | ||||
|     echo "\nAll checks passed.\n"; | ||||
| 
 | ||||
| } catch (Throwable $e) { | ||||
|     fwrite(STDERR, "Error: " . get_class($e) . ": " . $e->getMessage() . "\n"); | ||||
|     exit(1); | ||||
| } finally { | ||||
|     // Cleanup
 | ||||
|     if (isset($file) && is_file($file)) @unlink($file); | ||||
|     if (isset($dir) && is_dir($dir)) @rmdir($dir); | ||||
| } | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue