aeat.application.modelo._review_package_counter_sign module

Counter-signed accountant receipt round trip for signed review packages.

This module implements the counter-sign slice deferred by _review_package_signing: that module adds an AUTHENTICITY layer over a review package’s checksum manifest by having the operator sign the manifest digest with their own Ed25519 keypair (sign_review_package()). It makes no claim about what the RECEIVING accountant did with the package once it arrived.

A CounterSignedReceipt closes that loop: the accountant signs a second, independent Ed25519 signature over the operator’s ORIGINAL signature bytes plus a short free-text note (e.g. a verdict such as “reviewed, no changes” or “see attached corrections”). Verifying the receipt (verify_counter_signed_receipt()) re-checks BOTH layers – the operator’s original signature against the operator’s public key (delegating to verify_review_package_signature(), so the checksum-manifest integrity re-check happens first, exactly as it does for a bare SignedReviewPackage), and the accountant’s counter-signature against the accountant’s public key – so a receipt only verifies clean when neither party’s signature nor the note text has been tampered with.

Signing the ORIGINAL SIGNATURE BYTES (not the manifest digest a second time, and not a re-derived hash) means the counter-signature transitively commits the accountant to the specific operator signature they received: swapping in a different (even validly-signed) operator signature for the same package invalidates the counter-signature, because the bytes it covers changed.

Key custody (sensitive-financial-data-secure-storage-only / no-legacy-compatibility): the counter-signer’s (accountant’s) keypair is minted and persisted through the exact same ensure_review_package_signing_keypair() primitive the operator uses, scoped to whatever bucket_id the caller supplies for the counter-signer’s identity – there is no separate key-custody mechanism to introduce. The private key never leaves that primitive as raw bytes except transiently in process memory to sign.

See also

_review_package_signing

The operator-side signing primitive this module counter-signs on top of.

_review_package

Builds and integrity-verifies the review package that is signed.

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

Bases: AeatError

Base error for review-package counter-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]
class CounterSignedReceipt(**data)[source]

Bases: BaseModel

A review package’s operator signature, counter-signed by an accountant.

Wraps the operator’s SignedReviewPackage verbatim (the original_signature field) alongside the accountant’s own Ed25519 signature over original_signature.signature_hex plus note. Binding the counter-signature to the ORIGINAL SIGNATURE BYTES (rather than the manifest digest) means the counter-signature can only ever attest to that one specific operator signature: a different signature over the same manifest (e.g. re-signed by a rotated operator key) has different signature_hex bytes and would need a fresh counter-signature.

Parameters:
envelope_version: int
original_signature: SignedReviewPackage
note: str
counter_signature_hex: str
counter_public_key_hex: str
counter_signed_at: datetime
property counter_signed_message: bytes

Return the exact byte string the counter-signature covers.

Reconstructing this independently of counter_sign_review_package() lets verify_counter_signed_receipt() recompute the signed message from the receipt’s own fields rather than trusting a cached value, so a receipt whose note was edited after counter-signing fails verification instead of silently re-approving different text.

counter_sign_review_package(signed_package, *, counter_signer_keypair, note='', counter_signed_at=None)[source]

Counter-sign an operator-signed review package on behalf of the accountant.

Does NOT re-verify the operator’s signed_package signature or the underlying archive’s checksum manifest – that is verify_review_package_signature()’s job, and it is re-run unconditionally inside verify_counter_signed_receipt(). Counter-signing a signature that later turns out to be invalid is not itself an error: the receipt’s verification is what asserts both layers are clean, and a caller that wants to guarantee the original signature is valid BEFORE counter-signing should verify it first.

Parameters:
Return type:

CounterSignedReceipt

verify_counter_signed_receipt(package_path, receipt, *, operator_public_key_hex, counter_signer_public_key_hex)[source]

Verify BOTH signature layers of a counter-signed review-package receipt.

First re-verifies the operator’s original signature via verify_review_package_signature() – which itself re-runs the checksum-manifest integrity check against the package’s CURRENT bytes before touching any Ed25519 signature, so a tampered archive fails here regardless of either signature. Only once that layer passes does this function verify the accountant’s counter-signature against the message it recomputes from the receipt’s own original_signature.signature_hex and note fields (never a cached message), so an edited note invalidates the receipt.

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

  • receipt (CounterSignedReceipt) – The CounterSignedReceipt produced by counter_sign_review_package().

  • operator_public_key_hex (str) – The operator’s raw public key, as 64 lowercase hex characters. Passed explicitly (never read off the receipt) so a verifier must supply the key it actually trusts.

  • counter_signer_public_key_hex (str) – The accountant’s raw public key, as 64 lowercase hex characters. Passed explicitly for the same reason; the receipt’s own counter_public_key_hex is never trusted as the verification key.

Return type:

bool

Returns:

True iff the package is currently checksum-clean, the operator’s original signature verifies against operator_public_key_hex, AND the accountant’s counter-signature verifies against counter_signer_public_key_hex. Returns False (never raises) on any mismatch, tamper, or invalid-signature outcome.