Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Improve the API of the secio crate
  • Loading branch information
tomaka committed Dec 4, 2017
commit 33025ba22efbc45090a3fcd3892aea535e65ce14
2 changes: 0 additions & 2 deletions example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,5 @@ futures = "0.1"
libp2p-secio = { path = "../libp2p-secio" }
libp2p-swarm = { path = "../libp2p-swarm" }
libp2p-tcp-transport = { path = "../libp2p-tcp-transport" }
ring = { version = "0.12.1", features = ["rsa_signing"] }
tokio-core = "0.1"
tokio-io = "0.1"
untrusted = "0.6"
14 changes: 2 additions & 12 deletions example/examples/echo-dialer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,19 @@ extern crate futures;
extern crate libp2p_secio as secio;
extern crate libp2p_swarm as swarm;
extern crate libp2p_tcp_transport as tcp;
extern crate ring;
extern crate tokio_core;
extern crate tokio_io;
extern crate untrusted;

use bytes::Bytes;
use futures::future::{Future, FutureResult, IntoFuture};
use futures::{Stream, Sink};
use ring::signature::RSAKeyPair;
use std::io::Error as IoError;
use std::iter;
use std::sync::Arc;
use swarm::{Transport, ConnectionUpgrade};
use tcp::Tcp;
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::length_delimited;
use untrusted::Input;

fn main() {
let mut core = Core::new().unwrap();
Expand All @@ -49,15 +44,10 @@ fn main() {
let with_secio = tcp
.with_upgrade(swarm::PlainText)
.or_upgrade({
let private_key = {
let pkcs8 = include_bytes!("test-private-key.pk8");
Arc::new(RSAKeyPair::from_pkcs8(Input::from(&pkcs8[..])).unwrap())
};
let private_key = include_bytes!("test-private-key.pk8");
let public_key = include_bytes!("test-public-key.der").to_vec();

secio::SecioConnUpgrade {
local_public_key: public_key,
local_private_key: private_key,
key: secio::SecioKeyPair::rsa_from_pkcs8(private_key, public_key).unwrap(),
}
});

Expand Down
14 changes: 2 additions & 12 deletions example/examples/echo-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,19 @@ extern crate futures;
extern crate libp2p_secio as secio;
extern crate libp2p_swarm as swarm;
extern crate libp2p_tcp_transport as tcp;
extern crate ring;
extern crate tokio_core;
extern crate tokio_io;
extern crate untrusted;

use bytes::Bytes;
use futures::future::{Future, FutureResult, IntoFuture, loop_fn, Loop};
use futures::{Stream, Sink};
use ring::signature::RSAKeyPair;
use std::io::Error as IoError;
use std::iter;
use std::sync::Arc;
use swarm::{Transport, ConnectionUpgrade};
use tcp::Tcp;
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::length_delimited;
use untrusted::Input;

fn main() {
let mut core = Core::new().unwrap();
Expand All @@ -49,15 +44,10 @@ fn main() {
let with_secio = tcp
.with_upgrade(swarm::PlainText)
.or_upgrade({
let private_key = {
let pkcs8 = include_bytes!("test-private-key.pk8");
Arc::new(RSAKeyPair::from_pkcs8(Input::from(&pkcs8[..])).unwrap())
};
let private_key = include_bytes!("test-private-key.pk8");
let public_key = include_bytes!("test-public-key.der").to_vec();

secio::SecioConnUpgrade {
local_public_key: public_key,
local_private_key: private_key,
key: secio::SecioKeyPair::rsa_from_pkcs8(private_key, public_key).unwrap(),
}
});

Expand Down
85 changes: 70 additions & 15 deletions libp2p-secio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ use futures::{Future, Poll, StartSend, Sink, Stream};
use futures::stream::MapErr as StreamMapErr;
use ring::signature::RSAKeyPair;
use rw_stream_sink::RwStreamSink;
use std::error::Error;
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
use std::iter;
use std::sync::Arc;
use tokio_io::{AsyncRead, AsyncWrite};
use untrusted::Input;

mod algo_support;
mod codec;
Expand All @@ -67,11 +69,67 @@ mod structs_proto;
/// secio on any connection.
#[derive(Clone)]
pub struct SecioConnUpgrade {
/// Public key of the local node. Must match `local_private_key` or an error will happen during
/// the handshake.
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>,
/// Private and public keys of the local node.
pub key: SecioKeyPair,
}

/// 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
/// ley key_pair = SecioKeyPair::rsa_from_pkcs8(include_bytes!("private.pk8"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: this should say let

/// 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 SecioConnUpgrade
Expand All @@ -96,8 +154,7 @@ impl<S> libp2p_swarm::ConnectionUpgrade<S> for SecioConnUpgrade
fn upgrade(self, incoming: S, _: ()) -> Self::Future {
let fut = SecioMiddleware::handshake(
incoming,
self.local_public_key.clone(),
self.local_private_key.clone(),
self.key,
);
let wrapped = fut.map(|stream_sink| {
let mapped = stream_sink.map_err(map_err as fn(_) -> _);
Expand Down Expand Up @@ -126,19 +183,17 @@ impl<S> SecioMiddleware<S>
{
/// 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
/// communications.
pub fn handshake<'a>(
socket: S,
local_public_key: Vec<u8>,
local_private_key: Arc<RSAKeyPair>,
key_pair: SecioKeyPair,
) -> Box<Future<Item = SecioMiddleware<S>, Error = SecioError> + '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)| {
SecioMiddleware {
inner: inner,
Expand All @@ -150,8 +205,8 @@ impl<S> SecioMiddleware<S>

/// Returns the public key of the remote in the `DER` format.
#[inline]
pub fn remote_public_key_der(&self) -> &[u8] {
&self.remote_pubkey_der
pub fn remote_public_key_der(&self) -> SecioPublicKey {
SecioPublicKey::Rsa(&self.remote_pubkey_der)
}
}

Expand Down