Signature cleanup (#1921)
* Address renamed to H160 at bigint library level * moved uint specific test from util to bigint library * naming * unifing hashes in progress * unifing hashes * cleanup redundant unwraps in tests * Removing util/crypto in progress. * fixed compiling * signature cleanup in progress * new module - ethcrypto used by ethstore and ethcore-network * fixed compiling * fixed compiling * fixed merge
This commit is contained in:
@@ -23,6 +23,8 @@ rustc-serialize = "0.3"
|
||||
ethcore-io = { path = "../io" }
|
||||
ethcore-util = { path = ".." }
|
||||
ethcore-devtools = { path = "../../devtools" }
|
||||
ethkey = { path = "../../ethkey" }
|
||||
ethcrypto = { path = "../../ethcrypto" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -29,12 +29,12 @@ use error::*;
|
||||
use io::{IoContext, StreamToken};
|
||||
use handshake::Handshake;
|
||||
use stats::NetworkStats;
|
||||
use util::crypto;
|
||||
use rcrypto::blockmodes::*;
|
||||
use rcrypto::aessafe::*;
|
||||
use rcrypto::symmetriccipher::*;
|
||||
use rcrypto::buffer::*;
|
||||
use tiny_keccak::Keccak;
|
||||
use crypto;
|
||||
|
||||
const ENCRYPTED_HEADER_LEN: usize = 32;
|
||||
const RECIEVE_PAYLOAD_TIMEOUT: u64 = 30000;
|
||||
|
||||
@@ -24,11 +24,11 @@ use mio::udp::*;
|
||||
use util::sha3::*;
|
||||
use time;
|
||||
use util::hash::*;
|
||||
use util::crypto::*;
|
||||
use util::rlp::*;
|
||||
use node_table::*;
|
||||
use error::NetworkError;
|
||||
use io::{StreamToken, IoContext};
|
||||
use ethkey::{Secret, KeyPair, sign, recover};
|
||||
|
||||
use PROTOCOL_VERSION;
|
||||
|
||||
@@ -252,7 +252,7 @@ impl Discovery {
|
||||
|
||||
let bytes = rlp.drain();
|
||||
let hash = bytes.as_ref().sha3();
|
||||
let signature = match ec::sign(&self.secret, &hash) {
|
||||
let signature = match sign(&self.secret, &hash) {
|
||||
Ok(s) => s,
|
||||
Err(_) => {
|
||||
warn!("Error signing UDP packet");
|
||||
@@ -361,8 +361,8 @@ impl Discovery {
|
||||
}
|
||||
|
||||
let signed = &packet[(32 + 65)..];
|
||||
let signature = Signature::from_slice(&packet[32..(32 + 65)]);
|
||||
let node_id = try!(ec::recover(&signature, &signed.sha3()));
|
||||
let signature = H520::from_slice(&packet[32..(32 + 65)]);
|
||||
let node_id = try!(recover(&signature.into(), &signed.sha3()));
|
||||
|
||||
let packet_id = signed[0];
|
||||
let rlp = UntrustedRlp::new(&signed[1..]);
|
||||
@@ -536,9 +536,9 @@ mod tests {
|
||||
use util::hash::*;
|
||||
use std::net::*;
|
||||
use node_table::*;
|
||||
use util::crypto::KeyPair;
|
||||
use std::str::FromStr;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use ethkey::{Random, Generator};
|
||||
|
||||
#[test]
|
||||
fn find_node() {
|
||||
@@ -559,8 +559,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn discovery() {
|
||||
let key1 = KeyPair::create().unwrap();
|
||||
let key2 = KeyPair::create().unwrap();
|
||||
let key1 = Random.generate().unwrap();
|
||||
let key2 = Random.generate().unwrap();
|
||||
let ep1 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40444").unwrap(), udp_port: 40444 };
|
||||
let ep2 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40445").unwrap(), udp_port: 40445 };
|
||||
let mut discovery1 = Discovery::new(&key1, ep1.address.clone(), ep1.clone(), 0);
|
||||
@@ -594,7 +594,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn removes_expired() {
|
||||
let key = KeyPair::create().unwrap();
|
||||
let key = Random.generate().unwrap();
|
||||
let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40446").unwrap(), udp_port: 40447 };
|
||||
let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0);
|
||||
for _ in 0..1200 {
|
||||
@@ -622,7 +622,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn packets() {
|
||||
let key = KeyPair::create().unwrap();
|
||||
let key = Random.generate().unwrap();
|
||||
let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40447").unwrap(), udp_port: 40447 };
|
||||
let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0);
|
||||
discovery.check_timestamps = false;
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use io::IoError;
|
||||
use util::crypto::CryptoError;
|
||||
use util::rlp::*;
|
||||
use util::UtilError;
|
||||
use std::fmt;
|
||||
use ethkey::Error as KeyError;
|
||||
use crypto::Error as CryptoError;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum DisconnectReason
|
||||
@@ -153,6 +154,12 @@ impl From<UtilError> for NetworkError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyError> for NetworkError {
|
||||
fn from(_err: KeyError) -> Self {
|
||||
NetworkError::Auth
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CryptoError> for NetworkError {
|
||||
fn from(_err: CryptoError) -> NetworkError {
|
||||
NetworkError::Auth
|
||||
@@ -179,7 +186,7 @@ fn test_errors() {
|
||||
_ => panic!("Unexpeceted error"),
|
||||
}
|
||||
|
||||
match <NetworkError as From<CryptoError>>::from(CryptoError::InvalidSecret) {
|
||||
match <NetworkError as From<CryptoError>>::from(CryptoError::InvalidMessage) {
|
||||
NetworkError::Auth => {},
|
||||
_ => panic!("Unexpeceted error"),
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@ use util::hash::*;
|
||||
use util::rlp::*;
|
||||
use util::sha3::Hashable;
|
||||
use util::bytes::Bytes;
|
||||
use util::crypto::*;
|
||||
use util::crypto;
|
||||
use connection::{Connection};
|
||||
use host::{HostInfo};
|
||||
use node_table::NodeId;
|
||||
use error::*;
|
||||
use stats::NetworkStats;
|
||||
use io::{IoContext, StreamToken};
|
||||
use ethkey::{KeyPair, Public, Secret, recover, sign, Generator, Random};
|
||||
use crypto::{ecdh, ecies};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
enum HandshakeState {
|
||||
@@ -89,7 +89,7 @@ impl Handshake {
|
||||
connection: Connection::new(token, socket, stats),
|
||||
originated: false,
|
||||
state: HandshakeState::New,
|
||||
ecdhe: try!(KeyPair::create()),
|
||||
ecdhe: try!(Random.generate()),
|
||||
nonce: nonce.clone(),
|
||||
remote_ephemeral: Public::new(),
|
||||
remote_nonce: H256::new(),
|
||||
@@ -166,8 +166,8 @@ impl Handshake {
|
||||
self.remote_nonce.clone_from_slice(remote_nonce);
|
||||
self.remote_version = remote_version;
|
||||
let shared = try!(ecdh::agree(host_secret, &self.id));
|
||||
let signature = Signature::from_slice(sig);
|
||||
self.remote_ephemeral = try!(ec::recover(&signature, &(&shared ^ &self.remote_nonce)));
|
||||
let signature = H520::from_slice(sig);
|
||||
self.remote_ephemeral = try!(recover(&signature.into(), &(&shared ^ &self.remote_nonce)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ impl Handshake {
|
||||
self.auth_cipher.extend_from_slice(data);
|
||||
let auth = try!(ecies::decrypt(secret, &self.auth_cipher[0..2], &self.auth_cipher[2..]));
|
||||
let rlp = UntrustedRlp::new(&auth);
|
||||
let signature: Signature = try!(rlp.val_at(0));
|
||||
let signature: H520 = try!(rlp.val_at(0));
|
||||
let remote_public: Public = try!(rlp.val_at(1));
|
||||
let remote_nonce: H256 = try!(rlp.val_at(2));
|
||||
let remote_version: u64 = try!(rlp.val_at(3));
|
||||
@@ -271,13 +271,13 @@ impl Handshake {
|
||||
let (nonce, _) = rest.split_at_mut(32);
|
||||
|
||||
// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
|
||||
let shared = try!(crypto::ecdh::agree(secret, &self.id));
|
||||
try!(crypto::ec::sign(self.ecdhe.secret(), &(&shared ^ &self.nonce))).copy_to(sig);
|
||||
let shared = try!(ecdh::agree(secret, &self.id));
|
||||
sig.copy_from_slice(&*try!(sign(self.ecdhe.secret(), &(&shared ^ &self.nonce))));
|
||||
self.ecdhe.public().sha3_into(hepubk);
|
||||
public.copy_to(pubk);
|
||||
self.nonce.copy_to(nonce);
|
||||
pubk.copy_from_slice(public);
|
||||
nonce.copy_from_slice(&self.nonce);
|
||||
}
|
||||
let message = try!(crypto::ecies::encrypt(&self.id, &[], &data));
|
||||
let message = try!(ecies::encrypt(&self.id, &[], &data));
|
||||
self.auth_cipher = message.clone();
|
||||
self.connection.send(io, message);
|
||||
self.connection.expect(V4_ACK_PACKET_SIZE);
|
||||
@@ -297,7 +297,7 @@ impl Handshake {
|
||||
self.ecdhe.public().copy_to(epubk);
|
||||
self.nonce.copy_to(nonce);
|
||||
}
|
||||
let message = try!(crypto::ecies::encrypt(&self.id, &[], &data));
|
||||
let message = try!(ecies::encrypt(&self.id, &[], &data));
|
||||
self.ack_cipher = message.clone();
|
||||
self.connection.send(io, message);
|
||||
self.state = HandshakeState::StartSession;
|
||||
@@ -319,7 +319,7 @@ impl Handshake {
|
||||
let encoded = rlp.drain();
|
||||
let len = (encoded.len() + ECIES_OVERHEAD) as u16;
|
||||
let prefix = [ (len >> 8) as u8, (len & 0xff) as u8 ];
|
||||
let message = try!(crypto::ecies::encrypt(&self.id, &prefix, &encoded));
|
||||
let message = try!(ecies::encrypt(&self.id, &prefix, &encoded));
|
||||
self.ack_cipher.extend_from_slice(&prefix);
|
||||
self.ack_cipher.extend_from_slice(&message);
|
||||
self.connection.send(io, self.ack_cipher.clone());
|
||||
@@ -331,31 +331,29 @@ impl Handshake {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::sync::Arc;
|
||||
use std::str::FromStr;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use super::*;
|
||||
use util::crypto::*;
|
||||
use util::hash::*;
|
||||
use io::*;
|
||||
use std::net::SocketAddr;
|
||||
use mio::tcp::TcpStream;
|
||||
use stats::NetworkStats;
|
||||
use ethkey::Public;
|
||||
|
||||
fn check_auth(h: &Handshake, version: u64) {
|
||||
assert_eq!(h.id, Public::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap());
|
||||
assert_eq!(h.remote_nonce, H256::from_str("7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6").unwrap());
|
||||
assert_eq!(h.remote_ephemeral, Public::from_str("654d1044b69c577a44e5f01a1209523adb4026e70c62d1c13a067acabc09d2667a49821a0ad4b634554d330a15a58fe61f8a8e0544b310c6de7b0c8da7528a8d").unwrap());
|
||||
assert_eq!(h.id, "fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877".into());
|
||||
assert_eq!(h.remote_nonce, "7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6".into());
|
||||
assert_eq!(h.remote_ephemeral, "654d1044b69c577a44e5f01a1209523adb4026e70c62d1c13a067acabc09d2667a49821a0ad4b634554d330a15a58fe61f8a8e0544b310c6de7b0c8da7528a8d".into());
|
||||
assert_eq!(h.remote_version, version);
|
||||
}
|
||||
|
||||
fn check_ack(h: &Handshake, version: u64) {
|
||||
assert_eq!(h.remote_nonce, H256::from_str("559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd").unwrap());
|
||||
assert_eq!(h.remote_ephemeral, Public::from_str("b6d82fa3409da933dbf9cb0140c5dde89f4e64aec88d476af648880f4a10e1e49fe35ef3e69e93dd300b4797765a747c6384a6ecf5db9c2690398607a86181e4").unwrap());
|
||||
assert_eq!(h.remote_nonce, "559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd".into());
|
||||
assert_eq!(h.remote_ephemeral, "b6d82fa3409da933dbf9cb0140c5dde89f4e64aec88d476af648880f4a10e1e49fe35ef3e69e93dd300b4797765a747c6384a6ecf5db9c2690398607a86181e4".into());
|
||||
assert_eq!(h.remote_version, version);
|
||||
}
|
||||
|
||||
fn create_handshake(to: Option<&Public>) -> Handshake {
|
||||
let addr = SocketAddr::from_str("127.0.0.1:50556").unwrap();
|
||||
let addr = "127.0.0.1:50556".parse().unwrap();
|
||||
let socket = TcpStream::connect(&addr).unwrap();
|
||||
let nonce = H256::new();
|
||||
Handshake::new(0, to, socket, &nonce, Arc::new(NetworkStats::new())).unwrap()
|
||||
@@ -368,7 +366,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_handshake_auth_plain() {
|
||||
let mut h = create_handshake(None);
|
||||
let secret = Secret::from_str("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291").unwrap();
|
||||
let secret = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291".into();
|
||||
let auth =
|
||||
"\
|
||||
048ca79ad18e4b0659fab4853fe5bc58eb83992980f4c9cc147d2aa31532efd29a3d3dc6a3d89eaf\
|
||||
@@ -389,7 +387,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_handshake_auth_eip8() {
|
||||
let mut h = create_handshake(None);
|
||||
let secret = Secret::from_str("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291").unwrap();
|
||||
let secret = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291".into();
|
||||
let auth =
|
||||
"\
|
||||
01b304ab7578555167be8154d5cc456f567d5ba302662433674222360f08d5f1534499d3678b513b\
|
||||
@@ -415,7 +413,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_handshake_auth_eip8_2() {
|
||||
let mut h = create_handshake(None);
|
||||
let secret = Secret::from_str("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291").unwrap();
|
||||
let secret = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291".into();
|
||||
let auth =
|
||||
"\
|
||||
01b8044c6c312173685d1edd268aa95e1d495474c6959bcdd10067ba4c9013df9e40ff45f5bfd6f7\
|
||||
@@ -444,9 +442,9 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_handshake_ack_plain() {
|
||||
let remote = Public::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap();
|
||||
let remote = "fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877".into();
|
||||
let mut h = create_handshake(Some(&remote));
|
||||
let secret = Secret::from_str("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee").unwrap();
|
||||
let secret = "49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee".into();
|
||||
let ack =
|
||||
"\
|
||||
049f8abcfa9c0dc65b982e98af921bc0ba6e4243169348a236abe9df5f93aa69d99cadddaa387662\
|
||||
@@ -464,9 +462,9 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_handshake_ack_eip8() {
|
||||
let remote = Public::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap();
|
||||
let remote = "fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877".into();
|
||||
let mut h = create_handshake(Some(&remote));
|
||||
let secret = Secret::from_str("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee").unwrap();
|
||||
let secret = "49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee".into();
|
||||
let ack =
|
||||
"\
|
||||
01ea0451958701280a56482929d3b0757da8f7fbe5286784beead59d95089c217c9b917788989470\
|
||||
@@ -493,9 +491,9 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_handshake_ack_eip8_2() {
|
||||
let remote = Public::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap();
|
||||
let remote = "fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877".into();
|
||||
let mut h = create_handshake(Some(&remote));
|
||||
let secret = Secret::from_str("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee").unwrap();
|
||||
let secret = "49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee".into();
|
||||
let ack =
|
||||
"\
|
||||
01f004076e58aae772bb101ab1a8e64e01ee96e64857ce82b1113817c6cdd52c09d26f7b90981cd7\
|
||||
|
||||
@@ -23,12 +23,11 @@ use std::ops::*;
|
||||
use std::cmp::min;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::io::{Read, Write};
|
||||
use std::default::Default;
|
||||
use std::fs;
|
||||
use ethkey::{KeyPair, Secret, Random, Generator};
|
||||
use mio::*;
|
||||
use mio::tcp::*;
|
||||
use util::hash::*;
|
||||
use util::crypto::*;
|
||||
use util::Hashable;
|
||||
use util::rlp::*;
|
||||
use util::version;
|
||||
@@ -362,7 +361,7 @@ impl Host {
|
||||
} else {
|
||||
config.config_path.clone().and_then(|ref p| load_key(Path::new(&p)))
|
||||
.map_or_else(|| {
|
||||
let key = KeyPair::create().unwrap();
|
||||
let key = Random.generate().unwrap();
|
||||
if let Some(path) = config.config_path.clone() {
|
||||
save_key(Path::new(&path), key.secret());
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ extern crate rustc_serialize;
|
||||
extern crate igd;
|
||||
extern crate libc;
|
||||
extern crate slab;
|
||||
extern crate ethkey;
|
||||
extern crate ethcrypto as crypto;
|
||||
#[cfg(test)]
|
||||
extern crate ethcore_devtools as devtools;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ use std::thread;
|
||||
use std::time::*;
|
||||
use util::common::*;
|
||||
use io::TimerToken;
|
||||
use util::crypto::KeyPair;
|
||||
use ethkey::{Random, Generator};
|
||||
|
||||
pub struct TestProtocol {
|
||||
drop_session: bool,
|
||||
@@ -99,7 +99,7 @@ fn net_service() {
|
||||
#[test]
|
||||
fn net_connect() {
|
||||
::util::log::init_log();
|
||||
let key1 = KeyPair::create().unwrap();
|
||||
let key1 = Random.generate().unwrap();
|
||||
let mut config1 = NetworkConfiguration::new_local();
|
||||
config1.use_secret = Some(key1.secret().clone());
|
||||
config1.boot_nodes = vec![ ];
|
||||
@@ -130,7 +130,7 @@ fn net_start_stop() {
|
||||
|
||||
#[test]
|
||||
fn net_disconnect() {
|
||||
let key1 = KeyPair::create().unwrap();
|
||||
let key1 = Random.generate().unwrap();
|
||||
let mut config1 = NetworkConfiguration::new_local();
|
||||
config1.use_secret = Some(key1.secret().clone());
|
||||
config1.boot_nodes = vec![ ];
|
||||
|
||||
@@ -1,560 +0,0 @@
|
||||
// Copyright 2015, 2016 Ethcore (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/>.
|
||||
|
||||
//! Ethcore crypto.
|
||||
|
||||
use bigint::uint::*;
|
||||
use bigint::hash::*;
|
||||
use bytes::*;
|
||||
use secp256k1::{key, Secp256k1};
|
||||
use rand::os::OsRng;
|
||||
use sha3::Hashable;
|
||||
use std::fmt;
|
||||
use Address;
|
||||
|
||||
/// Secret key for secp256k1 EC operations. 256 bit generic "hash" data.
|
||||
pub type Secret = H256;
|
||||
/// Public key for secp256k1 EC operations. 512 bit generic "hash" data.
|
||||
pub type Public = H512;
|
||||
/// Signature for secp256k1 EC operations; encodes two 256-bit curve points
|
||||
/// and a third sign bit. 520 bit generic "hash" data.
|
||||
pub type Signature = H520;
|
||||
|
||||
lazy_static! {
|
||||
static ref SECP256K1: Secp256k1 = Secp256k1::new();
|
||||
}
|
||||
|
||||
/// Create a new signature from the R, S and V componenets.
|
||||
pub fn signature_from_rsv(r: &H256, s: &H256, v: u8) -> Signature {
|
||||
let mut ret: Signature = Signature::new();
|
||||
(&mut ret[0..32]).copy_from_slice(r);
|
||||
(&mut ret[32..64]).copy_from_slice(s);
|
||||
|
||||
ret[64] = v;
|
||||
ret
|
||||
}
|
||||
|
||||
/// Convert transaction to R, S and V components.
|
||||
pub fn signature_to_rsv(s: &Signature) -> (U256, U256, u8) {
|
||||
(U256::from(&s.as_slice()[0..32]), U256::from(&s.as_slice()[32..64]), s[64])
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Crypto error
|
||||
pub enum CryptoError {
|
||||
/// Invalid secret key
|
||||
InvalidSecret,
|
||||
/// Invalid public key
|
||||
InvalidPublic,
|
||||
/// Invalid EC signature
|
||||
InvalidSignature,
|
||||
/// Invalid AES message
|
||||
InvalidMessage,
|
||||
/// IO Error
|
||||
Io(::std::io::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for CryptoError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let msg = match *self {
|
||||
CryptoError::InvalidSecret => "Invalid secret key".into(),
|
||||
CryptoError::InvalidPublic => "Invalid public key".into(),
|
||||
CryptoError::InvalidSignature => "Invalid EC signature".into(),
|
||||
CryptoError::InvalidMessage => "Invalid AES message".into(),
|
||||
CryptoError::Io(ref err) => format!("I/O error: {}", err),
|
||||
};
|
||||
|
||||
f.write_fmt(format_args!("Crypto error ({})", msg))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::secp256k1::Error> for CryptoError {
|
||||
fn from(e: ::secp256k1::Error) -> CryptoError {
|
||||
match e {
|
||||
::secp256k1::Error::InvalidMessage => CryptoError::InvalidMessage,
|
||||
::secp256k1::Error::InvalidPublicKey => CryptoError::InvalidPublic,
|
||||
::secp256k1::Error::InvalidSecretKey => CryptoError::InvalidSecret,
|
||||
_ => CryptoError::InvalidSignature,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::std::io::Error> for CryptoError {
|
||||
fn from(err: ::std::io::Error) -> CryptoError {
|
||||
CryptoError::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
/// secp256k1 Key pair
|
||||
///
|
||||
/// Use `create()` to create a new random key pair.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util;
|
||||
/// use ethcore_util::crypto::*;
|
||||
/// use ethcore_util::hash::*;
|
||||
/// fn main() {
|
||||
/// let pair = KeyPair::create().unwrap();
|
||||
/// let message = H256::random();
|
||||
/// let signature = ec::sign(pair.secret(), &message).unwrap();
|
||||
///
|
||||
/// assert!(ec::verify(pair.public(), &signature, &message).unwrap());
|
||||
/// assert_eq!(ec::recover(&signature, &message).unwrap(), *pair.public());
|
||||
/// }
|
||||
/// ```
|
||||
pub struct KeyPair {
|
||||
secret: Secret,
|
||||
public: Public,
|
||||
}
|
||||
|
||||
impl KeyPair {
|
||||
/// Create a pair from secret key
|
||||
pub fn from_secret(secret: Secret) -> Result<KeyPair, CryptoError> {
|
||||
let context = &SECP256K1;
|
||||
let s: key::SecretKey = try!(key::SecretKey::from_slice(context, &secret));
|
||||
let pub_key = try!(key::PublicKey::from_secret_key(context, &s));
|
||||
let serialized = pub_key.serialize_vec(context, false);
|
||||
let p: Public = Public::from_slice(&serialized[1..65]);
|
||||
Ok(KeyPair {
|
||||
secret: secret,
|
||||
public: p,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// TODO: move to ethstore/secret.rs once @debris has refactored necessary dependencies into own crate
|
||||
/// Convert the given phrase into a secret as per brain-wallet spec.
|
||||
/// Taken from https://github.com/ethereum/wiki/wiki/Brain-Wallet
|
||||
/// Note particularly secure for low-entropy keys.
|
||||
pub fn from_phrase(phrase: &str) -> KeyPair {
|
||||
let mut h = phrase.as_bytes().sha3();
|
||||
for _ in 0..16384 {
|
||||
h = h.sha3();
|
||||
}
|
||||
loop {
|
||||
let r = KeyPair::from_secret(h);
|
||||
if r.is_ok() {
|
||||
let r = r.unwrap();
|
||||
if r.address()[0] == 0 {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
h = h.sha3();
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new random key pair
|
||||
pub fn create() -> Result<KeyPair, CryptoError> {
|
||||
let context = &SECP256K1;
|
||||
let mut rng = try!(OsRng::new());
|
||||
let (sec, publ) = try!(context.generate_keypair(&mut rng));
|
||||
let serialized = publ.serialize_vec(context, false);
|
||||
let p: Public = Public::from_slice(&serialized[1..65]);
|
||||
|
||||
let mut s = Secret::new();
|
||||
s.copy_from_slice(&sec[0..32]);
|
||||
|
||||
Ok(KeyPair {
|
||||
secret: s,
|
||||
public: p,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns public key
|
||||
pub fn public(&self) -> &Public {
|
||||
&self.public
|
||||
}
|
||||
|
||||
/// Returns private key
|
||||
pub fn secret(&self) -> &Secret {
|
||||
&self.secret
|
||||
}
|
||||
|
||||
/// Returns address.
|
||||
pub fn address(&self) -> Address {
|
||||
Address::from(self.public.sha3())
|
||||
}
|
||||
|
||||
/// Sign a message with our secret key.
|
||||
pub fn sign(&self, message: &H256) -> Result<Signature, CryptoError> { ec::sign(&self.secret, message) }
|
||||
}
|
||||
|
||||
/// EC functions
|
||||
#[cfg_attr(feature="dev", allow(similar_names))]
|
||||
pub mod ec {
|
||||
use bigint::hash::*;
|
||||
use bigint::uint::*;
|
||||
use standard::*;
|
||||
use crypto::*;
|
||||
use crypto::{self};
|
||||
|
||||
/// Recovers Public key from signed message hash.
|
||||
pub fn recover(signature: &Signature, message: &H256) -> Result<Public, CryptoError> {
|
||||
use secp256k1::*;
|
||||
let context = &crypto::SECP256K1;
|
||||
let rsig = try!(RecoverableSignature::from_compact(context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32))));
|
||||
let publ = try!(context.recover(&try!(Message::from_slice(&message)), &rsig));
|
||||
let serialized = publ.serialize_vec(context, false);
|
||||
let p: Public = Public::from_slice(&serialized[1..65]);
|
||||
//TODO: check if it's the zero key and fail if so.
|
||||
Ok(p)
|
||||
}
|
||||
/// Returns siganture of message hash.
|
||||
pub fn sign(secret: &Secret, message: &H256) -> Result<Signature, CryptoError> {
|
||||
// TODO: allow creation of only low-s signatures.
|
||||
use secp256k1::{Message, key};
|
||||
|
||||
let context = &crypto::SECP256K1;
|
||||
// no way to create from raw byte array.
|
||||
let sec: &key::SecretKey = unsafe { ::std::mem::transmute(secret) };
|
||||
let s = try!(context.sign_recoverable(&try!(Message::from_slice(&message)), sec));
|
||||
let (rec_id, data) = s.serialize_compact(context);
|
||||
let mut signature = crypto::Signature::new();
|
||||
signature.clone_from_slice(&data);
|
||||
signature[64] = rec_id.to_i32() as u8;
|
||||
|
||||
let (_, s, v) = signature_to_rsv(&signature);
|
||||
let secp256k1n = U256::from_str("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap();
|
||||
if !is_low_s(&s) {
|
||||
signature = super::signature_from_rsv(&H256::from_slice(&signature[0..32]), &H256::from(secp256k1n - s), v ^ 1);
|
||||
}
|
||||
Ok(signature)
|
||||
}
|
||||
|
||||
/// Verify signature.
|
||||
pub fn verify(public: &Public, signature: &Signature, message: &H256) -> Result<bool, CryptoError> {
|
||||
use secp256k1::*;
|
||||
let context = &crypto::SECP256K1;
|
||||
let rsig = try!(RecoverableSignature::from_compact(context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32))));
|
||||
let sig = rsig.to_standard(context);
|
||||
|
||||
let pdata: [u8; 65] = {
|
||||
let mut temp = [4u8; 65];
|
||||
(&mut temp[1..65]).copy_from_slice(public);
|
||||
temp
|
||||
};
|
||||
|
||||
let publ = try!(key::PublicKey::from_slice(context, &pdata));
|
||||
match context.verify(&try!(Message::from_slice(&message)), &sig, &publ) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(Error::IncorrectSignature) => Ok(false),
|
||||
Err(x) => Err(CryptoError::from(x))
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if this is a "low" signature.
|
||||
pub fn is_low(sig: &Signature) -> bool {
|
||||
H256::from_slice(&sig[32..64]) <= "7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0".into()
|
||||
}
|
||||
|
||||
/// Check if this is a "low" signature.
|
||||
pub fn is_low_s(s: &U256) -> bool {
|
||||
s <= &U256::from_str("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0").unwrap()
|
||||
}
|
||||
|
||||
/// Check if each component of the signature is in range.
|
||||
pub fn is_valid(sig: &Signature) -> bool {
|
||||
sig[64] <= 1 &&
|
||||
H256::from_slice(&sig[0..32]) < "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into() &&
|
||||
H256::from_slice(&sig[32..64]) < "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into() &&
|
||||
H256::from_slice(&sig[32..64]) >= 1.into() &&
|
||||
H256::from_slice(&sig[0..32]) >= 1.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// ECDH functions
|
||||
#[cfg_attr(feature="dev", allow(similar_names))]
|
||||
pub mod ecdh {
|
||||
use hash::FixedHash;
|
||||
use crypto::{self, Secret, Public, CryptoError};
|
||||
|
||||
/// Agree on a shared secret
|
||||
pub fn agree(secret: &Secret, public: &Public) -> Result<Secret, CryptoError> {
|
||||
use secp256k1::{ecdh, key};
|
||||
|
||||
let context = &crypto::SECP256K1;
|
||||
let pdata = {
|
||||
let mut temp = [4u8; 65];
|
||||
(&mut temp[1..65]).copy_from_slice(&public[0..64]);
|
||||
temp
|
||||
};
|
||||
|
||||
let publ = try!(key::PublicKey::from_slice(context, &pdata));
|
||||
// no way to create SecretKey from raw byte array.
|
||||
let sec: &key::SecretKey = unsafe { ::std::mem::transmute(secret) };
|
||||
let shared = ecdh::SharedSecret::new_raw(context, &publ, sec);
|
||||
|
||||
let mut s = crypto::Secret::new();
|
||||
s.copy_from_slice(&shared[0..32]);
|
||||
Ok(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// ECIES function
|
||||
#[cfg_attr(feature="dev", allow(similar_names))]
|
||||
pub mod ecies {
|
||||
use hash::*;
|
||||
use bytes::*;
|
||||
use crypto::*;
|
||||
use sha3::Hashable;
|
||||
|
||||
/// Encrypt a message with a public key
|
||||
pub fn encrypt(public: &Public, shared_mac: &[u8], plain: &[u8]) -> Result<Bytes, CryptoError> {
|
||||
use ::rcrypto::digest::Digest;
|
||||
use ::rcrypto::sha2::Sha256;
|
||||
use ::rcrypto::hmac::Hmac;
|
||||
use ::rcrypto::mac::Mac;
|
||||
let r = try!(KeyPair::create());
|
||||
let z = try!(ecdh::agree(r.secret(), public));
|
||||
let mut key = [0u8; 32];
|
||||
let mut mkey = [0u8; 32];
|
||||
kdf(&z, &[0u8; 0], &mut key);
|
||||
let mut hasher = Sha256::new();
|
||||
let mkey_material = &key[16..32];
|
||||
hasher.input(mkey_material);
|
||||
hasher.result(&mut mkey);
|
||||
let ekey = &key[0..16];
|
||||
|
||||
let mut msg = vec![0u8; (1 + 64 + 16 + plain.len() + 32)];
|
||||
msg[0] = 0x04u8;
|
||||
{
|
||||
let msgd = &mut msg[1..];
|
||||
r.public().copy_to(&mut msgd[0..64]);
|
||||
let iv = H128::random();
|
||||
iv.copy_to(&mut msgd[64..(64+16)]);
|
||||
{
|
||||
let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())];
|
||||
aes::encrypt(ekey, &iv, plain, cipher);
|
||||
}
|
||||
let mut hmac = Hmac::new(Sha256::new(), &mkey);
|
||||
{
|
||||
let cipher_iv = &msgd[64..(64 + 16 + plain.len())];
|
||||
hmac.input(cipher_iv);
|
||||
}
|
||||
hmac.input(shared_mac);
|
||||
hmac.raw_result(&mut msgd[(64 + 16 + plain.len())..]);
|
||||
}
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
/// Encrypt a message with a public key
|
||||
pub fn encrypt_single_message(public: &Public, plain: &[u8]) -> Result<Bytes, CryptoError> {
|
||||
use ::rcrypto::digest::Digest;
|
||||
use ::rcrypto::sha2::Sha256;
|
||||
let r = try!(KeyPair::create());
|
||||
let z = try!(ecdh::agree(r.secret(), public));
|
||||
let mut key = [0u8; 32];
|
||||
let mut mkey = [0u8; 32];
|
||||
kdf(&z, &[0u8; 0], &mut key);
|
||||
let mut hasher = Sha256::new();
|
||||
let mkey_material = &key[16..32];
|
||||
hasher.input(mkey_material);
|
||||
hasher.result(&mut mkey);
|
||||
let ekey = &key[0..16];
|
||||
|
||||
let mut msgd = vec![0u8; (64 + plain.len())];
|
||||
{
|
||||
r.public().copy_to(&mut msgd[0..64]);
|
||||
let iv = H128::from_slice(&z.sha3()[0..16]);
|
||||
{
|
||||
let cipher = &mut msgd[64..(64 + plain.len())];
|
||||
aes::encrypt(ekey, &iv, plain, cipher);
|
||||
}
|
||||
}
|
||||
Ok(msgd)
|
||||
}
|
||||
|
||||
/// Decrypt a message with a secret key
|
||||
pub fn decrypt(secret: &Secret, shared_mac: &[u8], encrypted: &[u8]) -> Result<Bytes, CryptoError> {
|
||||
use ::rcrypto::digest::Digest;
|
||||
use ::rcrypto::sha2::Sha256;
|
||||
use ::rcrypto::hmac::Hmac;
|
||||
use ::rcrypto::mac::Mac;
|
||||
|
||||
let meta_len = 1 + 64 + 16 + 32;
|
||||
if encrypted.len() < meta_len || encrypted[0] < 2 || encrypted[0] > 4 {
|
||||
return Err(CryptoError::InvalidMessage); //invalid message: publickey
|
||||
}
|
||||
|
||||
let e = &encrypted[1..];
|
||||
let p = Public::from_slice(&e[0..64]);
|
||||
let z = try!(ecdh::agree(secret, &p));
|
||||
let mut key = [0u8; 32];
|
||||
kdf(&z, &[0u8; 0], &mut key);
|
||||
let ekey = &key[0..16];
|
||||
let mkey_material = &key[16..32];
|
||||
let mut hasher = Sha256::new();
|
||||
let mut mkey = [0u8; 32];
|
||||
hasher.input(mkey_material);
|
||||
hasher.result(&mut mkey);
|
||||
|
||||
let clen = encrypted.len() - meta_len;
|
||||
let cipher_with_iv = &e[64..(64+16+clen)];
|
||||
let cipher_iv = &cipher_with_iv[0..16];
|
||||
let cipher_no_iv = &cipher_with_iv[16..];
|
||||
let msg_mac = &e[(64+16+clen)..];
|
||||
|
||||
// Verify tag
|
||||
let mut hmac = Hmac::new(Sha256::new(), &mkey);
|
||||
hmac.input(cipher_with_iv);
|
||||
hmac.input(shared_mac);
|
||||
let mut mac = H256::new();
|
||||
hmac.raw_result(&mut mac);
|
||||
if &mac[..] != msg_mac {
|
||||
return Err(CryptoError::InvalidMessage);
|
||||
}
|
||||
|
||||
let mut msg = vec![0u8; clen];
|
||||
aes::decrypt(ekey, cipher_iv, cipher_no_iv, &mut msg[..]);
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
/// Decrypt single message with a secret key
|
||||
pub fn decrypt_single_message(secret: &Secret, encrypted: &[u8]) -> Result<Bytes, CryptoError> {
|
||||
use ::rcrypto::digest::Digest;
|
||||
use ::rcrypto::sha2::Sha256;
|
||||
|
||||
let meta_len = 64;
|
||||
if encrypted.len() < meta_len {
|
||||
return Err(CryptoError::InvalidMessage); //invalid message: publickey
|
||||
}
|
||||
|
||||
let e = encrypted;
|
||||
let p = Public::from_slice(&e[0..64]);
|
||||
let z = try!(ecdh::agree(secret, &p));
|
||||
let mut key = [0u8; 32];
|
||||
kdf(&z, &[0u8; 0], &mut key);
|
||||
let ekey = &key[0..16];
|
||||
let mkey_material = &key[16..32];
|
||||
let mut hasher = Sha256::new();
|
||||
let mut mkey = [0u8; 32];
|
||||
hasher.input(mkey_material);
|
||||
hasher.result(&mut mkey);
|
||||
|
||||
let clen = encrypted.len() - meta_len;
|
||||
let cipher = &e[64..(64+clen)];
|
||||
let mut msg = vec![0u8; clen];
|
||||
let iv = H128::from_slice(&z.sha3()[0..16]);
|
||||
aes::decrypt(ekey, &iv, cipher, &mut msg[..]);
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) {
|
||||
use ::rcrypto::digest::Digest;
|
||||
use ::rcrypto::sha2::Sha256;
|
||||
let mut hasher = Sha256::new();
|
||||
// SEC/ISO/Shoup specify counter size SHOULD be equivalent
|
||||
// to size of hash output, however, it also notes that
|
||||
// the 4 bytes is okay. NIST specifies 4 bytes.
|
||||
let mut ctr = 1u32;
|
||||
let mut written = 0usize;
|
||||
while written < dest.len() {
|
||||
let ctrs = [(ctr >> 24) as u8, (ctr >> 16) as u8, (ctr >> 8) as u8, ctr as u8];
|
||||
hasher.input(&ctrs);
|
||||
hasher.input(secret);
|
||||
hasher.input(s1);
|
||||
hasher.result(&mut dest[written..(written + 32)]);
|
||||
hasher.reset();
|
||||
written += 32;
|
||||
ctr += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// AES encryption
|
||||
pub mod aes {
|
||||
use ::rcrypto::blockmodes::*;
|
||||
use ::rcrypto::aessafe::*;
|
||||
use ::rcrypto::symmetriccipher::*;
|
||||
use ::rcrypto::buffer::*;
|
||||
|
||||
/// Encrypt a message
|
||||
pub fn encrypt(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) {
|
||||
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
|
||||
encryptor.encrypt(&mut RefReadBuffer::new(plain), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
|
||||
}
|
||||
|
||||
/// Decrypt a message
|
||||
pub fn decrypt(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) {
|
||||
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
|
||||
encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hash::*;
|
||||
use crypto::*;
|
||||
|
||||
// TODO: tests for sign/recover roundtrip, at least.
|
||||
|
||||
#[test]
|
||||
fn test_signature() {
|
||||
let pair = KeyPair::create().unwrap();
|
||||
let message = H256::random();
|
||||
let signature = ec::sign(pair.secret(), &message).unwrap();
|
||||
|
||||
assert!(ec::verify(pair.public(), &signature, &message).unwrap());
|
||||
assert_eq!(ec::recover(&signature, &message).unwrap(), *pair.public());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_key() {
|
||||
assert!(KeyPair::from_secret("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".into()).is_err());
|
||||
assert!(KeyPair::from_secret("0000000000000000000000000000000000000000000000000000000000000000".into()).is_err());
|
||||
assert!(KeyPair::from_secret("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_key() {
|
||||
let pair = KeyPair::from_secret("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2".into()).unwrap();
|
||||
assert_eq!(pair.public().hex(), "101b3ef5a4ea7a1c7928e24c4c75fd053c235d7b80c22ae5c03d145d0ac7396e2a4ffff9adee3133a7b05044a5cee08115fd65145e5165d646bde371010d803c");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_key_from_phrase() {
|
||||
assert_eq!(KeyPair::from_phrase("correct horse battery staple").address(), "0021f80b7f29b9c84e8099c2c6c74a46ed2268c4".into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ecies_shared() {
|
||||
let kp = KeyPair::create().unwrap();
|
||||
let message = b"So many books, so little time";
|
||||
|
||||
let shared = b"shared";
|
||||
let wrong_shared = b"incorrect";
|
||||
let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap();
|
||||
assert!(encrypted[..] != message[..]);
|
||||
assert_eq!(encrypted[0], 0x04);
|
||||
|
||||
assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err());
|
||||
let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap();
|
||||
assert_eq!(decrypted[..message.len()], message[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ecies_shared_single() {
|
||||
let kp = KeyPair::create().unwrap();
|
||||
let message = b"So many books, so little time";
|
||||
let encrypted = ecies::encrypt_single_message(kp.public(), message).unwrap();
|
||||
assert!(encrypted[..] != message[..]);
|
||||
let decrypted = ecies::decrypt_single_message(kp.secret(), &encrypted).unwrap();
|
||||
assert_eq!(decrypted[..message.len()], message[..]);
|
||||
}
|
||||
}
|
||||
@@ -44,8 +44,6 @@ impl fmt::Display for BaseDataError {
|
||||
#[derive(Debug)]
|
||||
/// General error type which should be capable of representing all errors in ethcore.
|
||||
pub enum UtilError {
|
||||
/// Error concerning the crypto utility subsystem.
|
||||
Crypto(::crypto::CryptoError),
|
||||
/// Error concerning the Rust standard library's IO subsystem.
|
||||
StdIo(::std::io::Error),
|
||||
/// Error concerning the hex conversion logic.
|
||||
@@ -65,7 +63,6 @@ pub enum UtilError {
|
||||
impl fmt::Display for UtilError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
UtilError::Crypto(ref err) => f.write_fmt(format_args!("{}", err)),
|
||||
UtilError::StdIo(ref err) => f.write_fmt(format_args!("{}", err)),
|
||||
UtilError::FromHex(ref err) => f.write_fmt(format_args!("{}", err)),
|
||||
UtilError::BaseData(ref err) => f.write_fmt(format_args!("{}", err)),
|
||||
@@ -134,12 +131,6 @@ impl From<::std::io::Error> for UtilError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::crypto::CryptoError> for UtilError {
|
||||
fn from(err: ::crypto::CryptoError) -> UtilError {
|
||||
UtilError::Crypto(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::rlp::DecoderError> for UtilError {
|
||||
fn from(err: ::rlp::DecoderError) -> UtilError {
|
||||
UtilError::Decoder(err)
|
||||
|
||||
@@ -132,7 +132,6 @@ pub mod migration;
|
||||
pub mod overlaydb;
|
||||
pub mod journaldb;
|
||||
pub mod kvdb;
|
||||
pub mod crypto;
|
||||
pub mod triehash;
|
||||
pub mod trie;
|
||||
pub mod nibbleslice;
|
||||
@@ -150,7 +149,6 @@ pub use hashdb::*;
|
||||
pub use memorydb::*;
|
||||
pub use overlaydb::*;
|
||||
pub use journaldb::JournalDB;
|
||||
pub use crypto::*;
|
||||
pub use triehash::*;
|
||||
pub use trie::{Trie, TrieMut, TrieDB, TrieDBMut, TrieFactory, TrieError, SecTrieDB, SecTrieDBMut};
|
||||
pub use nibbleslice::*;
|
||||
@@ -162,3 +160,5 @@ pub use timer::*;
|
||||
/// 160-bit integer representing account address
|
||||
pub type Address = H160;
|
||||
|
||||
/// Secret
|
||||
pub type Secret = H256;
|
||||
|
||||
Reference in New Issue
Block a user