aeat.application.modelo._review_package_signing module

Ed25519 signing and signature verification for review packages.

This module implements the signing slice deferred by _review_package: that module’s verify_review_package() is an INTEGRITY check only (did every archived member arrive byte-for-byte as built); it makes no claim about WHO built the package. This module adds the AUTHENTICITY layer on top of that integrity check by signing the package’s self-attesting manifest_sha256 digest with a per-profile Ed25519 keypair.

Signing the manifest digest (not the archive bytes or a re-derived hash) means the signature transitively covers every archived member: the digest is a SHA-256 over the canonical JSON of the manifest’s per-file entries, and a tampered member is already caught by verify_corpus_bundle() before signature verification is even attempted (see verify_review_package_signature()).

Key custody (sensitive-financial-data-secure-storage-only / no-legacy-compatibility): the private key is generated once per profile bucket and persisted ONLY as ciphertext through SecureObjectRepository at SECRET sensitivity (MODELO_REVIEW_PACKAGE_SIGNING_KEY_NAMESPACE). It is never logged, never written to a plaintext file, and never leaves this module as raw bytes except transiently in process memory to sign. The public key is, by construction, safe to export and hand to a receiving accountant for signature verification – it carries no secrecy requirement.

Counter-signed accountant feedback-package round trips remain OUT OF SCOPE for this module; it exposes only the primitive: mint/load a per-profile keypair, sign a package’s manifest digest, verify a signature against a public key.

See also

_review_package

Builds and integrity-verifies the review package this module signs.

SecureObjectRepository

Encrypted substrate the private key is persisted through.

SensitivityClass

Storage classification policy used for the persisted signing keypair.

exception ReviewPackageSigningError(message=None, *, context=None, suggestion=None, translated_message=None)[source]

Bases: AeatError

Base error for review-package signing/verification failures.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • suggestion (str | None)

  • translated_message (str | None)

Return type:

None

code: ClassVar[ErrorCode]
exception ReviewPackageSigningKeyNotFoundError(message=None, *, context=None, suggestion=None, translated_message=None)[source]

Bases: ReviewPackageSigningError

Raised when no signing keypair has been minted for a profile bucket yet.

Callers should mint one via ensure_review_package_signing_keypair() before signing a package for the first time in a given profile.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • suggestion (str | None)

  • translated_message (str | None)

Return type:

None

code: ClassVar[ErrorCode]
class ReviewPackageSigningKeypair(**data)[source]

Bases: BaseModel

A profile’s Ed25519 signing keypair, private key included.

This model is the PLAINTEXT in-memory shape used only transiently around generation, persistence, and signing; private_key() / public_key() reconstruct live cryptography key objects from the stored raw hex bytes. Nothing about this model changes the secure-storage contract: the caller (ensure_review_package_signing_keypair()) is responsible for persisting it only through SecureObjectRepository.

Parameters:
bucket_id: str
private_key_hex: str
public_key_hex: str
created_at: datetime
private_key()[source]

Reconstruct the live Ed25519PrivateKey from stored raw bytes.

Return type:

Ed25519PrivateKey

public_key()[source]

Reconstruct the live Ed25519PublicKey from stored raw bytes.

Return type:

Ed25519PublicKey

class ReviewPackageSigningPublicKey(**data)[source]

Bases: BaseModel

The exportable, non-secret half of a profile’s signing keypair.

Safe to hand to a receiving accountant so they can verify a package’s signature independently. Carries no secrecy requirement – unlike ReviewPackageSigningKeypair, this model is fine to write to a plaintext file, print, or transmit.

Parameters:
bucket_id: str
public_key_hex: str
created_at: datetime
class SignedReviewPackage(**data)[source]

Bases: BaseModel

Signature envelope binding a review package’s manifest digest to a signer.

manifest_sha256 is the review package’s own self-attesting manifest_sha256 (recovered via verify_review_package()), NOT a re-derived hash of the archive bytes: signing the manifest digest transitively covers every archived member because the manifest digest already covers every per-file checksum record.

Parameters:
  • envelope_version (int)

  • bucket_id (str)

  • calculation_revision_id (str)

  • manifest_sha256 (str)

  • signature_hex (str)

  • public_key_hex (str)

  • signed_at (datetime)

envelope_version: int
bucket_id: str
calculation_revision_id: str
manifest_sha256: str
signature_hex: str
public_key_hex: str
signed_at: datetime
ensure_review_package_signing_keypair(*, bucket_id, repository, generated_at=None)[source]

Return the profile’s Ed25519 signing keypair, minting one on first use.

Loads the existing keypair from MODELO_REVIEW_PACKAGE_SIGNING_KEY_NAMESPACE when present; otherwise generates a fresh keypair via Ed25519PrivateKey.generate(), persists it (private key included) as ciphertext, and returns it. Idempotent: a second call against the same bucket returns the SAME keypair rather than rotating it, so a package signed today verifies against a keypair fetched next week.

Parameters:
Return type:

ReviewPackageSigningKeypair

load_review_package_signing_keypair(*, bucket_id, repository)[source]

Load the profile’s existing Ed25519 signing keypair.

Parameters:
Raises:

ReviewPackageSigningKeyNotFoundError – If no keypair has been minted yet for bucket_id. Call ensure_review_package_signing_keypair() first.

Return type:

ReviewPackageSigningKeypair

review_package_signing_public_key(keypair)[source]

Project the exportable public half out of a full keypair.

The projection never touches private_key_hex; the returned model is safe to hand to a receiving accountant.

Return type:

ReviewPackageSigningPublicKey

Parameters:

keypair (ReviewPackageSigningKeypair)

sign_review_package(package_path, *, keypair, signed_at=None)[source]

Verify package_path’s checksum manifest, then sign its digest.

Delegates the integrity check entirely to assert_review_package_verifies() (no hashing logic is re-derived here): a package that is not checksum-clean raises before any signature is produced, so a signature can never be minted over a package this module itself cannot vouch is intact.

Parameters:
Raises:
Return type:

SignedReviewPackage

verify_review_package_signature(package_path, signed_package, *, public_key_hex)[source]

Verify signed_package’s signature against public_key_hex.

Re-runs the checksum-manifest integrity check (a fresh verify_corpus_bundle() call, not a trust of signed_package.manifest_sha256) first. This matters because manifest_sha256 is a digest over the embedded manifest’s OWN recorded per-file hashes – it does NOT change if an archived member’s bytes are swapped without touching the manifest metadata; only the mismatched check (re-hashing every archived file against its manifest record) catches that tamper. So a package whose CURRENT bytes are not checksum-clean, or whose current manifest digest no longer matches the signed digest, fails here even before the Ed25519 check runs.

Parameters:
  • package_path (Path) – Path to the review-package ZIP to verify.

  • signed_package (SignedReviewPackage) – The SignedReviewPackage envelope produced by sign_review_package().

  • public_key_hex (str) – The signer’s raw public key, as 64 lowercase hex characters (see public_key_hex). Passed explicitly (never read off signed_package) so a verifier must supply the key it actually trusts, rather than trusting whatever key the envelope claims.

Return type:

bool

Returns:

True iff the package is currently checksum-clean, its manifest digest matches the signed digest, AND the Ed25519 signature verifies against public_key_hex. Returns False (never raises) on any mismatch or invalid-signature outcome – signature verification is an authenticity check, not an assertion; callers that want a raising assertion should call sign_review_package()’s sibling assert_review_package_verifies() first and test this function’s boolean themselves.