Aeneas-compat: single-call sha512_hash3 oracle (sha2-0.10 stack)

This fork's sha2-0.10 Sha512 type alias cannot be declared opaque by the
extractor (generic-array expansion), so the three stateful hasher wrappers
collapse into one monomorphic sha512_hash3(r, a, m) -> [u8; 64] whose
signature carries no foreign types. Semantically Sha512 over r || a || m —
exactly the H(R || A || M) the verification equation hashes. Extraction
builds with --no-default-features (the no-std From<InternalError> branch
uses Error::new, avoiding the boxed dyn-Error source path).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mrwulf 2026-07-04 22:11:30 +02:00
parent f6007690f5
commit f17cbd1a19

View file

@ -701,15 +701,15 @@ impl<'d> Deserialize<'d> for VerifyingKey {
// Semantics identical; pure refactor for extraction only.
// ─────────────────────────────────────────────────────────────────────────────
pub(crate) fn sha512_new() -> Sha512 {
Digest::new()
}
pub(crate) fn sha512_update(h: &mut Sha512, m: &[u8]) {
Digest::update(h, m)
}
pub(crate) fn sha512_finalize_bytes(h: Sha512) -> [u8; 64] {
/// AENEAS-COMPAT: the whole three-part hash as ONE monomorphic call whose
/// signature carries no foreign types (this fork's sha2-0.10 `Sha512` type
/// alias cannot be declared opaque by the extractor). Semantically:
/// `Sha512::new().chain(r).chain(a).chain(m).finalize()`.
pub(crate) fn sha512_hash3(r: &[u8], a: &[u8], m: &[u8]) -> [u8; 64] {
let mut h: Sha512 = Digest::new();
Digest::update(&mut h, r);
Digest::update(&mut h, a);
Digest::update(&mut h, m);
Digest::finalize(h).into()
}
@ -719,11 +719,11 @@ pub(crate) fn recompute_r_sha512(
sig: &InternalSignature,
message: &[u8],
) -> CompressedEdwardsY {
let mut h = sha512_new();
sha512_update(&mut h, sig.R.as_bytes());
sha512_update(&mut h, key.compressed.as_bytes());
sha512_update(&mut h, message);
let k = Scalar::from_bytes_mod_order_wide(&sha512_finalize_bytes(h));
let k = Scalar::from_bytes_mod_order_wide(&sha512_hash3(
sig.R.as_bytes(),
key.compressed.as_bytes(),
message,
));
let minus_A: EdwardsPoint = -key.point;
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &minus_A, &sig.s).compress()