#![allow(unused_assignments)]
use sodiumoxide::crypto;
use cbor::CborTagEncode;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::fmt;
use rand::random;
use sodiumoxide;
pub fn array_as_vector(arr: &[u8]) -> Vec<u8> {
let mut vector = Vec::new();
for i in arr.iter() {
vector.push(*i);
}
vector
}
pub fn vector_as_u8_64_array(vector: Vec<u8>) -> [u8;64] {
let mut arr = [0u8;64];
for i in (0..64) {
arr[i] = vector[i];
}
arr
}
pub fn vector_as_u8_32_array(vector: Vec<u8>) -> [u8;32] {
let mut arr = [0u8;32];
for i in (0..32) {
arr[i] = vector[i];
}
arr
}
pub fn generate_random_vec_u8(size: usize) -> Vec<u8> {
let mut vec: Vec<u8> = Vec::with_capacity(size);
for i in 0..size {
vec.push(random::<u8>());
}
vec
}
pub static GROUP_SIZE: u32 = 23;
pub static QUORUM_SIZE: u32 = 19;
#[derive(Default, PartialEq, Eq, Hash, Clone, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub struct DhtId(pub Vec<u8>);
impl DhtId {
pub fn new(array : &[u8; 64]) -> DhtId {
DhtId(array.to_vec())
}
pub fn from_data(data : &[u8]) -> DhtId {
DhtId::new(&crypto::hash::sha512::hash(data).0)
}
pub fn generate_random() -> DhtId {
DhtId(generate_random_vec_u8(64))
}
pub fn is_valid(&self) -> bool {
if self.0.len() != 64 {
return false;
}
for it in self.0.iter() {
if *it != 0 {
return true;
}
}
false
}
}
impl fmt::Debug for DhtId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let &DhtId(ref v) = self;
write!(f, "DhtId({:x}{:x})", v[0], v[1])
}
}
pub fn closer_to_target(lhs: &DhtId, rhs: &DhtId, target: &DhtId) -> bool {
for i in 0..lhs.0.len() {
let res_0 = lhs.0[i] ^ target.0[i];
let res_1 = rhs.0[i] ^ target.0[i];
if res_0 != res_1 {
return res_0 < res_1
}
}
false
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub enum Authority {
ClientManager, NaeManager, NodeManager, ManagedNode, ManagedClient, Client, Unknown
}
impl Encodable for Authority {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
let mut authority = "";
match *self {
Authority::ClientManager => authority = "ClientManager",
Authority::NaeManager => authority = "NaeManager",
Authority::NodeManager => authority = "NodeManager",
Authority::ManagedNode => authority = "ManagedNode",
Authority::ManagedClient => authority = "ManagedClient",
Authority::Client => authority = "Client",
Authority::Unknown => authority = "Unknown",
};
CborTagEncode::new(5483_100, &(&authority)).encode(e)
}
}
impl Decodable for Authority {
fn decode<D: Decoder>(d: &mut D)->Result<Authority, D::Error> {
try!(d.read_u64());
let mut authority : String = String::new();
authority = try!(Decodable::decode(d));
match &authority[..] {
"ClientManager" => Ok(Authority::ClientManager),
"NaeManager" => Ok(Authority::NaeManager),
"NodeManager" => Ok(Authority::NodeManager),
"ManagedNode" => Ok(Authority::ManagedNode),
"ManagedClient" => Ok(Authority::ManagedClient),
"Client" => Ok(Authority::Client),
_ => Ok(Authority::Unknown)
}
}
}
pub type MessageId = u32;
pub type NodeAddress = DhtId; pub type GroupAddress = DhtId; pub type SerialisedMessage = Vec<u8>;
pub type CloseGroupDifference = (Vec<DhtId>, Vec<DhtId>);
pub type PmidNode = DhtId;
pub type PmidNodes = Vec<PmidNode>;
pub type FilterType = (DhtId, MessageId);
pub trait RoutingTrait {
fn get_name(&self)->DhtId;
fn get_owner(&self)->Vec<u8>;
fn refresh(&self)->bool;
fn merge(&self, &Vec<AccountTransferInfo>) -> Option<AccountTransferInfo>;
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct NameAndTypeId {
pub name : Vec<u8>,
pub type_id : u32
}
impl NameAndTypeId {
pub fn generate_random() -> NameAndTypeId {
NameAndTypeId {
name: generate_random_vec_u8(64),
type_id: random::<u32>(),
}
}
}
impl Encodable for NameAndTypeId {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_000, &(&self.name, &self.type_id)).encode(e)
}
}
impl Decodable for NameAndTypeId {
fn decode<D: Decoder>(d: &mut D)->Result<NameAndTypeId, D::Error> {
try!(d.read_u64());
let (name, type_id) = try!(Decodable::decode(d));
Ok(NameAndTypeId { name: name, type_id: type_id })
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct Signature {
pub signature : Vec<u8>
}
impl Signature {
pub fn new(signature : crypto::sign::Signature) -> Signature {
assert_eq!(signature.0.len(), 32);
Signature{
signature : signature.0.to_vec()
}
}
pub fn generate_random() -> Signature {
Signature { signature: generate_random_vec_u8(32) }
}
pub fn get_crypto_signature(&self) -> crypto::sign::Signature {
crypto::sign::Signature(vector_as_u8_64_array(self.signature.clone()))
}
}
impl Encodable for Signature {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_000, &(&self.signature)).encode(e)
}
}
impl Decodable for Signature {
fn decode<D: Decoder>(d: &mut D)->Result<Signature, D::Error> {
try!(d.read_u64());
let signature = try!(Decodable::decode(d));
Ok(Signature { signature: signature })
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct PublicSignKey {
pub public_sign_key : Vec<u8>
}
impl PublicSignKey {
pub fn new(public_sign_key : crypto::sign::PublicKey) -> PublicSignKey {
assert_eq!(public_sign_key.0.len(), 32);
PublicSignKey{
public_sign_key : public_sign_key.0.to_vec()
}
}
pub fn generate_random() -> PublicSignKey {
PublicSignKey { public_sign_key: generate_random_vec_u8(32) }
}
pub fn get_crypto_public_sign_key(&self) -> crypto::sign::PublicKey {
crypto::sign::PublicKey(vector_as_u8_32_array(self.public_sign_key.clone()))
}
}
impl Encodable for PublicSignKey {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_000, &(&self.public_sign_key)).encode(e)
}
}
impl Decodable for PublicSignKey {
fn decode<D: Decoder>(d: &mut D)->Result<PublicSignKey, D::Error> {
try!(d.read_u64());
let public_sign_key = try!(Decodable::decode(d));
Ok(PublicSignKey { public_sign_key: public_sign_key })
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct PublicKey {
pub public_key : Vec<u8>
}
impl PublicKey {
pub fn new(public_key : crypto::asymmetricbox::PublicKey) -> PublicKey {
PublicKey{
public_key : public_key.0.to_vec()
}
}
pub fn generate_random() -> PublicKey {
PublicKey { public_key: generate_random_vec_u8(32) }
}
pub fn get_crypto_public_key(&self) -> crypto::asymmetricbox::PublicKey {
crypto::asymmetricbox::PublicKey(vector_as_u8_32_array(self.public_key.clone()))
}
}
impl Encodable for PublicKey {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_000, &(&self.public_key)).encode(e)
}
}
impl Decodable for PublicKey {
fn decode<D: Decoder>(d: &mut D)->Result<PublicKey, D::Error> {
try!(d.read_u64());
let public_key = try!(Decodable::decode(d));
Ok(PublicKey { public_key: public_key })
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct PublicPmid {
pub public_key: PublicKey,
pub public_sign_key: PublicSignKey,
pub validation_token: Signature,
pub name: DhtId
}
impl PublicPmid {
pub fn new(pmid : &Pmid) -> PublicPmid {
PublicPmid {
public_key : pmid.get_public_key(),
public_sign_key : pmid.get_public_sign_key(),
validation_token : pmid.get_validation_token(),
name : pmid.get_name()
}
}
pub fn generate_random() -> PublicPmid {
PublicPmid {
public_key : PublicKey::generate_random(),
public_sign_key : PublicSignKey::generate_random(),
validation_token : Signature::generate_random(),
name : DhtId::generate_random()
}
}
}
impl RoutingTrait for PublicPmid {
fn get_name(&self) -> DhtId { self.name.clone() }
fn get_owner(&self)->Vec<u8> { Vec::<u8>::new() } fn refresh(&self)->bool { false }
fn merge(&self, _ : &Vec<AccountTransferInfo>) -> Option<AccountTransferInfo> { None }
}
impl Encodable for PublicPmid {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_001, &(&self.public_key,
&self.public_sign_key,
&self.validation_token, &self.name)).encode(e)
}
}
impl Decodable for PublicPmid {
fn decode<D: Decoder>(d: &mut D)->Result<PublicPmid, D::Error> {
try!(d.read_u64());
let (public_key, public_sign_key,
validation_token, name) = try!(Decodable::decode(d));
Ok(PublicPmid { public_key: public_key,
public_sign_key : public_sign_key,
validation_token: validation_token, name : name })
}
}
#[derive(Clone)]
pub struct Pmid {
public_keys: (crypto::sign::PublicKey, crypto::asymmetricbox::PublicKey),
secret_keys: (crypto::sign::SecretKey, crypto::asymmetricbox::SecretKey),
validation_token: Signature,
name: DhtId
}
impl RoutingTrait for Pmid {
fn get_name(&self) -> DhtId { self.name.clone() }
fn get_owner(&self)->Vec<u8> { Vec::<u8>::new() } fn refresh(&self)->bool { false }
fn merge(&self, _ : &Vec<AccountTransferInfo>) -> Option<AccountTransferInfo> { None }
}
impl Pmid {
pub fn new() -> Pmid {
let (pub_sign_key, sec_sign_key) = sodiumoxide::crypto::sign::gen_keypair();
let (pub_asym_key, sec_asym_key) = sodiumoxide::crypto::asymmetricbox::gen_keypair();
let sign_arr = &pub_sign_key.0;
let asym_arr = &pub_asym_key.0;
let mut arr_combined = [0u8; 64 * 2];
for i in 0..sign_arr.len() {
arr_combined[i] = sign_arr[i];
}
for i in 0..asym_arr.len() {
arr_combined[64 + i] = asym_arr[i];
}
let validation_token = Signature{signature :
crypto::sign::sign(&arr_combined, &sec_sign_key)};
let digest = crypto::hash::sha512::hash(&arr_combined);
Pmid {
public_keys : (pub_sign_key, pub_asym_key),
secret_keys : (sec_sign_key, sec_asym_key),
validation_token : validation_token,
name : DhtId(digest.0.to_vec())
}
}
pub fn get_public_key(&self) -> PublicKey {
PublicKey::new(self.public_keys.1.clone())
}
pub fn get_public_sign_key(&self) -> PublicSignKey {
PublicSignKey::new(self.public_keys.0.clone())
}
pub fn get_crypto_public_key(&self) -> crypto::asymmetricbox::PublicKey {
self.public_keys.1.clone()
}
pub fn get_crypto_secret_key(&self) -> crypto::asymmetricbox::SecretKey {
self.secret_keys.1.clone()
}
pub fn get_crypto_public_sign_key(&self) -> crypto::sign::PublicKey {
self.public_keys.0.clone()
}
pub fn get_crypto_secret_sign_key(&self) -> crypto::sign::SecretKey {
self.secret_keys.0.clone()
}
pub fn get_validation_token(&self) -> Signature {
self.validation_token.clone()
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct AccountTransferInfo {
pub name : DhtId
}
impl Encodable for AccountTransferInfo {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_000, &(&self.name)).encode(e)
}
}
impl Decodable for AccountTransferInfo {
fn decode<D: Decoder>(d: &mut D)->Result<AccountTransferInfo, D::Error> {
try!(d.read_u64());
let name = try!(Decodable::decode(d));
Ok(AccountTransferInfo { name: name })
}
}
impl RoutingTrait for AccountTransferInfo {
fn get_name(&self)->DhtId { self.name.clone() }
fn get_owner(&self)->Vec<u8> { Vec::<u8>::new() } fn refresh(&self)->bool { true }
fn merge(&self, _ : &Vec<AccountTransferInfo>) -> Option<AccountTransferInfo> { None }
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct SourceAddress {
pub from_node : DhtId,
pub from_group : Option<DhtId>,
pub reply_to : Option<DhtId>
}
impl SourceAddress {
pub fn generate_random() -> SourceAddress {
SourceAddress {
from_node: DhtId::generate_random(),
from_group: None,
reply_to: None,
}
}
}
impl Encodable for SourceAddress {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_102 , &(&self.from_node, &self.from_group, &self.reply_to)).encode(e)
}
}
impl Decodable for SourceAddress {
fn decode<D: Decoder>(d: &mut D)->Result<SourceAddress, D::Error> {
try!(d.read_u64());
let (from_node, from_group, reply_to) = try!(Decodable::decode(d));
Ok(SourceAddress { from_node: from_node, from_group: from_group, reply_to: reply_to })
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub struct DestinationAddress {
pub dest : DhtId,
pub reply_to : Option<DhtId>
}
impl Encodable for DestinationAddress {
fn encode<E: Encoder>(&self, e: &mut E)->Result<(), E::Error> {
CborTagEncode::new(5483_101, &(&self.dest, &self.reply_to)).encode(e)
}
}
impl Decodable for DestinationAddress {
fn decode<D: Decoder>(d: &mut D)->Result<DestinationAddress, D::Error> {
try!(d.read_u64());
let (dest, reply_to) = try!(Decodable::decode(d));
Ok(DestinationAddress { dest: dest, reply_to: reply_to })
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
pub enum MessageTypeTag {
Connect,
ConnectResponse,
FindGroup,
FindGroupResponse,
GetData,
GetDataResponse,
GetClientKey,
GetClientKeyResponse,
GetGroupKey,
GetGroupKeyResponse,
Post,
PostResponse,
PutData,
PutDataResponse,
PutKey,
AccountTransfer
}
#[cfg(test)]
#[allow(deprecated)]
mod test {
extern crate cbor;
use super::*;
use rand::random;
use rustc_serialize::{Decodable, Encodable};
pub fn generate_address() -> Vec<u8> {
let mut address: Vec<u8> = vec![];
for _ in (0..64) {
address.push(random::<u8>());
}
address
}
fn test_object<T>(obj_before : T) where T: for<'a> Encodable + Decodable + Eq {
let mut e = cbor::Encoder::from_memory();
e.encode(&[&obj_before]).unwrap();
let mut d = cbor::Decoder::from_bytes(e.as_bytes());
let obj_after: T = d.decode().next().unwrap().unwrap();
assert_eq!(obj_after == obj_before, true)
}
#[test]
fn dhtid_from_data() {
use rustc_serialize::hex::ToHex;
let data = "this is a known string".to_string().into_bytes();
let expected_name = "8758b09d420bdb901d68fdd6888b38ce9ede06aad7f\
e1e0ea81feffc76260554b9d46fb6ea3b169ff8bb02\
ef14a03a122da52f3063bcb1bfb22cffc614def522".to_string();
assert_eq!(&expected_name, &DhtId::from_data(&data).0.to_hex());
}
#[test]
fn test_authority() {
test_object(Authority::ClientManager);
test_object(Authority::NaeManager);
test_object(Authority::NodeManager);
test_object(Authority::ManagedNode);
test_object(Authority::Client);
test_object(Authority::Unknown);
}
#[test]
fn test_destination_address() {
test_object(DestinationAddress { dest: DhtId::generate_random(), reply_to: None });
}
#[test]
fn test_source_address() {
test_object(SourceAddress { from_node : DhtId::generate_random(),
from_group : None,
reply_to: None });
}
}