mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-20 21:36:31 +00:00
Merge pull request #56 from tomaka/secio-api-improvement
Improve the API of the secio crate
This commit is contained in:
@ -9,7 +9,5 @@ futures = "0.1"
|
|||||||
libp2p-secio = { path = "../libp2p-secio" }
|
libp2p-secio = { path = "../libp2p-secio" }
|
||||||
libp2p-swarm = { path = "../libp2p-swarm" }
|
libp2p-swarm = { path = "../libp2p-swarm" }
|
||||||
libp2p-tcp-transport = { path = "../libp2p-tcp-transport" }
|
libp2p-tcp-transport = { path = "../libp2p-tcp-transport" }
|
||||||
ring = { version = "0.12.1", features = ["rsa_signing"] }
|
|
||||||
tokio-core = "0.1"
|
tokio-core = "0.1"
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1"
|
||||||
untrusted = "0.6"
|
|
||||||
|
@ -23,24 +23,19 @@ extern crate futures;
|
|||||||
extern crate libp2p_secio as secio;
|
extern crate libp2p_secio as secio;
|
||||||
extern crate libp2p_swarm as swarm;
|
extern crate libp2p_swarm as swarm;
|
||||||
extern crate libp2p_tcp_transport as tcp;
|
extern crate libp2p_tcp_transport as tcp;
|
||||||
extern crate ring;
|
|
||||||
extern crate tokio_core;
|
extern crate tokio_core;
|
||||||
extern crate tokio_io;
|
extern crate tokio_io;
|
||||||
extern crate untrusted;
|
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::future::{Future, FutureResult, IntoFuture};
|
use futures::future::{Future, FutureResult, IntoFuture};
|
||||||
use futures::{Stream, Sink};
|
use futures::{Stream, Sink};
|
||||||
use ring::signature::RSAKeyPair;
|
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::sync::Arc;
|
|
||||||
use swarm::{Transport, ConnectionUpgrade};
|
use swarm::{Transport, ConnectionUpgrade};
|
||||||
use tcp::TcpConfig;
|
use tcp::TcpConfig;
|
||||||
use tokio_core::reactor::Core;
|
use tokio_core::reactor::Core;
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_io::codec::length_delimited;
|
use tokio_io::codec::length_delimited;
|
||||||
use untrusted::Input;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut core = Core::new().unwrap();
|
let mut core = Core::new().unwrap();
|
||||||
@ -49,15 +44,10 @@ fn main() {
|
|||||||
let with_secio = tcp
|
let with_secio = tcp
|
||||||
.with_upgrade(swarm::PlainTextConfig)
|
.with_upgrade(swarm::PlainTextConfig)
|
||||||
.or_upgrade({
|
.or_upgrade({
|
||||||
let private_key = {
|
let private_key = include_bytes!("test-private-key.pk8");
|
||||||
let pkcs8 = include_bytes!("test-private-key.pk8");
|
|
||||||
Arc::new(RSAKeyPair::from_pkcs8(Input::from(&pkcs8[..])).unwrap())
|
|
||||||
};
|
|
||||||
let public_key = include_bytes!("test-public-key.der").to_vec();
|
let public_key = include_bytes!("test-public-key.der").to_vec();
|
||||||
|
secio::SecioConfig {
|
||||||
secio::SecioConnUpgrade {
|
key: secio::SecioKeyPair::rsa_from_pkcs8(private_key, public_key).unwrap(),
|
||||||
local_public_key: public_key,
|
|
||||||
local_private_key: private_key,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,24 +23,19 @@ extern crate futures;
|
|||||||
extern crate libp2p_secio as secio;
|
extern crate libp2p_secio as secio;
|
||||||
extern crate libp2p_swarm as swarm;
|
extern crate libp2p_swarm as swarm;
|
||||||
extern crate libp2p_tcp_transport as tcp;
|
extern crate libp2p_tcp_transport as tcp;
|
||||||
extern crate ring;
|
|
||||||
extern crate tokio_core;
|
extern crate tokio_core;
|
||||||
extern crate tokio_io;
|
extern crate tokio_io;
|
||||||
extern crate untrusted;
|
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::future::{Future, FutureResult, IntoFuture, loop_fn, Loop};
|
use futures::future::{Future, FutureResult, IntoFuture, loop_fn, Loop};
|
||||||
use futures::{Stream, Sink};
|
use futures::{Stream, Sink};
|
||||||
use ring::signature::RSAKeyPair;
|
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::sync::Arc;
|
|
||||||
use swarm::{Transport, ConnectionUpgrade};
|
use swarm::{Transport, ConnectionUpgrade};
|
||||||
use tcp::TcpConfig;
|
use tcp::TcpConfig;
|
||||||
use tokio_core::reactor::Core;
|
use tokio_core::reactor::Core;
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_io::codec::length_delimited;
|
use tokio_io::codec::length_delimited;
|
||||||
use untrusted::Input;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut core = Core::new().unwrap();
|
let mut core = Core::new().unwrap();
|
||||||
@ -49,15 +44,10 @@ fn main() {
|
|||||||
let with_secio = tcp
|
let with_secio = tcp
|
||||||
.with_upgrade(swarm::PlainTextConfig)
|
.with_upgrade(swarm::PlainTextConfig)
|
||||||
.or_upgrade({
|
.or_upgrade({
|
||||||
let private_key = {
|
let private_key = include_bytes!("test-private-key.pk8");
|
||||||
let pkcs8 = include_bytes!("test-private-key.pk8");
|
|
||||||
Arc::new(RSAKeyPair::from_pkcs8(Input::from(&pkcs8[..])).unwrap())
|
|
||||||
};
|
|
||||||
let public_key = include_bytes!("test-public-key.der").to_vec();
|
let public_key = include_bytes!("test-public-key.der").to_vec();
|
||||||
|
secio::SecioConfig {
|
||||||
secio::SecioConnUpgrade {
|
key: secio::SecioKeyPair::rsa_from_pkcs8(private_key, public_key).unwrap(),
|
||||||
local_public_key: public_key,
|
|
||||||
local_private_key: private_key,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
//! `SecioMiddleware` that implements `Sink` and `Stream` and can be used to send packets of data.
|
//! `SecioMiddleware` that implements `Sink` and `Stream` and can be used to send packets of data.
|
||||||
//!
|
//!
|
||||||
//! However for integration with the rest of `libp2p` you are encouraged to use the
|
//! However for integration with the rest of `libp2p` you are encouraged to use the
|
||||||
//! `SecioConnUpgrade` struct instead. This struct implements the `ConnectionUpgrade` trait and
|
//! `SecioConfig` struct instead. This struct implements the `ConnectionUpgrade` trait and
|
||||||
//! will automatically apply secio on any incoming or outgoing connection.
|
//! will automatically apply secio on any incoming or outgoing connection.
|
||||||
|
|
||||||
extern crate bytes;
|
extern crate bytes;
|
||||||
@ -50,10 +50,12 @@ use futures::{Future, Poll, StartSend, Sink, Stream};
|
|||||||
use futures::stream::MapErr as StreamMapErr;
|
use futures::stream::MapErr as StreamMapErr;
|
||||||
use ring::signature::RSAKeyPair;
|
use ring::signature::RSAKeyPair;
|
||||||
use rw_stream_sink::RwStreamSink;
|
use rw_stream_sink::RwStreamSink;
|
||||||
|
use std::error::Error;
|
||||||
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
|
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
use untrusted::Input;
|
||||||
|
|
||||||
mod algo_support;
|
mod algo_support;
|
||||||
mod codec;
|
mod codec;
|
||||||
@ -62,18 +64,74 @@ mod keys_proto;
|
|||||||
mod handshake;
|
mod handshake;
|
||||||
mod structs_proto;
|
mod structs_proto;
|
||||||
|
|
||||||
/// Implementation of the `ConnectionUpgrade` trait of `libp2p_swarm`. Automatically applies any
|
/// Implementation of the `ConnectionUpgrade` trait of `libp2p_swarm`. Automatically applies
|
||||||
/// secio on any connection.
|
/// secio on any connection.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SecioConnUpgrade {
|
pub struct SecioConfig {
|
||||||
/// Public key of the local node. Must match `local_private_key` or an error will happen during
|
/// Private and public keys of the local node.
|
||||||
/// the handshake.
|
pub key: SecioKeyPair,
|
||||||
pub local_public_key: Vec<u8>,
|
|
||||||
/// Private key that will be used to prove the identity of the local node.
|
|
||||||
pub local_private_key: Arc<RSAKeyPair>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> libp2p_swarm::ConnectionUpgrade<S> for SecioConnUpgrade
|
/// Private and public keys of the local node.
|
||||||
|
///
|
||||||
|
/// # Generating offline keys with OpenSSL
|
||||||
|
///
|
||||||
|
/// ## RSA
|
||||||
|
///
|
||||||
|
/// Generating the keys:
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// openssl genrsa -out private.pem 2048
|
||||||
|
/// openssl rsa -in private.pem -outform DER -pubout -out public.der
|
||||||
|
/// openssl pkcs8 -in private.pem -topk8 -nocrypt -out private.pk8
|
||||||
|
/// rm private.pem # optional
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Loading the keys:
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// let key_pair = SecioKeyPair::rsa_from_pkcs8(include_bytes!("private.pk8"),
|
||||||
|
/// include_bytes!("public.der"));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SecioKeyPair {
|
||||||
|
inner: SecioKeyPairInner,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SecioKeyPair {
|
||||||
|
pub fn rsa_from_pkcs8<P>(private: &[u8], public: P)
|
||||||
|
-> Result<SecioKeyPair, Box<Error + Send + Sync>>
|
||||||
|
where P: Into<Vec<u8>>
|
||||||
|
{
|
||||||
|
let private = RSAKeyPair::from_pkcs8(Input::from(&private[..]))
|
||||||
|
.map_err(|err| Box::new(err))?;
|
||||||
|
|
||||||
|
Ok(SecioKeyPair {
|
||||||
|
inner: SecioKeyPairInner::Rsa {
|
||||||
|
public: public.into(),
|
||||||
|
private: Arc::new(private),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner content of `SecioKeyPair`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum SecioKeyPairInner {
|
||||||
|
Rsa {
|
||||||
|
public: Vec<u8>,
|
||||||
|
private: Arc<RSAKeyPair>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum SecioPublicKey<'a> {
|
||||||
|
/// DER format.
|
||||||
|
Rsa(&'a [u8]),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> libp2p_swarm::ConnectionUpgrade<S> for SecioConfig
|
||||||
where S: AsyncRead + AsyncWrite + 'static
|
where S: AsyncRead + AsyncWrite + 'static
|
||||||
{
|
{
|
||||||
type Output = RwStreamSink<
|
type Output = RwStreamSink<
|
||||||
@ -95,8 +153,7 @@ impl<S> libp2p_swarm::ConnectionUpgrade<S> for SecioConnUpgrade
|
|||||||
fn upgrade(self, incoming: S, _: ()) -> Self::Future {
|
fn upgrade(self, incoming: S, _: ()) -> Self::Future {
|
||||||
let fut = SecioMiddleware::handshake(
|
let fut = SecioMiddleware::handshake(
|
||||||
incoming,
|
incoming,
|
||||||
self.local_public_key.clone(),
|
self.key,
|
||||||
self.local_private_key.clone(),
|
|
||||||
);
|
);
|
||||||
let wrapped = fut.map(|stream_sink| {
|
let wrapped = fut.map(|stream_sink| {
|
||||||
let mapped = stream_sink.map_err(map_err as fn(_) -> _);
|
let mapped = stream_sink.map_err(map_err as fn(_) -> _);
|
||||||
@ -125,19 +182,17 @@ impl<S> SecioMiddleware<S>
|
|||||||
{
|
{
|
||||||
/// Attempts to perform a handshake on the given socket.
|
/// Attempts to perform a handshake on the given socket.
|
||||||
///
|
///
|
||||||
/// `local_public_key` and `local_private_key` must match. `local_public_key` must be in the
|
|
||||||
/// DER format.
|
|
||||||
///
|
|
||||||
/// On success, produces a `SecioMiddleware` that can then be used to encode/decode
|
/// On success, produces a `SecioMiddleware` that can then be used to encode/decode
|
||||||
/// communications.
|
/// communications.
|
||||||
pub fn handshake<'a>(
|
pub fn handshake<'a>(
|
||||||
socket: S,
|
socket: S,
|
||||||
local_public_key: Vec<u8>,
|
key_pair: SecioKeyPair,
|
||||||
local_private_key: Arc<RSAKeyPair>,
|
|
||||||
) -> Box<Future<Item = SecioMiddleware<S>, Error = SecioError> + 'a>
|
) -> Box<Future<Item = SecioMiddleware<S>, Error = SecioError> + 'a>
|
||||||
where S: 'a
|
where S: 'a
|
||||||
{
|
{
|
||||||
let fut = handshake::handshake(socket, local_public_key, local_private_key)
|
let SecioKeyPairInner::Rsa { private, public } = key_pair.inner;
|
||||||
|
|
||||||
|
let fut = handshake::handshake(socket, public, private)
|
||||||
.map(|(inner, pubkey)| {
|
.map(|(inner, pubkey)| {
|
||||||
SecioMiddleware {
|
SecioMiddleware {
|
||||||
inner: inner,
|
inner: inner,
|
||||||
@ -149,8 +204,8 @@ impl<S> SecioMiddleware<S>
|
|||||||
|
|
||||||
/// Returns the public key of the remote in the `DER` format.
|
/// Returns the public key of the remote in the `DER` format.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn remote_public_key_der(&self) -> &[u8] {
|
pub fn remote_public_key_der(&self) -> SecioPublicKey {
|
||||||
&self.remote_pubkey_der
|
SecioPublicKey::Rsa(&self.remote_pubkey_der)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user