signing

package
v2.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: GPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package signing provides package signing infrastructure for YAP.

This package establishes the foundation for signing packages across all supported formats (APK, DEB, RPM, Pacman). It defines the Signer interface, signing configuration, and resolution logic for keys and passphrases.

Phase 0 (this phase) provides infrastructure only. Actual signing implementations are added in Phase 3 (APK RSA) and Phase 4 (DEB/RPM/Pacman GPG).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Algorithm

type Algorithm string

Algorithm names a signing algorithm/key family.

const (
	// AlgorithmRSA uses PKCS#1 v1.5 SHA1, used by APK.
	AlgorithmRSA Algorithm = "rsa"
	// AlgorithmGPG uses OpenPGP, used by DEB/RPM/Pacman.
	AlgorithmGPG Algorithm = "gpg"
)

type Config

type Config struct {
	// Enabled indicates whether signing is active.
	Enabled bool
	// KeyPath is the resolved absolute path to the private key
	// (PEM format for RSA, ASCII-armored for GPG).
	KeyPath string
	// Passphrase is the resolved passphrase, may be empty.
	Passphrase string
	// KeyName is optional, used for APK key naming (e.g., "mykey").
	KeyName string
}

Config holds resolved signing configuration for a build.

func Resolve

func Resolve(
	format Format,
	flagKey, flagPass, configKey, configPass string,
) (Config, error)

Resolve produces a final Config for a given Format, applying the priority: CLI flag > environment variable > project config > ~/.config/yap/keys/ default.

For keys, the resolution order is:

  1. flagKey (CLI --sign-key)
  2. YAP_<FORMAT>_KEY env var (e.g., YAP_DEB_KEY)
  3. YAP_SIGN_KEY env var
  4. configKey (from yap.json signing.keyPath)
  5. Default search in ~/.config/yap/keys/

For passphrases, the resolution order is:

  1. flagPass (CLI --sign-passphrase)
  2. YAP_<FORMAT>_PASSPHRASE env var (e.g., YAP_DEB_PASSPHRASE)
  3. YAP_SIGN_PASSPHRASE env var
  4. configPass (from yap.json signing.passphrase)
  5. Empty string (no passphrase)

If signing is requested but no key can be resolved, an error is returned. If no key is found, signing is disabled and passphrase is cleared.

func ResolveGeneric

func ResolveGeneric(
	flagKey, flagPass, configKey, configPass string,
) (Config, error)

ResolveGeneric produces a final Config without format-specific resolution. This is used at the project level where the actual artifact format is not yet known. Format-specific resolution happens later in signArtifact() for each artifact.

For keys, the resolution order is:

  1. flagKey (CLI --sign-key)
  2. YAP_SIGN_KEY env var (global only, no format-specific vars)
  3. configKey (from yap.json signing.keyPath)
  4. Default search in ~/.config/yap/keys/ (tries both default.rsa and default.gpg)

For passphrases, the resolution order is:

  1. flagPass (CLI --sign-passphrase)
  2. YAP_SIGN_PASSPHRASE env var (global only, no format-specific vars)
  3. configPass (from yap.json signing.passphrase)
  4. Empty string (no passphrase)

If no key is found, signing is disabled and passphrase is cleared.

type Format

type Format string

Format identifies a package format that needs signing.

const (
	// FormatAPK represents Alpine Linux APK packages.
	FormatAPK Format = "apk"
	// FormatDEB represents Debian packages.
	FormatDEB Format = "deb"
	// FormatRPM represents Red Hat RPM packages.
	FormatRPM Format = "rpm"
	// FormatPacman represents Arch Linux Pacman packages.
	FormatPacman Format = "pacman"
)

type GPGSigner

type GPGSigner struct {
	// contains filtered or unexported fields
}

GPGSigner produces detached OpenPGP signatures for DEB, RPM, and Pacman formats. - DEB: writes <package>.deb.asc (ASCII-armored detached signature) - RPM: provides signing function for rpmpack.SetPGPSigner (binary signature) - Pacman: writes <package>.pkg.tar.zst.sig (binary detached signature)

func NewGPGSigner

func NewGPGSigner(cfg Config, format Format) (*GPGSigner, error)

NewGPGSigner loads the private key from cfg.KeyPath. The key must be an ASCII-armored OpenPGP private key. If cfg.Passphrase is set, it is used to decrypt the key.

func (*GPGSigner) Sign

func (s *GPGSigner) Sign(ctx context.Context, artifactPath string) error

Sign signs the artifact and writes a detached signature file. Output convention by format:

FormatDEB    -> <artifactPath>.asc (ASCII-armored)
FormatRPM    -> returns a signing function for rpmpack.SetPGPSigner
FormatPacman -> <artifactPath>.sig (binary, NOT armored)

type NoopSigner

type NoopSigner struct{}

NoopSigner is returned when signing is disabled. It implements Signer but performs no operation.

func (NoopSigner) Sign

func (NoopSigner) Sign(_ context.Context, _ string) error

Sign is a no-op implementation of the Signer interface.

type RSASigner

type RSASigner struct {
	// contains filtered or unexported fields
}

RSASigner signs APK packages with PKCS#1 v1.5 SHA1, matching Alpine abuild-sign. The signature is computed over the control.tar.gz bytes and prepended as a third gzip stream in the final APK file.

func NewRSASigner

func NewRSASigner(cfg Config) (*RSASigner, error)

NewRSASigner loads the private key from cfg.KeyPath. The key must be a PEM-encoded RSA private key (PKCS#1 or PKCS#8 unencrypted).

Encrypted PEM blocks (RFC 1423) are not supported because the underlying stdlib helpers (x509.IsEncryptedPEMBlock, x509.DecryptPEMBlock) are deprecated and the format is cryptographically broken. Users with password-protected keys should re-encode them as unencrypted PEM (e.g. via openssl rsa) or use PKCS#8 without password.

func (*RSASigner) Sign

func (s *RSASigner) Sign(ctx context.Context, artifactPath string) error

Sign reads the APK at artifactPath, computes the RSA signature over the control.tar.gz stream, and rewrites the APK with the signature stream prepended.

The final APK structure is:

  1. signature.tar.gz — contains .SIGN.RSA.<keyname>.rsa.pub with signature bytes
  2. control.tar.gz — unchanged from original
  3. data.tar.gz — unchanged from original

The signature is computed as PKCS#1 v1.5 SHA1(control.tar.gz bytes).

type Signer

type Signer interface {
	// Sign signs the artifact at artifactPath.
	Sign(ctx context.Context, artifactPath string) error
}

Signer signs a package artifact in place or writes a detached signature. Concrete implementations live in this package (RSA for APK, GPG for others).

The behavior depends on the format:

  • APK: rebuilds the package with a third concatenated gzip stream containing .SIGN.RSA.<keyname>.rsa.pub (Phase 3)
  • DEB: appends _gpgorigin to the ar archive (dpkg-sig style) (Phase 4)
  • RPM: writes signature into the RPM lead/header (delegated to rpmpack) (Phase 4)
  • Pacman: writes detached <artifactPath>.sig (Phase 4)

func NewSigner

func NewSigner(format Format, cfg Config) (Signer, error)

NewSigner constructs the appropriate concrete Signer for the format.

For FormatAPK, returns an RSASigner (Phase 3 — PKCS#1 v1.5 SHA1). For FormatDEB, FormatRPM, FormatPacman, returns a GPGSigner (Phase 4 — OpenPGP).

If signing is disabled (cfg.Enabled == false), a NoopSigner is returned.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL