"Cloud" password managers got some attention recently due to publication Zero Knowledge (About) Encryption: A Comparative Security Analysis of Three Cloud-based Password Managers (preprint) about vulnerabilities in some of them, such as BitWarden in cases where the server is compromised:
SPHINX password storage is an online password manager that is theoretically secure against similar attacks. I don't use cloud password managers myself and synchronize passwords with Firefox Sync and KeePassXC shared between hosts using Syncthing.
I still want to try SPHINX to see how it works, but it is not packaged for Arch Linux,
and neither its dependencies like liboprf.
According to the client install guide it is packaged in Debian as pwdsphinx,
but not in other distributions that are not Debian-based.
This post is my notes about writing PKGBUILDs and submitting them to AUR.
First dependency that is not packaged is liboprf.
AUR web page links to AUR submission guidelines on the Arch Wiki. Good starting point for writing PKGBUILDs is Arch package guidelines page, it is linked as a related page and in the warning, but I overlooked it at first anyway because I started reading AUR submission guidelines first. It would be more helpful if the link to package guidelines was at the right place in AUR submission guidelines and not only at the top.
I normally build packages in ~/build, so I started by cloning
empty repository into ~/build/liboprf with git -c init.defaultBranch=master clone ssh://aur@aur.archlinux.org/liboprf.git
and copying /usr/share/pacman/PKGBUILD.proto into ~/build/liboprf/PKGBUILD.
Writing PKGBUILD is straightforward, it only requires filling in the fields in the template and removing unused ones. The only part that cannot be written directly is checksums and PGP keys.
To generate checksums I used updpkgsums from the pacman-contrib package.
It generated b2sums array.
It is not necessary to use this tool, the same can be done with makepkg -g
or directly running b2sum on downloaded files left by pkgctl build after failing and copying the result into PKGBUILD.
I also downloaded the key for .asc signature which appeared to be expired but otherwise verified correctly.
At least pkgctl build was happy.
$ sq inspect liboprf-0.9.3.tar.gz.asc
liboprf-0.9.3.tar.gz.asc: Detached signature.
Alleged signer: signer's cert not found
AABDE16CB6AF5CD10A28DFF2970DEB6694D50988
(signature subkey)
Note: Signatures have NOT been verified!
$ gpg --recv-keys AABDE16CB6AF5CD10A28DFF2970DEB6694D50988
gpg: key 970DEB6694D50988: public key "stefan marsiske (temp online key) <s@ctrlc.hu>" imported
gpg: Total number processed: 1
gpg: imported: 1
$ gpg --list-key AABDE16CB6AF5CD10A28DFF2970DEB6694D50988
pub rsa4096 2014-08-23 [SC] [expired: 2018-09-03]
AABDE16CB6AF5CD10A28DFF2970DEB6694D50988
uid [ expired] stefan marsiske (temp online key) <s@ctrlc.hu>
I asked stf@chaos.social and he sent be the link to the same key without expiration.
wcurl https://ctrlc.hu/~stef/stf-pubkey.asc gpg --import stf-pubkey.asc
Wiki menitons only makepkg, but I used pkgctl build instead.
pkgctl is part of the devtools package.
The difference is that pkgctl builds the package in a chroot environment,
so it is not possible to forget adding build dependencies to PKGBUILD when they are already installed system-wide.
Running pkgctl build also generates .SRCINFO automatically
so there is no need to learn about makepkg --printsrcinfo and run it each time.
Then I installed the package with sudo pacman -U liboprf-0.9.3-1-x86_64.pkg.tar.zst and commited PKGBUILD and .SRCINFO as "Initial commit".
Then I remembered that Arch Linux at some point introduced pkgctl license.
I committed generated REUSE.toml and LICENSE and added it to the initial commit with git commit --amend.
I am fine with 0BSD.
I ran git clean -xffd . to make sure REUSE does not complain about uncommited files.
Then ran pkgctl license setup -f.
Eventually pkgctl license check was happy.
When initial commit was fine, I pushed with git push.
Package appeared on AUR website.
I then did some fixups, like adding .gitignore to ignore files that pkgctl build generates.
Then I packaged equihash.
I started with git clone -c init.defaultBranch=master ssh://aur@aur.archlinux.org/equihash.git.
Added the following .gitignore to make sure artifacts from pkgctl build will not be committed.
*.asc *.log *.pkg.tar.zst *.tar.gz
After creating PKGBUILD without checksums and running pkgctl build I got an error
==> ERROR: Integrity checks are missing for: source
Source was already downloaded, so I calculated the checksum manually with b2sum equihash-1.0.10.tar.gz and inserted it into the PKGBUILD.
The package then failed to build because of missing libsodium dependency. This is the good thing about using pkgctl build instead of makepkg,it builds packages in a separate chroot and does not use packages that I have installed in my local system.
I installed resulting package with sudo pacman -U equihash-1.0.10-1-x86_64.pkg.tar.zst and checked that files look correctly installed (not into /usr/local but in /usr) with pacman -Ql equihash.
Then I pushed to AUR and the package appeared on the website.
At this point when liboprf and libequihash are available, it is possible to install pwdsphinx from PyPI.
I did not package SPHINX itself yet, but now it can be installed by running:
python3 -m venv venv . venv/bin/activate pip install pwdsphinx
Then it is possible to run sphinx, but no man pages are available.
Without liboprf or libequihash installed I got either ValueError: Unable to find liboprf from pyoprf package or ValueError: Unable to find libequihash from equihash Python package, so the libraries from AUR are used and not compiled during installation from PyPI.
Next step is to try packaging pwdsphinx itself.
It has some more Python dependencies.
I decided not to try to package all dependencies in advance,
but start with packaging pwdsphinx directly and add dependencies as the build fails.
I did git clone -c init.defaultBranch=master ssh://aur@aur.archlinux.org/pwdsphinx.git. Copied .gitignore.
Since pwdsphinx is a Python program, I opened Python package guidlines.
I made the first version of PKGBUILD:
# Maintainer: link2xt <link2xt@testrun.org>
pkgname=pwdsphinx
pkgver=2.0.3
pkgrel=1
pkgdesc="SPHINX: A Password Store that Perfectly Hides from Itself (No Xaggeration)"
arch=(x86_64)
url="https://github.com/stef/pwdsphinx"
license=('GPL-3.0-or-later')
makedepends=(python-build python-installer python-wheel python-setuptools)
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/stef/$pkgname/archive/refs/tags/v$pkgver.tar.gz"
"https://github.com/stef/$pkgname/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz.asc")
noextract=()
b2sums=('310bc54e839187d879288cbccbd2334c548337d957e3449d30a5427d0e32f768eac57eb740b1b1549f1d31d3fd97c59d84c382b5449021a2826738dd22d47683'
'SKIP')
validpgpkeys=('AABDE16CB6AF5CD10A28DFF2970DEB6694D50988')
build() {
cd "$pkgname-$pkgver"
python -m build --wheel --no-isolation
}
package() {
cd "$pkgname-$pkgver"
python -m installer --destdir="$pkgdir" dist/*.whl
}
Package buliding worked and I installed it with sudo pacman -U pwdsphinx-2.0.3-1-x86_64.pkg.tar.zst. Running failed:
$ sphinx
Traceback (most recent call last):
File "/usr/bin/sphinx", line 5, in <module>
from pwdsphinx.sphinx import main
File "/usr/lib/python3.14/site-packages/pwdsphinx/sphinx.py", line 8, in <module>
from SecureString import clearmem
ModuleNotFoundError: No module named 'SecureString'
So now I packaged SecureString as python-securestring package.
pysodium is already packaged, so I cloned it and installed with pkgctl build -i all.
Then I got ModuleNotFoundError: No module named 'pyoprf' error when running sphinx.
Packaging it was straightforward, but because it depends on liboprf that is only packaged in AUR, it has to be built with pkgctl build -I ../liboprf/liboprf-0.9.3-1-x86_64.pkg.tar.zst.
I also uploaded it to AUR.
Next dependency was qrcodegen. It is already in AUR twice, as python-qrcodegen and qrcodegen. I installed python-qrcodegen.
Then I packaged python-pyequihash.
Afterwards it turned out that pyoprf depends on python-pyserial-asyncio, so I added python-pyserial-asyncio to python-pyoprf dependencies.
Finally sphinx started successfully:
$ sphinx
Error: No configuration found. Check out man sphinx(1) to get started.
Look at https://sphinx.pm/servers.html to choose some servers.
Continuing with default values, which will probably not work
usage:
SPHINX style passwords
/usr/bin/sphinx init
echo -n 'password' | /usr/bin/sphinx <create|change> <user> <site> <[u][l][d][s] [<size>] [<symbols>]> | [<target password>]
echo -n 'password' | /usr/bin/sphinx get <user> <site>
/usr/bin/sphinx <commit|undo|delete> <user> <site>
/usr/bin/sphinx list <site>
/usr/bin/sphinx healthcheck
/usr/bin/sphinx qr [svg] [key]
Then I have built and reinstalled the package with pkgctl build -I ../python-securestring/python-securestring-0.2-1-x86_64.pkg.tar.zst -I ../python-pysodium/python-pysodium-0.7.18-1-any.pkg.tar.zst -I ../python-pyoprf/python-pyoprf-0.9.3-1-any.pkg.tar.zst -I ../liboprf/liboprf-0.9.3-1-x86_64.pkg.tar.zst -I ../python-pyserial-asyncio/python-pyserial-asyncio-0.6-3-any.pkg.tar.zst -I ../python-qrcodegen/python-qrcodegen-1.8.0-1-any.pkg.tar.zst -I ../equihash/equihash-1.0.10-1-x86_64.pkg.tar.zst -I ../python-pyequihash/python-pyequihash-0.2-1-any.pkg.tar.zst -i all. This updated .SRCINFO. I added license with pkgctl license setup -f and pushed pwdsphinx.
Trying to use it for real failed, so I opened an issue. The problem was caused by incompatible change in Python 3.14 and fixed in pyoprf.
With updates to releases of liboprf (and pyoprf) 0.9.4 and pwdsphinx 2.0.4 it worked.
Overall I uploaded five packages to AUR: