mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
fix: 1.0.2 hotfix — heal wallets broken by per-build random crypto secrets
CI ran tool/generate_new_secrets.dart unpinned, so every release binary shipped different AES keys/salts for the stored PIN and wallet passwords. Updating the app then failed to decrypt what the previous build stored: 'Invalid or corrupted pad block' at PIN entry and the 'Corrupted seeds' dialog, with wallet files fully intact. - entities/encrypt.dart: legacy-key fallback decode for PIN and wallet password blobs (candidate sets recovered from the shipped 1.0.1 binary; output validated to reject PKCS7 false positives) - key_service/auth_service: on successful legacy decode, re-encrypt under the pinned key — installs self-heal at first unlock - all build workflows: inject the eight pinned CRYPTO_* repo secrets after secret generation and hard-fail if any is missing, so crypto salts can never silently rotate again (values pinned via ~keys/set-gitea-crypto-secrets.sh) - bump 1.0.2+12
This commit is contained in:
@@ -134,6 +134,42 @@ jobs:
|
||||
flutter pub get
|
||||
dart run tool/generate_new_secrets.dart
|
||||
|
||||
|
||||
- name: Pin crypto secrets (never ship random salts)
|
||||
env:
|
||||
CRYPTO_SALT: ${{ secrets.CRYPTO_SALT }}
|
||||
CRYPTO_KEYCHAIN_SALT: ${{ secrets.CRYPTO_KEYCHAIN_SALT }}
|
||||
CRYPTO_KEY: ${{ secrets.CRYPTO_KEY }}
|
||||
CRYPTO_WALLET_SALT: ${{ secrets.CRYPTO_WALLET_SALT }}
|
||||
CRYPTO_SHORT_KEY: ${{ secrets.CRYPTO_SHORT_KEY }}
|
||||
CRYPTO_BACKUP_SALT: ${{ secrets.CRYPTO_BACKUP_SALT }}
|
||||
CRYPTO_BACKUP_KEYCHAIN_SALT: ${{ secrets.CRYPTO_BACKUP_KEYCHAIN_SALT }}
|
||||
CRYPTO_WALLET_GROUP_SALT: ${{ secrets.CRYPTO_WALLET_GROUP_SALT }}
|
||||
run: |
|
||||
set -e
|
||||
# generate_new_secrets.dart mints RANDOM salts each run. Shipping
|
||||
# those breaks decryption of everything the previous build stored
|
||||
# (2026-08-29 "Corrupted seeds" incident). Overwrite with the pinned
|
||||
# values and refuse to build if any is missing.
|
||||
for v in CRYPTO_SALT CRYPTO_KEYCHAIN_SALT CRYPTO_KEY CRYPTO_WALLET_SALT CRYPTO_SHORT_KEY CRYPTO_BACKUP_SALT CRYPTO_BACKUP_KEYCHAIN_SALT CRYPTO_WALLET_GROUP_SALT; do
|
||||
eval "val=\${$v:-}"
|
||||
[ -n "$val" ] || { echo "FATAL: $v is empty — refusing to ship random crypto secrets"; exit 1; }
|
||||
done
|
||||
sed -i.bak \
|
||||
-e "s|const salt = '.*';|const salt = '${CRYPTO_SALT}';|" \
|
||||
-e "s|const keychainSalt = '.*';|const keychainSalt = '${CRYPTO_KEYCHAIN_SALT}';|" \
|
||||
-e "s|const key = '.*';|const key = '${CRYPTO_KEY}';|" \
|
||||
-e "s|const walletSalt = '.*';|const walletSalt = '${CRYPTO_WALLET_SALT}';|" \
|
||||
-e "s|const shortKey = '.*';|const shortKey = '${CRYPTO_SHORT_KEY}';|" \
|
||||
-e "s|const backupSalt = '.*';|const backupSalt = '${CRYPTO_BACKUP_SALT}';|" \
|
||||
-e "s|const backupKeychainSalt = '.*';|const backupKeychainSalt = '${CRYPTO_BACKUP_KEYCHAIN_SALT}';|" \
|
||||
-e "s|const walletGroupSalt = '.*';|const walletGroupSalt = '${CRYPTO_WALLET_GROUP_SALT}';|" \
|
||||
lib/.secrets.g.dart
|
||||
rm -f lib/.secrets.g.dart.bak
|
||||
for c in salt keychainSalt key walletSalt shortKey backupSalt backupKeychainSalt walletGroupSalt; do
|
||||
grep -qE "^const $c = '[0-9a-f]{8,}';" lib/.secrets.g.dart || { echo "FATAL: $c not pinned"; exit 1; }
|
||||
done
|
||||
echo "crypto secrets pinned (values not printed)"
|
||||
- name: Inject Trocador affiliate secrets into lib/.secrets.g.dart
|
||||
env:
|
||||
TROCADOR_API_KEY: ${{ secrets.TROCADOR_API_KEY }}
|
||||
|
||||
Reference in New Issue
Block a user