2019-12-01 21:45:25 +00:00
|
|
|
extern crate crypto;
|
|
|
|
extern crate serde;
|
2021-01-17 23:18:35 +00:00
|
|
|
extern crate serde_json;
|
|
|
|
|
2019-12-01 21:45:25 +00:00
|
|
|
use crypto::ed25519::{keypair, signature, verify};
|
|
|
|
use rand::{thread_rng, Rng};
|
|
|
|
use std::fmt;
|
2021-02-16 21:06:03 +00:00
|
|
|
use std::fmt::{Error, Formatter};
|
2021-01-17 23:18:35 +00:00
|
|
|
use std::fs;
|
|
|
|
use std::fs::File;
|
2021-02-14 17:20:30 +00:00
|
|
|
use std::io::Write;
|
2019-12-01 21:45:25 +00:00
|
|
|
use std::path::Path;
|
|
|
|
use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
2019-12-02 15:33:19 +00:00
|
|
|
// For deserialization
|
|
|
|
use serde::de::{Error as DeError, Visitor};
|
2021-02-21 20:56:56 +00:00
|
|
|
#[allow(unused_imports)]
|
2021-02-20 15:28:10 +00:00
|
|
|
use log::{trace, debug, info, warn, error};
|
2021-01-17 23:18:35 +00:00
|
|
|
use crate::hash_is_good;
|
2021-03-02 17:11:17 +00:00
|
|
|
use std::cmp::Ordering;
|
|
|
|
use num_bigint::BigUint;
|
2021-03-06 20:28:06 +00:00
|
|
|
use std::convert::TryInto;
|
2019-12-01 21:45:25 +00:00
|
|
|
|
2019-12-02 15:33:19 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2020-04-18 19:31:40 +00:00
|
|
|
pub struct Keystore {
|
2021-01-17 23:18:35 +00:00
|
|
|
private_key: Bytes,
|
|
|
|
public_key: Bytes,
|
2020-04-18 19:31:40 +00:00
|
|
|
#[serde(skip)]
|
2021-02-15 22:09:30 +00:00
|
|
|
path: String,
|
|
|
|
#[serde(skip)]
|
2020-04-18 19:31:40 +00:00
|
|
|
seed: Vec<u8>
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
2020-04-18 19:31:40 +00:00
|
|
|
impl Keystore {
|
2019-12-01 21:45:25 +00:00
|
|
|
pub fn new() -> Self {
|
2021-02-14 17:20:30 +00:00
|
|
|
let mut buf = [0u8; 32];
|
2019-12-01 21:45:25 +00:00
|
|
|
let mut rng = thread_rng();
|
|
|
|
rng.fill(&mut buf);
|
|
|
|
let (private, public) = keypair(&buf);
|
2021-02-15 22:09:30 +00:00
|
|
|
Keystore {private_key: Bytes::from_bytes(&private), public_key: Bytes::from_bytes(&public), path: String::new(), seed: Vec::from(&buf[..])}
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_bytes(seed: &[u8]) -> Self {
|
|
|
|
let (private, public) = keypair(&seed);
|
2021-02-15 22:09:30 +00:00
|
|
|
Keystore {private_key: Bytes::from_bytes(&private), public_key: Bytes::from_bytes(&public), path: String::new(), seed: Vec::from(seed)}
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_file(filename: &str, _password: &str) -> Option<Self> {
|
2021-02-15 22:09:30 +00:00
|
|
|
let path = Path::new(filename);
|
|
|
|
match fs::read(&path) {
|
2019-12-01 21:45:25 +00:00
|
|
|
Ok(key) => {
|
2021-02-15 22:09:30 +00:00
|
|
|
let mut keystore = Self::from_bytes(key.as_slice());
|
|
|
|
keystore.path = path.to_str().unwrap().to_owned();
|
|
|
|
Some(keystore)
|
2019-12-01 21:45:25 +00:00
|
|
|
},
|
|
|
|
Err(_) => {
|
|
|
|
None
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
//TODO Implement error conditions
|
2021-02-15 22:09:30 +00:00
|
|
|
pub fn save(&mut self, filename: &str, _password: &str) {
|
2021-01-17 23:18:35 +00:00
|
|
|
match File::create(Path::new(filename)) {
|
|
|
|
Ok(mut f) => {
|
|
|
|
//TODO implement key encryption
|
2021-02-14 17:20:30 +00:00
|
|
|
f.write_all(&self.seed).expect("Error saving keystore");
|
2021-02-15 22:09:30 +00:00
|
|
|
self.path = filename.to_owned();
|
2021-01-17 23:18:35 +00:00
|
|
|
}
|
2021-02-20 15:28:10 +00:00
|
|
|
Err(_) => { error!("Error saving key file!"); }
|
2021-01-17 23:18:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_public(&self) -> Bytes {
|
2019-12-01 21:45:25 +00:00
|
|
|
self.public_key.clone()
|
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
pub fn get_private(&self) -> Bytes {
|
2019-12-01 21:45:25 +00:00
|
|
|
self.private_key.clone()
|
|
|
|
}
|
|
|
|
|
2021-02-15 22:09:30 +00:00
|
|
|
pub fn get_path(&self) -> &str {
|
|
|
|
&self.path
|
|
|
|
}
|
|
|
|
|
2019-12-01 21:45:25 +00:00
|
|
|
pub fn sign(&self, message: &[u8]) -> [u8; 64] {
|
2021-02-14 17:20:30 +00:00
|
|
|
signature(message, self.private_key.data.as_slice())
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
2021-02-14 17:20:30 +00:00
|
|
|
pub fn check(message: &[u8], public_key: &[u8], signature: &[u8]) -> bool {
|
2019-12-02 15:33:19 +00:00
|
|
|
verify(message, public_key, signature)
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
2021-01-17 23:18:35 +00:00
|
|
|
|
|
|
|
pub fn hash_is_good(&self, difficulty: usize) -> bool {
|
|
|
|
hash_is_good(self.public_key.as_bytes(), difficulty)
|
|
|
|
}
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
2019-12-02 15:33:19 +00:00
|
|
|
#[derive(Clone)]
|
2021-01-17 23:18:35 +00:00
|
|
|
pub struct Bytes {
|
2019-12-02 15:33:19 +00:00
|
|
|
data: Vec<u8>
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
impl Bytes {
|
2019-12-02 15:33:19 +00:00
|
|
|
pub fn new(data: Vec<u8>) -> Self {
|
2021-01-17 23:18:35 +00:00
|
|
|
Bytes { data }
|
2019-12-02 15:33:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_bytes(data: &[u8]) -> Self {
|
2021-01-17 23:18:35 +00:00
|
|
|
Bytes { data: Vec::from(data) }
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn length(&self) -> usize {
|
|
|
|
self.data.len()
|
|
|
|
}
|
|
|
|
|
2019-12-02 15:33:19 +00:00
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.data.is_empty()
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 17:34:43 +00:00
|
|
|
pub fn is_zero(&self) -> bool {
|
|
|
|
if self.data.is_empty() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
for x in self.data.iter() {
|
|
|
|
if *x != 0 {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-12-02 15:33:19 +00:00
|
|
|
/// Returns a byte slice of the hash contents.
|
|
|
|
pub fn as_bytes(&self) -> &[u8] {
|
2021-02-14 17:20:30 +00:00
|
|
|
self.data.as_slice()
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
2021-02-15 22:09:30 +00:00
|
|
|
pub fn to_string(&self) -> String {
|
|
|
|
crate::utils::to_hex(&self.data)
|
|
|
|
}
|
|
|
|
|
2021-03-06 20:28:06 +00:00
|
|
|
pub fn get_tail_u64(&self) -> u64 {
|
|
|
|
let index = self.data.len() - 8;
|
|
|
|
let bytes: [u8; 8] = self.data[index..].try_into().unwrap();
|
|
|
|
u64::from_be_bytes(bytes)
|
|
|
|
}
|
|
|
|
|
2019-12-02 15:33:19 +00:00
|
|
|
pub fn zero32() -> Self {
|
2021-01-17 23:18:35 +00:00
|
|
|
Bytes { data: [0u8; 32].to_vec() }
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
2019-12-02 15:33:19 +00:00
|
|
|
pub fn zero64() -> Self {
|
2021-01-17 23:18:35 +00:00
|
|
|
Bytes { data: [0u8; 64].to_vec() }
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
impl Default for Bytes {
|
|
|
|
fn default() -> Bytes {
|
|
|
|
Bytes { data: Vec::new() }
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
impl PartialEq for Bytes {
|
2019-12-01 21:45:25 +00:00
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
crate::utils::same_hash(&self.data, &other.data)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn ne(&self, other: &Self) -> bool {
|
|
|
|
!crate::utils::same_hash(&self.data, &other.data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-02 17:11:17 +00:00
|
|
|
impl Eq for Bytes {}
|
|
|
|
|
|
|
|
impl PartialOrd for Bytes {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
let self_hash_int = BigUint::from_bytes_be(&self.data);
|
|
|
|
let other_hash_int = BigUint::from_bytes_be(&other.data);
|
|
|
|
Some(self_hash_int.cmp(&other_hash_int))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ord for Bytes {
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
|
|
let self_hash_int = BigUint::from_bytes_be(&self.data);
|
|
|
|
let other_hash_int = BigUint::from_bytes_be(&other.data);
|
|
|
|
self_hash_int.cmp(&other_hash_int)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
impl fmt::Debug for Bytes {
|
2019-12-01 21:45:25 +00:00
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fmt.write_str(&crate::utils::to_hex(&self.data))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
impl Serialize for Bytes {
|
2019-12-01 21:45:25 +00:00
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error> where
|
|
|
|
S: Serializer {
|
|
|
|
serializer.serialize_str(&crate::utils::to_hex(&self.data))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
struct BytesVisitor;
|
2019-12-01 21:45:25 +00:00
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
impl<'de> Visitor<'de> for BytesVisitor {
|
|
|
|
type Value = Bytes;
|
2019-12-01 21:45:25 +00:00
|
|
|
|
|
|
|
fn expecting(&self, formatter: &mut Formatter) -> Result<(), Error> {
|
2019-12-02 15:33:19 +00:00
|
|
|
formatter.write_str("32 or 64 bytes")
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
|
2019-12-02 15:33:19 +00:00
|
|
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: DeError, {
|
|
|
|
if value.len() == 64 || value.len() == 128 {
|
2021-01-17 23:18:35 +00:00
|
|
|
Ok(Bytes::new(crate::from_hex(value).unwrap()))
|
2019-12-01 21:45:25 +00:00
|
|
|
} else {
|
2019-12-02 15:33:19 +00:00
|
|
|
Err(E::custom("Key must be 32 or 64 bytes!"))
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-02 15:33:19 +00:00
|
|
|
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E> where E: DeError, {
|
|
|
|
if value.len() == 32 || value.len() == 64 {
|
2021-01-17 23:18:35 +00:00
|
|
|
Ok(Bytes::from_bytes(value))
|
2019-12-01 21:45:25 +00:00
|
|
|
} else {
|
2019-12-02 15:33:19 +00:00
|
|
|
Err(E::custom("Key must be 32 or 64 bytes!"))
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 23:18:35 +00:00
|
|
|
impl<'dd> Deserialize<'dd> for Bytes {
|
2019-12-02 15:33:19 +00:00
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'dd>>::Error> where D: Deserializer<'dd> {
|
2021-01-17 23:18:35 +00:00
|
|
|
deserializer.deserialize_str(BytesVisitor)
|
2019-12-01 21:45:25 +00:00
|
|
|
}
|
|
|
|
}
|
2021-02-14 17:20:30 +00:00
|
|
|
|
2021-02-20 15:28:10 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2021-03-06 20:28:06 +00:00
|
|
|
use crate::{Keystore, Bytes};
|
2021-02-21 20:56:56 +00:00
|
|
|
|
2021-02-20 15:28:10 +00:00
|
|
|
#[test]
|
|
|
|
pub fn test_signature() {
|
|
|
|
let keystore: Keystore = Keystore::new();
|
|
|
|
let data = b"{ identity: 178135D209C697625E3EC71DA5C760382E54936F824EE5083908DA66B14ECE18,\
|
2021-02-14 17:20:30 +00:00
|
|
|
confirmation: A4A0AFECD1A511825226F0D3437C6C6BDAE83554040AA7AEB49DEFEAB0AE9EA4 }";
|
2021-02-20 15:28:10 +00:00
|
|
|
let signature = keystore.sign(data);
|
|
|
|
assert!(Keystore::check(data, keystore.get_public().as_bytes(), &signature), "Wrong signature!")
|
|
|
|
}
|
2021-03-06 20:28:06 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
pub fn test_tail_bytes() {
|
|
|
|
let bytes = Bytes::new(vec![0,255,255,255]);
|
|
|
|
assert_eq!(bytes.get_tail_u64(), 16777215);
|
|
|
|
}
|
2021-02-20 15:28:10 +00:00
|
|
|
}
|