Skip to main content
This document is the normative specification for .aipkg package signing. It defines the signing algorithm, signature file format, verification procedure, and trust anchor model.
Current Status: The .signature.p7s path is reserved in all .aipkg archives (see Package Format). At MVP, unsigned packages are accepted with a warning. Signature enforcement for verified publishers is a post-MVP requirement.

What Gets Signed

The signature covers the content of the archive, not the ZIP metadata (timestamps, compression levels, etc.). This ensures bit-for-bit reproducibility across tools. The signed hash input is constructed as follows:
  1. For every entry in the archive except .signature.p7s:
    • Normalize the entry path to forward slashes, lowercase
    • Compute the SHA-256 hash of the uncompressed entry content
    • Produce the string {normalized-path}:{hex-hash}
  2. Sort all such strings lexicographically
  3. Concatenate with newlines
  4. UTF-8 encode the resulting string
  5. Compute SHA-256 of the encoded string — this is the content hash

Signature File

The signature is stored at .signature.p7s at the archive root as a PKCS#7/CMS detached signature in DER encoding. The CMS SignedData structure contains:
  • The content hash (from the algorithm above) as the messageDigest signed attribute
  • An RFC 3161 timestamp token countersignature
  • The signing certificate chain up to (but not including) a trusted root
The .aispec manifest is included in the content hash computation. This means any modification to the manifest invalidates the signature.

Supported Signing Mechanisms

MechanismBadgeNotes
X.509 certificate from Microsoft Trusted Root CAVerifiedStandard code signing cert
GitHub Actions OIDC via Sigstore (Fulcio)VerifiedPreferred for CI/CD pipelines
Self-signed certificateNo badgeAccepted; flagged in UI as “unverified signature”
No signature (unsigned)No badgeAccepted at MVP with informational warning
For CI/CD publishing via GitHub Actions, Sigstore is the recommended mechanism. It requires no certificate management — identity is derived from the OIDC token of the GitHub Actions workflow.

Trust Anchors

The registry maintains a list of trusted root certificates and Sigstore roots, updated quarterly. The current trust anchor list is published at:
GET /api/trust-anchors
{
  "version": "2025-Q1",
  "roots": [
    { "type": "x509", "subject": "CN=Microsoft Root Certificate Authority 2011", "thumbprint": "8f43288ad272..." },
    { "type": "sigstore", "url": "https://fulcio.sigstore.dev", "fingerprint": "sha256:..." }
  ]
}
The trust anchor list is the sole authoritative source. Client implementations must not hardcode trust anchors.

Signature Verification in aipkg install

When a package has a .signature.p7s entry, aipkg install must verify the signature before installing any files:
1

Read signature

Read and DER-decode .signature.p7s from the archive root.
2

Reconstruct hash input

Recompute the content hash from the archive entries using the algorithm defined above.
3

Verify CMS signature

Verify the CMS SignedData structure: the messageDigest attribute must match the computed content hash; the signature must validate against the signer’s certificate.
4

Verify RFC 3161 timestamp

Verify the embedded RFC 3161 timestamp countersignature. The timestamp must be from an approved TSA (see Timestamping section).
5

Verify certificate chain

Verify the signing certificate chains to a trust anchor in the current trust anchor list. The certificate must not be revoked at the timestamp time.
Exit behavior:
  • Any verification failure → non-zero exit code + error message; no files installed
  • Self-signed certificate → proceed with prominent warning; no badge
  • Unsigned package → proceed with informational notice; no badge

Timestamping

An RFC 3161 timestamp is required for all signatures submitted to verified publishers. The timestamp:
  • Must come from an approved Timestamp Authority (TSA) from the list below
  • Must be within 10 minutes of the package push time (verified server-side at push)
  • Is embedded in the CMS SignedData as a countersignature
Approved Timestamp Authorities:
TSAURL
Sectigohttp://timestamp.sectigo.com
DigiCerthttp://timestamp.digicert.com
GlobalSignhttp://timestamp.globalsign.com/scripts/timstamp.dll
Sigstore TSAhttps://tsa.sigstore.dev

aipkg sign Command (Post-MVP)

The aipkg sign command is reserved for a post-MVP release. It will:
  1. Compute the content hash from the archive
  2. Sign it using the specified certificate or Sigstore OIDC token
  3. Embed the RFC 3161 timestamp
  4. Write .signature.p7s into the archive
See SDK Interface for the planned command syntax.

Registry Push Behavior

Publisher typeMVP behaviorPost-MVP behavior
Any publisher, unsigned packageAccepted; warning in UIAccepted; no verified badge
Any publisher, self-signedAccepted; “unverified signature” flagAccepted; no verified badge
Verified publisher, signedAccepted; verified badgeRequired; enforcement on push
Verified publisher, unsignedAccepted; warning in UIPush rejected with 403 Forbidden