2017-04-03 11:13:51 +02:00
|
|
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
|
|
|
// This file is part of Parity.
|
|
|
|
|
|
|
|
// Parity is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
|
|
|
// Parity is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
use std::io::Cursor;
|
|
|
|
use std::u16;
|
|
|
|
use std::ops::Deref;
|
|
|
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
|
|
|
use serde_json;
|
2017-04-08 11:26:16 +02:00
|
|
|
use ethcrypto::ecies::{encrypt_single_message, decrypt_single_message};
|
2017-08-09 11:09:40 +02:00
|
|
|
use ethkey::{Secret, KeyPair};
|
2017-04-08 11:26:16 +02:00
|
|
|
use ethkey::math::curve_order;
|
2017-09-04 16:36:49 +02:00
|
|
|
use bigint::prelude::U256;
|
|
|
|
use bigint::hash::H256;
|
2017-04-03 11:13:51 +02:00
|
|
|
use key_server_cluster::Error;
|
2017-07-06 14:02:10 +02:00
|
|
|
use key_server_cluster::message::{Message, ClusterMessage, GenerationMessage, EncryptionMessage,
|
|
|
|
DecryptionMessage, SigningMessage};
|
2017-04-03 11:13:51 +02:00
|
|
|
|
|
|
|
/// Size of serialized header.
|
|
|
|
pub const MESSAGE_HEADER_SIZE: usize = 4;
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
/// Message header.
|
|
|
|
pub struct MessageHeader {
|
|
|
|
/// Message/Header version.
|
|
|
|
pub version: u8,
|
|
|
|
/// Message kind.
|
|
|
|
pub kind: u8,
|
|
|
|
/// Message payload size (without header).
|
|
|
|
pub size: u16,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
/// Serialized message.
|
|
|
|
pub struct SerializedMessage(Vec<u8>);
|
|
|
|
|
|
|
|
impl Deref for SerializedMessage {
|
|
|
|
type Target = [u8];
|
|
|
|
|
|
|
|
fn deref(&self) -> &[u8] {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<Vec<u8>> for SerializedMessage {
|
|
|
|
fn into(self) -> Vec<u8> {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Serialize message.
|
|
|
|
pub fn serialize_message(message: Message) -> Result<SerializedMessage, Error> {
|
|
|
|
let (message_kind, payload) = match message {
|
|
|
|
Message::Cluster(ClusterMessage::NodePublicKey(payload)) => (1, serde_json::to_vec(&payload)),
|
|
|
|
Message::Cluster(ClusterMessage::NodePrivateKeySignature(payload)) => (2, serde_json::to_vec(&payload)),
|
|
|
|
Message::Cluster(ClusterMessage::KeepAlive(payload)) => (3, serde_json::to_vec(&payload)),
|
|
|
|
Message::Cluster(ClusterMessage::KeepAliveResponse(payload)) => (4, serde_json::to_vec(&payload)),
|
|
|
|
|
2017-07-06 14:02:10 +02:00
|
|
|
Message::Generation(GenerationMessage::InitializeSession(payload)) => (50, serde_json::to_vec(&payload)),
|
|
|
|
Message::Generation(GenerationMessage::ConfirmInitialization(payload)) => (51, serde_json::to_vec(&payload)),
|
|
|
|
Message::Generation(GenerationMessage::CompleteInitialization(payload)) => (52, serde_json::to_vec(&payload)),
|
|
|
|
Message::Generation(GenerationMessage::KeysDissemination(payload)) => (53, serde_json::to_vec(&payload)),
|
|
|
|
Message::Generation(GenerationMessage::PublicKeyShare(payload)) => (54, serde_json::to_vec(&payload)),
|
|
|
|
Message::Generation(GenerationMessage::SessionError(payload)) => (55, serde_json::to_vec(&payload)),
|
|
|
|
Message::Generation(GenerationMessage::SessionCompleted(payload)) => (56, serde_json::to_vec(&payload)),
|
|
|
|
|
|
|
|
Message::Encryption(EncryptionMessage::InitializeEncryptionSession(payload)) => (100, serde_json::to_vec(&payload)),
|
|
|
|
Message::Encryption(EncryptionMessage::ConfirmEncryptionInitialization(payload)) => (101, serde_json::to_vec(&payload)),
|
|
|
|
Message::Encryption(EncryptionMessage::EncryptionSessionError(payload)) => (102, serde_json::to_vec(&payload)),
|
|
|
|
|
|
|
|
Message::Decryption(DecryptionMessage::DecryptionConsensusMessage(payload)) => (150, serde_json::to_vec(&payload)),
|
|
|
|
Message::Decryption(DecryptionMessage::RequestPartialDecryption(payload)) => (151, serde_json::to_vec(&payload)),
|
|
|
|
Message::Decryption(DecryptionMessage::PartialDecryption(payload)) => (152, serde_json::to_vec(&payload)),
|
|
|
|
Message::Decryption(DecryptionMessage::DecryptionSessionError(payload)) => (153, serde_json::to_vec(&payload)),
|
|
|
|
Message::Decryption(DecryptionMessage::DecryptionSessionCompleted(payload)) => (154, serde_json::to_vec(&payload)),
|
|
|
|
|
|
|
|
Message::Signing(SigningMessage::SigningConsensusMessage(payload)) => (200, serde_json::to_vec(&payload)),
|
|
|
|
Message::Signing(SigningMessage::SigningGenerationMessage(payload)) => (201, serde_json::to_vec(&payload)),
|
|
|
|
Message::Signing(SigningMessage::RequestPartialSignature(payload)) => (202, serde_json::to_vec(&payload)),
|
|
|
|
Message::Signing(SigningMessage::PartialSignature(payload)) => (203, serde_json::to_vec(&payload)),
|
|
|
|
Message::Signing(SigningMessage::SigningSessionError(payload)) => (204, serde_json::to_vec(&payload)),
|
|
|
|
Message::Signing(SigningMessage::SigningSessionCompleted(payload)) => (205, serde_json::to_vec(&payload)),
|
2017-04-03 11:13:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
let payload = payload.map_err(|err| Error::Serde(err.to_string()))?;
|
2017-04-08 11:26:16 +02:00
|
|
|
build_serialized_message(MessageHeader {
|
2017-04-03 11:13:51 +02:00
|
|
|
kind: message_kind,
|
|
|
|
version: 1,
|
2017-04-08 11:26:16 +02:00
|
|
|
size: 0,
|
|
|
|
}, payload)
|
2017-04-03 11:13:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Deserialize message.
|
|
|
|
pub fn deserialize_message(header: &MessageHeader, payload: Vec<u8>) -> Result<Message, Error> {
|
|
|
|
Ok(match header.kind {
|
|
|
|
1 => Message::Cluster(ClusterMessage::NodePublicKey(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
2 => Message::Cluster(ClusterMessage::NodePrivateKeySignature(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
3 => Message::Cluster(ClusterMessage::KeepAlive(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
4 => Message::Cluster(ClusterMessage::KeepAliveResponse(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
|
2017-07-06 14:02:10 +02:00
|
|
|
50 => Message::Generation(GenerationMessage::InitializeSession(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
51 => Message::Generation(GenerationMessage::ConfirmInitialization(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
52 => Message::Generation(GenerationMessage::CompleteInitialization(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
53 => Message::Generation(GenerationMessage::KeysDissemination(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
54 => Message::Generation(GenerationMessage::PublicKeyShare(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
55 => Message::Generation(GenerationMessage::SessionError(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
56 => Message::Generation(GenerationMessage::SessionCompleted(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
|
|
|
|
100 => Message::Encryption(EncryptionMessage::InitializeEncryptionSession(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
101 => Message::Encryption(EncryptionMessage::ConfirmEncryptionInitialization(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
102 => Message::Encryption(EncryptionMessage::EncryptionSessionError(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
|
|
|
|
150 => Message::Decryption(DecryptionMessage::DecryptionConsensusMessage(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
151 => Message::Decryption(DecryptionMessage::RequestPartialDecryption(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
152 => Message::Decryption(DecryptionMessage::PartialDecryption(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
153 => Message::Decryption(DecryptionMessage::DecryptionSessionError(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
154 => Message::Decryption(DecryptionMessage::DecryptionSessionCompleted(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
|
|
|
|
200 => Message::Signing(SigningMessage::SigningConsensusMessage(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
201 => Message::Signing(SigningMessage::SigningGenerationMessage(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
202 => Message::Signing(SigningMessage::RequestPartialSignature(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
203 => Message::Signing(SigningMessage::PartialSignature(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
204 => Message::Signing(SigningMessage::SigningSessionError(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
|
|
|
205 => Message::Signing(SigningMessage::SigningSessionCompleted(serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?)),
|
2017-04-03 11:13:51 +02:00
|
|
|
|
|
|
|
_ => return Err(Error::Serde(format!("unknown message type {}", header.kind))),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Encrypt serialized message.
|
2017-04-08 11:26:16 +02:00
|
|
|
pub fn encrypt_message(key: &KeyPair, message: SerializedMessage) -> Result<SerializedMessage, Error> {
|
|
|
|
let mut header: Vec<_> = message.into();
|
|
|
|
let payload = header.split_off(MESSAGE_HEADER_SIZE);
|
|
|
|
let encrypted_payload = encrypt_single_message(key.public(), &payload)?;
|
|
|
|
|
|
|
|
let header = deserialize_header(&header)?;
|
|
|
|
build_serialized_message(header, encrypted_payload)
|
2017-04-03 11:13:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Decrypt serialized message.
|
2017-04-08 11:26:16 +02:00
|
|
|
pub fn decrypt_message(key: &KeyPair, payload: Vec<u8>) -> Result<Vec<u8>, Error> {
|
|
|
|
Ok(decrypt_single_message(key.secret(), &payload)?)
|
2017-04-03 11:13:51 +02:00
|
|
|
}
|
|
|
|
|
2017-08-09 11:09:40 +02:00
|
|
|
/// Fix shared encryption key.
|
|
|
|
pub fn fix_shared_key(shared_secret: &Secret) -> Result<KeyPair, Error> {
|
2017-04-08 11:26:16 +02:00
|
|
|
// secret key created in agree function is invalid, as it is not calculated mod EC.field.n
|
|
|
|
// => let's do it manually
|
2017-08-09 11:09:40 +02:00
|
|
|
let shared_secret: H256 = (**shared_secret).into();
|
2017-04-08 11:26:16 +02:00
|
|
|
let shared_secret: U256 = shared_secret.into();
|
|
|
|
let shared_secret: H256 = (shared_secret % curve_order()).into();
|
|
|
|
let shared_key_pair = KeyPair::from_secret_slice(&*shared_secret)?;
|
|
|
|
Ok(shared_key_pair)
|
2017-04-03 11:13:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Serialize message header.
|
|
|
|
fn serialize_header(header: &MessageHeader) -> Result<Vec<u8>, Error> {
|
|
|
|
let mut buffer = Vec::with_capacity(MESSAGE_HEADER_SIZE);
|
|
|
|
buffer.write_u8(header.version)?;
|
|
|
|
buffer.write_u8(header.kind)?;
|
|
|
|
buffer.write_u16::<LittleEndian>(header.size)?;
|
|
|
|
Ok(buffer)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Deserialize message header.
|
|
|
|
pub fn deserialize_header(data: &[u8]) -> Result<MessageHeader, Error> {
|
|
|
|
let mut reader = Cursor::new(data);
|
|
|
|
Ok(MessageHeader {
|
|
|
|
version: reader.read_u8()?,
|
|
|
|
kind: reader.read_u8()?,
|
|
|
|
size: reader.read_u16::<LittleEndian>()?,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-04-08 11:26:16 +02:00
|
|
|
/// Build serialized message from header && payload
|
|
|
|
fn build_serialized_message(mut header: MessageHeader, payload: Vec<u8>) -> Result<SerializedMessage, Error> {
|
|
|
|
let payload_len = payload.len();
|
|
|
|
if payload_len > u16::MAX as usize {
|
|
|
|
return Err(Error::InvalidMessage);
|
|
|
|
}
|
|
|
|
header.size = payload.len() as u16;
|
|
|
|
|
|
|
|
let mut message = serialize_header(&header)?;
|
|
|
|
message.extend(payload);
|
|
|
|
Ok(SerializedMessage(message))
|
|
|
|
}
|
|
|
|
|
2017-04-03 11:13:51 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
pub mod tests {
|
|
|
|
use std::io;
|
2017-04-08 11:26:16 +02:00
|
|
|
use futures::Poll;
|
|
|
|
use tokio_io::{AsyncRead, AsyncWrite};
|
2017-04-03 11:13:51 +02:00
|
|
|
use ethkey::{KeyPair, Public};
|
2017-08-09 11:09:40 +02:00
|
|
|
use ethcrypto::ecdh::agree;
|
2017-04-03 11:13:51 +02:00
|
|
|
use key_server_cluster::message::Message;
|
2017-08-09 11:09:40 +02:00
|
|
|
use super::{MESSAGE_HEADER_SIZE, MessageHeader, fix_shared_key, encrypt_message, serialize_message,
|
2017-04-08 11:26:16 +02:00
|
|
|
serialize_header, deserialize_header};
|
2017-04-03 11:13:51 +02:00
|
|
|
|
|
|
|
pub struct TestIo {
|
|
|
|
self_key_pair: KeyPair,
|
|
|
|
peer_public: Public,
|
2017-04-08 11:26:16 +02:00
|
|
|
shared_key_pair: KeyPair,
|
2017-04-03 11:13:51 +02:00
|
|
|
input_buffer: io::Cursor<Vec<u8>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TestIo {
|
|
|
|
pub fn new(self_key_pair: KeyPair, peer_public: Public) -> Self {
|
2017-08-09 11:09:40 +02:00
|
|
|
let shared_key_pair = fix_shared_key(&agree(self_key_pair.secret(), &peer_public).unwrap()).unwrap();
|
2017-04-03 11:13:51 +02:00
|
|
|
TestIo {
|
|
|
|
self_key_pair: self_key_pair,
|
|
|
|
peer_public: peer_public,
|
2017-04-08 11:26:16 +02:00
|
|
|
shared_key_pair: shared_key_pair,
|
2017-04-03 11:13:51 +02:00
|
|
|
input_buffer: io::Cursor::new(Vec::new()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn self_key_pair(&self) -> &KeyPair {
|
|
|
|
&self.self_key_pair
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn peer_public(&self) -> &Public {
|
|
|
|
&self.peer_public
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_input_message(&mut self, message: Message) {
|
|
|
|
let serialized_message = serialize_message(message).unwrap();
|
|
|
|
let serialized_message: Vec<_> = serialized_message.into();
|
|
|
|
let input_buffer = self.input_buffer.get_mut();
|
|
|
|
for b in serialized_message {
|
|
|
|
input_buffer.push(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-08 11:26:16 +02:00
|
|
|
pub fn add_encrypted_input_message(&mut self, message: Message) {
|
|
|
|
let serialized_message = encrypt_message(&self.shared_key_pair, serialize_message(message).unwrap()).unwrap();
|
2017-04-03 11:13:51 +02:00
|
|
|
let serialized_message: Vec<_> = serialized_message.into();
|
2017-04-08 11:26:16 +02:00
|
|
|
let input_buffer = self.input_buffer.get_mut();
|
|
|
|
for b in serialized_message {
|
|
|
|
input_buffer.push(b);
|
|
|
|
}
|
2017-04-03 11:13:51 +02:00
|
|
|
}
|
2017-04-08 11:26:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AsyncRead for TestIo {}
|
2017-04-03 11:13:51 +02:00
|
|
|
|
2017-04-08 11:26:16 +02:00
|
|
|
impl AsyncWrite for TestIo {
|
|
|
|
fn shutdown(&mut self) -> Poll<(), io::Error> {
|
|
|
|
Ok(().into())
|
2017-04-03 11:13:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl io::Read for TestIo {
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
|
|
io::Read::read(&mut self.input_buffer, buf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl io::Write for TestIo {
|
|
|
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
2017-04-08 11:26:16 +02:00
|
|
|
Ok(buf.len())
|
2017-04-03 11:13:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn flush(&mut self) -> io::Result<()> {
|
2017-04-08 11:26:16 +02:00
|
|
|
Ok(())
|
2017-04-03 11:13:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn header_serialization_works() {
|
|
|
|
let header = MessageHeader {
|
|
|
|
kind: 1,
|
|
|
|
version: 2,
|
|
|
|
size: 3,
|
|
|
|
};
|
|
|
|
|
|
|
|
let serialized_header = serialize_header(&header).unwrap();
|
|
|
|
assert_eq!(serialized_header.len(), MESSAGE_HEADER_SIZE);
|
|
|
|
|
|
|
|
let deserialized_header = deserialize_header(&serialized_header).unwrap();
|
|
|
|
assert_eq!(deserialized_header, header);
|
|
|
|
}
|
|
|
|
}
|