Skip to content

improve signing key encryption password handling#355

Closed
SolidEva wants to merge 3 commits intonix-community:masterfrom
SolidEva:improve_signing_password_handling
Closed

improve signing key encryption password handling#355
SolidEva wants to merge 3 commits intonix-community:masterfrom
SolidEva:improve_signing_password_handling

Conversation

@SolidEva
Copy link
Contributor

@SolidEva SolidEva commented Feb 5, 2026

preferably after #352 since this includes that change.

Background:
moving from the graphene build system, i was looking for a way to automatically decrypt my keys as part of singing

part of that is encrypting all of the keys with the same password so we don't need to prompt the user for ~30+ passwords at signing time
of course this doesn't replace the user storing keys properly and securely, but it limits how much they are sitting around in the clear

as a bonus, we can now encrypt the avb device key!

more info in the commit messages:

signing: allow noninteractive key generation

adds the `--no-password` argument to the generate keys script to allow
users to handle key encryption themselves

adds the `--single-password` argument to the generate keys script to allow users to
specify a single password to encrypt all generate keys with

while a single password is less secure than each key using its own password, since
roughly 30 keys are generated, its unlikely most users are setting
unique passwords per key anyway

users that want to set unique passwords per key can still do so

additionally, these changes allow the avb key to be encrypted as well

the most annoying part of this change was working around avbtool
wrapping the openssl cli, which meant none of the openssl
`-passin` options were available and user interaction was forced.

a minor patch for avbtool is included to add support for the various
`-passin` options


signing: allow noninteractive signing with encrypted keys

if `signing.decryptKeysForSigning` is enabled, prompt the user for a
single password at the start of signing.

the password is used to decrypt all keys, which are stored temporarily
in memory by decrypting them to a tmpdir in /dev/shm

this is identical to how grapheneos handles signing with encrypted keys

using `signing.decryptKeysForSigning` requires all keys to be
encrypted with the same password.

this is intended to be used alongside noninteractive key generation,
which encrypts all keys using the same password like so:
`./generate-keys ./keys --single-password`

make_key "$key" "/CN=Robotnix ''${key/\// }/" && exit 1
if [ "$nopassword" = true ]; then
# make_key exits with unsuccessful code 1 instead of 0
make_key "$key" "/CN=${config.signing.keyCn} ''${key/\// }/" <<< "" && exit 1
Copy link
Contributor Author

Choose a reason for hiding this comment

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

i'm tempted to stop using make_key entirely, and just call openssl directly since it would make all of this logic much more clean

but i think i'll leave that for a future PR

@SolidEva SolidEva force-pushed the improve_signing_password_handling branch from 81e797d to 326c5d9 Compare February 5, 2026 19:49
@SolidEva
Copy link
Contributor Author

SolidEva commented Feb 5, 2026

some manual testing:

  1. the new generate-keys flags
/generate-keys ./keys --single-password
Please enter the password to encrypt all keys with (if you want an empty password use the --no-password flag instead):
Generating tokay/releasekey key
creating tokay/releasekey.pk8 with password [TEST]

Generating tokay/gmscompat_lib key
creating tokay/gmscompat_lib.pk8 with password [TEST]

Generating tokay/media key
creating tokay/media.pk8 with password [TEST]

Generating tokay/networkstack key
creating tokay/networkstack.pk8 with password [TEST]
....

and

❯ ./generate-keys ./keys --no-password
Generating tokay/releasekey key
creating tokay/releasekey.pk8 with no password

Generating tokay/gmscompat_lib key
creating tokay/gmscompat_lib.pk8 with no password

Generating tokay/media key
creating tokay/media.pk8 with no password

Generating tokay/networkstack key
creating tokay/networkstack.pk8 with no password

Generating tokay/platform key
creating tokay/platform.pk8 with no password
...
  1. manual password entry still works
❯ ./generate-keys ./keys
Generating tokay/releasekey key
Enter password for 'tokay/releasekey' (blank for none; password will be visible): pass1
creating tokay/releasekey.pk8 with password [pass1]

Generating tokay/gmscompat_lib key
Enter password for 'tokay/gmscompat_lib' (blank for none; password will be visible): pass2
creating tokay/gmscompat_lib.pk8 with password [pass2]

Generating tokay/media key
Enter password for 'tokay/media' (blank for none; password will be visible): pass3
creating tokay/media.pk8 with password [pass3]
  1. signing with signing.decryptKeysForSigning = true;
    prompts user for a single key at the start and never again
❯ ./release-script keys/
Enter key passphrase (empty if none):
Signing target files
extra_apks flag for APK OsuLogin.apk, key Path("/dev/shm/robotnix_keys.XXXXUQwzjA/tokay/releasekey") is never used
extra_apks flag for APK ServiceWifiResources.apk, key Path("/dev/shm/robotnix_keys.XXXXUQwzjA/tokay/releasekey") is never used
extra_apks flag for APK com.android.art.debug.apex, key Path("/dev/shm/robotnix_keys.XXXXUQwzjA/com.android.art.debug") is never used
extra_apks flag for APK com.android.art.host.apex, key Path("/dev/shm/robotnix_keys.XXXXUQwzjA/com.android.art.host") is never used
...
  1. signing with signing.decryptKeysForSigning = false; (default)
    prompts user for a password for each key
❯ ./release-script keys/
Enter pass phrase for tokay/avb.pem:
Signing target files
extra_apks flag for APK OsuLogin.apk, key Path("/dev/shm/robotnix_keys.XXXXyd96dx/tokay/releasekey") is never used
extra_apks flag for APK ServiceWifiResources.apk, key Path("/dev/shm/robotnix_keys.XXXXyd96dx/tokay/releasekey") is never used
extra_apks flag for APK com.android.art.debug.apex, key Path("/dev/shm/robotnix_keys.XXXXyd96dx/com.android.art.debug") is never used
extra_apks flag for APK com.android.art.host.apex, key Path("/dev/shm/robotnix_keys.XXXXyd96dx/com.android.art.host") is never used
extra_apks flag for APK com.android.art.testing.apex, key Path("/dev/shm/robotnix_keys.XXXXyd96dx/com.android.art.testing") is never used
extra_apks flag for APK com.android.btservices.apex, key Path("/dev/shm/robotnix_keys.XXXXyd96dx/com.android.btservices") is never used
extra_apks flag for APK com.android.geotz.apex, key Path("/dev/shm/robotnix_keys.XXXXyd96dx/com.android.geotz") is never used
...

adds the `--no-password` argument to the generate keys script to allow
users to handle key encryption themselves

adds the `--single-password` argument to the generate keys script to allow users to
specify a single password to encrypt all generate keys with

while a single password is less secure than each key using its own password, since
roughly 30 keys are generated, its unlikely most users are setting
unique passwords per key anyway

users that want to set unique passwords per key can still do so

additionally, these changes allow the avb key to be encrypted as well

the most annoying part of this change was working around avbtool
wrapping the openssl cli, which meant none of the openssl
`-passin` options were available and user interaction was forced.

a minor patch for avbtool is included to add support for the various
`-passin` options
@SolidEva SolidEva force-pushed the improve_signing_password_handling branch from 326c5d9 to cec1619 Compare February 5, 2026 20:42
if `signing.decryptKeysForSigning` is enabled, prompt the user for a
single password at the start of signing.

the password is used to decrypt all keys, which are stored temporarily
in memory by decrypting them to a tmpdir in /dev/shm

this is identical to how grapheneos handles signing with encrypted keys

using `signing.decryptKeysForSigning` requires all keys to be
encrypted with the same password.

this is intended to be used alongside noninteractive key generation,
which encrypts all keys using the same password like so:
`./generate-keys ./keys --single-password`
@SolidEva SolidEva force-pushed the improve_signing_password_handling branch from cec1619 to 4644b9d Compare February 5, 2026 20:44
@cyclic-pentane
Copy link
Collaborator

TBH I feel like this is out-of-scope for robotnix. If you want to encrypt your keys, what's stopping you from doing so with a separate tool (e.g. age), decrypting them into a tmpfs whenever you need them, and then point the robotnix release script to that tempfs? That'd be a lot cleaner in terms of separation of concerns imo.

@SolidEva
Copy link
Contributor Author

SolidEva commented Feb 8, 2026

hm, i'm not sure i understand?
robotnix already has the user generate encrypted keys by default, just with a rather obnoxious process that requires the user either spam enter (for no encryption/password), spam paste with their password, or enter a bunch of different passwords.
unless there are plans to remove that entirely, or i am misunderstanding something, i don't think this changes the scope of the project?

the goal here was to make that process less painful, and to make it easier to ensure that decrypted keys never hit the disk.
i agree that the user could also do something with age, or some script of their own choice, and nothing here stops them from doing so.

@cyclic-pentane
Copy link
Collaborator

robotnix already has the user generate encrypted keys by default, just with a rather obnoxious process that requires the user either spam enter

Oh, that - the fact that the key generation script is prompting the user for a password for every key is a by-product of the fact that we're using the upstream AOSP APK key generation script make_key. I agree that for consistency, we should turn off that feature in this case.

@cyclic-pentane
Copy link
Collaborator

I've done so for now in cb070a9. But still, thanks for the contribution! :)

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.

2 participants