diff --git a/core/src/lib.rs b/core/src/lib.rs index 51b64ee3..c60b3931 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -226,6 +226,7 @@ pub extern crate multiaddr; mod connection_reuse; mod peer_id; +mod public_key; pub mod either; pub mod muxing; @@ -236,7 +237,8 @@ pub mod upgrade; pub use self::connection_reuse::ConnectionReuse; pub use self::multiaddr::{AddrComponent, Multiaddr}; pub use self::muxing::StreamMuxer; -pub use self::peer_id::{PeerId, PublicKeyBytes, PublicKeyBytesSlice}; +pub use self::peer_id::PeerId; +pub use self::public_key::{PublicKey, PublicKeyBytes, PublicKeyBytesSlice}; pub use self::swarm::{swarm, SwarmController, SwarmFuture}; pub use self::transport::{MuxedTransport, Transport}; pub use self::upgrade::{ConnectionUpgrade, Endpoint}; diff --git a/core/src/peer_id.rs b/core/src/peer_id.rs index 789fce89..e0bf0d31 100644 --- a/core/src/peer_id.rs +++ b/core/src/peer_id.rs @@ -21,56 +21,7 @@ use bs58; use multihash; use std::{fmt, str::FromStr}; - -/// The raw bytes of a public key. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct PublicKeyBytes(pub Vec); - -impl PublicKeyBytes { - /// Turns this into a `PublicKeyBytesSlice`. - #[inline] - pub fn as_slice(&self) -> PublicKeyBytesSlice { - PublicKeyBytesSlice(&self.0) - } - - /// Turns this into a `PeerId`. - #[inline] - pub fn to_peer_id(&self) -> PeerId { - self.as_slice().into() - } -} - -/// The raw bytes of a public key. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct PublicKeyBytesSlice<'a>(pub &'a [u8]); - -impl<'a> PublicKeyBytesSlice<'a> { - /// Turns this into a `PublicKeyBytes`. - #[inline] - pub fn to_owned(&self) -> PublicKeyBytes { - PublicKeyBytes(self.0.to_owned()) - } - - /// Turns this into a `PeerId`. - #[inline] - pub fn to_peer_id(&self) -> PeerId { - PeerId::from_public_key(*self) - } -} - -impl<'a> PartialEq for PublicKeyBytesSlice<'a> { - #[inline] - fn eq(&self, other: &PublicKeyBytes) -> bool { - self.0 == &other.0[..] - } -} - -impl<'a> PartialEq> for PublicKeyBytes { - #[inline] - fn eq(&self, other: &PublicKeyBytesSlice<'a>) -> bool { - self.0 == &other.0[..] - } -} +use {PublicKeyBytes, PublicKeyBytesSlice}; /// Identifier of a peer of the network. /// diff --git a/core/src/public_key.rs b/core/src/public_key.rs new file mode 100644 index 00000000..8af95939 --- /dev/null +++ b/core/src/public_key.rs @@ -0,0 +1,126 @@ +// 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. + +use PeerId; + +/// Public key used by the remote. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum PublicKey { + /// DER format. + Rsa(Vec), + /// Format = ??? + // TODO: ^ + Ed25519(Vec), + /// Format = ??? + // TODO: ^ + Secp256k1(Vec), +} + +impl PublicKey { + /// Turns this public key into a raw representation. + #[inline] + pub fn as_raw(&self) -> PublicKeyBytesSlice { + match self { + PublicKey::Rsa(ref data) => PublicKeyBytesSlice(data), + PublicKey::Ed25519(ref data) => PublicKeyBytesSlice(data), + PublicKey::Secp256k1(ref data) => PublicKeyBytesSlice(data), + } + } + + /// Turns this public key into a raw representation. + #[inline] + pub fn into_raw(self) -> PublicKeyBytes { + match self { + PublicKey::Rsa(data) => PublicKeyBytes(data), + PublicKey::Ed25519(data) => PublicKeyBytes(data), + PublicKey::Secp256k1(data) => PublicKeyBytes(data), + } + } + + /// Builds a `PeerId` corresponding to the public key of the node. + #[inline] + pub fn to_peer_id(&self) -> PeerId { + self.as_raw().into() + } +} + +impl From for PeerId { + #[inline] + fn from(key: PublicKey) -> PeerId { + key.to_peer_id() + } +} + +impl From for PublicKeyBytes { + #[inline] + fn from(key: PublicKey) -> PublicKeyBytes { + key.into_raw() + } +} + +/// The raw bytes of a public key. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PublicKeyBytes(pub Vec); + +impl PublicKeyBytes { + /// Turns this into a `PublicKeyBytesSlice`. + #[inline] + pub fn as_slice(&self) -> PublicKeyBytesSlice { + PublicKeyBytesSlice(&self.0) + } + + /// Turns this into a `PeerId`. + #[inline] + pub fn to_peer_id(&self) -> PeerId { + self.as_slice().into() + } +} + +/// The raw bytes of a public key. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct PublicKeyBytesSlice<'a>(pub &'a [u8]); + +impl<'a> PublicKeyBytesSlice<'a> { + /// Turns this into a `PublicKeyBytes`. + #[inline] + pub fn to_owned(&self) -> PublicKeyBytes { + PublicKeyBytes(self.0.to_owned()) + } + + /// Turns this into a `PeerId`. + #[inline] + pub fn to_peer_id(&self) -> PeerId { + PeerId::from_public_key(*self) + } +} + +impl<'a> PartialEq for PublicKeyBytesSlice<'a> { + #[inline] + fn eq(&self, other: &PublicKeyBytes) -> bool { + self.0 == &other.0[..] + } +} + +impl<'a> PartialEq> for PublicKeyBytes { + #[inline] + fn eq(&self, other: &PublicKeyBytesSlice<'a>) -> bool { + self.0 == &other.0[..] + } +} diff --git a/identify/keys.proto b/identify/keys.proto new file mode 100644 index 00000000..786c7a74 --- /dev/null +++ b/identify/keys.proto @@ -0,0 +1,15 @@ +enum KeyType { + RSA = 0; + Ed25519 = 1; + Secp256k1 = 2; +} + +message PublicKey { + required KeyType Type = 1; + required bytes Data = 2; +} + +message PrivateKey { + required KeyType Type = 1; + required bytes Data = 2; +} \ No newline at end of file diff --git a/identify/regen_structs_proto.sh b/identify/regen_structs_proto.sh index 7210eb97..948def96 100755 --- a/identify/regen_structs_proto.sh +++ b/identify/regen_structs_proto.sh @@ -7,6 +7,8 @@ sudo docker run --rm -v `pwd`:/usr/code:z -w /usr/code rust /bin/bash -c " \ apt-get update; \ apt-get install -y protobuf-compiler; \ cargo install --version 1 protobuf; \ - protoc --rust_out . structs.proto" + protoc --rust_out . structs.proto; \ + protoc --rust_out . keys.proto" mv -f structs.rs ./src/structs_proto.rs +mv -f keys.rs ./src/keys_proto.rs diff --git a/identify/src/keys_proto.rs b/identify/src/keys_proto.rs new file mode 100644 index 00000000..ff5ed486 --- /dev/null +++ b/identify/src/keys_proto.rs @@ -0,0 +1,593 @@ +// This file is generated. Do not edit +// @generated + +// https://github.com/Manishearth/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy)] + +#![cfg_attr(rustfmt, rustfmt_skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unsafe_code)] +#![allow(unused_imports)] +#![allow(unused_results)] + +use protobuf::Message as Message_imported_for_functions; +use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions; + +#[derive(PartialEq,Clone,Default)] +pub struct PublicKey { + // message fields + Type: ::std::option::Option, + Data: ::protobuf::SingularField<::std::vec::Vec>, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +// see codegen.rs for the explanation why impl Sync explicitly +unsafe impl ::std::marker::Sync for PublicKey {} + +impl PublicKey { + pub fn new() -> PublicKey { + ::std::default::Default::default() + } + + pub fn default_instance() -> &'static PublicKey { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const PublicKey, + }; + unsafe { + instance.get(PublicKey::new) + } + } + + // required .KeyType Type = 1; + + pub fn clear_Type(&mut self) { + self.Type = ::std::option::Option::None; + } + + pub fn has_Type(&self) -> bool { + self.Type.is_some() + } + + // Param is passed by value, moved + pub fn set_Type(&mut self, v: KeyType) { + self.Type = ::std::option::Option::Some(v); + } + + pub fn get_Type(&self) -> KeyType { + self.Type.unwrap_or(KeyType::RSA) + } + + fn get_Type_for_reflect(&self) -> &::std::option::Option { + &self.Type + } + + fn mut_Type_for_reflect(&mut self) -> &mut ::std::option::Option { + &mut self.Type + } + + // required bytes Data = 2; + + pub fn clear_Data(&mut self) { + self.Data.clear(); + } + + pub fn has_Data(&self) -> bool { + self.Data.is_some() + } + + // Param is passed by value, moved + pub fn set_Data(&mut self, v: ::std::vec::Vec) { + self.Data = ::protobuf::SingularField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_Data(&mut self) -> &mut ::std::vec::Vec { + if self.Data.is_none() { + self.Data.set_default(); + } + self.Data.as_mut().unwrap() + } + + // Take field + pub fn take_Data(&mut self) -> ::std::vec::Vec { + self.Data.take().unwrap_or_else(|| ::std::vec::Vec::new()) + } + + pub fn get_Data(&self) -> &[u8] { + match self.Data.as_ref() { + Some(v) => &v, + None => &[], + } + } + + fn get_Data_for_reflect(&self) -> &::protobuf::SingularField<::std::vec::Vec> { + &self.Data + } + + fn mut_Data_for_reflect(&mut self) -> &mut ::protobuf::SingularField<::std::vec::Vec> { + &mut self.Data + } +} + +impl ::protobuf::Message for PublicKey { + fn is_initialized(&self) -> bool { + if self.Type.is_none() { + return false; + } + if self.Data.is_none() { + return false; + } + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_proto2_enum_with_unknown_fields_into(wire_type, is, &mut self.Type, 1, &mut self.unknown_fields)? + }, + 2 => { + ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.Data)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if let Some(v) = self.Type { + my_size += ::protobuf::rt::enum_size(1, v); + } + if let Some(ref v) = self.Data.as_ref() { + my_size += ::protobuf::rt::bytes_size(2, &v); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if let Some(v) = self.Type { + os.write_enum(1, v.value())?; + } + if let Some(ref v) = self.Data.as_ref() { + os.write_bytes(2, &v)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + ::protobuf::MessageStatic::descriptor_static(None::) + } +} + +impl ::protobuf::MessageStatic for PublicKey { + fn new() -> PublicKey { + PublicKey::new() + } + + fn descriptor_static(_: ::std::option::Option) -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_option_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "Type", + PublicKey::get_Type_for_reflect, + PublicKey::mut_Type_for_reflect, + )); + fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "Data", + PublicKey::get_Data_for_reflect, + PublicKey::mut_Data_for_reflect, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "PublicKey", + fields, + file_descriptor_proto() + ) + }) + } + } +} + +impl ::protobuf::Clear for PublicKey { + fn clear(&mut self) { + self.clear_Type(); + self.clear_Data(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for PublicKey { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for PublicKey { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct PrivateKey { + // message fields + Type: ::std::option::Option, + Data: ::protobuf::SingularField<::std::vec::Vec>, + // special fields + unknown_fields: ::protobuf::UnknownFields, + cached_size: ::protobuf::CachedSize, +} + +// see codegen.rs for the explanation why impl Sync explicitly +unsafe impl ::std::marker::Sync for PrivateKey {} + +impl PrivateKey { + pub fn new() -> PrivateKey { + ::std::default::Default::default() + } + + pub fn default_instance() -> &'static PrivateKey { + static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const PrivateKey, + }; + unsafe { + instance.get(PrivateKey::new) + } + } + + // required .KeyType Type = 1; + + pub fn clear_Type(&mut self) { + self.Type = ::std::option::Option::None; + } + + pub fn has_Type(&self) -> bool { + self.Type.is_some() + } + + // Param is passed by value, moved + pub fn set_Type(&mut self, v: KeyType) { + self.Type = ::std::option::Option::Some(v); + } + + pub fn get_Type(&self) -> KeyType { + self.Type.unwrap_or(KeyType::RSA) + } + + fn get_Type_for_reflect(&self) -> &::std::option::Option { + &self.Type + } + + fn mut_Type_for_reflect(&mut self) -> &mut ::std::option::Option { + &mut self.Type + } + + // required bytes Data = 2; + + pub fn clear_Data(&mut self) { + self.Data.clear(); + } + + pub fn has_Data(&self) -> bool { + self.Data.is_some() + } + + // Param is passed by value, moved + pub fn set_Data(&mut self, v: ::std::vec::Vec) { + self.Data = ::protobuf::SingularField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_Data(&mut self) -> &mut ::std::vec::Vec { + if self.Data.is_none() { + self.Data.set_default(); + } + self.Data.as_mut().unwrap() + } + + // Take field + pub fn take_Data(&mut self) -> ::std::vec::Vec { + self.Data.take().unwrap_or_else(|| ::std::vec::Vec::new()) + } + + pub fn get_Data(&self) -> &[u8] { + match self.Data.as_ref() { + Some(v) => &v, + None => &[], + } + } + + fn get_Data_for_reflect(&self) -> &::protobuf::SingularField<::std::vec::Vec> { + &self.Data + } + + fn mut_Data_for_reflect(&mut self) -> &mut ::protobuf::SingularField<::std::vec::Vec> { + &mut self.Data + } +} + +impl ::protobuf::Message for PrivateKey { + fn is_initialized(&self) -> bool { + if self.Type.is_none() { + return false; + } + if self.Data.is_none() { + return false; + } + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_proto2_enum_with_unknown_fields_into(wire_type, is, &mut self.Type, 1, &mut self.unknown_fields)? + }, + 2 => { + ::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.Data)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if let Some(v) = self.Type { + my_size += ::protobuf::rt::enum_size(1, v); + } + if let Some(ref v) = self.Data.as_ref() { + my_size += ::protobuf::rt::bytes_size(2, &v); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { + if let Some(v) = self.Type { + os.write_enum(1, v.value())?; + } + if let Some(ref v) = self.Data.as_ref() { + os.write_bytes(2, &v)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &::std::any::Any { + self as &::std::any::Any + } + fn as_any_mut(&mut self) -> &mut ::std::any::Any { + self as &mut ::std::any::Any + } + fn into_any(self: Box) -> ::std::boxed::Box<::std::any::Any> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + ::protobuf::MessageStatic::descriptor_static(None::) + } +} + +impl ::protobuf::MessageStatic for PrivateKey { + fn new() -> PrivateKey { + PrivateKey::new() + } + + fn descriptor_static(_: ::std::option::Option) -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_option_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "Type", + PrivateKey::get_Type_for_reflect, + PrivateKey::mut_Type_for_reflect, + )); + fields.push(::protobuf::reflect::accessor::make_singular_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( + "Data", + PrivateKey::get_Data_for_reflect, + PrivateKey::mut_Data_for_reflect, + )); + ::protobuf::reflect::MessageDescriptor::new::( + "PrivateKey", + fields, + file_descriptor_proto() + ) + }) + } + } +} + +impl ::protobuf::Clear for PrivateKey { + fn clear(&mut self) { + self.clear_Type(); + self.clear_Data(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for PrivateKey { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for PrivateKey { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +#[derive(Clone,PartialEq,Eq,Debug,Hash)] +pub enum KeyType { + RSA = 0, + Ed25519 = 1, + Secp256k1 = 2, +} + +impl ::protobuf::ProtobufEnum for KeyType { + fn value(&self) -> i32 { + *self as i32 + } + + fn from_i32(value: i32) -> ::std::option::Option { + match value { + 0 => ::std::option::Option::Some(KeyType::RSA), + 1 => ::std::option::Option::Some(KeyType::Ed25519), + 2 => ::std::option::Option::Some(KeyType::Secp256k1), + _ => ::std::option::Option::None + } + } + + fn values() -> &'static [Self] { + static values: &'static [KeyType] = &[ + KeyType::RSA, + KeyType::Ed25519, + KeyType::Secp256k1, + ]; + values + } + + fn enum_descriptor_static(_: ::std::option::Option) -> &'static ::protobuf::reflect::EnumDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::EnumDescriptor, + }; + unsafe { + descriptor.get(|| { + ::protobuf::reflect::EnumDescriptor::new("KeyType", file_descriptor_proto()) + }) + } + } +} + +impl ::std::marker::Copy for KeyType { +} + +impl ::protobuf::reflect::ProtobufValue for KeyType { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Enum(self.descriptor()) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\nkeys.proto\"=\n\tPublicKey\x12\x1c\n\x04Type\x18\x01\x20\x02(\x0e2\ + \x08.KeyTypeR\x04type\x12\x12\n\x04Data\x18\x02\x20\x02(\x0cR\x04data\">\ + \n\nPrivateKey\x12\x1c\n\x04Type\x18\x01\x20\x02(\x0e2\x08.KeyTypeR\x04t\ + ype\x12\x12\n\x04Data\x18\x02\x20\x02(\x0cR\x04data*.\n\x07KeyType\x12\ + \x07\n\x03RSA\x10\0\x12\x0b\n\x07Ed25519\x10\x01\x12\r\n\tSecp256k1\x10\ + \x02J\xdf\x03\n\x06\x12\x04\0\0\x0e\x01\n\n\n\x02\x05\0\x12\x04\0\0\x04\ + \x01\n\n\n\x03\x05\0\x01\x12\x03\0\x05\x0c\n\x0b\n\x04\x05\0\x02\0\x12\ + \x03\x01\x02\n\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x01\x02\x05\n\x0c\n\ + \x05\x05\0\x02\0\x02\x12\x03\x01\x08\t\n\x0b\n\x04\x05\0\x02\x01\x12\x03\ + \x02\x02\x0e\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x02\x02\t\n\x0c\n\x05\ + \x05\0\x02\x01\x02\x12\x03\x02\x0c\r\n\x0b\n\x04\x05\0\x02\x02\x12\x03\ + \x03\x02\x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x03\x02\x0b\n\x0c\n\ + \x05\x05\0\x02\x02\x02\x12\x03\x03\x0e\x0f\n\n\n\x02\x04\0\x12\x04\x06\0\ + \t\x01\n\n\n\x03\x04\0\x01\x12\x03\x06\x08\x11\n\x0b\n\x04\x04\0\x02\0\ + \x12\x03\x07\x02\x1c\n\x0c\n\x05\x04\0\x02\0\x04\x12\x03\x07\x02\n\n\x0c\ + \n\x05\x04\0\x02\0\x06\x12\x03\x07\x0b\x12\n\x0c\n\x05\x04\0\x02\0\x01\ + \x12\x03\x07\x13\x17\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x07\x1a\x1b\n\ + \x0b\n\x04\x04\0\x02\x01\x12\x03\x08\x02\x1a\n\x0c\n\x05\x04\0\x02\x01\ + \x04\x12\x03\x08\x02\n\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x08\x0b\x10\ + \n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x08\x11\x15\n\x0c\n\x05\x04\0\x02\ + \x01\x03\x12\x03\x08\x18\x19\n\n\n\x02\x04\x01\x12\x04\x0b\0\x0e\x01\n\n\ + \n\x03\x04\x01\x01\x12\x03\x0b\x08\x12\n\x0b\n\x04\x04\x01\x02\0\x12\x03\ + \x0c\x02\x1c\n\x0c\n\x05\x04\x01\x02\0\x04\x12\x03\x0c\x02\n\n\x0c\n\x05\ + \x04\x01\x02\0\x06\x12\x03\x0c\x0b\x12\n\x0c\n\x05\x04\x01\x02\0\x01\x12\ + \x03\x0c\x13\x17\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x0c\x1a\x1b\n\x0b\ + \n\x04\x04\x01\x02\x01\x12\x03\r\x02\x1a\n\x0c\n\x05\x04\x01\x02\x01\x04\ + \x12\x03\r\x02\n\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\r\x0b\x10\n\x0c\ + \n\x05\x04\x01\x02\x01\x01\x12\x03\r\x11\x15\n\x0c\n\x05\x04\x01\x02\x01\ + \x03\x12\x03\r\x18\x19\ +"; + +static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto, +}; + +fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { + ::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() +} + +pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { + unsafe { + file_descriptor_proto_lazy.get(|| { + parse_descriptor_proto() + }) + } +} diff --git a/identify/src/lib.rs b/identify/src/lib.rs index 7ff22db1..ed108d8e 100644 --- a/identify/src/lib.rs +++ b/identify/src/lib.rs @@ -77,9 +77,11 @@ extern crate tokio_codec; extern crate tokio_io; extern crate varint; -pub use self::protocol::{IdentifyInfo, IdentifyOutput, IdentifyProtocolConfig, IdentifySender}; +pub use self::protocol::{IdentifyInfo, IdentifyOutput}; +pub use self::protocol::{IdentifyProtocolConfig, IdentifySender}; pub use self::transport::IdentifyTransport; +mod keys_proto; mod protocol; mod structs_proto; mod transport; diff --git a/identify/src/protocol.rs b/identify/src/protocol.rs index 5c70bc71..17114348 100644 --- a/identify/src/protocol.rs +++ b/identify/src/protocol.rs @@ -20,7 +20,8 @@ use bytes::{Bytes, BytesMut}; use futures::{future, Future, Sink, Stream}; -use libp2p_core::{ConnectionUpgrade, Endpoint, PublicKeyBytes}; +use keys_proto::{KeyType as KeyTypeProtobuf, PublicKey as PublicKeyProtobuf}; +use libp2p_core::{ConnectionUpgrade, Endpoint, PublicKey}; use multiaddr::Multiaddr; use protobuf::Message as ProtobufMessage; use protobuf::parse_from_bytes as protobuf_parse_from_bytes; @@ -40,6 +41,7 @@ pub struct IdentifyProtocolConfig; pub enum IdentifyOutput { /// We obtained information from the remote. Happens when we are the dialer. RemoteInfo { + /// Information about the remote. info: IdentifyInfo, /// Address the remote sees for us. observed_addr: Multiaddr, @@ -77,10 +79,27 @@ where .map(|addr| addr.into_bytes()) .collect(); + let mut public_key = PublicKeyProtobuf::new(); + match info.public_key { + PublicKey::Rsa(data) => { + public_key.set_Type(KeyTypeProtobuf::RSA); + public_key.set_Data(data); + }, + PublicKey::Ed25519(data) => { + public_key.set_Type(KeyTypeProtobuf::Ed25519); + public_key.set_Data(data); + }, + PublicKey::Secp256k1(data) => { + public_key.set_Type(KeyTypeProtobuf::Secp256k1); + public_key.set_Data(data); + }, + }; + let mut message = structs_proto::Identify::new(); message.set_agentVersion(info.agent_version); message.set_protocolVersion(info.protocol_version); - message.set_publicKey(info.public_key.0); + message.set_publicKey(public_key.write_to_bytes() + .expect("protobuf writing should always be valid")); message.set_listenAddrs(listen_addrs); message.set_observedAddr(observed_addr.to_bytes()); message.set_protocols(RepeatedField::from_vec(info.protocols)); @@ -98,7 +117,7 @@ where #[derive(Debug, Clone)] pub struct IdentifyInfo { /// Public key of the node. - pub public_key: PublicKeyBytes, + pub public_key: PublicKey, /// Version of the "global" protocol, eg. `ipfs/1.0.0` or `polkadot/1.0.0`. pub protocol_version: String, /// Name and version of the client. Can be thought as similar to the `User-Agent` header @@ -206,8 +225,28 @@ fn parse_proto_msg(msg: BytesMut) -> Result<(IdentifyInfo, Multiaddr), IoError> let observed_addr = bytes_to_multiaddr(msg.take_observedAddr())?; + let pubkey = { + let mut pubkey = protobuf_parse_from_bytes::(msg.get_publicKey()) + .map_err(|err| { + debug!("failed to parse remote's infos' pubkey protobuf"); + IoError::new(IoErrorKind::InvalidData, err) + })?; + + match pubkey.get_Type() { + KeyTypeProtobuf::RSA => { + PublicKey::Rsa(pubkey.take_Data()) + }, + KeyTypeProtobuf::Ed25519 => { + PublicKey::Ed25519(pubkey.take_Data()) + }, + KeyTypeProtobuf::Secp256k1 => { + PublicKey::Secp256k1(pubkey.take_Data()) + }, + } + }; + let info = IdentifyInfo { - public_key: PublicKeyBytes(msg.take_publicKey()), + public_key: pubkey, protocol_version: msg.take_protocolVersion(), agent_version: msg.take_agentVersion(), listen_addrs: listen_addrs, @@ -229,7 +268,7 @@ mod tests { use self::libp2p_tcp_transport::TcpConfig; use self::tokio_core::reactor::Core; use futures::{Future, Stream}; - use libp2p_core::{Transport, PublicKeyBytes}; + use libp2p_core::{PublicKey, PublicKeyBytesSlice, Transport}; use std::sync::mpsc; use std::thread; use {IdentifyInfo, IdentifyOutput, IdentifyProtocolConfig}; @@ -257,7 +296,7 @@ mod tests { .and_then(|identify| match identify { IdentifyOutput::Sender { sender, .. } => sender.send( IdentifyInfo { - public_key: PublicKeyBytes(vec![1, 2, 3, 4, 5, 7]), + public_key: PublicKey::Ed25519(vec![1, 2, 3, 4, 5, 7]), protocol_version: "proto_version".to_owned(), agent_version: "agent_version".to_owned(), listen_addrs: vec![ @@ -289,7 +328,7 @@ mod tests { observed_addr, "/ip4/100.101.102.103/tcp/5000".parse().unwrap() ); - assert_eq!(info.public_key.0, &[1, 2, 3, 4, 5, 7]); + assert_eq!(info.public_key.as_raw(), PublicKeyBytesSlice(&[1, 2, 3, 4, 5, 7])); assert_eq!(info.protocol_version, "proto_version"); assert_eq!(info.agent_version, "agent_version"); assert_eq!( diff --git a/secio/src/handshake.rs b/secio/src/handshake.rs index 484b5fba..9a46d378 100644 --- a/secio/src/handshake.rs +++ b/secio/src/handshake.rs @@ -28,6 +28,7 @@ use futures::future; use futures::sink::Sink; use futures::stream::Stream; use keys_proto::{KeyType as KeyTypeProtobuf, PublicKey as PublicKeyProtobuf}; +use libp2p_core::PublicKey; use protobuf::Message as ProtobufMessage; use protobuf::parse_from_bytes as protobuf_parse_from_bytes; use ring::agreement::EphemeralPrivateKey; @@ -45,7 +46,7 @@ use structs_proto::{Exchange, Propose}; use tokio_io::codec::length_delimited; use tokio_io::{AsyncRead, AsyncWrite}; use untrusted::Input as UntrustedInput; -use {SecioKeyPair, SecioKeyPairInner, SecioPublicKey}; +use {SecioKeyPair, SecioKeyPairInner}; /// Performs a handshake on the given socket. /// @@ -58,7 +59,7 @@ use {SecioKeyPair, SecioKeyPairInner, SecioPublicKey}; pub fn handshake<'a, S: 'a>( socket: S, local_key: SecioKeyPair, -) -> Box, SecioPublicKey), Error = SecioError> + 'a> +) -> Box, PublicKey), Error = SecioError> + 'a> where S: AsyncRead + AsyncWrite, { @@ -81,7 +82,7 @@ where // The remote proposition's raw bytes. remote_proposition_bytes: BytesMut, remote_public_key_in_protobuf_bytes: Vec, - remote_public_key: Option, + remote_public_key: Option, // The remote peer's version of `local_nonce`. // If the NONCE size is actually part of the protocol, we can change this to a fixed-size @@ -214,13 +215,13 @@ where context.remote_nonce = prop.take_rand(); context.remote_public_key = Some(match pubkey.get_Type() { KeyTypeProtobuf::RSA => { - SecioPublicKey::Rsa(pubkey.take_Data()) + PublicKey::Rsa(pubkey.take_Data()) }, KeyTypeProtobuf::Ed25519 => { - SecioPublicKey::Ed25519(pubkey.take_Data()) + PublicKey::Ed25519(pubkey.take_Data()) }, KeyTypeProtobuf::Secp256k1 => { - SecioPublicKey::Secp256k1(pubkey.take_Data()) + PublicKey::Secp256k1(pubkey.take_Data()) }, }); trace!("received proposition from remote ; pubkey = {:?} ; nonce = {:?}", @@ -403,7 +404,7 @@ where data_to_verify.extend_from_slice(remote_exch.get_epubkey()); match context.remote_public_key { - Some(SecioPublicKey::Rsa(ref remote_public_key)) => { + Some(PublicKey::Rsa(ref remote_public_key)) => { // TODO: The ring library doesn't like some stuff in our DER public key, // therefore we scrap the first 24 bytes of the key. A proper fix would // be to write a DER parser, but that's not trivial. @@ -419,7 +420,7 @@ where }, } }, - Some(SecioPublicKey::Ed25519(ref remote_public_key)) => { + Some(PublicKey::Ed25519(ref remote_public_key)) => { match signature_verify(&ED25519, UntrustedInput::from(remote_public_key), UntrustedInput::from(&data_to_verify), @@ -433,7 +434,7 @@ where } }, #[cfg(feature = "secp256k1")] - Some(SecioPublicKey::Secp256k1(ref remote_public_key)) => { + Some(PublicKey::Secp256k1(ref remote_public_key)) => { let data_to_verify = digest::digest(&digest::SHA256, &data_to_verify); let message = secp256k1::Message::from_slice(data_to_verify.as_ref()) .expect("digest output length doesn't match secp256k1 input length"); @@ -454,7 +455,7 @@ where } }, #[cfg(not(feature = "secp256k1"))] - Some(SecioPublicKey::Secp256k1(_)) => { + Some(PublicKey::Secp256k1(_)) => { debug!("support for secp256k1 was disabled at compile-time"); return Err(SecioError::SignatureVerificationFailed); }, diff --git a/secio/src/lib.rs b/secio/src/lib.rs index 63f249dd..140e2f75 100644 --- a/secio/src/lib.rs +++ b/secio/src/lib.rs @@ -105,7 +105,7 @@ use asn1_der::{DerObject, traits::FromDerEncoded, traits::FromDerObject}; use bytes::{Bytes, BytesMut}; use futures::stream::MapErr as StreamMapErr; use futures::{Future, Poll, Sink, StartSend, Stream}; -use libp2p_core::{PeerId, PublicKeyBytes, PublicKeyBytesSlice}; +use libp2p_core::{PeerId, PublicKey, PublicKeyBytesSlice}; use ring::signature::{Ed25519KeyPair, RSAKeyPair}; use ring::rand::SystemRandom; use rw_stream_sink::RwStreamSink; @@ -230,20 +230,20 @@ impl SecioKeyPair { } /// Returns the public key corresponding to this key pair. - pub fn to_public_key(&self) -> SecioPublicKey { + pub fn to_public_key(&self) -> PublicKey { match self.inner { SecioKeyPairInner::Rsa { ref public, .. } => { - SecioPublicKey::Rsa(public.clone()) + PublicKey::Rsa(public.clone()) }, SecioKeyPairInner::Ed25519 { ref key_pair } => { - SecioPublicKey::Ed25519(key_pair.public_key_bytes().to_vec()) + PublicKey::Ed25519(key_pair.public_key_bytes().to_vec()) }, #[cfg(feature = "secp256k1")] SecioKeyPairInner::Secp256k1 { ref private } => { let secp = secp256k1::Secp256k1::with_caps(secp256k1::ContextFlag::SignOnly); let pubkey = secp256k1::key::PublicKey::from_secret_key(&secp, private) .expect("wrong secp256k1 private key ; type safety violated"); - SecioPublicKey::Secp256k1(pubkey.serialize().to_vec()) + PublicKey::Secp256k1(pubkey.serialize().to_vec()) }, } } @@ -289,61 +289,6 @@ enum SecioKeyPairInner { }, } -/// Public key used by the remote. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum SecioPublicKey { - /// DER format. - Rsa(Vec), - /// Format = ??? - // TODO: ^ - Ed25519(Vec), - /// Format = ??? - // TODO: ^ - Secp256k1(Vec), -} - -impl SecioPublicKey { - /// Turns this public key into a raw representation. - #[inline] - pub fn as_raw(&self) -> PublicKeyBytesSlice { - match self { - SecioPublicKey::Rsa(ref data) => PublicKeyBytesSlice(data), - SecioPublicKey::Ed25519(ref data) => PublicKeyBytesSlice(data), - SecioPublicKey::Secp256k1(ref data) => PublicKeyBytesSlice(data), - } - } - - /// Turns this public key into a raw representation. - #[inline] - pub fn into_raw(self) -> PublicKeyBytes { - match self { - SecioPublicKey::Rsa(data) => PublicKeyBytes(data), - SecioPublicKey::Ed25519(data) => PublicKeyBytes(data), - SecioPublicKey::Secp256k1(data) => PublicKeyBytes(data), - } - } - - /// Builds a `PeerId` corresponding to the public key of the node. - #[inline] - pub fn to_peer_id(&self) -> PeerId { - self.as_raw().into() - } -} - -impl From for PeerId { - #[inline] - fn from(key: SecioPublicKey) -> PeerId { - key.to_peer_id() - } -} - -impl From for PublicKeyBytes { - #[inline] - fn from(key: SecioPublicKey) -> PublicKeyBytes { - key.into_raw() - } -} - impl libp2p_core::ConnectionUpgrade for SecioConfig where S: AsyncRead + AsyncWrite + 'static, // TODO: 'static :( @@ -351,7 +296,7 @@ where { type Output = ( RwStreamSink, fn(SecioError) -> IoError>>, - SecioPublicKey, + PublicKey, ); type MultiaddrFuture = Maf; type Future = Box>; @@ -407,7 +352,7 @@ where pub fn handshake<'a>( socket: S, key_pair: SecioKeyPair, - ) -> Box, SecioPublicKey), Error = SecioError> + 'a> + ) -> Box, PublicKey), Error = SecioError> + 'a> where S: 'a, {