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_signingThe operator-side signing primitive this module counter-signs on top of.
_review_packageBuilds and integrity-verifies the review package that is signed.
- exception ReviewPackageCounterSigningError(message=None, *, context=None, suggestion=None, translated_message=None)[source]¶
Bases:
AeatErrorBase error for review-package counter-signing/verification failures.
- Parameters:
- Return type:
None
- code: ClassVar[ErrorCode]¶
- class CounterSignedReceipt(**data)[source]¶
Bases:
BaseModelA review package’s operator signature, counter-signed by an accountant.
Wraps the operator’s
SignedReviewPackageverbatim (theoriginal_signaturefield) alongside the accountant’s own Ed25519 signature overoriginal_signature.signature_hexplusnote. 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 differentsignature_hexbytes 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()letsverify_counter_signed_receipt()recompute the signed message from the receipt’s own fields rather than trusting a cached value, so a receipt whosenotewas 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_packagesignature or the underlying archive’s checksum manifest – that isverify_review_package_signature()’s job, and it is re-run unconditionally insideverify_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:
signed_package (
SignedReviewPackage) – The operator’sSignedReviewPackageenvelope (seesign_review_package()).counter_signer_keypair (
ReviewPackageSigningKeypair) – The accountant’sReviewPackageSigningKeypair(minted the same way as the operator’s, viaensure_review_package_signing_keypair()scoped to the accountant’s own identity).note (
str) – Optional free-text counter-signer note or verdict (e.g."reviewed, no changes"). Bound into the signed message, so editing the note after counter-signing invalidates the receipt.counter_signed_at (
datetime|None) – Optional override for the envelope’scounter_signed_attimestamp (tests only); defaults to the current UTC time.
- Return type:
- 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 ownoriginal_signature.signature_hexandnotefields (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) – TheCounterSignedReceiptproduced bycounter_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 owncounter_public_key_hexis never trusted as the verification key.
- Return type:
- Returns:
Trueiff the package is currently checksum-clean, the operator’s original signature verifies againstoperator_public_key_hex, AND the accountant’s counter-signature verifies againstcounter_signer_public_key_hex. ReturnsFalse(never raises) on any mismatch, tamper, or invalid-signature outcome.