Skip to content

ci(workflow): add PGP key and checksum signing - #682

Open
xmready wants to merge 7 commits into
quik-sms:masterfrom
xmready:feature/signed-checksums
Open

ci(workflow): add PGP key and checksum signing#682
xmready wants to merge 7 commits into
quik-sms:masterfrom
xmready:feature/signed-checksums

Conversation

@xmready

@xmready xmready commented Jan 14, 2026

Copy link
Copy Markdown

No description provided.

@Inhishonor Inhishonor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good to me!

@xmready

xmready commented Jan 14, 2026

Copy link
Copy Markdown
Author

Should I push the signing key changes as a separate PR, or push it to this one? Given the title of the PR might be good to separate them..

@xmready xmready changed the title ci(workflow): remove paths from checksum filenames ci(workflow): add PGP key and checksum signing Jan 16, 2026
@xmready

xmready commented Jan 16, 2026

Copy link
Copy Markdown
Author

A strategy for generating the signing key and importing it into GitHub secrets still needs to be decided upon

@Inhishonor

Copy link
Copy Markdown
Collaborator

@xmready Would you mind rebasing your changes on top of the latest version of the workflow?

 Conflicts:
	.github/workflows/build-and-release.yml

 Changes to be committed:
	modified:   .github/workflows/build-and-release.yml
	new file:   .github/workflows/generate-release-notes.yml
	modified:   .github/workflows/manual-release.yml
	modified:   data/src/main/assets/changelog.json
	new file:   data/src/main/assets/emojis/ckb.json
	modified:   data/src/main/assets/emojis/cs.json
	modified:   domain/src/main/java/com/moez/QKSMS/interactor/DeduplicateMessages.kt
	modified:   metadata/bg/full_description.txt
	modified:   metadata/bg/short_description.txt
	new file:   metadata/ckb/full_description.txt
	new file:   metadata/ckb/short_description.txt
	modified:   metadata/cs/full_description.txt
	modified:   metadata/cs/short_description.txt
	modified:   metadata/de/full_description.txt
	modified:   metadata/de/short_description.txt
	modified:   metadata/et/full_description.txt
	modified:   metadata/et/short_description.txt
	modified:   metadata/fr-FR/full_description.txt
	modified:   metadata/fr-FR/short_description.txt
	modified:   metadata/hu/full_description.txt
	modified:   metadata/hu/short_description.txt
	modified:   presentation/build.gradle
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeView.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/messageutils/MessageUtilsActivity.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/messageutils/MessageUtilsController.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/messageutils/MessageUtilsPresenter.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/messageutils/MessageUtilsState.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/messageutils/MessageUtilsView.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsController.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsPresenter.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsState.kt
	modified:   presentation/src/main/java/com/moez/QKSMS/feature/settings/SettingsView.kt
	modified:   presentation/src/main/res/layout/message_list_item_in.xml
	modified:   presentation/src/main/res/layout/message_list_item_out.xml
	modified:   presentation/src/main/res/layout/message_utils_controller.xml
	modified:   presentation/src/main/res/layout/settings_controller.xml
	new file:   presentation/src/main/res/values-ckb/strings.xml
	modified:   presentation/src/main/res/values-cs/strings.xml
	modified:   presentation/src/main/res/values-de/strings.xml
	modified:   presentation/src/main/res/values-fr/strings.xml
	modified:   presentation/src/main/res/values-hu/strings.xml
	modified:   presentation/src/main/res/values-it/strings.xml
	modified:   presentation/src/main/res/values-vi/strings.xml
	modified:   presentation/src/main/res/values-zh-rTW/strings.xml
	modified:   presentation/src/main/res/values/strings.xml
@xmready

xmready commented Jan 27, 2026

Copy link
Copy Markdown
Author

@Inhishonor I merged the changes from master. I prefer merge instead of rebase. It's good practice for shared projects because rebasing can rewrite commit hashes and things get ugly if working in the same branch.

I also pushed a fix commit to make sure the signature file is in the outputs. I almost did a good job keeping those changes separate from the merge commit. Next time I'll do it perfectly haha

@xmready
xmready requested a review from Inhishonor January 27, 2026 00:49
@beackers

beackers commented Feb 10, 2026

Copy link
Copy Markdown

@xmready A method strategy for generating the signing key and importing it into Github secrets still needs to be decided on

Suggestion for signing. I've used this method a few times and it seems to work well.

In short: convert a keystore to a base-64 file, put the contents in a Github repo secret, then use that secret to reconstruct the keystore in the runs.

  1. JDK versions come with keytool; use that to generate the keystore. I do this in a Codespace. (Replace stuff with <>.)
keytool -genkey -alias <a random alias> -keystore \<the keystore filename>.jks \\
-keyalg RSA -keysize 2048 \\
-validity 360000

Remember the alias and keystore password. Kinda important.
2. Convert to a base64 file:

base64 \<the keystore filename>.jks > \<some other filename>.jks.b64
  1. Paste the contents of the b64:
cat \<the base64 file>.jks.b64

Copy that.
4. Create a new GitHub repository secret, call it something like "RELEASE_KEYSTORE_B64" or something, and paste the b64 contents as the secret.
5. In your CI workflow, add a step to decode the keystore and save it:

      - name: Reconstruct keystore
        env:
          RELEASE_KEYSTORE_B64: ${{ secrets.RELEASE_KEYSTORE_B64 }}
        run: |
          echo "$RELEASE_KEYSTORE_B64" | base64 --decode > regenwall.keystore

      - name: Build release APK
        run: ./gradlew assembleRelease
        env:
          RELEASE_KEYSTORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }}
          RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }}
          RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }}

(taken from my app ReGenWall's release workflow)
6. If you feel like you need to clean up (i.e. you'll use the Codespace for actually commiting stuff later), remove the keystore and b64 file.

If this question still needs an answer, hope that helps.

Edit: change quote

@Inhishonor

Copy link
Copy Markdown
Collaborator

@xmready Can you remove the PGP change, and just add the checksum signing? I would like to get that part merged asap, but the rest needs some more careful consideration.

@xmready

xmready commented Mar 11, 2026

Copy link
Copy Markdown
Author

@xmready Can you remove the PGP change, and just add the checksum signing? I would like to get that part merged asap, but the rest needs some more careful consideration.

@Inhishonor I don't understand rushing the checksum changes without the PGP part. Checksums are meaningless to anyone serious about security if they lack cryptographic verification. If we need to make considerations, let's go ahead and do it. This is an area that I have experience in. I posted a plan in the development matrix room. Generating a signing key in a codespace is not secure. I'll repost my thoughts here for transparency:

For the PGP signing key, I'm thinking we generate it offline with a revocation certificate. The main key would not expire, but we would generate a subkey with an expiration date. The subkey would be rotated out as need after expiration. This way only subkey is trusted to GitHub secrets, and the parent key is generated and stored only offline. The public key would be published to a keyserver so people can fetch and update the key as needed. We could also decide to have more than one signing key belonging to more than one maintainer both signing the checksums, depends on how robust we want to make this. This is common practice for high stakes projects, maybe only one key is needed in this situation.

@Inhishonor

Copy link
Copy Markdown
Collaborator

Thanks @xmready. Sorry about missing your post in Matrix. I was unsure how to handle it, as I have little experience here and then I forgot about it. Let's figure this out then and get it merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants