diff --git a/.github/workflows/build-sqlcipher3.yml b/.github/workflows/build-sqlcipher3.yml new file mode 100644 index 00000000000..31eeffd9ed3 --- /dev/null +++ b/.github/workflows/build-sqlcipher3.yml @@ -0,0 +1,167 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Based on the `wheels` job of +# https://github.com/coleifer/sqlcipher3/blob/0.6.2/.github/workflows/wheels.yaml +name: Build sqlcipher3 wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/sqlcipher3.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-sqlcipher3.yml' + - 'docs/packages/sqlcipher3.yaml' + - 'patches/sqlcipher3/**' + push: + branches: [main] + paths: + - '.github/workflows/build-sqlcipher3.yml' + - 'docs/packages/sqlcipher3.yaml' + - 'patches/sqlcipher3/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + MUSLLINUX_RISCV64_IMAGE: quay.io/pypa/musllinux_1_2_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: sqlcipher3 + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build sqlcipher3 ${{ matrix.version }} ${{ matrix.python }}-${{ matrix.libc }}_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + python: ["cp312", "cp313", "cp314", "cp314t"] + libc: [manylinux, musllinux] + + env: + SQLCIPHER3_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout sqlcipher3 ${{ env.SQLCIPHER3_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: coleifer/sqlcipher3 + ref: ${{ env.SQLCIPHER3_VERSION }} + persist-credentials: false + + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + persist-credentials: false + + - name: Patch sqlcipher3 source + run: git apply python-wheels/patches/sqlcipher3/${{ env.SQLCIPHER3_VERSION }}/*.patch + + # Upstream's suite never sets a key, so check the statically linked OpenSSL and the + # licences of what the wheel bundles. + - name: Write encryption smoke test + run: | + cat > smoke_test.py <<'EOF' + import importlib.metadata + import os + import tempfile + + from sqlcipher3 import dbapi2 as sqlite + + licenses = sorted( + p.name for p in importlib.metadata.files("sqlcipher3") if ".dist-info/licenses/" in str(p) + ) + assert licenses == ["LICENSE", "LICENSE.openssl", "LICENSE.sqlcipher"], licenses + + with tempfile.TemporaryDirectory() as tmp: + path = os.path.join(tmp, "enc.db") + conn = sqlite.connect(path) + conn.execute("PRAGMA key = 'riscv64'") + provider = conn.execute("PRAGMA cipher_provider_version").fetchone()[0] + assert provider.startswith("OpenSSL 3."), provider + conn.execute("CREATE TABLE t (v TEXT)") + conn.execute("INSERT INTO t VALUES ('plaintext-marker')") + conn.commit() + conn.close() + with open(path, "rb") as fh: + assert b"plaintext-marker" not in fh.read() + + conn = sqlite.connect(path) + conn.execute("PRAGMA key = 'riscv64'") + assert conn.execute("PRAGMA cipher_integrity_check").fetchall() == [] + assert conn.execute("SELECT v FROM t").fetchall() == [("plaintext-marker",)] + conn.close() + + conn = sqlite.connect(path) + conn.execute("PRAGMA key = 'wrong'") + try: + conn.execute("SELECT v FROM t").fetchall() + except sqlite.DatabaseError: + pass + else: + raise AssertionError("wrong key decrypted the database") + print(provider, "ok") + EOF + + - uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + env: + CIBW_BUILD_FRONTEND: build + CIBW_ARCHS: riscv64 + CIBW_BUILD: ${{ matrix.python }}-${{ matrix.libc }}_riscv64 + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + CIBW_MUSLLINUX_RISCV64_IMAGE: ${{ env.MUSLLINUX_RISCV64_IMAGE }} + # Conan's openssl recipe has no riscv64 entry and falls back to linux-generic32; + # linux64-riscv64's AES asm `jal`s a global symbol, which overflows R_RISCV_JAL here. + CIBW_ENVIRONMENT: >- + SQLCIPHER3_COMPILE_TARGET=riscv64 + CONAN_OPENSSL_CONFIGURATION=linux-generic64 + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + CIBW_BEFORE_ALL_LINUX: command -v yum >/dev/null && yum -y install perl-core || command -v apk >/dev/null && apk add perl || true + # -P keeps the build's {project}/sqlcipher3.egg-info from shadowing the installed metadata. + CIBW_TEST_COMMAND: > + mv {project}/sqlcipher3 {project}/sqlcipher3_ && + python {project}/tests/ && + python -P {project}/smoke_test.py && + mv {project}/sqlcipher3_ {project}/sqlcipher3 + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sqlcipher3-${{ env.SQLCIPHER3_VERSION }}-${{ matrix.python }}-${{ matrix.libc }}_riscv64 + path: ./wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish sqlcipher3 ${{ matrix.version }} + needs: [setup, build_wheels] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + secrets: + app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} + with: + artifact-pattern: sqlcipher3-${{ matrix.version }}-*riscv64 diff --git a/docs/packages/sqlcipher3.yaml b/docs/packages/sqlcipher3.yaml new file mode 100644 index 00000000000..6e78519920d --- /dev/null +++ b/docs/packages/sqlcipher3.yaml @@ -0,0 +1,6 @@ +package-name: sqlcipher3 +source-code: https://github.com/coleifer/sqlcipher3 +license: MIT +versions: +- version: 0.6.2 + patched: true diff --git a/patches/sqlcipher3/0.6.2/0001-Ship-the-licences-of-the-bundled-SQLCipher-and-OpenSSL.patch b/patches/sqlcipher3/0.6.2/0001-Ship-the-licences-of-the-bundled-SQLCipher-and-OpenSSL.patch new file mode 100644 index 00000000000..b0f58149e1e --- /dev/null +++ b/patches/sqlcipher3/0.6.2/0001-Ship-the-licences-of-the-bundled-SQLCipher-and-OpenSSL.patch @@ -0,0 +1,241 @@ +From 31789749ddb0b2157642b1c005ef1bf76476bff0 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Fri, 2 Oct 2026 18:18:49 +0000 +Subject: [PATCH] Ship the licences of the bundled SQLCipher and OpenSSL + +The extension compiles the vendored SQLCipher 4.12.0 amalgamation +(vendor/sqlite3.c, BSD-3-Clause, ZETETIC LLC) and statically links the +libcrypto of the OpenSSL 3.6.0 that conanfile.py builds (Apache-2.0), +but the wheel ships only sqlcipher3's own LICENSE. Both licences +require their notice to travel with binary redistributions. + +Add LICENSE.sqlcipher (SQLCipher's LICENSE.md at v4.12.0) and +LICENSE.openssl (OpenSSL's LICENSE.txt at openssl-3.6.0) at the project +root, where the default PEP 639 license-files glob picks them up into +dist-info/licenses/ with no packaging change. The SQLite core in the +amalgamation is public domain and needs no notice. + +Upstream-Status: To upstream [needs a pull request against coleifer/sqlcipher3; not submitted from this automated port run] +--- + LICENSE.openssl | 177 ++++++++++++++++++++++++++++++++++++++++++++++ + LICENSE.sqlcipher | 24 +++++++ + 2 files changed, 201 insertions(+) + create mode 100644 LICENSE.openssl + create mode 100644 LICENSE.sqlcipher + +diff --git a/LICENSE.openssl b/LICENSE.openssl +new file mode 100644 +index 0000000..49cc83d +--- /dev/null ++++ b/LICENSE.openssl +@@ -0,0 +1,177 @@ ++ ++ Apache License ++ Version 2.0, January 2004 ++ https://www.apache.org/licenses/ ++ ++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION ++ ++ 1. Definitions. ++ ++ "License" shall mean the terms and conditions for use, reproduction, ++ and distribution as defined by Sections 1 through 9 of this document. ++ ++ "Licensor" shall mean the copyright owner or entity authorized by ++ the copyright owner that is granting the License. ++ ++ "Legal Entity" shall mean the union of the acting entity and all ++ other entities that control, are controlled by, or are under common ++ control with that entity. For the purposes of this definition, ++ "control" means (i) the power, direct or indirect, to cause the ++ direction or management of such entity, whether by contract or ++ otherwise, or (ii) ownership of fifty percent (50%) or more of the ++ outstanding shares, or (iii) beneficial ownership of such entity. ++ ++ "You" (or "Your") shall mean an individual or Legal Entity ++ exercising permissions granted by this License. ++ ++ "Source" form shall mean the preferred form for making modifications, ++ including but not limited to software source code, documentation ++ source, and configuration files. ++ ++ "Object" form shall mean any form resulting from mechanical ++ transformation or translation of a Source form, including but ++ not limited to compiled object code, generated documentation, ++ and conversions to other media types. ++ ++ "Work" shall mean the work of authorship, whether in Source or ++ Object form, made available under the License, as indicated by a ++ copyright notice that is included in or attached to the work ++ (an example is provided in the Appendix below). ++ ++ "Derivative Works" shall mean any work, whether in Source or Object ++ form, that is based on (or derived from) the Work and for which the ++ editorial revisions, annotations, elaborations, or other modifications ++ represent, as a whole, an original work of authorship. For the purposes ++ of this License, Derivative Works shall not include works that remain ++ separable from, or merely link (or bind by name) to the interfaces of, ++ the Work and Derivative Works thereof. ++ ++ "Contribution" shall mean any work of authorship, including ++ the original version of the Work and any modifications or additions ++ to that Work or Derivative Works thereof, that is intentionally ++ submitted to Licensor for inclusion in the Work by the copyright owner ++ or by an individual or Legal Entity authorized to submit on behalf of ++ the copyright owner. For the purposes of this definition, "submitted" ++ means any form of electronic, verbal, or written communication sent ++ to the Licensor or its representatives, including but not limited to ++ communication on electronic mailing lists, source code control systems, ++ and issue tracking systems that are managed by, or on behalf of, the ++ Licensor for the purpose of discussing and improving the Work, but ++ excluding communication that is conspicuously marked or otherwise ++ designated in writing by the copyright owner as "Not a Contribution." ++ ++ "Contributor" shall mean Licensor and any individual or Legal Entity ++ on behalf of whom a Contribution has been received by Licensor and ++ subsequently incorporated within the Work. ++ ++ 2. Grant of Copyright License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ copyright license to reproduce, prepare Derivative Works of, ++ publicly display, publicly perform, sublicense, and distribute the ++ Work and such Derivative Works in Source or Object form. ++ ++ 3. Grant of Patent License. Subject to the terms and conditions of ++ this License, each Contributor hereby grants to You a perpetual, ++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable ++ (except as stated in this section) patent license to make, have made, ++ use, offer to sell, sell, import, and otherwise transfer the Work, ++ where such license applies only to those patent claims licensable ++ by such Contributor that are necessarily infringed by their ++ Contribution(s) alone or by combination of their Contribution(s) ++ with the Work to which such Contribution(s) was submitted. If You ++ institute patent litigation against any entity (including a ++ cross-claim or counterclaim in a lawsuit) alleging that the Work ++ or a Contribution incorporated within the Work constitutes direct ++ or contributory patent infringement, then any patent licenses ++ granted to You under this License for that Work shall terminate ++ as of the date such litigation is filed. ++ ++ 4. Redistribution. You may reproduce and distribute copies of the ++ Work or Derivative Works thereof in any medium, with or without ++ modifications, and in Source or Object form, provided that You ++ meet the following conditions: ++ ++ (a) You must give any other recipients of the Work or ++ Derivative Works a copy of this License; and ++ ++ (b) You must cause any modified files to carry prominent notices ++ stating that You changed the files; and ++ ++ (c) You must retain, in the Source form of any Derivative Works ++ that You distribute, all copyright, patent, trademark, and ++ attribution notices from the Source form of the Work, ++ excluding those notices that do not pertain to any part of ++ the Derivative Works; and ++ ++ (d) If the Work includes a "NOTICE" text file as part of its ++ distribution, then any Derivative Works that You distribute must ++ include a readable copy of the attribution notices contained ++ within such NOTICE file, excluding those notices that do not ++ pertain to any part of the Derivative Works, in at least one ++ of the following places: within a NOTICE text file distributed ++ as part of the Derivative Works; within the Source form or ++ documentation, if provided along with the Derivative Works; or, ++ within a display generated by the Derivative Works, if and ++ wherever such third-party notices normally appear. The contents ++ of the NOTICE file are for informational purposes only and ++ do not modify the License. You may add Your own attribution ++ notices within Derivative Works that You distribute, alongside ++ or as an addendum to the NOTICE text from the Work, provided ++ that such additional attribution notices cannot be construed ++ as modifying the License. ++ ++ You may add Your own copyright statement to Your modifications and ++ may provide additional or different license terms and conditions ++ for use, reproduction, or distribution of Your modifications, or ++ for any such Derivative Works as a whole, provided Your use, ++ reproduction, and distribution of the Work otherwise complies with ++ the conditions stated in this License. ++ ++ 5. Submission of Contributions. Unless You explicitly state otherwise, ++ any Contribution intentionally submitted for inclusion in the Work ++ by You to the Licensor shall be under the terms and conditions of ++ this License, without any additional terms or conditions. ++ Notwithstanding the above, nothing herein shall supersede or modify ++ the terms of any separate license agreement you may have executed ++ with Licensor regarding such Contributions. ++ ++ 6. Trademarks. This License does not grant permission to use the trade ++ names, trademarks, service marks, or product names of the Licensor, ++ except as required for reasonable and customary use in describing the ++ origin of the Work and reproducing the content of the NOTICE file. ++ ++ 7. Disclaimer of Warranty. Unless required by applicable law or ++ agreed to in writing, Licensor provides the Work (and each ++ Contributor provides its Contributions) on an "AS IS" BASIS, ++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ++ implied, including, without limitation, any warranties or conditions ++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A ++ PARTICULAR PURPOSE. You are solely responsible for determining the ++ appropriateness of using or redistributing the Work and assume any ++ risks associated with Your exercise of permissions under this License. ++ ++ 8. Limitation of Liability. In no event and under no legal theory, ++ whether in tort (including negligence), contract, or otherwise, ++ unless required by applicable law (such as deliberate and grossly ++ negligent acts) or agreed to in writing, shall any Contributor be ++ liable to You for damages, including any direct, indirect, special, ++ incidental, or consequential damages of any character arising as a ++ result of this License or out of the use or inability to use the ++ Work (including but not limited to damages for loss of goodwill, ++ work stoppage, computer failure or malfunction, or any and all ++ other commercial damages or losses), even if such Contributor ++ has been advised of the possibility of such damages. ++ ++ 9. Accepting Warranty or Additional Liability. While redistributing ++ the Work or Derivative Works thereof, You may choose to offer, ++ and charge a fee for, acceptance of support, warranty, indemnity, ++ or other liability obligations and/or rights consistent with this ++ License. However, in accepting such obligations, You may act only ++ on Your own behalf and on Your sole responsibility, not on behalf ++ of any other Contributor, and only if You agree to indemnify, ++ defend, and hold each Contributor harmless for any liability ++ incurred by, or claims asserted against, such Contributor by reason ++ of your accepting any such warranty or additional liability. ++ ++ END OF TERMS AND CONDITIONS +diff --git a/LICENSE.sqlcipher b/LICENSE.sqlcipher +new file mode 100644 +index 0000000..3f71443 +--- /dev/null ++++ b/LICENSE.sqlcipher +@@ -0,0 +1,24 @@ ++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. +-- +2.43.0 +