ed25519_dalek/
signature.rs

1// -*- mode: rust; -*-
2//
3// This file is part of ed25519-dalek.
4// Copyright (c) 2017-2019 isis lovecruft
5// See LICENSE for licensing information.
6//
7// Authors:
8// - isis agora lovecruft <isis@patternsinthevoid.net>
9
10//! An ed25519 signature.
11
12use core::fmt::Debug;
13
14use curve25519_dalek::edwards::CompressedEdwardsY;
15use curve25519_dalek::scalar::Scalar;
16
17use crate::constants::*;
18use crate::errors::*;
19
20/// An ed25519 signature.
21///
22/// # Note
23///
24/// These signatures, unlike the ed25519 signature reference implementation, are
25/// "detached"—that is, they do **not** include a copy of the message which has
26/// been signed.
27#[allow(non_snake_case)]
28#[derive(Copy, Eq, PartialEq)]
29pub(crate) struct InternalSignature {
30    /// `R` is an `EdwardsPoint`, formed by using an hash function with
31    /// 512-bits output to produce the digest of:
32    ///
33    /// - the nonce half of the `ExpandedSecretKey`, and
34    /// - the message to be signed.
35    ///
36    /// This digest is then interpreted as a `Scalar` and reduced into an
37    /// element in ℤ/lℤ.  The scalar is then multiplied by the distinguished
38    /// basepoint to produce `R`, and `EdwardsPoint`.
39    pub(crate) R: CompressedEdwardsY,
40
41    /// `s` is a `Scalar`, formed by using an hash function with 512-bits output
42    /// to produce the digest of:
43    ///
44    /// - the `r` portion of this `Signature`,
45    /// - the `PublicKey` which should be used to verify this `Signature`, and
46    /// - the message to be signed.
47    ///
48    /// This digest is then interpreted as a `Scalar` and reduced into an
49    /// element in ℤ/lℤ.
50    pub(crate) s: Scalar,
51}
52
53impl Clone for InternalSignature {
54    fn clone(&self) -> Self {
55        *self
56    }
57}
58
59impl Debug for InternalSignature {
60    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
61        write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s)
62    }
63}
64
65/// Ensures that the scalar `s` of a signature is within the bounds [0, 2^253).
66///
67/// **Unsafe**: This version of `check_scalar` permits signature malleability. See README.
68#[cfg(feature = "legacy_compatibility")]
69#[inline(always)]
70fn check_scalar(bytes: [u8; 32]) -> Result<Scalar, SignatureError> {
71    // The highest 3 bits must not be set.  No other checking for the
72    // remaining 2^253 - 2^252 + 27742317777372353535851937790883648493
73    // potential non-reduced scalars is performed.
74    //
75    // This is compatible with ed25519-donna and libsodium when
76    // `-D ED25519_COMPAT` is NOT specified.
77    if bytes[31] & 224 != 0 {
78        return Err(InternalError::ScalarFormat.into());
79    }
80
81    // You cannot do arithmetic with scalars construct with Scalar::from_bits. We only use this
82    // scalar for EdwardsPoint::vartime_double_scalar_mul_basepoint, which is an accepted usecase.
83    // The `from_bits` method is deprecated because it's unsafe. We know this.
84    #[allow(deprecated)]
85    Ok(Scalar::from_bits(bytes))
86}
87
88/// Ensures that the scalar `s` of a signature is within the bounds [0, ℓ)
89#[cfg(not(feature = "legacy_compatibility"))]
90#[inline(always)]
91fn check_scalar(bytes: [u8; 32]) -> Result<Scalar, SignatureError> {
92    match Scalar::from_canonical_bytes(bytes).into() {
93        None => Err(InternalError::ScalarFormat.into()),
94        Some(x) => Ok(x),
95    }
96}
97
98impl InternalSignature {
99    /// Construct a `Signature` from a slice of bytes.
100    ///
101    /// # Scalar Malleability Checking
102    ///
103    /// As originally specified in the ed25519 paper (cf. the "Malleability"
104    /// section of the README in this repo), no checks whatsoever were performed
105    /// for signature malleability.
106    ///
107    /// Later, a semi-functional, hacky check was added to most libraries to
108    /// "ensure" that the scalar portion, `s`, of the signature was reduced `mod
109    /// \ell`, the order of the basepoint:
110    ///
111    /// ```ignore
112    /// if signature.s[31] & 224 != 0 {
113    ///     return Err();
114    /// }
115    /// ```
116    ///
117    /// This bit-twiddling ensures that the most significant three bits of the
118    /// scalar are not set:
119    ///
120    /// ```python,ignore
121    /// >>> 0b00010000 & 224
122    /// 0
123    /// >>> 0b00100000 & 224
124    /// 32
125    /// >>> 0b01000000 & 224
126    /// 64
127    /// >>> 0b10000000 & 224
128    /// 128
129    /// ```
130    ///
131    /// However, this check is hacky and insufficient to check that the scalar is
132    /// fully reduced `mod \ell = 2^252 + 27742317777372353535851937790883648493` as
133    /// it leaves us with a guanteed bound of 253 bits.  This means that there are
134    /// `2^253 - 2^252 + 2774231777737235353585193779088364849311` remaining scalars
135    /// which could cause malleabilllity.
136    ///
137    /// RFC8032 [states](https://tools.ietf.org/html/rfc8032#section-5.1.7):
138    ///
139    /// > To verify a signature on a message M using public key A, [...]
140    /// > first split the signature into two 32-octet halves.  Decode the first
141    /// > half as a point R, and the second half as an integer S, in the range
142    /// > 0 <= s < L.  Decode the public key A as point A'.  If any of the
143    /// > decodings fail (including S being out of range), the signature is
144    /// > invalid.
145    ///
146    /// However, by the time this was standardised, most libraries in use were
147    /// only checking the most significant three bits.  (See also the
148    /// documentation for [`crate::VerifyingKey::verify_strict`].)
149    #[inline]
150    #[allow(non_snake_case)]
151    pub fn from_bytes(bytes: &[u8; SIGNATURE_LENGTH]) -> Result<InternalSignature, SignatureError> {
152        // TODO: Use bytes.split_array_ref once it’s in MSRV.
153        let mut R_bytes: [u8; 32] = [0u8; 32];
154        let mut s_bytes: [u8; 32] = [0u8; 32];
155        R_bytes.copy_from_slice(&bytes[00..32]);
156        s_bytes.copy_from_slice(&bytes[32..64]);
157
158        Ok(InternalSignature {
159            R: CompressedEdwardsY(R_bytes),
160            s: check_scalar(s_bytes)?,
161        })
162    }
163}
164
165impl TryFrom<&ed25519::Signature> for InternalSignature {
166    type Error = SignatureError;
167
168    fn try_from(sig: &ed25519::Signature) -> Result<InternalSignature, SignatureError> {
169        InternalSignature::from_bytes(&sig.to_bytes())
170    }
171}
172
173impl From<InternalSignature> for ed25519::Signature {
174    fn from(sig: InternalSignature) -> ed25519::Signature {
175        ed25519::Signature::from_components(*sig.R.as_bytes(), *sig.s.as_bytes())
176    }
177}