pub struct PrehashedDataToSign<E: Curve>(/* private fields */);Expand description
A pre-hashed message digest intended for signing, where the original message (preimage) may be unknown.
This struct wraps a scalar value representing a message digest. Unlike its safer counterpart,
DataToSign, this struct can be constructed directly from a raw scalar, bypassing the safety
check that ensures the original message is known.
§Context: PrehashedDataToSign vs. DataToSign
This library provides two types for data to be signed:
DataToSign(Recommended): This is the safe, default option. Its API requires you to provide the original message bytes. The library then handles the hashing internally. This acts as a type-safe guard, guaranteeing that the signature corresponds to a known message.PrehashedDataToSign(Advanced): This is a low-level type for specific, advanced use cases. It contains a hash that was computed externally.
This PrehashedDataToSign struct is only accepted by library functions where it is safe to do
so—specifically, in the full interactive signing protocol where the forgery attacks described
below are not applicable.
§⚠️ Assume Preimage Known: Advanced Use Only
This library offers a feature flag named insecure-assume-preimage-known for
highly specialized use cases. When enabled, this feature exposes the method
PrehashedDataToSign::insecure_assume_preimage_known which allows you to convert a
PrehashedDataToSign directly into a DataToSign. This is a powerful but extremely dangerous
operation. It overrides the library’s type safety, telling the system to trust that a known
original message exists for the given hash, even if one does not.
This feature completely bypasses the security guarantees provided by the DataToSign type
and should almost never be used.
§Potential Attack: Signature Forgery via Raw Hash Signing
This attack, detailed in this paper (Section 1.1.2, “An attack on ECDSA with presignatures”), enables signature forgery when a system signs raw hashes in combination with presignatures.
The core idea is that an attacker can forge a signature for a message of their choice, m', by
tricking the system into signing a different, maliciously crafted hash, h.
Here’s a simplified breakdown of how it works:
- Message Selection: The attacker first chooses a target message,
m', that they want a forged signature for - Malicious Hash Construction: Instead of submitting
h' = H(m'), the attacker uses the hash of their target message,H(m'), and public data from the presignature to compute a new, malicious hash value,h. Thishhas no known preimage and appears random. - Signing Request: The attacker submits this raw hash
hto the signing protocol. - Forgery: The protocol signs
hand returns a signature component. The attacker then uses this component to mathematically compute the final, valid signature for their original target message,m'.
Essentially, the attacker exploits the signing algorithm’s structure. By carefully crafting the hash input, they can predict and manipulate the output to forge a signature for an entirely different message. This is why signing a hash without knowing its original message (preimage) is extremely dangerous in this context.
Implementations§
Source§impl<E: Curve> PrehashedDataToSign<E>
impl<E: Curve> PrehashedDataToSign<E>
Sourcepub fn from_scalar(scalar: Scalar<E>) -> Self
pub fn from_scalar(scalar: Scalar<E>) -> Self
Constructs a PrehashedDataToSign from scalar
scalar must be output of cryptographic hash function applied to original message to be signed
Sourcepub fn insecure_assume_preimage_known(self) -> DataToSign<E>
Available on crate feature insecure-assume-preimage-known only.
pub fn insecure_assume_preimage_known(self) -> DataToSign<E>
insecure-assume-preimage-known only.Converts a PrehashedDataToSign directly into a DataToSign
⚠️ Extremely dangerous operation. It overrides the library’s type safety, telling the
system to trust that a known original message exists for the given hash, even if one does
not. Read PrehashedDataToSign docs to learn why it’s dangerous.
It’s only safe to use this method if you have either:
- Hashed the original message yourself to generate this scalar (prefer directly using
DataToSignwhen possible). - Can otherwise completely verify and trust the source of the prehashed data.
Trait Implementations§
Source§impl<E: Curve> AnyDataToSign<E> for PrehashedDataToSign<E>
impl<E: Curve> AnyDataToSign<E> for PrehashedDataToSign<E>
Source§impl<E: Clone + Curve> Clone for PrehashedDataToSign<E>
impl<E: Clone + Curve> Clone for PrehashedDataToSign<E>
Source§fn clone(&self) -> PrehashedDataToSign<E>
fn clone(&self) -> PrehashedDataToSign<E>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl<E: Copy + Curve> Copy for PrehashedDataToSign<E>
Auto Trait Implementations§
impl<E> Freeze for PrehashedDataToSign<E>
impl<E> RefUnwindSafe for PrehashedDataToSign<E>
impl<E> Send for PrehashedDataToSign<E>
impl<E> Sync for PrehashedDataToSign<E>
impl<E> Unpin for PrehashedDataToSign<E>
impl<E> UnsafeUnpin for PrehashedDataToSign<E>
impl<E> UnwindSafe for PrehashedDataToSign<E>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CheckedAs for T
impl<T> CheckedAs for T
Source§fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
Source§impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
Source§fn checked_cast_from(src: Src) -> Option<Dst>
fn checked_cast_from(src: Src) -> Option<Dst>
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> OverflowingAs for T
impl<T> OverflowingAs for T
Source§fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
Source§impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
Source§fn overflowing_cast_from(src: Src) -> (Dst, bool)
fn overflowing_cast_from(src: Src) -> (Dst, bool)
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> SaturatingAs for T
impl<T> SaturatingAs for T
Source§fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
Source§impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
Source§fn saturating_cast_from(src: Src) -> Dst
fn saturating_cast_from(src: Src) -> Dst
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.