diff --git a/Cargo.toml b/Cargo.toml index 9ea458b63c1..bdd25c539a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ members = [ "misc/multiaddr", "misc/multihash", "misc/multistream-select", + "misc/peer-id-generator", "misc/rw-stream-sink", "transports/dns", "protocols/floodsub", diff --git a/misc/peer-id-generator/Cargo.toml b/misc/peer-id-generator/Cargo.toml new file mode 100644 index 00000000000..101d33153ea --- /dev/null +++ b/misc/peer-id-generator/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "peer-id-generator" +version = "0.1.0" +description = "Generate peer ids that are prefixed with a specific string" +authors = ["Parity Technologies "] +license = "MIT" + +[dependencies] +libp2p-core = { path = "../../core" } +libp2p-secio = { path = "../../protocols/secio" } +num_cpus = "1.8" +rand = "0.5" diff --git a/misc/peer-id-generator/src/main.rs b/misc/peer-id-generator/src/main.rs new file mode 100644 index 00000000000..ce1cfb57ed4 --- /dev/null +++ b/misc/peer-id-generator/src/main.rs @@ -0,0 +1,89 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +extern crate libp2p_core; +extern crate libp2p_secio; +extern crate num_cpus; +extern crate rand; + +use libp2p_core::PeerId; +use libp2p_secio::SecioKeyPair; +use std::{env, str, thread, time::Duration}; + +fn main() { + // Due to the fact that a peer id uses a SHA-256 multihash, it always starts with the + // bytes 0x1220, meaning that only some characters are valid. + const ALLOWED_FIRST_BYTE: &'static [u8] = b"NPQRSTUVWXYZ"; + + let prefix = + match env::args().nth(1) { + Some(prefix) => prefix, + None => { + println!( + "Usage: {} \n\n\ + Generates a peer id that starts with the chosen prefix using a secp256k1 public \ + key.\n\n\ + Prefix must be a sequence of characters in the base58 \ + alphabet, and must start with one of the following: {}", + env::current_exe().unwrap().file_name().unwrap().to_str().unwrap(), + str::from_utf8(ALLOWED_FIRST_BYTE).unwrap() + ); + return; + } + }; + + // The base58 alphabet is not necessarily obvious. + const ALPHABET: &'static [u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + if prefix.as_bytes().iter().any(|c| !ALPHABET.contains(c)) { + println!("Prefix {} is not valid base58", prefix); + return; + } + + // Checking conformity to ALLOWED_FIRST_BYTE. + if !prefix.is_empty() { + if !ALLOWED_FIRST_BYTE.contains(&prefix.as_bytes()[0]) { + println!("Prefix {} is not reachable", prefix); + println!( + "Only the following bytes are possible as first byte: {}", + str::from_utf8(ALLOWED_FIRST_BYTE).unwrap() + ); + return; + } + } + + // Find peer IDs in a multithreaded fashion. + for _ in 0..num_cpus::get() { + let prefix = prefix.clone(); + thread::spawn(move || loop { + let private_key: [u8; 32] = rand::random(); + let generated = SecioKeyPair::secp256k1_raw_key(private_key).unwrap(); + let peer_id: PeerId = generated.to_public_key().into_peer_id(); + let base58 = peer_id.to_base58(); + if base58[2..].starts_with(&prefix) { + println!("Found {:?}", peer_id); + println!("=> Private key = {:?}", private_key); + } + }); + } + + loop { + thread::sleep(Duration::from_secs(3600)); + } +}