cfxkey/
signature.rs

1// Copyright 2015-2019 Parity Technologies (UK) Ltd.
2// This file is part of Parity Ethereum.
3
4// Parity Ethereum is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Ethereum is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Ethereum.  If not, see <http://www.gnu.org/licenses/>.
16
17use crate::{
18    public_to_address, Address, Error, Message, Public, Secret, SECP256K1,
19};
20use cfx_types::{H256, H520};
21use rustc_hex::{FromHex, ToHex};
22use secp256k1::{
23    key::{PublicKey, SecretKey},
24    Error as SecpError, Message as SecpMessage, RecoverableSignature,
25    RecoveryId,
26};
27use std::{
28    cmp::PartialEq,
29    fmt,
30    hash::{Hash, Hasher},
31    ops::{Deref, DerefMut},
32    str::FromStr,
33};
34
35/// Signature encoded as RSV components
36#[repr(C)]
37pub struct Signature([u8; 65]);
38
39impl Signature {
40    /// Get a slice into the 'r' portion of the data.
41    pub fn r(&self) -> &[u8] { &self.0[0..32] }
42
43    /// Get a slice into the 's' portion of the data.
44    pub fn s(&self) -> &[u8] { &self.0[32..64] }
45
46    /// Get the recovery byte.
47    pub fn v(&self) -> u8 { self.0[64] }
48
49    /// Encode the signature into RSV array (V altered to be in "Electrum"
50    /// notation).
51    pub fn into_electrum(mut self) -> [u8; 65] {
52        self.0[64] += 27;
53        self.0
54    }
55
56    /// Parse bytes as a signature encoded as RSV (V in "Electrum" notation).
57    /// May return empty (invalid) signature if given data has invalid length.
58    pub fn from_electrum(data: &[u8]) -> Self {
59        if data.len() != 65 || data[64] < 27 {
60            // fallback to empty (invalid) signature
61            return Signature::default();
62        }
63
64        let mut sig = [0u8; 65];
65        sig.copy_from_slice(data);
66        sig[64] -= 27;
67        Signature(sig)
68    }
69
70    /// Create a signature object from the sig.
71    pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Self {
72        let mut sig = [0u8; 65];
73        sig[0..32].copy_from_slice(r.as_ref());
74        sig[32..64].copy_from_slice(s.as_ref());
75        sig[64] = v;
76        Signature(sig)
77    }
78
79    /// Check if this is a "low" signature.
80    pub fn is_low_s(&self) -> bool {
81        // "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0"
82        const MASK: H256 = H256([
83            0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
84            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0x57, 0x6E, 0x73, 0x57, 0xA4,
85            0x50, 0x1D, 0xDF, 0xE9, 0x2F, 0x46, 0x68, 0x1B, 0x20, 0xA0,
86        ]);
87        H256::from_slice(self.s()) <= MASK
88    }
89
90    /// Check if each component of the signature is in range.
91    pub fn is_valid(&self) -> bool {
92        // "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
93        const MASK: H256 = H256([
94            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95            0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48,
96            0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41,
97        ]);
98        const ONE: H256 = H256([
99            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
102        ]);
103        let r = H256::from_slice(self.r());
104        let s = H256::from_slice(self.s());
105        self.v() <= 1 && r < MASK && r >= ONE && s < MASK && s >= ONE
106    }
107}
108
109// manual implementation large arrays don't have trait impls by default.
110// remove when integer generics exist
111impl PartialEq for Signature {
112    fn eq(&self, other: &Self) -> bool { &self.0[..] == &other.0[..] }
113}
114
115// manual implementation required in Rust 1.13+, see
116// `std::cmp::AssertParamIsEq`.
117impl Eq for Signature {}
118
119// also manual for the same reason, but the pretty printing might be useful.
120impl fmt::Debug for Signature {
121    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
122        f.debug_struct("Signature")
123            .field("r", &self.0[0..32].to_hex::<String>())
124            .field("s", &self.0[32..64].to_hex::<String>())
125            .field("v", &self.0[64..65].to_hex::<String>())
126            .finish()
127    }
128}
129
130impl fmt::Display for Signature {
131    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
132        write!(f, "{}", self.to_hex::<String>())
133    }
134}
135
136impl FromStr for Signature {
137    type Err = Error;
138
139    fn from_str(s: &str) -> Result<Self, Self::Err> {
140        match s.from_hex::<Vec<u8>>() {
141            Ok(ref hex) if hex.len() == 65 => {
142                let mut data = [0; 65];
143                data.copy_from_slice(&hex[0..65]);
144                Ok(Signature(data))
145            }
146            _ => Err(Error::InvalidSignature),
147        }
148    }
149}
150
151impl Default for Signature {
152    fn default() -> Self { Signature([0; 65]) }
153}
154
155impl Hash for Signature {
156    fn hash<H: Hasher>(&self, state: &mut H) { H520::from(self.0).hash(state); }
157}
158
159impl Clone for Signature {
160    fn clone(&self) -> Self { Signature(self.0) }
161}
162
163impl From<[u8; 65]> for Signature {
164    fn from(s: [u8; 65]) -> Self { Signature(s) }
165}
166
167impl Into<[u8; 65]> for Signature {
168    fn into(self) -> [u8; 65] { self.0 }
169}
170
171impl From<Signature> for H520 {
172    fn from(s: Signature) -> Self { H520::from(s.0) }
173}
174
175impl From<H520> for Signature {
176    fn from(bytes: H520) -> Self { Signature(bytes.into()) }
177}
178
179impl Deref for Signature {
180    type Target = [u8; 65];
181
182    fn deref(&self) -> &Self::Target { &self.0 }
183}
184
185impl DerefMut for Signature {
186    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
187}
188
189pub fn sign(secret: &Secret, message: &Message) -> Result<Signature, Error> {
190    let context = &SECP256K1;
191    let sec = SecretKey::from_slice(context, secret.as_ref())?;
192    let s = context
193        .sign_recoverable(&SecpMessage::from_slice(&message[..])?, &sec)?;
194    let (rec_id, data) = s.serialize_compact(context);
195    let mut data_arr = [0; 65];
196
197    // no need to check if s is low, it always is
198    data_arr[0..64].copy_from_slice(&data[0..64]);
199    data_arr[64] = rec_id.to_i32() as u8;
200    Ok(Signature(data_arr))
201}
202
203pub fn verify_public(
204    public: &Public, signature: &Signature, message: &Message,
205) -> Result<bool, Error> {
206    let context = &SECP256K1;
207    let rsig = RecoverableSignature::from_compact(
208        context,
209        &signature[0..64],
210        RecoveryId::from_i32(signature[64] as i32)?,
211    )?;
212    let sig = rsig.to_standard(context);
213
214    let pdata: [u8; 65] = {
215        let mut temp = [4u8; 65];
216        temp[1..65].copy_from_slice(public.as_bytes());
217        temp
218    };
219
220    let publ = PublicKey::from_slice(context, &pdata)?;
221    match context.verify(&SecpMessage::from_slice(&message[..])?, &sig, &publ) {
222        Ok(_) => Ok(true),
223        Err(SecpError::IncorrectSignature) => Ok(false),
224        Err(x) => Err(Error::from(x)),
225    }
226}
227
228pub fn verify_address(
229    address: &Address, signature: &Signature, message: &Message,
230) -> Result<bool, Error> {
231    let public = recover(signature, message)?;
232    let recovered_address = public_to_address(&public, true);
233    Ok(address == &recovered_address)
234}
235
236pub fn recover(
237    signature: &Signature, message: &Message,
238) -> Result<Public, Error> {
239    let context = &SECP256K1;
240    let rsig = RecoverableSignature::from_compact(
241        context,
242        &signature[0..64],
243        RecoveryId::from_i32(signature[64] as i32)?,
244    )?;
245    let pubkey =
246        context.recover(&SecpMessage::from_slice(&message[..])?, &rsig)?;
247    let serialized = pubkey.serialize_vec(context, false);
248
249    let mut public = Public::default();
250    public.as_bytes_mut().copy_from_slice(&serialized[1..65]);
251    Ok(public)
252}
253
254#[cfg(test)]
255mod tests {
256    use super::{recover, sign, verify_address, verify_public, Signature};
257    use crate::{KeyPairGenerator, Message, Random};
258    use std::str::FromStr;
259
260    #[test]
261    fn vrs_conversion() {
262        // given
263        let keypair = Random.generate().unwrap();
264        let message = Message::default();
265        let signature = sign(keypair.secret(), &message).unwrap();
266
267        // when
268        let vrs = signature.clone().into_electrum();
269        let from_vrs = Signature::from_electrum(&vrs);
270
271        // then
272        assert_eq!(signature, from_vrs);
273    }
274
275    #[test]
276    fn signature_to_and_from_str() {
277        let keypair = Random.generate().unwrap();
278        let message = Message::default();
279        let signature = sign(keypair.secret(), &message).unwrap();
280        let string = format!("{}", signature);
281        let deserialized = Signature::from_str(&string).unwrap();
282        assert_eq!(signature, deserialized);
283    }
284
285    #[test]
286    fn sign_and_recover_public() {
287        let keypair = Random.generate().unwrap();
288        let message = Message::default();
289        let signature = sign(keypair.secret(), &message).unwrap();
290        assert_eq!(keypair.public(), &recover(&signature, &message).unwrap());
291    }
292
293    #[test]
294    fn sign_and_verify_public() {
295        let keypair = Random.generate().unwrap();
296        let message = Message::default();
297        let signature = sign(keypair.secret(), &message).unwrap();
298        assert!(verify_public(keypair.public(), &signature, &message).unwrap());
299    }
300
301    #[test]
302    fn sign_and_verify_address() {
303        let keypair = Random.generate().unwrap();
304        let message = Message::default();
305        let signature = sign(keypair.secret(), &message).unwrap();
306        assert!(
307            verify_address(&keypair.address(), &signature, &message).unwrap()
308        );
309    }
310}