Skip to content

Store gh-gate private key behind Secure Enclave-backed user presence #23

Description

@connorads

Problem

gh-gate currently stores the GitHub App private key via biokc, a small Swift helper that gates Keychain reads behind Touch ID. This improves UX and avoids plain file storage, but the private key itself is still a generic Keychain secret. Touch ID is enforced by the helper before release, not by a Secure Enclave-backed cryptographic key.

The desired property is stronger at-rest protection: the GitHub App PEM should only be recoverable through a non-exportable Secure Enclave key that requires local user presence.

Goal

Replace or augment biokc with a storage path where:

  • the GitHub App private key is encrypted at rest
  • the decrypting key is non-exportable and Secure Enclave-backed
  • retrieval requires Touch ID/passcode user presence
  • gh-gate grant can still obtain the PEM briefly to sign GitHub App JWTs
  • migration from the current Keychain/biokc setup is explicit and reversible

Candidate approach

Use age + age-plugin-se:

  • generate a Secure Enclave-backed age identity
  • encrypt the GitHub App PEM to that recipient
  • store:
    • ~/.config/gh-gate/se-identity.txt
    • ~/.config/gh-gate/private-key.pem.age
  • update gh-gate to decrypt via age when minting a token
  • add a one-shot migration command from the existing biokc storage

Suggested access policy: any-biometry-or-passcode, unless stricter Touch ID-only semantics are preferred later.

Notes

This does not make GitHub App signing happen inside Secure Enclave. GitHub App auth still requires an RS256 JWT signed with the App private key, so gh-gate will still need the plaintext PEM briefly in process memory.

The improvement is at-rest protection and removal of bespoke biometric Keychain helper code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions