GPG and SSH Key Management

This document defines the procedures for generating, storing, backing up, and using GPG and SSH keys within the Shyft project.

It serves as the identity foundation for:

  • developer authentication using SSH

  • commit, tag, and artifact signing using GPG

  • release trust and recovery procedures

Scope

Two levels of usage are defined:

  1. single-person setup

  2. organization-level setup

The single-person setup is suitable for contributors and maintainers operating without organizational escrow or recovery.

The organization-level setup is intended for release management and controlled project governance, where backup, certification, and recovery must be handled according to defined policy.

Preconditions

Required hardware and setup:

  • daily-use device: Nitrokey 3A NFC

  • backup offline device: Nitrokey Pro 2 Storage with encrypted storage enabled

  • both devices must have PIN and Admin PIN configured

  • PIN and Admin PIN should use at least 6 digits, with 8 or more recommended

  • key generation must be performed on a trusted laptop or similarly controlled device

Security model

The following rules apply:

  • private key material must not persist unnecessarily on general-purpose systems

  • smartcards should hold subkeys, not the long-term offline certification root

  • backups must be encrypted and verified immediately after creation

  • revocation material must be created and protected

  • temporary key material on the trusted host must be securely removed after use

Single-person setup

Purpose

This procedure is suitable for contributors and maintainers who need:

  • a hardware-backed signing key

  • an SSH authorization key for GitLab access

  • a recoverable encrypted backup under their own control

GPG key procedure

  1. Generate a root GPG key on a trusted device

    Use a trusted laptop or dedicated server in a controlled environment.

    Recommended structure:

    • master key for certification

    • signing subkey for daily use

    Example:

    gpg --expert --full-generate-key
    

    Select (11) ECC (set your own capabilities)

    Then disable all but Certify, (toggle S E A ), and ‘Q’ to guit capabilities selection.

    Select Curve 25519 (default)

    And expiration according to policy, e.g. 10y for 10 years.

    Choose a strong password for the key.

  2. Add a signing subkey

    Example:

    gpg --edit-key <KEY-ID>
    addkey
    

    Select a signing-capable subkey.

  3. Create encrypted backup on Nitrokey Pro 2 Storage

    Store backups below:

    /gpg/<user>/key-backup/
    

    Export at minimum:

    • secret keys

    • secret subkeys

    • revocation certificate

    Example:

    gpg --export-secret-keys <KEY-ID> > secret-keys.gpg
    gpg --export-secret-subkeys <KEY-ID> > subkeys.gpg
    gpg --gen-revoke <KEY-ID> > revoke.asc
    
  4. Verify the backup

    Import the backup into a temporary GNUPGHOME and verify that the expected keys are present.

    Example:

    GNUPGHOME=$(mktemp -d)
    gpg --homedir "$GNUPGHOME" --import secret-keys.gpg
    gpg --homedir "$GNUPGHOME" --list-secret-keys
    
  5. Move the signing subkey to Nitrokey 3A NFC

    Example:

    gpg --edit-key <KEY-ID>
    key 1
    keytocard
    

    Choose the signature key slot.

    Where supported by the device and tooling, require PIN and touch or presence confirmation for signing operations.

  6. Remove secret key material from the trusted host

    Example:

    gpg --delete-secret-keys <KEY-ID>
    

    Securely erase exported backup files from the trusted host after they have been copied to the encrypted backup device and verified.

    Example:

    shred -u secret-keys.gpg subkeys.gpg revoke.asc
    
  7. Verify card-based signing

    Example:

    gpg --card-status
    echo "test" | gpg --clearsign
    

SSH key procedure using Nitrokey 3A/C NFC

The daily-use Nitrokey may also be used as the SSH authorization key source for GitLab access through GPG agent SSH support.

  1. Enable SSH support in gpg-agent

    Example:

    echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf
    gpgconf --kill gpg-agent
    
  2. Export the SSH public key

    Example:

    gpg --export-ssh-key <KEY-ID>
    
  3. Register the SSH public key in GitLab

    Add the exported public key to the user account in GitLab.

  4. Verify SSH authentication

    Example:

    ssh -T git@gitlab.com
    

Organization-level setup

Purpose

This setup is intended for release managers or controlled project roles where a project or organizational trust root is required.

The main difference from the single-person setup is that the certification root must be treated as organizational key material, with controlled backup and recovery procedures.

Procedure

  1. Generate the root key on an offline trusted system

    Example:

    gpg --full-generate-key
    

    The root key should be retained offline and should not be used for daily signing activity.

  2. Add the signing subkey

    Example:

    gpg --edit-key <ROOT-KEY-ID>
    addkey
    
  3. Backup the root key and supporting material

    Store the protected backup below:

    /gpg/org/root/<key-id>/
    

    The backup should include:

    • secret root key material

    • subkeys

    • revocation certificate

    • associated metadata needed for recovery

    Access to this material should be governed and logged according to project policy.

  4. Verify the root backup

    Before continuing, perform a restore test into an isolated temporary keyring.

  5. Move only the signing subkey to the daily-use Nitrokey

    Example:

    gpg --edit-key <ROOT-KEY-ID>
    key <subkey-number>
    keytocard
    
  6. Remove secret material from the operational host

    Example:

    gpg --delete-secret-keys <ROOT-KEY-ID>
    
  7. Use the root key for certification only

    The organizational root key may be used to certify developer or release keys.

    Example:

    gpg --sign-key <DEV-KEY-ID>
    
  8. Protect revocation material

    Store revocation certificates under a controlled location such as:

    /gpg/org/revocations/
    

Operational guidance

Loss of daily-use Nitrokey

If the daily-use Nitrokey is lost:

  • revoke the affected subkey if appropriate

  • restore from verified backup if recovery is intended

  • issue a replacement subkey and device

  • update any relying systems such as GitLab or release infrastructure

Loss of backup device

If the encrypted backup device is lost, the impact must be assessed according to whether the device, encryption, and recovery material are believed to remain protected.

For organization-level keys, this event should be handled as a formal incident, and the need for revocation and re-issuance should be evaluated immediately.

Offboarding

When a contributor or maintainer leaves a role:

  • remove SSH access

  • remove or disable release permissions

  • revoke or retire keys as required by policy

  • update trust and signer documentation

Relationship to release procedures

Release signing procedures should reference this document for the requirements on how signing keys are generated, protected, backed up, and recovered.

The releases section should define who is allowed to use which keys and under what governance and approval model.