Validating sha3 of a dapp bundle (#1993)
* Validating sha3 of a file * sha3 in utils * Removing devtools
This commit is contained in:
parent
3dd1bdda50
commit
33e0a234f2
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -289,6 +289,7 @@ version = "1.4.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clippy 0.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clippy 0.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethabi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ethcore-devtools 1.4.0",
|
||||||
"ethcore-rpc 1.4.0",
|
"ethcore-rpc 1.4.0",
|
||||||
"ethcore-util 1.4.0",
|
"ethcore-util 1.4.0",
|
||||||
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
"hyper 0.9.4 (git+https://github.com/ethcore/hyper)",
|
||||||
@ -502,6 +503,7 @@ dependencies = [
|
|||||||
"table 0.1.0",
|
"table 0.1.0",
|
||||||
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"using_queue 0.1.0",
|
"using_queue 0.1.0",
|
||||||
"vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -30,7 +30,8 @@ use hyper::Control;
|
|||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
|
|
||||||
use random_filename;
|
use random_filename;
|
||||||
use util::Mutex;
|
use util::{Mutex, H256};
|
||||||
|
use util::sha3::sha3;
|
||||||
use page::LocalPageEndpoint;
|
use page::LocalPageEndpoint;
|
||||||
use handlers::{ContentHandler, AppFetcherHandler, DappHandler};
|
use handlers::{ContentHandler, AppFetcherHandler, DappHandler};
|
||||||
use endpoint::{Endpoint, EndpointPath, Handler};
|
use endpoint::{Endpoint, EndpointPath, Handler};
|
||||||
@ -137,10 +138,12 @@ impl<R: URLHint> AppFetcher<R> {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
ManifestNotFound,
|
|
||||||
ManifestSerialization(String),
|
|
||||||
Io(io::Error),
|
Io(io::Error),
|
||||||
Zip(zip::result::ZipError),
|
Zip(zip::result::ZipError),
|
||||||
|
InvalidDappId,
|
||||||
|
ManifestNotFound,
|
||||||
|
ManifestSerialization(String),
|
||||||
|
HashMismatch { expected: H256, got: H256, },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<io::Error> for ValidationError {
|
impl From<io::Error> for ValidationError {
|
||||||
@ -198,8 +201,15 @@ impl DappHandler for DappInstaller {
|
|||||||
|
|
||||||
fn validate_and_install(&self, app_path: PathBuf) -> Result<Manifest, ValidationError> {
|
fn validate_and_install(&self, app_path: PathBuf) -> Result<Manifest, ValidationError> {
|
||||||
trace!(target: "dapps", "Opening dapp bundle at {:?}", app_path);
|
trace!(target: "dapps", "Opening dapp bundle at {:?}", app_path);
|
||||||
// TODO [ToDr] Validate file hash
|
let mut file = try!(fs::File::open(app_path));
|
||||||
let file = try!(fs::File::open(app_path));
|
let hash = try!(sha3(&mut file));
|
||||||
|
let dapp_id = try!(self.dapp_id.as_str().parse().map_err(|_| ValidationError::InvalidDappId));
|
||||||
|
if dapp_id != hash {
|
||||||
|
return Err(ValidationError::HashMismatch {
|
||||||
|
expected: dapp_id,
|
||||||
|
got: hash,
|
||||||
|
});
|
||||||
|
}
|
||||||
// Unpack archive
|
// Unpack archive
|
||||||
let mut zip = try!(zip::ZipArchive::new(file));
|
let mut zip = try!(zip::ZipArchive::new(file));
|
||||||
// First find manifest file
|
// First find manifest file
|
||||||
|
@ -55,11 +55,11 @@ extern crate rand;
|
|||||||
extern crate ethabi;
|
extern crate ethabi;
|
||||||
extern crate jsonrpc_core;
|
extern crate jsonrpc_core;
|
||||||
extern crate jsonrpc_http_server;
|
extern crate jsonrpc_http_server;
|
||||||
|
extern crate mime_guess;
|
||||||
|
extern crate rustc_serialize;
|
||||||
extern crate parity_dapps;
|
extern crate parity_dapps;
|
||||||
extern crate ethcore_rpc;
|
extern crate ethcore_rpc;
|
||||||
extern crate ethcore_util as util;
|
extern crate ethcore_util as util;
|
||||||
extern crate mime_guess;
|
|
||||||
extern crate rustc_serialize;
|
|
||||||
|
|
||||||
mod endpoint;
|
mod endpoint;
|
||||||
mod apps;
|
mod apps;
|
||||||
|
@ -67,13 +67,21 @@ impl RandomTempPath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<Path> for RandomTempPath {
|
||||||
|
fn as_ref(&self) -> &Path {
|
||||||
|
self.as_path()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for RandomTempPath {
|
impl Drop for RandomTempPath {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Err(e) = fs::remove_dir_all(self.as_path()) {
|
if let Err(_) = fs::remove_dir_all(&self) {
|
||||||
|
if let Err(e) = fs::remove_file(&self) {
|
||||||
panic!("Failed to remove temp directory. Here's what prevented this from happening: ({})", e);
|
panic!("Failed to remove temp directory. Here's what prevented this from happening: ({})", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct GuardedTempResult<T> {
|
pub struct GuardedTempResult<T> {
|
||||||
pub result: Option<T>,
|
pub result: Option<T>,
|
||||||
|
@ -32,6 +32,7 @@ parking_lot = "0.2.6"
|
|||||||
using_queue = { path = "using_queue" }
|
using_queue = { path = "using_queue" }
|
||||||
table = { path = "table" }
|
table = { path = "table" }
|
||||||
ansi_term = "0.7"
|
ansi_term = "0.7"
|
||||||
|
tiny-keccak= "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
@ -112,6 +112,7 @@ extern crate parking_lot;
|
|||||||
pub extern crate using_queue;
|
pub extern crate using_queue;
|
||||||
pub extern crate table;
|
pub extern crate table;
|
||||||
extern crate ansi_term;
|
extern crate ansi_term;
|
||||||
|
extern crate tiny_keccak;
|
||||||
|
|
||||||
pub mod bloom;
|
pub mod bloom;
|
||||||
pub mod standard;
|
pub mod standard;
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
//! Wrapper around tiny-keccak crate.
|
//! Wrapper around tiny-keccak crate.
|
||||||
extern crate sha3 as sha3_ext;
|
extern crate sha3 as sha3_ext;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
use std::mem::uninitialized;
|
use std::mem::uninitialized;
|
||||||
|
use tiny_keccak::Keccak;
|
||||||
use bytes::{BytesConvertable, Populatable};
|
use bytes::{BytesConvertable, Populatable};
|
||||||
use hash::{H256, FixedHash};
|
use hash::{H256, FixedHash};
|
||||||
use self::sha3_ext::*;
|
use self::sha3_ext::*;
|
||||||
@ -64,6 +66,31 @@ impl<T> Hashable for T where T: BytesConvertable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate SHA3 of given stream.
|
||||||
|
pub fn sha3<R: io::Read>(r: &mut R) -> Result<H256, io::Error> {
|
||||||
|
let mut output = [0u8; 32];
|
||||||
|
let mut input = [0u8; 1024];
|
||||||
|
let mut sha3 = Keccak::new_keccak256();
|
||||||
|
|
||||||
|
// read file
|
||||||
|
loop {
|
||||||
|
let some = try!(r.read(&mut input));
|
||||||
|
if some == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sha3.update(&input[0..some]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sha3.finalize(&mut output);
|
||||||
|
Ok(output.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::fs;
|
||||||
|
use std::io::Write;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sha3_empty() {
|
fn sha3_empty() {
|
||||||
assert_eq!([0u8; 0].sha3(), SHA3_EMPTY);
|
assert_eq!([0u8; 0].sha3(), SHA3_EMPTY);
|
||||||
@ -73,3 +100,22 @@ fn sha3_as() {
|
|||||||
assert_eq!([0x41u8; 32].sha3(), From::from("59cad5948673622c1d64e2322488bf01619f7ff45789741b15a9f782ce9290a8"));
|
assert_eq!([0x41u8; 32].sha3(), From::from("59cad5948673622c1d64e2322488bf01619f7ff45789741b15a9f782ce9290a8"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_sha3_a_file() {
|
||||||
|
// given
|
||||||
|
use devtools::RandomTempPath;
|
||||||
|
let path = RandomTempPath::new();
|
||||||
|
// Prepare file
|
||||||
|
{
|
||||||
|
let mut file = fs::File::create(&path).unwrap();
|
||||||
|
file.write_all(b"something").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut file = fs::File::open(&path).unwrap();
|
||||||
|
// when
|
||||||
|
let hash = sha3(&mut file).unwrap();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(format!("{:?}", hash), "68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user