1pub use secp256k1::{XOnlyPublicKey, Keypair as KeyPair};
20
21use prelude::*;
22
23use core::{ops, str::FromStr};
24use core::fmt::{self, Write as _fmtWrite};
25use io;
26#[cfg(feature = "std")] use std::error;
27
28use secp256k1::{self, Secp256k1};
29use network::constants::Network;
30use hashes::{Hash, hash160, hex, hex::FromHex};
31use hash_types::{PubkeyHash, WPubkeyHash};
32use util::base58;
33#[cfg(feature = "schemars")] use schemars::schema::{Schema, SchemaObject};
34#[cfg(feature = "schemars")] use schemars::{gen::SchemaGenerator, JsonSchema};
35
36#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
38pub enum Error {
39 Base58(base58::Error),
41 Secp256k1(secp256k1::Error),
43 InvalidKeyPrefix(u8),
45 Hex(hex::Error)
47}
48
49impl fmt::Display for Error {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 match *self {
52 Error::Base58(ref e) => write!(f, "Key base58 error: {}", e),
53 Error::Secp256k1(ref e) => write!(f, "Key secp256k1 error: {}", e),
54 Error::InvalidKeyPrefix(ref e) => write!(f, "Key prefix invalid: {}", e),
55 Error::Hex(ref e) => write!(f, "Key hex decoding error: {}", e)
56 }
57 }
58}
59
60#[cfg(feature = "std")]
61#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
62impl ::std::error::Error for Error {
63 fn cause(&self) -> Option<&dyn error::Error> {
64 match *self {
65 Error::Base58(ref e) => Some(e),
66 Error::Secp256k1(ref e) => Some(e),
67 Error::InvalidKeyPrefix(_) => None,
68 Error::Hex(ref e) => Some(e)
69 }
70 }
71}
72
73#[doc(hidden)]
74impl From<base58::Error> for Error {
75 fn from(e: base58::Error) -> Error {
76 Error::Base58(e)
77 }
78}
79
80#[doc(hidden)]
81impl From<secp256k1::Error> for Error {
82 fn from(e: secp256k1::Error) -> Error {
83 Error::Secp256k1(e)
84 }
85}
86
87#[doc(hidden)]
88impl From<hex::Error> for Error {
89 fn from(e: hex::Error) -> Self {
90 Error::Hex(e)
91 }
92}
93
94
95#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
97pub struct PublicKey {
98 pub compressed: bool,
100 pub inner: secp256k1::PublicKey,
102}
103
104impl PublicKey {
105 pub fn new(key: secp256k1::PublicKey) -> PublicKey {
107 PublicKey {
108 compressed: true,
109 inner: key,
110 }
111 }
112
113 pub fn new_uncompressed(key: secp256k1::PublicKey) -> PublicKey {
116 PublicKey {
117 compressed: false,
118 inner: key,
119 }
120 }
121
122 pub fn pubkey_hash(&self) -> PubkeyHash {
124 if self.compressed {
125 PubkeyHash::hash(&self.inner.serialize())
126 } else {
127 PubkeyHash::hash(&self.inner.serialize_uncompressed())
128 }
129 }
130
131 pub fn wpubkey_hash(&self) -> Option<WPubkeyHash> {
133 if self.compressed {
134 Some(WPubkeyHash::from_inner(
135 hash160::Hash::hash(&self.inner.serialize()).into_inner()
136 ))
137 } else {
138 None
141 }
142 }
143
144 pub fn write_into<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
146 if self.compressed {
147 writer.write_all(&self.inner.serialize())
148 } else {
149 writer.write_all(&self.inner.serialize_uncompressed())
150 }
151 }
152
153 pub fn read_from<R: io::Read>(mut reader: R) -> Result<Self, io::Error> {
158 let mut bytes = [0; 65];
159
160 reader.read_exact(&mut bytes[0..1])?;
161 let bytes = if bytes[0] < 4 { &mut bytes[..33] } else { &mut bytes[..65] };
162
163 reader.read_exact(&mut bytes[1..])?;
164 Self::from_slice(bytes).map_err(|e| {
165 #[cfg(feature = "std")]
167 let reason = e;
168 #[cfg(not(feature = "std"))]
169 let reason = match e {
170 Error::Base58(_) => "base58 error",
171 Error::Secp256k1(_) => "secp256k1 error",
172 Error::InvalidKeyPrefix(_) => "invalid key prefix",
173 Error::Hex(_) => "hex decoding error"
174 };
175 io::Error::new(io::ErrorKind::InvalidData, reason)
176 })
177 }
178
179 pub fn to_bytes(&self) -> Vec<u8> {
181 let mut buf = Vec::new();
182 self.write_into(&mut buf).expect("vecs don't error");
183 buf
184 }
185
186 pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
188 let compressed = match data.len() {
189 33 => true,
190 65 => false,
191 len => {
192 return Err(base58::Error::InvalidLength(len).into());
193 },
194 };
195
196 if !compressed && data[0] != 0x04 {
197 return Err(Error::InvalidKeyPrefix(data[0]))
198 }
199
200 Ok(PublicKey {
201 compressed,
202 inner: secp256k1::PublicKey::from_slice(data)?,
203 })
204 }
205
206 pub fn from_private_key<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &PrivateKey) -> PublicKey {
208 sk.public_key(secp)
209 }
210}
211
212impl fmt::Display for PublicKey {
213 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214 if self.compressed {
215 for ch in &self.inner.serialize()[..] {
216 write!(f, "{:02x}", ch)?;
217 }
218 } else {
219 for ch in &self.inner.serialize_uncompressed()[..] {
220 write!(f, "{:02x}", ch)?;
221 }
222 }
223 Ok(())
224 }
225}
226
227#[cfg(feature = "schemars")]
228impl JsonSchema for PublicKey {
229 fn schema_name() -> String {
230 "PublicKey".into()
231 }
232 fn json_schema(gen: &mut SchemaGenerator) -> Schema {
233 let mut schema: SchemaObject = <String>::json_schema(gen).into();
234 const PAT: &'static str = "^([0-9a-fA-F]{2})*$";
235 schema.string = Some(Box::new(schemars::schema::StringValidation {
236 max_length: Some(65*2),
237 min_length: Some(33*2),
238 pattern: Some(PAT.to_owned()),
239 }));
240 schema.into()
241 }
242}
243
244
245impl FromStr for PublicKey {
246 type Err = Error;
247 fn from_str(s: &str) -> Result<PublicKey, Error> {
248 match s.len() {
249 66 => PublicKey::from_slice(&<[u8; 33]>::from_hex(s)?),
250 130 => PublicKey::from_slice(&<[u8; 65]>::from_hex(s)?),
251 len => return Err(Error::Hex(hex::Error::InvalidLength(66, len)))
252 }
253 }
254}
255
256#[derive(Copy, Clone, PartialEq, Eq)]
258#[cfg_attr(feature = "std", derive(Debug))]
259pub struct PrivateKey {
260 pub compressed: bool,
262 pub network: Network,
264 pub inner: secp256k1::SecretKey,
266}
267
268impl PrivateKey {
269 pub fn new(key: secp256k1::SecretKey, network: Network) -> PrivateKey {
272 PrivateKey {
273 compressed: true,
274 network,
275 inner: key,
276 }
277 }
278
279 pub fn new_uncompressed(key: secp256k1::SecretKey, network: Network) -> PrivateKey {
282 PrivateKey {
283 compressed: false,
284 network,
285 inner: key,
286 }
287 }
288
289 pub fn public_key<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> PublicKey {
291 PublicKey {
292 compressed: self.compressed,
293 inner: secp256k1::PublicKey::from_secret_key(secp, &self.inner)
294 }
295 }
296
297 pub fn to_bytes(&self) -> Vec<u8> {
299 self.inner[..].to_vec()
300 }
301
302 pub fn from_slice(data: &[u8], network: Network) -> Result<PrivateKey, Error> {
304 Ok(PrivateKey::new(secp256k1::SecretKey::from_slice(data)?, network))
305 }
306
307 pub fn fmt_wif(&self, fmt: &mut dyn fmt::Write) -> fmt::Result {
309 let mut ret = [0; 34];
310 ret[0] = match self.network {
311 Network::Bitcoin => 128,
312 Network::Testnet | Network::Signet | Network::Regtest => 239,
313 };
314 ret[1..33].copy_from_slice(&self.inner[..]);
315 let privkey = if self.compressed {
316 ret[33] = 1;
317 base58::check_encode_slice(&ret[..])
318 } else {
319 base58::check_encode_slice(&ret[..33])
320 };
321 fmt.write_str(&privkey)
322 }
323
324 pub fn to_wif(&self) -> String {
326 let mut buf = String::new();
327 buf.write_fmt(format_args!("{}", self)).unwrap();
328 buf.shrink_to_fit();
329 buf
330 }
331
332 pub fn from_wif(wif: &str) -> Result<PrivateKey, Error> {
334 let data = base58::from_check(wif)?;
335
336 let compressed = match data.len() {
337 33 => false,
338 34 => true,
339 _ => {
340 return Err(Error::Base58(base58::Error::InvalidLength(data.len())));
341 }
342 };
343
344 let network = match data[0] {
345 128 => Network::Bitcoin,
346 239 => Network::Testnet,
347 x => {
348 return Err(Error::Base58(base58::Error::InvalidAddressVersion(x)));
349 }
350 };
351
352 Ok(PrivateKey {
353 compressed,
354 network,
355 inner: secp256k1::SecretKey::from_slice(&data[1..33])?,
356 })
357 }
358}
359
360impl fmt::Display for PrivateKey {
361 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
362 self.fmt_wif(f)
363 }
364}
365
366#[cfg(feature = "schemars")]
367impl JsonSchema for PrivateKey {
368 fn schema_name() -> String {
369 "PrivateKey".into()
370 }
371 fn json_schema(gen: &mut SchemaGenerator) -> Schema {
372 let mut schema: SchemaObject = <String>::json_schema(gen).into();
373 const PAT: &'static str = "^[5KLc9][1-9A-HJ-NP-Za-km-z]{50,51}$";
375 schema.string = Some(Box::new(schemars::schema::StringValidation {
376 max_length: Some(52),
377 min_length: Some(51),
378 pattern: Some(PAT.to_owned()),
379 }));
380 schema.into()
381 }
382}
383
384#[cfg(not(feature = "std"))]
385impl fmt::Debug for PrivateKey {
386 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
387 write!(f, "[private key data]")
388 }
389}
390
391impl FromStr for PrivateKey {
392 type Err = Error;
393 fn from_str(s: &str) -> Result<PrivateKey, Error> {
394 PrivateKey::from_wif(s)
395 }
396}
397
398impl ops::Index<ops::RangeFull> for PrivateKey {
399 type Output = [u8];
400 fn index(&self, _: ops::RangeFull) -> &[u8] {
401 &self.inner[..]
402 }
403}
404
405#[cfg(feature = "serde")]
406#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
407impl ::serde::Serialize for PrivateKey {
408 fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
409 s.collect_str(self)
410 }
411}
412
413#[cfg(feature = "serde")]
414#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
415impl<'de> ::serde::Deserialize<'de> for PrivateKey {
416 fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PrivateKey, D::Error> {
417 struct WifVisitor;
418
419 impl<'de> ::serde::de::Visitor<'de> for WifVisitor {
420 type Value = PrivateKey;
421
422 fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
423 formatter.write_str("an ASCII WIF string")
424 }
425
426 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
427 where
428 E: ::serde::de::Error,
429 {
430 if let Ok(s) = ::core::str::from_utf8(v) {
431 PrivateKey::from_str(s).map_err(E::custom)
432 } else {
433 Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
434 }
435 }
436
437 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
438 where
439 E: ::serde::de::Error,
440 {
441 PrivateKey::from_str(v).map_err(E::custom)
442 }
443 }
444
445 d.deserialize_str(WifVisitor)
446 }
447}
448
449#[cfg(feature = "serde")]
450#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
451impl ::serde::Serialize for PublicKey {
452 fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
453 if s.is_human_readable() {
454 s.collect_str(self)
455 } else {
456 if self.compressed {
457 s.serialize_bytes(&self.inner.serialize()[..])
458 } else {
459 s.serialize_bytes(&self.inner.serialize_uncompressed()[..])
460 }
461 }
462 }
463}
464
465#[cfg(feature = "serde")]
466#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
467impl<'de> ::serde::Deserialize<'de> for PublicKey {
468 fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
469 if d.is_human_readable() {
470 struct HexVisitor;
471
472 impl<'de> ::serde::de::Visitor<'de> for HexVisitor {
473 type Value = PublicKey;
474
475 fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
476 formatter.write_str("an ASCII hex string")
477 }
478
479 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
480 where
481 E: ::serde::de::Error,
482 {
483 if let Ok(hex) = ::core::str::from_utf8(v) {
484 PublicKey::from_str(hex).map_err(E::custom)
485 } else {
486 Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
487 }
488 }
489
490 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
491 where
492 E: ::serde::de::Error,
493 {
494 PublicKey::from_str(v).map_err(E::custom)
495 }
496 }
497 d.deserialize_str(HexVisitor)
498 } else {
499 struct BytesVisitor;
500
501 impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
502 type Value = PublicKey;
503
504 fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
505 formatter.write_str("a bytestring")
506 }
507
508 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
509 where
510 E: ::serde::de::Error,
511 {
512 PublicKey::from_slice(v).map_err(E::custom)
513 }
514 }
515
516 d.deserialize_bytes(BytesVisitor)
517 }
518 }
519}
520
521#[cfg(test)]
522mod tests {
523 use io;
524 use super::{PrivateKey, PublicKey};
525 use secp256k1::Secp256k1;
526 use std::str::FromStr;
527 use hashes::hex::ToHex;
528 use network::constants::Network::Testnet;
529 use network::constants::Network::Bitcoin;
530 use util::address::Address;
531
532 #[test]
533 fn test_key_derivation() {
534 let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
536 assert_eq!(sk.network, Testnet);
537 assert_eq!(sk.compressed, true);
538 assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
539
540 let secp = Secp256k1::new();
541 let pk = Address::p2pkh(&sk.public_key(&secp), sk.network);
542 assert_eq!(&pk.to_string(), "mqwpxxvfv3QbM8PU8uBx2jaNt9btQqvQNx");
543
544 assert_eq!(&sk.to_string(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
546 let sk_str =
547 PrivateKey::from_str("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
548 assert_eq!(&sk.to_wif(), &sk_str.to_wif());
549
550 let sk = PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap();
552 assert_eq!(sk.network, Bitcoin);
553 assert_eq!(sk.compressed, false);
554 assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3");
555
556 let secp = Secp256k1::new();
557 let mut pk = sk.public_key(&secp);
558 assert_eq!(pk.compressed, false);
559 assert_eq!(&pk.to_string(), "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133");
560 assert_eq!(pk, PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap());
561 let addr = Address::p2pkh(&pk, sk.network);
562 assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8");
563 pk.compressed = true;
564 assert_eq!(&pk.to_string(), "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af");
565 assert_eq!(pk, PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap());
566 }
567
568 #[test]
569 fn test_pubkey_hash() {
570 let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
571 let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
572 assert_eq!(pk.pubkey_hash().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
573 assert_eq!(upk.pubkey_hash().to_hex(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a");
574 }
575
576 #[test]
577 fn test_wpubkey_hash() {
578 let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
579 let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
580 assert_eq!(pk.wpubkey_hash().unwrap().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
581 assert_eq!(upk.wpubkey_hash(), None);
582 }
583
584 #[cfg(feature = "serde")]
585 #[test]
586 fn test_key_serde() {
587 use serde_test::{Configure, Token, assert_tokens};
588
589 static KEY_WIF: &'static str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy";
590 static PK_STR: &'static str = "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef";
591 static PK_STR_U: &'static str = "\
592 04\
593 9b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef\
594 87288ed73ce47fc4f5c79d19ebfa57da7cff3aff6e819e4ee971d86b5e61875d\
595 ";
596 static PK_BYTES: [u8; 33] = [
597 0x03,
598 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec,
599 0x93, 0x82, 0x6d, 0xc6, 0x1c, 0x19, 0xf4, 0x7c,
600 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e,
601 0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef,
602 ];
603 static PK_BYTES_U: [u8; 65] = [
604 0x04,
605 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec,
606 0x93, 0x82, 0x6d, 0xc6, 0x1c, 0x19, 0xf4, 0x7c,
607 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e,
608 0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef,
609 0x87, 0x28, 0x8e, 0xd7, 0x3c, 0xe4, 0x7f, 0xc4,
610 0xf5, 0xc7, 0x9d, 0x19, 0xeb, 0xfa, 0x57, 0xda,
611 0x7c, 0xff, 0x3a, 0xff, 0x6e, 0x81, 0x9e, 0x4e,
612 0xe9, 0x71, 0xd8, 0x6b, 0x5e, 0x61, 0x87, 0x5d,
613 ];
614
615 let s = Secp256k1::new();
616 let sk = PrivateKey::from_str(&KEY_WIF).unwrap();
617 let pk = PublicKey::from_private_key(&s, &sk);
618 let pk_u = PublicKey {
619 inner: pk.inner,
620 compressed: false,
621 };
622
623 assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]);
624 assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]);
625 assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]);
626 assert_tokens(&pk_u.compact(), &[Token::BorrowedBytes(&PK_BYTES_U[..])]);
627 assert_tokens(&pk_u.readable(), &[Token::BorrowedStr(PK_STR_U)]);
628
629 #[cfg(feature = "schemars")] {
630 {
631 let js = serde_json::from_str(&serde_json::to_string(&sk).unwrap()).unwrap();
632 let s = schemars::schema_for!(PrivateKey);
633 let string_schema = serde_json::to_string_pretty(&s).unwrap();
634 let schema = serde_json::from_str(&string_schema).unwrap();
635
636 assert!(jsonschema_valid::is_valid(&js, &schema, None, true));
637 }
638
639 {
640
641 let js = serde_json::from_str(&serde_json::to_string(&pk).unwrap()).unwrap();
642 let s = schemars::schema_for!(PublicKey);
643 let string_schema = serde_json::to_string_pretty(&s).unwrap();
644 let schema = serde_json::from_str(&string_schema).unwrap();
645
646 assert!(jsonschema_valid::is_valid(&js, &schema, None, true));
647 }
648
649 {
650
651 let js = serde_json::from_str(&serde_json::to_string(&pk_u).unwrap()).unwrap();
652 let s = schemars::schema_for!(PublicKey);
653 let string_schema = serde_json::to_string_pretty(&s).unwrap();
654 let schema = serde_json::from_str(&string_schema).unwrap();
655
656 assert!(jsonschema_valid::is_valid(&js, &schema, None, true));
657 }
658 }
659 }
660
661 fn random_key(mut seed: u8) -> PublicKey {
662 loop {
663 let mut data = [0; 65];
664 for byte in &mut data[..] {
665 *byte = seed;
666 seed = seed.wrapping_mul(41).wrapping_add(43);
668 }
669 if data[0] % 2 == 0 {
670 data[0] = 4;
671 if let Ok(key) = PublicKey::from_slice(&data[..]) {
672 return key;
673 }
674 } else {
675 data[0] = 2 + (data[0] >> 7);
676 if let Ok(key) = PublicKey::from_slice(&data[..33]) {
677 return key;
678 }
679 }
680 }
681 }
682
683 #[test]
684 fn pubkey_read_write() {
685 const N_KEYS: usize = 20;
686 let keys: Vec<_> = (0..N_KEYS).map(|i| random_key(i as u8)).collect();
687
688 let mut v = vec![];
689 for k in &keys {
690 k.write_into(&mut v).expect("writing into vec");
691 }
692
693 let mut dec_keys = vec![];
694 let mut cursor = io::Cursor::new(&v);
695 for _ in 0..N_KEYS {
696 dec_keys.push(PublicKey::read_from(&mut cursor).expect("reading from vec"));
697 }
698
699 assert_eq!(keys, dec_keys);
700
701 assert!(PublicKey::read_from(&mut cursor).is_err());
703 assert!(PublicKey::read_from(io::Cursor::new(&[])).is_err());
704 assert!(PublicKey::read_from(io::Cursor::new(&[0; 33][..])).is_err());
705 assert!(PublicKey::read_from(io::Cursor::new(&[2; 32][..])).is_err());
706 assert!(PublicKey::read_from(io::Cursor::new(&[0; 65][..])).is_err());
707 assert!(PublicKey::read_from(io::Cursor::new(&[4; 64][..])).is_err());
708 }
709}