1use prelude::*;
22
23use hashes::{sha256d, Hash, HashEngine};
24
25use blockdata::opcodes;
26use consensus::{encode, Encodable};
27
28#[cfg(feature = "secp-recovery")]
29#[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))]
30pub use self::message_signing::{MessageSignature, MessageSignatureError};
31
32pub const BITCOIN_SIGNED_MSG_PREFIX: &[u8] = b"\x18Bitcoin Signed Message:\n";
34
35#[cfg(feature = "secp-recovery")]
36mod message_signing {
37 #[cfg(feature = "base64")] use prelude::*;
38 use core::fmt;
39 #[cfg(feature = "std")] use std::error;
40
41 use hashes::sha256d;
42 use secp256k1;
43 use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
44
45 use util::key::PublicKey;
46 use util::address::{Address, AddressType};
47
48 #[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))]
50 #[derive(Debug, PartialEq, Eq)]
51 pub enum MessageSignatureError {
52 InvalidLength,
54 InvalidEncoding(secp256k1::Error),
56 InvalidBase64,
58 UnsupportedAddressType(AddressType),
60 }
61
62 impl fmt::Display for MessageSignatureError {
63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 match *self {
65 MessageSignatureError::InvalidLength => write!(f, "length not 65 bytes"),
66 MessageSignatureError::InvalidEncoding(ref e) => write!(f, "invalid encoding: {}", e),
67 MessageSignatureError::InvalidBase64 => write!(f, "invalid base64"),
68 MessageSignatureError::UnsupportedAddressType(ref address_type) => write!(f, "unsupported address type: {}", address_type),
69 }
70 }
71 }
72
73 #[cfg(feature = "std")]
74 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
75 impl error::Error for MessageSignatureError {
76 fn cause(&self) -> Option<&dyn error::Error> {
77 match *self {
78 MessageSignatureError::InvalidEncoding(ref e) => Some(e),
79 _ => None,
80 }
81 }
82 }
83
84 #[doc(hidden)]
85 impl From<secp256k1::Error> for MessageSignatureError {
86 fn from(e: secp256k1::Error) -> MessageSignatureError {
87 MessageSignatureError::InvalidEncoding(e)
88 }
89 }
90
91 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
97 #[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))]
98 pub struct MessageSignature {
99 pub signature: RecoverableSignature,
101 pub compressed: bool,
103 }
104
105 impl MessageSignature {
106 pub fn new(signature: RecoverableSignature, compressed: bool) -> MessageSignature {
108 MessageSignature {
109 signature,
110 compressed,
111 }
112 }
113
114 pub fn serialize(&self) -> [u8; 65] {
116 let (recid, raw) = self.signature.serialize_compact();
117 let mut serialized = [0u8; 65];
118 serialized[0] = 27;
119 serialized[0] += recid.to_i32() as u8;
120 if self.compressed {
121 serialized[0] += 4;
122 }
123 serialized[1..].copy_from_slice(&raw[..]);
124 serialized
125 }
126
127 pub fn from_slice(bytes: &[u8]) -> Result<MessageSignature, MessageSignatureError> {
129 if bytes.len() != 65 {
130 return Err(MessageSignatureError::InvalidLength);
131 }
132 if bytes[0] < 27 {
134 return Err(MessageSignatureError::InvalidEncoding(secp256k1::Error::InvalidRecoveryId));
135 };
136 let recid = RecoveryId::from_i32(((bytes[0] - 27) & 0x03) as i32)?;
137 Ok(MessageSignature {
138 signature: RecoverableSignature::from_compact(&bytes[1..], recid)?,
139 compressed: ((bytes[0] - 27) & 0x04) != 0,
140 })
141 }
142
143 pub fn recover_pubkey<C: secp256k1::Verification>(
147 &self,
148 secp_ctx: &secp256k1::Secp256k1<C>,
149 msg_hash: sha256d::Hash
150 ) -> Result<PublicKey, MessageSignatureError> {
151 let msg = secp256k1::Message::from_slice(&msg_hash[..])
152 .expect("cannot fail");
153 let pubkey = secp_ctx.recover_ecdsa(&msg, &self.signature)?;
154 Ok(PublicKey {
155 inner: pubkey,
156 compressed: self.compressed,
157 })
158 }
159
160 pub fn is_signed_by_address<C: secp256k1::Verification>(
164 &self,
165 secp_ctx: &secp256k1::Secp256k1<C>,
166 address: &Address,
167 msg_hash: sha256d::Hash
168 ) -> Result<bool, MessageSignatureError> {
169 match address.address_type() {
170 Some(AddressType::P2pkh) => {
171 let pubkey = self.recover_pubkey(secp_ctx, msg_hash)?;
172 Ok(*address == Address::p2pkh(&pubkey, address.network))
173 }
174 Some(address_type) => Err(MessageSignatureError::UnsupportedAddressType(address_type)),
175 None => Ok(false),
176 }
177 }
178
179 #[cfg(feature = "base64")]
181 #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
182 pub fn from_base64(s: &str) -> Result<MessageSignature, MessageSignatureError> {
183 let bytes = ::base64::decode(s).map_err(|_| MessageSignatureError::InvalidBase64)?;
184 MessageSignature::from_slice(&bytes)
185 }
186
187 #[cfg(feature = "base64")]
189 #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
190 pub fn to_base64(&self) -> String {
191 ::base64::encode(&self.serialize()[..])
192 }
193 }
194
195 #[cfg(feature = "base64")]
196 #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
197 impl fmt::Display for MessageSignature {
198 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199 let bytes = self.serialize();
200 write!(f, "{}", ::base64::display::Base64Display::with_config(
202 &bytes[..], ::base64::STANDARD))
203 }
204 }
205
206 #[cfg(feature = "base64")]
207 #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
208 impl ::core::str::FromStr for MessageSignature {
209 type Err = MessageSignatureError;
210 fn from_str(s: &str) -> Result<MessageSignature, MessageSignatureError> {
211 MessageSignature::from_base64(s)
212 }
213 }
214}
215
216pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
220 if needle.len() > haystack.len() {
221 return 0;
222 }
223 if needle.is_empty() {
224 return 0;
225 }
226
227 let mut top = haystack.len() - needle.len();
228 let mut n_deleted = 0;
229
230 let mut i = 0;
231 while i <= top {
232 if &haystack[i..(i + needle.len())] == needle {
233 for j in i..top {
234 haystack.swap(j + needle.len(), j);
235 }
236 n_deleted += 1;
237 let overflow = top < needle.len();
239 top = top.wrapping_sub(needle.len());
240 if overflow {
241 break;
242 }
243 } else {
244 i += match opcodes::All::from((*haystack)[i]).classify(opcodes::ClassifyContext::Legacy) {
245 opcodes::Class::PushBytes(n) => n as usize + 1,
246 opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA1) => 2,
247 opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA2) => 3,
248 opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA4) => 5,
249 _ => 1
250 };
251 }
252 }
253 haystack.truncate(top.wrapping_add(needle.len()));
254 n_deleted
255}
256
257pub fn signed_msg_hash(msg: &str) -> sha256d::Hash {
259 let mut engine = sha256d::Hash::engine();
260 engine.input(BITCOIN_SIGNED_MSG_PREFIX);
261 let msg_len = encode::VarInt(msg.len() as u64);
262 msg_len.consensus_encode(&mut engine).expect("engines don't error");
263 engine.input(msg.as_bytes());
264 sha256d::Hash::from_engine(engine)
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270 use hashes::hex::ToHex;
271 use super::script_find_and_remove;
272 use super::signed_msg_hash;
273
274 #[test]
275 fn test_script_find_and_remove() {
276 let mut v = vec![101u8, 102, 103, 104, 102, 103, 104, 102, 103, 104, 105, 106, 107, 108, 109];
277
278 assert_eq!(script_find_and_remove(&mut v, &[]), 0);
279 assert_eq!(script_find_and_remove(&mut v, &[105, 105, 105]), 0);
280 assert_eq!(v, vec![101, 102, 103, 104, 102, 103, 104, 102, 103, 104, 105, 106, 107, 108, 109]);
281
282 assert_eq!(script_find_and_remove(&mut v, &[105, 106, 107]), 1);
283 assert_eq!(v, vec![101, 102, 103, 104, 102, 103, 104, 102, 103, 104, 108, 109]);
284
285 assert_eq!(script_find_and_remove(&mut v, &[104, 108, 109]), 1);
286 assert_eq!(v, vec![101, 102, 103, 104, 102, 103, 104, 102, 103]);
287
288 assert_eq!(script_find_and_remove(&mut v, &[101]), 1);
289 assert_eq!(v, vec![102, 103, 104, 102, 103, 104, 102, 103]);
290
291 assert_eq!(script_find_and_remove(&mut v, &[102]), 3);
292 assert_eq!(v, vec![103, 104, 103, 104, 103]);
293
294 assert_eq!(script_find_and_remove(&mut v, &[103, 104]), 2);
295 assert_eq!(v, vec![103]);
296
297 assert_eq!(script_find_and_remove(&mut v, &[105, 105, 5]), 0);
298 assert_eq!(script_find_and_remove(&mut v, &[105]), 0);
299 assert_eq!(script_find_and_remove(&mut v, &[103]), 1);
300 assert_eq!(v, Vec::<u8>::new());
301
302 assert_eq!(script_find_and_remove(&mut v, &[105, 105, 5]), 0);
303 assert_eq!(script_find_and_remove(&mut v, &[105]), 0);
304 }
305
306 #[test]
307 fn test_script_codesep_remove() {
308 let mut s = vec![33u8, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 171, 33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 171, 81];
309 assert_eq!(script_find_and_remove(&mut s, &[171]), 2);
310 assert_eq!(s, vec![33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 81]);
311 }
312
313 #[test]
314 fn test_signed_msg_hash() {
315 let hash = signed_msg_hash("test");
316 assert_eq!(hash.to_hex(), "a6f87fe6d58a032c320ff8d1541656f0282c2c7bfcc69d61af4c8e8ed528e49c");
317 }
318
319 #[test]
320 #[cfg(all(feature = "secp-recovery", feature = "base64"))]
321 fn test_message_signature() {
322 use core::str::FromStr;
323 use secp256k1;
324 use ::AddressType;
325
326 let secp = secp256k1::Secp256k1::new();
327 let message = "rust-bitcoin MessageSignature test";
328 let msg_hash = super::signed_msg_hash(&message);
329 let msg = secp256k1::Message::from_slice(&msg_hash).expect("message");
330
331
332 let privkey = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng());
333 let secp_sig = secp.sign_ecdsa_recoverable(&msg, &privkey);
334 let signature = super::MessageSignature {
335 signature: secp_sig,
336 compressed: true,
337 };
338
339 assert_eq!(signature.to_base64(), signature.to_string());
340 let signature2 = super::MessageSignature::from_str(&signature.to_string()).unwrap();
341 let pubkey = signature2.recover_pubkey(&secp, msg_hash).unwrap();
342 assert_eq!(pubkey.compressed, true);
343 assert_eq!(pubkey.inner, secp256k1::PublicKey::from_secret_key(&secp, &privkey));
344
345 let p2pkh = ::Address::p2pkh(&pubkey, ::Network::Bitcoin);
346 assert_eq!(signature2.is_signed_by_address(&secp, &p2pkh, msg_hash), Ok(true));
347 let p2wpkh = ::Address::p2wpkh(&pubkey, ::Network::Bitcoin).unwrap();
348 assert_eq!(
349 signature2.is_signed_by_address(&secp, &p2wpkh, msg_hash),
350 Err(MessageSignatureError::UnsupportedAddressType(AddressType::P2wpkh))
351 );
352 let p2shwpkh = ::Address::p2shwpkh(&pubkey, ::Network::Bitcoin).unwrap();
353 assert_eq!(
354 signature2.is_signed_by_address(&secp, &p2shwpkh, msg_hash),
355 Err(MessageSignatureError::UnsupportedAddressType(AddressType::P2sh))
356 );
357 }
358
359 #[test]
360 #[cfg(all(feature = "secp-recovery", feature = "base64"))]
361 fn test_incorrect_message_signature() {
362 use secp256k1;
363 use util::key::PublicKey;
364
365 let secp = secp256k1::Secp256k1::new();
366 let message = "a different message from what was signed";
367 let msg_hash = super::signed_msg_hash(&message);
368
369 let signature_base64 = "IAM2qX24tYx/bdBTIgVLhD8QEAjrPlJpmjB4nZHdRYGIBa4DmVulAcwjPnWe6Q5iEwXH6F0pUCJP/ZeHPWS1h1o=";
372 let pubkey_base64 = "A1FTfMEntPpAty3qkEo0q2Dc1FEycI10a3jmwEFy+Qr6";
373 let signature = super::MessageSignature::from_base64(signature_base64).expect("message signature");
374
375 let pubkey = PublicKey::from_slice(
376 &::base64::decode(&pubkey_base64).expect("base64 string")
377 ).expect("pubkey slice");
378
379 let p2pkh = ::Address::p2pkh(&pubkey, ::Network::Bitcoin);
380 assert_eq!(signature.is_signed_by_address(&secp, &p2pkh, msg_hash), Ok(false));
381 }
382}