mirror of
https://github.com/Revertron/Alfis
synced 2024-11-03 15:40:19 +00:00
Refactored a lot of cryptography. Moved from "rust-crypto" to https://github.com/RustCrypto
This commit is contained in:
parent
0d719324a9
commit
c5204aaed1
10
Cargo.toml
10
Cargo.toml
@ -14,8 +14,12 @@ getopts = "0.2.21"
|
||||
log = "0.4.14"
|
||||
simple_logger = "1.11.0"
|
||||
toml = "0.5.8"
|
||||
rust-crypto = "^0.2"
|
||||
blakeout = "0.1.0"
|
||||
digest = "0.9.0"
|
||||
sha2 = "0.9.3"
|
||||
ed25519-dalek = "1.0.1"
|
||||
signature = "1.3.0"
|
||||
#rust-crypto = "^0.2"
|
||||
blakeout = "0.3.0"
|
||||
num_cpus = "1.13.0"
|
||||
byteorder = "1.4.3"
|
||||
serde = { version = "1.0.123", features = ["derive"] }
|
||||
@ -24,6 +28,8 @@ num-bigint = "0.4.0"
|
||||
num-traits = "0.2.14"
|
||||
chrono = { version = "0.4.13", features = ["serde"] }
|
||||
rand = "0.8.3"
|
||||
# For ed25519-dalek
|
||||
rand-old = { package = "rand", version = "0.7.0" }
|
||||
sqlite = "0.25.3"
|
||||
uuid = { version = "0.8.2", features = ["serde", "v4"] }
|
||||
mio = { version = "0.7.10", features = ["os-poll", "net"] }
|
||||
|
@ -5,13 +5,14 @@ listen = "[::]:4244"
|
||||
public = false
|
||||
|
||||
# Bootstrap nodes
|
||||
peers = ["test-ip4.alfis.name:4244", "test-ip6.alfis.name:4244"]
|
||||
#peers = ["test-ip4.alfis.name:4244", "test-ip6.alfis.name:4244"]
|
||||
peers = ["[300:1251::1]:4244"]
|
||||
|
||||
# DNS server options
|
||||
[dns]
|
||||
listen = "127.0.0.1:5300"
|
||||
threads = 20
|
||||
#AdGuard DNS servers to filter ads and trackers
|
||||
forwarders = ["94.140.14.14:53", "94.140.15.15:53"]
|
||||
#forwarders = ["[301:2522::53]:53", "[301:2923::53]:53"]
|
||||
#forwarders = ["94.140.14.14:53", "94.140.15.15:53"]
|
||||
forwarders = ["[301:2522::53]:53", "[303:8b1a::53]:53"]
|
||||
#forwarders = ["[301:2522::53]:53", "[301:2923::53]:53", "94.140.14.14:53", "94.140.15.15:53"]
|
||||
|
@ -1,18 +1,9 @@
|
||||
use blakeout::Blakeout;
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha2::Sha256;
|
||||
use num_bigint::BigUint;
|
||||
use num_traits::One;
|
||||
|
||||
use crate::{Block, Bytes, Keystore};
|
||||
|
||||
/// Creates needed hasher by current blockchain version
|
||||
pub(crate) fn get_hasher_for_version(version: u32) -> Box<dyn Digest> {
|
||||
match version {
|
||||
2 => Box::new(Blakeout::default()),
|
||||
_ => Box::new(Sha256::new())
|
||||
}
|
||||
}
|
||||
use sha2::{Sha256, Digest};
|
||||
|
||||
/// Checks block's hash and returns true on valid hash or false otherwise
|
||||
pub fn check_block_hash(block: &Block) -> bool {
|
||||
@ -20,21 +11,14 @@ pub fn check_block_hash(block: &Block) -> bool {
|
||||
copy.hash = Bytes::default();
|
||||
copy.signature = Bytes::default();
|
||||
let data = serde_json::to_string(©).unwrap();
|
||||
let mut hasher = get_hasher_for_version(block.version);
|
||||
hash_data(&mut *hasher, data.as_bytes()) == block.hash
|
||||
blakeout_data(data.as_bytes()) == block.hash
|
||||
}
|
||||
|
||||
/// Hashes data by given hasher
|
||||
pub fn hash_data(digest: &mut dyn Digest, data: &[u8]) -> Bytes {
|
||||
let mut buf = match digest.output_bytes() {
|
||||
32 => Bytes::zero32(),
|
||||
64 => Bytes::zero64(),
|
||||
_ => panic!("Supplied wrong digest!")
|
||||
};
|
||||
|
||||
digest.input(data);
|
||||
digest.result(buf.as_mut_slice());
|
||||
buf
|
||||
pub fn blakeout_data(data: &[u8]) -> Bytes {
|
||||
let mut digest = Blakeout::default();
|
||||
digest.update(data);
|
||||
Bytes::from_bytes(digest.result())
|
||||
}
|
||||
|
||||
/// Checks block's signature, returns true if the signature is valid, false otherwise
|
||||
@ -47,14 +31,12 @@ pub fn check_block_signature(block: &Block) -> bool {
|
||||
/// Hashes some identity (domain in case of DNS). If you give it a public key, it will hash with it as well.
|
||||
/// Giving public key is needed to create a confirmation field in [Transaction]
|
||||
pub fn hash_identity(identity: &str, key: Option<&Bytes>) -> Bytes {
|
||||
let mut buf: [u8; 32] = [0; 32];
|
||||
let mut digest = Sha256::new();
|
||||
digest.input_str(identity);
|
||||
let mut digest = Sha256::default();
|
||||
digest.update(identity.as_bytes());
|
||||
if let Some(key) = key {
|
||||
digest.input(key.as_slice());
|
||||
digest.update(key.as_slice());
|
||||
}
|
||||
digest.result(&mut buf);
|
||||
Bytes::from_bytes(&buf)
|
||||
Bytes::from_bytes(&digest.finalize()[..])
|
||||
}
|
||||
|
||||
/// There is no default PartialEq implementation for arrays > 32 in size
|
||||
|
@ -1,9 +1,9 @@
|
||||
pub const CHAIN_VERSION: u32 = 1;
|
||||
pub const CHAIN_VERSION: u32 = 2;
|
||||
|
||||
pub const ZONE_DIFFICULTY: u32 = 28;
|
||||
pub const ZONE_DIFFICULTY: u32 = 26;
|
||||
pub const BLOCK_DIFFICULTY: u32 = 24;
|
||||
pub const LOCKER_DIFFICULTY: u32 = 18;
|
||||
pub const KEYSTORE_DIFFICULTY: usize = 25;
|
||||
pub const KEYSTORE_DIFFICULTY: usize = 23;
|
||||
|
||||
pub const LOCKER_BLOCK_START: u64 = 12;
|
||||
pub const LOCKER_BLOCK_LOCKERS: u64 = 6;
|
||||
|
88
src/keys.rs
88
src/keys.rs
@ -1,4 +1,5 @@
|
||||
extern crate crypto;
|
||||
extern crate rand;
|
||||
extern crate ed25519_dalek;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
@ -10,11 +11,9 @@ use std::path::Path;
|
||||
use std::sync::{Arc, atomic, Mutex};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||
|
||||
use crypto::ed25519::{keypair, signature, verify};
|
||||
use ed25519_dalek::Keypair;
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use rand::{Rng, RngCore, thread_rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::blockchain::hash_utils::*;
|
||||
use crate::Context;
|
||||
@ -22,40 +21,51 @@ use crate::event::Event;
|
||||
use crate::commons::KEYSTORE_DIFFICULTY;
|
||||
use crate::bytes::Bytes;
|
||||
use blakeout::Blakeout;
|
||||
use self::crypto::digest::Digest;
|
||||
use std::time::Instant;
|
||||
use std::cell::RefCell;
|
||||
use self::ed25519_dalek::{Signer, PublicKey, Verifier, SecretKey};
|
||||
use self::ed25519_dalek::ed25519::signature::Signature;
|
||||
use rand_old::{CryptoRng, RngCore};
|
||||
use rand_old::rngs::OsRng;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[derive(Debug)]
|
||||
pub struct Keystore {
|
||||
private_key: Bytes,
|
||||
public_key: Bytes,
|
||||
#[serde(skip)]
|
||||
keypair: Keypair,
|
||||
hash: RefCell<Bytes>,
|
||||
#[serde(skip)]
|
||||
path: String,
|
||||
#[serde(skip)]
|
||||
seed: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Keystore {
|
||||
pub fn new() -> Self {
|
||||
let mut buf = [0u8; 32];
|
||||
let mut rng = thread_rng();
|
||||
rng.fill(&mut buf);
|
||||
let (private, public) = keypair(&buf);
|
||||
Keystore { private_key: Bytes::from_bytes(&private), public_key: Bytes::from_bytes(&public), hash: RefCell::new(Bytes::default()), path: String::new(), seed: Vec::from(&buf[..]) }
|
||||
let mut csprng = OsRng::default();
|
||||
let keypair = ed25519_dalek::Keypair::generate(&mut csprng);
|
||||
Keystore { keypair, hash: RefCell::new(Bytes::default()), path: String::new() }
|
||||
}
|
||||
|
||||
pub fn from_random<R>(csprng: &mut R) -> Self where R: CryptoRng + RngCore {
|
||||
let keypair = ed25519_dalek::Keypair::generate(csprng);
|
||||
Keystore { keypair, hash: RefCell::new(Bytes::default()), path: String::new() }
|
||||
}
|
||||
|
||||
pub fn from_bytes(seed: &[u8]) -> Self {
|
||||
let (private, public) = keypair(&seed);
|
||||
Keystore { private_key: Bytes::from_bytes(&private), public_key: Bytes::from_bytes(&public), hash: RefCell::new(Bytes::default()), path: String::new(), seed: Vec::from(seed) }
|
||||
let keypair = Keypair::from_bytes(seed).expect("Error creating keypair from bytes!");
|
||||
Keystore { keypair, hash: RefCell::new(Bytes::default()), path: String::new() }
|
||||
}
|
||||
|
||||
pub fn from_random_bytes(key: &[u8]) -> Self {
|
||||
let secret = SecretKey::from_bytes(&key).unwrap();
|
||||
let public = PublicKey::from(&secret);
|
||||
let keypair = Keypair { secret, public };
|
||||
Keystore { keypair, hash: RefCell::new(Bytes::default()), path: String::new() }
|
||||
}
|
||||
|
||||
pub fn from_file(filename: &str, _password: &str) -> Option<Self> {
|
||||
let path = Path::new(filename);
|
||||
match fs::read(&path) {
|
||||
Ok(key) => {
|
||||
if key.len() == 32 {
|
||||
return Some(Keystore::from_random_bytes(key.as_slice()));
|
||||
}
|
||||
let mut keystore = Self::from_bytes(key.as_slice());
|
||||
keystore.path = path.to_str().unwrap().to_owned();
|
||||
Some(keystore)
|
||||
@ -66,12 +76,12 @@ impl Keystore {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Implement error conditions
|
||||
pub fn save(&mut self, filename: &str, _password: &str) {
|
||||
match File::create(Path::new(filename)) {
|
||||
Ok(mut f) => {
|
||||
//TODO implement key encryption
|
||||
f.write_all(&self.seed).expect("Error saving keystore");
|
||||
let bytes = self.keypair.to_bytes();
|
||||
f.write_all(&bytes).expect("Error saving keystore");
|
||||
self.path = filename.to_owned();
|
||||
}
|
||||
Err(_) => { error!("Error saving key file!"); }
|
||||
@ -79,11 +89,11 @@ impl Keystore {
|
||||
}
|
||||
|
||||
pub fn get_public(&self) -> Bytes {
|
||||
self.public_key.clone()
|
||||
Bytes::from_bytes(&self.keypair.public.to_bytes())
|
||||
}
|
||||
|
||||
pub fn get_private(&self) -> Bytes {
|
||||
self.private_key.clone()
|
||||
Bytes::from_bytes(&self.keypair.secret.to_bytes())
|
||||
}
|
||||
|
||||
pub fn get_path(&self) -> &str {
|
||||
@ -92,24 +102,36 @@ impl Keystore {
|
||||
|
||||
pub fn get_hash(&self) -> Bytes {
|
||||
if self.hash.borrow().is_empty() {
|
||||
self.hash.replace(hash_data(&mut Blakeout::default(), &self.public_key));
|
||||
self.hash.replace(blakeout_data(&self.get_public()));
|
||||
}
|
||||
self.hash.borrow().clone()
|
||||
}
|
||||
|
||||
pub fn sign(&self, message: &[u8]) -> [u8; 64] {
|
||||
signature(message, &self.private_key)
|
||||
self.keypair.sign(message).to_bytes()
|
||||
}
|
||||
|
||||
pub fn check(message: &[u8], public_key: &[u8], signature: &[u8]) -> bool {
|
||||
verify(message, public_key, signature)
|
||||
let key = PublicKey::from_bytes(public_key).expect("Wrong public key!");
|
||||
let signature = Signature::from_bytes(signature).unwrap();
|
||||
match key.verify(message, &signature) {
|
||||
Ok(_) => { true }
|
||||
Err(_) => { false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Keystore {
|
||||
fn clone(&self) -> Self {
|
||||
let keypair = Keypair::from_bytes(&self.keypair.to_bytes()).unwrap();
|
||||
Self { keypair, hash: RefCell::new(Bytes::default()), path: self.path.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if some public key is "strong" enough to mine domains
|
||||
/// TODO Optimize by caching Blakeout somewhere
|
||||
pub fn check_public_key_strength(key: &Bytes, strength: usize) -> bool {
|
||||
let bytes = hash_data(&mut Blakeout::default(), &key);
|
||||
let bytes = blakeout_data(&key);
|
||||
hash_is_good(&bytes, strength)
|
||||
}
|
||||
|
||||
@ -154,18 +176,18 @@ pub fn create_key(context: Arc<Mutex<Context>>) {
|
||||
}
|
||||
|
||||
fn generate_key(difficulty: usize, mining: Arc<AtomicBool>) -> Option<Keystore> {
|
||||
use self::rand::RngCore;
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut buf = [0u8; 32];
|
||||
let mut digest = Blakeout::default();
|
||||
let mut time = Instant::now();
|
||||
let mut count = 0u128;
|
||||
let mut digest = Blakeout::default();
|
||||
let mut buf = [0u8; 32];
|
||||
loop {
|
||||
rng.fill_bytes(&mut buf);
|
||||
let keystore = Keystore::from_bytes(&buf);
|
||||
let keystore = Keystore::from_random_bytes(&buf);
|
||||
digest.reset();
|
||||
digest.input(&keystore.public_key);
|
||||
digest.result(&mut buf);
|
||||
if hash_is_good(&buf, difficulty) {
|
||||
digest.update(keystore.get_public().as_slice());
|
||||
if hash_is_good(digest.result(), difficulty) {
|
||||
info!("Generated keypair with public key: {:?} and hash {:?}", &keystore.get_public(), &keystore.get_hash());
|
||||
return Some(keystore);
|
||||
}
|
||||
|
16
src/miner.rs
16
src/miner.rs
@ -4,7 +4,6 @@ use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use chrono::Utc;
|
||||
use crypto::digest::Digest;
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use num_cpus;
|
||||
@ -15,6 +14,7 @@ use crate::blockchain::enums::BlockQuality;
|
||||
use crate::blockchain::hash_utils::*;
|
||||
use crate::keys::check_public_key_strength;
|
||||
use crate::event::Event;
|
||||
use blakeout::Blakeout;
|
||||
|
||||
pub struct Miner {
|
||||
context: Arc<Mutex<Context>>,
|
||||
@ -149,8 +149,7 @@ impl Miner {
|
||||
let live_threads = Arc::clone(&live_threads);
|
||||
thread::spawn(move || {
|
||||
live_threads.fetch_add(1, Ordering::SeqCst);
|
||||
let mut hasher = get_hasher_for_version(block.version);
|
||||
match find_hash(Arc::clone(&context), &mut *hasher, block, Arc::clone(&mining)) {
|
||||
match find_hash(Arc::clone(&context), block, Arc::clone(&mining)) {
|
||||
None => {
|
||||
debug!("Mining was cancelled");
|
||||
let count = live_threads.fetch_sub(1, Ordering::SeqCst);
|
||||
@ -185,10 +184,10 @@ impl Miner {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_hash(context: Arc<Mutex<Context>>, digest: &mut dyn Digest, mut block: Block, running: Arc<AtomicBool>) -> Option<Block> {
|
||||
let mut buf: [u8; 32] = [0; 32];
|
||||
fn find_hash(context: Arc<Mutex<Context>>, mut block: Block, running: Arc<AtomicBool>) -> Option<Block> {
|
||||
let difficulty = block.difficulty as usize;
|
||||
let full = block.transaction.is_some();
|
||||
let mut digest = Blakeout::new();
|
||||
loop {
|
||||
block.random = rand::random();
|
||||
let next_allowed_block = {
|
||||
@ -215,10 +214,9 @@ fn find_hash(context: Arc<Mutex<Context>>, digest: &mut dyn Digest, mut block: B
|
||||
block.nonce = nonce;
|
||||
|
||||
digest.reset();
|
||||
digest.input(&block.as_bytes());
|
||||
digest.result(&mut buf);
|
||||
if hash_is_good(&buf, difficulty) {
|
||||
block.hash = Bytes::from_bytes(&buf);
|
||||
digest.update(&block.as_bytes());
|
||||
if hash_is_good(digest.result(), difficulty) {
|
||||
block.hash = Bytes::from_bytes(digest.result());
|
||||
return Some(block);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user