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