5.28 Package Signatures
A package signature binds a package's bytes to a signing key. Verifying it establishes that the package has not been altered since signing, and that the signer held the trusted private key.
5.28.1 The signature entry #
The signature is the final entry in the tar archive, at
.peipkg/signature (§5.12). Its content is a UTF-8 JSON document. Every
tar attribute of the entry — mode, owner, mtime, magic — follows the
determinism rules of §5.11 unmodified, so the entry is mode 0777 like
every other, and §5.16's rationale applies to it identically.
5.28.2 The signed bytes #
The signature is over a SHA-256 hash computed across the concatenation
of every complete tar entry block — header, content, and content-block
padding to the next 512-byte boundary — for every entry preceding
.peipkg/signature, in archive order.
The signed bytes do not include:
- the tar entry header or content of
.peipkg/signatureitself; - the two trailing zero blocks that terminate a tar archive;
- any compression artifact — signing operates on the uncompressed tar bytes.
5.28.3 The envelope #
| Field | Description |
|---|---|
schema_version | MUST be 1 in this version. |
algorithm | MUST be ed25519 in this version. |
key_fingerprint | Fingerprint of the public key (§5.29). Lowercase hex, 64 characters. |
signature | The signature value, base64 per RFC 4648 §4 without padding. For Ed25519 the decoded value is 64 bytes. |
An envelope MUST contain all four fields. A missing field, or an
unrecognised algorithm or schema_version, MUST cause the package to
be rejected.
5.28.4 Strict parsing #
The envelope MUST NOT contain any field beyond the four above, and MUST NOT contain a duplicate key. An implementation of this version parsing an envelope from a future version MUST reject the package with an error naming the schema version mismatch, rather than silently ignoring the unknown fields.
This is a deliberate exception to §5.9's forward-compatibility rule. For security-critical signing data, strict parsing is preferred to permissive ignoring.
5.28.5 Signing procedure #
To sign a package, a producer:
- Constructs every tar entry except
.peipkg/signature. - Serialises them as an uncompressed tar byte stream in archive order.
- Computes the SHA-256 of that stream.
- Signs the resulting 32-byte hash with its Ed25519 private key, per RFC 8032.
- Constructs the envelope with the signature value and key fingerprint.
- Appends the
.peipkg/signatureentry — header, JSON content, and padding — to the tar byte stream. - Compresses the complete stream to produce the
.peipkgfile.
Note that the Ed25519 message is the 32-byte SHA-256 digest, not the tar stream itself. A verifier MUST do the same.
5.28.6 Determinism #
Given identical signed bytes and an identical key, the Ed25519 signature is deterministic per RFC 8032 §5.1.6. A producer that builds the same tar archive and signs it with the same key MUST produce a byte-identical signature entry.
5.28.7 Unsigned packages #
A package without a .peipkg/signature entry is unsigned.
The format permits unsigned packages. A consumer MAY install one if the originating repository's trust policy permits it (§5.37).
An unsigned package MUST conform to every other requirement of this chapter. The manifest, the files manifest, the payload rules, and the integrity rules apply identically to signed and unsigned packages.