From 2a7c56aef796964bedb27ac7fff1e212b4a98c91 Mon Sep 17 00:00:00 2001
From: Gav Wood <i@gavwood.com>
Date: Sat, 25 Jul 2015 20:47:05 +0200
Subject: [PATCH] Introduce vector_ref::cleanse, code adapted from openSSL.
 Introduce secure_vector and bytesSec, make Secret auto-cleansing.

---
 alethzero/MainWin.cpp              |  4 ++--
 ethminer/CMakeLists.txt            |  1 +
 libdevcore/Common.h                | 10 ++++++++++
 libdevcore/FixedHash.h             |  2 ++
 libdevcore/vector_ref.h            | 20 ++++++++++++++++++++
 libdevcrypto/Common.cpp            | 14 +++++++-------
 libdevcrypto/Common.h              | 12 ++++++++++--
 libdevcrypto/CryptoPP.cpp          |  2 +-
 libdevcrypto/CryptoPP.h            |  2 +-
 libdevcrypto/ECDHE.h               |  2 +-
 libdevcrypto/SecretStore.cpp       |  4 ++--
 libdevcrypto/SecretStore.h         |  4 ++--
 libethcore/CMakeLists.txt          |  4 +---
 libethcore/Common.cpp              |  2 +-
 libethereum/BlockChain.cpp         |  7 ++-----
 libethereum/BlockChain.h           | 13 +++++++++++--
 libethereum/CanonBlockChain.cpp    |  1 +
 libethereum/CanonBlockChain.h      |  5 ++++-
 libethereumx/Ethereum.cpp          |  4 ++--
 libethereumx/Ethereum.h            |  4 ++--
 libweb3jsonrpc/JsonHelper.cpp      |  2 +-
 libweb3jsonrpc/JsonHelper.h        |  2 +-
 libwhisper/CMakeLists.txt          |  4 ++--
 libwhisper/Interface.h             |  4 ++--
 libwhisper/Message.cpp             |  2 +-
 libwhisper/Message.h               |  4 ++--
 mix/ClientModel.h                  |  2 +-
 test/libdevcrypto/crypto.cpp       |  4 ++--
 test/libethereum/stateOriginal.cpp |  4 ++--
 29 files changed, 97 insertions(+), 48 deletions(-)

diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 812721b53..b24d89a30 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -360,8 +360,8 @@ void Main::refreshWhisper()
 
 void Main::addNewId(QString _ids)
 {
-	Secret _id = jsToSecret(_ids.toStdString());
-	KeyPair kp(_id);
+	Secret const& id = jsToSecret(_ids.toStdString());
+	KeyPair kp(id);
 	m_myIdentities.push_back(kp);
 	m_server->setIdentities(keysAsVector(owned()));
 	refreshWhisper();
diff --git a/ethminer/CMakeLists.txt b/ethminer/CMakeLists.txt
index 8b79afd72..cda6aa8b8 100644
--- a/ethminer/CMakeLists.txt
+++ b/ethminer/CMakeLists.txt
@@ -30,6 +30,7 @@ endif()
 
 target_link_libraries(${EXECUTABLE} ethcore)
 target_link_libraries(${EXECUTABLE} ethash)
+target_link_libraries(${EXECUTABLE} devcrypto)
 
 if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
 	eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
diff --git a/libdevcore/Common.h b/libdevcore/Common.h
index 612b7c685..0d632a550 100644
--- a/libdevcore/Common.h
+++ b/libdevcore/Common.h
@@ -79,6 +79,16 @@ using bytes = std::vector<byte>;
 using bytesRef = vector_ref<byte>;
 using bytesConstRef = vector_ref<byte const>;
 
+template <class T>
+class secure_vector: public std::vector<T>
+{
+public:
+	template <class ... Args> secure_vector(Args&& ... _args): std::vector<T>(_args ...) {}
+	~secure_vector() { vector_ref<T>(this).cleanse(); }
+};
+
+using bytesSec = secure_vector<byte>;
+
 // Numeric types.
 using bigint = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>>;
 using u64 =  boost::multiprecision::number<boost::multiprecision::cpp_int_backend<64, 64, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h
index 3127b349a..98d457da3 100644
--- a/libdevcore/FixedHash.h
+++ b/libdevcore/FixedHash.h
@@ -214,6 +214,8 @@ public:
 		return ret;
 	}
 
+	void clear() { m_data.fill(0); }
+
 private:
 	std::array<byte, N> m_data;		///< The binary data.
 };
diff --git a/libdevcore/vector_ref.h b/libdevcore/vector_ref.h
index b05342f71..6f2bff5bd 100644
--- a/libdevcore/vector_ref.h
+++ b/libdevcore/vector_ref.h
@@ -9,6 +9,8 @@
 namespace dev
 {
 
+static unsigned char s_cleanseCounter = 0;
+
 /**
  * A modifiable reference to an existing object or vector in memory.
  */
@@ -65,6 +67,24 @@ public:
 	void copyTo(vector_ref<typename std::remove_const<_T>::type> _t) const { if (overlapsWith(_t)) memmove(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); else memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); }
 	/// Copies the contents of this vector_ref to the contents of @a _t, and zeros further trailing elements in @a _t.
 	void populate(vector_ref<typename std::remove_const<_T>::type> _t) const { copyTo(_t); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); }
+	/// Securely overwrite the memory.
+	/// @note adapted from OpenSSL's implementation.
+	void cleanse()
+	{
+		uint8_t* p = (uint8_t*)begin();
+		size_t len = (uint8_t*)end() - p;
+		size_t loop = len;
+		size_t count = s_cleanseCounter;
+		while (loop--)
+		{
+			*(p++) = (uint8_t)count;
+			count += (17 + ((size_t)p & 0xf));
+		}
+		p = (uint8_t*)memchr((uint8_t*)begin(), (uint8_t)count, len);
+		if (p)
+			count += (63 + (size_t)p);
+		s_cleanseCounter = (uint8_t)count;
+	}
 
 	_T* begin() { return m_data; }
 	_T* end() { return m_data + m_count; }
diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp
index 7cc16bd03..b64535f51 100644
--- a/libdevcrypto/Common.cpp
+++ b/libdevcrypto/Common.cpp
@@ -272,6 +272,13 @@ bytes dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uin
 	return ret;
 }
 
+void KeyPair::populateFromSecret(Secret const& _sec)
+{
+	m_secret = _sec;
+	if (s_secp256k1pp.verifySecret(m_secret, m_public))
+		m_address = toAddress(m_public);
+}
+
 KeyPair KeyPair::create()
 {
 	for (int i = 0; i < 100; ++i)
@@ -283,13 +290,6 @@ KeyPair KeyPair::create()
 	return KeyPair();
 }
 
-KeyPair::KeyPair(h256 _sec):
-	m_secret(_sec)
-{
-	if (s_secp256k1pp.verifySecret(m_secret, m_public))
-		m_address = toAddress(m_public);
-}
-
 KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
 {
 	return KeyPair(sha3(aesDecrypt(_seed, _password)));
diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h
index 9aeb85a4c..44d1c8155 100644
--- a/libdevcrypto/Common.h
+++ b/libdevcrypto/Common.h
@@ -34,7 +34,13 @@ namespace dev
 
 /// A secret key: 32 bytes.
 /// @NOTE This is not endian-specific; it's just a bunch of bytes.
-using Secret = h256;
+class Secret: public h256
+{
+public:
+	template <class ... Args> Secret(Args&& ... _args): h256(_args ...) {}
+	Secret(bytesSec const& _b): h256(bytesConstRef(&_b)) {}
+	~Secret() { ref().cleanse(); }
+};
 
 /// A public key: 64 bytes.
 /// @NOTE This is not endian-specific; it's just a bunch of bytes.
@@ -151,7 +157,7 @@ public:
 	KeyPair() {}
 
 	/// Normal constructor - populates object from the given secret key.
-	KeyPair(Secret _k);
+	KeyPair(Secret const& _k) { populateFromSecret(_k); }
 
 	/// Create a new, randomly generated object.
 	static KeyPair create();
@@ -174,6 +180,8 @@ public:
 	bool operator!=(KeyPair const& _c) const { return m_secret != _c.m_secret; }
 
 private:
+	void populateFromSecret(Secret const& _k);
+
 	Secret m_secret;
 	Public m_public;
 	Address m_address;
diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp
index 8beb8e495..693952d5f 100644
--- a/libdevcrypto/CryptoPP.cpp
+++ b/libdevcrypto/CryptoPP.cpp
@@ -33,7 +33,7 @@ static_assert(dev::Secret::size == 32, "Secret key must be 32 bytes.");
 static_assert(dev::Public::size == 64, "Public key must be 64 bytes.");
 static_assert(dev::Signature::size == 65, "Signature must be 65 bytes.");
 
-bytes Secp256k1PP::eciesKDF(Secret _z, bytes _s1, unsigned kdByteLen)
+bytes Secp256k1PP::eciesKDF(Secret const& _z, bytes _s1, unsigned kdByteLen)
 {
 	auto reps = ((kdByteLen + 7) * 8) / (CryptoPP::SHA256::BLOCKSIZE * 8);
 	// SEC/ISO/Shoup specify counter size SHOULD be equivalent
diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h
index 6a0453330..fca094242 100644
--- a/libdevcrypto/CryptoPP.h
+++ b/libdevcrypto/CryptoPP.h
@@ -87,7 +87,7 @@ public:
 	bool decryptECIES(Secret const& _k, bytes& io_text);
 	
 	/// Key derivation function used by encryptECIES and decryptECIES.
-	bytes eciesKDF(Secret _z, bytes _s1, unsigned kdBitLen = 256);
+	bytes eciesKDF(Secret const& _z, bytes _s1, unsigned kdBitLen = 256);
 	
 	/// @returns siganture of message.
 	Signature sign(Secret const& _k, bytesConstRef _message);
diff --git a/libdevcrypto/ECDHE.h b/libdevcrypto/ECDHE.h
index 0fd5a8d3f..1a2442727 100644
--- a/libdevcrypto/ECDHE.h
+++ b/libdevcrypto/ECDHE.h
@@ -39,7 +39,7 @@ using AliasSession = std::pair<Public,h256>;
 class Alias
 {
 public:
-	Alias(Secret _s): m_secret(_s) {};
+	Alias(Secret const& _s): m_secret(_s) {};
 	
 	AliasSession session(Address _a) { return m_sessions.count(_a) ? m_sessions.find(_a)->second : AliasSession(); }
 	
diff --git a/libdevcrypto/SecretStore.cpp b/libdevcrypto/SecretStore.cpp
index 55c944e8e..b823ba02f 100644
--- a/libdevcrypto/SecretStore.cpp
+++ b/libdevcrypto/SecretStore.cpp
@@ -91,13 +91,13 @@ SecretStore::SecretStore(string const& _path): m_path(_path)
 	load();
 }
 
-bytes SecretStore::secret(h128 const& _uuid, function<string()> const& _pass, bool _useCache) const
+bytesSec SecretStore::secret(h128 const& _uuid, function<string()> const& _pass, bool _useCache) const
 {
 	auto rit = m_cached.find(_uuid);
 	if (_useCache && rit != m_cached.end())
 		return rit->second;
 	auto it = m_keys.find(_uuid);
-	bytes key;
+	bytesSec key;
 	if (it != m_keys.end())
 	{
 		key = decrypt(it->second.encryptedKey, _pass());
diff --git a/libdevcrypto/SecretStore.h b/libdevcrypto/SecretStore.h
index 029630b4e..ea08a48b2 100644
--- a/libdevcrypto/SecretStore.h
+++ b/libdevcrypto/SecretStore.h
@@ -52,7 +52,7 @@ public:
 	/// @returns the secret key stored by the given @a _uuid.
 	/// @param _pass function that returns the password for the key.
 	/// @param _useCache if true, allow previously decrypted keys to be returned directly.
-	bytes secret(h128 const& _uuid, std::function<std::string()> const& _pass, bool _useCache = true) const;
+	bytesSec secret(h128 const& _uuid, std::function<std::string()> const& _pass, bool _useCache = true) const;
 	/// Imports the (encrypted) key stored in the file @a _file and copies it to the managed directory.
 	h128 importKey(std::string const& _file) { auto ret = readKey(_file, false); if (ret) save(); return ret; }
 	/// Imports the (encrypted) key contained in the json formatted @a _content and stores it in
@@ -107,7 +107,7 @@ private:
 	static bytes decrypt(std::string const& _v, std::string const& _pass);
 
 	/// Stores decrypted keys by uuid.
-	mutable std::unordered_map<h128, bytes> m_cached;
+	mutable std::unordered_map<h128, bytesSec> m_cached;
 	/// Stores encrypted keys together with the file they were loaded from by uuid.
 	std::unordered_map<h128, EncryptedKey> m_keys;
 
diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt
index 73ea75c8c..d740da2a2 100644
--- a/libethcore/CMakeLists.txt
+++ b/libethcore/CMakeLists.txt
@@ -23,13 +23,11 @@ file(GLOB HEADERS "*.h")
 add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
 
 target_link_libraries(${EXECUTABLE} ethash)
-target_link_libraries(${EXECUTABLE} devcrypto)
 target_link_libraries(${EXECUTABLE} evmcore)
-
 if (ETHASHCL)
 	target_link_libraries(${EXECUTABLE} ethash-cl)
 endif ()
-
+target_link_libraries(${EXECUTABLE} devcrypto)
 if (CPUID_FOUND)
 	target_link_libraries(${EXECUTABLE} ${CPUID_LIBRARIES})
 endif ()
diff --git a/libethcore/Common.cpp b/libethcore/Common.cpp
index b95564b9b..85121c4f0 100644
--- a/libethcore/Common.cpp
+++ b/libethcore/Common.cpp
@@ -65,7 +65,7 @@ Network resetNetwork(Network _n)
 	c_gasLimitBoundDivisor = 1024;
 	c_minimumDifficulty = 131072;
 	c_difficultyBoundDivisor = 2048;
-	c_durationLimit = c_network == Network::Turbo ? 2 : c_network == Network::Olympic ? 8 : 12;
+	c_durationLimit = c_network == Network::Turbo ? 2 : c_network == Network::Olympic ? 8 : 13;
 	c_blockReward = c_network == Network::Olympic ? (1500 * finney) : (5 * ether);
 	return _n;
 }
diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp
index 37fd68673..d639ba428 100644
--- a/libethereum/BlockChain.cpp
+++ b/libethereum/BlockChain.cpp
@@ -152,7 +152,7 @@ BlockChain::BlockChain(bytes const& _genesisBlock, std::unordered_map<Address, A
 	open(_genesisBlock, _genesisState, _path, _we, _p);
 }
 
-void BlockChain::open(bytes const& _genesisBlock, std::unordered_map<Address, Account> const& _genesisState, std::string const& _path, WithExisting _we, ProgressCallback const& _p)
+void BlockChain::open(bytes const& _genesisBlock, std::unordered_map<Address, Account> const& _genesisState, std::string const& _path, WithExisting, ProgressCallback const&)
 {
 	// initialise deathrow.
 	m_cacheUsage.resize(c_collectionQueueSize);
@@ -165,9 +165,6 @@ void BlockChain::open(bytes const& _genesisBlock, std::unordered_map<Address, Ac
 
 	// remove the next line real soon. we don't need to be supporting this forever.
 	upgradeDatabase(_path, genesisHash());
-
-	if (openDatabase(_path, _we) != c_minorProtocolVersion)
-		rebuild(_path, _p);
 }
 
 BlockChain::~BlockChain()
@@ -289,7 +286,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
 	// Keep extras DB around, but under a temp name
 	delete m_extrasDB;
 	m_extrasDB = nullptr;
-	boost::filesystem::rename(path + "/details", path + "/extras.old");
+	boost::filesystem::rename(extrasPath + "/extras", extrasPath + "/extras.old");
 	ldb::DB* oldExtrasDB;
 	ldb::Options o;
 	o.create_if_missing = true;
diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h
index 9c81f85f1..c047fc4b6 100644
--- a/libethereum/BlockChain.h
+++ b/libethereum/BlockChain.h
@@ -104,6 +104,8 @@ public:
 class BlockChain
 {
 public:
+	/// Doesn't open the database - if you want it open it's up to you to subclass this and open it
+	/// in the constructor there.
 	BlockChain(bytes const& _genesisBlock, StateDefinition const& _genesisState, std::string const& _path, WithExisting _we = WithExisting::Trust, ProgressCallback const& _p = ProgressCallback());
 	~BlockChain();
 
@@ -292,13 +294,20 @@ public:
 protected:
 	static h256 chunkId(unsigned _level, unsigned _index) { return h256(_index * 0xff + _level); }
 
-	/// Initialise everything and open the database.
+	/// Initialise everything and ready for openning the database.
 	void open(bytes const& _genesisBlock, std::unordered_map<Address, Account> const& _genesisState, std::string const& _path, WithExisting _we, ProgressCallback const& _p);
 	/// Open the database.
-	unsigned openDatabase(std::string const& _path, WithExisting _we = WithExisting::Trust);
+	unsigned openDatabase(std::string const& _path, WithExisting _we);
 	/// Finalise everything and close the database.
 	void close();
 
+	/// Open the database, rebuilding if necessary.
+	void openDatabase(std::string const& _path, WithExisting _we, ProgressCallback const& _pc)
+	{
+		if (openDatabase(_path, _we) != c_minorProtocolVersion || _we == WithExisting::Verify)
+			rebuild(_path, _pc);
+	}
+
 	template<class T, class K, unsigned N> T queryExtras(K const& _h, std::unordered_map<K, T>& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const
 	{
 		{
diff --git a/libethereum/CanonBlockChain.cpp b/libethereum/CanonBlockChain.cpp
index 2a7408437..b921d67e4 100644
--- a/libethereum/CanonBlockChain.cpp
+++ b/libethereum/CanonBlockChain.cpp
@@ -47,6 +47,7 @@ bytes CanonBlockChain<Ethash>::s_genesisExtraData;
 CanonBlockChain<Ethash>::CanonBlockChain(std::string const& _path, WithExisting _we, ProgressCallback const& _pc):
 	FullBlockChain<Ethash>(createGenesisBlock(), createGenesisState(), _path, _we, _pc)
 {
+	BlockChain::openDatabase(_path, _we, _pc);
 }
 
 void CanonBlockChain<Ethash>::reopen(WithExisting _we, ProgressCallback const& _pc)
diff --git a/libethereum/CanonBlockChain.h b/libethereum/CanonBlockChain.h
index d09108b38..0ff9c6521 100644
--- a/libethereum/CanonBlockChain.h
+++ b/libethereum/CanonBlockChain.h
@@ -52,7 +52,10 @@ class CanonBlockChain: public FullBlockChain<Sealer>
 public:
 	CanonBlockChain(WithExisting _we = WithExisting::Trust, ProgressCallback const& _pc = ProgressCallback()): CanonBlockChain<Sealer>(std::string(), _we, _pc) {}
 	CanonBlockChain(std::string const& _path, WithExisting _we = WithExisting::Trust, ProgressCallback const& _pc = ProgressCallback()):
-		FullBlockChain<Sealer>(createGenesisBlock(), StateDefinition(), _path, _we, _pc) {}
+		FullBlockChain<Sealer>(createGenesisBlock(), StateDefinition(), _path, _we, _pc)
+	{
+		BlockChain::openDatabase(_path, _we, _pc);
+	}
 	~CanonBlockChain() {}
 
 	/// @returns the genesis block as its RLP-encoded byte array.
diff --git a/libethereumx/Ethereum.cpp b/libethereumx/Ethereum.cpp
index 8ab4243a1..675614c1a 100644
--- a/libethereumx/Ethereum.cpp
+++ b/libethereumx/Ethereum.cpp
@@ -83,7 +83,7 @@ void Ethereum::connect(std::string const& _seedHost, unsigned short _port)
 {
 }
 
-void Ethereum::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
+void Ethereum::submitTransaction(Secret const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
 {
 }
 
@@ -92,7 +92,7 @@ bytes Ethereum::call(Address const& _from, u256 _value, Address _dest, bytes con
 	return bytes();
 }
 
-Address Ethereum::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice)
+Address Ethereum::submitTransaction(Secret const& _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice)
 {
 	return Address();
 }
diff --git a/libethereumx/Ethereum.h b/libethereumx/Ethereum.h
index 0e81b8e0c..1e24b396c 100644
--- a/libethereumx/Ethereum.h
+++ b/libethereumx/Ethereum.h
@@ -62,11 +62,11 @@ public:
 	~Ethereum();
 
 	/// Submits the given message-call transaction.
-	void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
+	void submitTransaction(Secret const& _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
 
 	/// Submits a new contract-creation transaction.
 	/// @returns the new contract's address (assuming it all goes through).
-	Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
+	Address submitTransaction(Secret const& _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
 
 	/// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
 	void inject(bytesConstRef _rlp);
diff --git a/libweb3jsonrpc/JsonHelper.cpp b/libweb3jsonrpc/JsonHelper.cpp
index c074525b9..9ccad947d 100644
--- a/libweb3jsonrpc/JsonHelper.cpp
+++ b/libweb3jsonrpc/JsonHelper.cpp
@@ -482,7 +482,7 @@ shh::Message toMessage(Json::Value const& _json)
 	return ret;
 }
 
-shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, Secret _from)
+shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, Secret const& _from)
 {
 	unsigned ttl = 50;
 	unsigned workToProve = 50;
diff --git a/libweb3jsonrpc/JsonHelper.h b/libweb3jsonrpc/JsonHelper.h
index 11219fc55..9be59bcab 100644
--- a/libweb3jsonrpc/JsonHelper.h
+++ b/libweb3jsonrpc/JsonHelper.h
@@ -89,7 +89,7 @@ namespace shh
 
 Json::Value toJson(h256 const& _h, Envelope const& _e, Message const& _m);
 Message toMessage(Json::Value const& _json);
-Envelope toSealed(Json::Value const& _json, Message const& _m, Secret _from);
+Envelope toSealed(Json::Value const& _json, Message const& _m, Secret const& _from);
 std::pair<Topics, Public> toWatch(Json::Value const& _json);
 
 }
diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt
index 5af43d0b2..05bf2ae20 100644
--- a/libwhisper/CMakeLists.txt
+++ b/libwhisper/CMakeLists.txt
@@ -21,10 +21,10 @@ file(GLOB HEADERS "*.h")
 
 add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
 
-target_link_libraries(${EXECUTABLE} ethcore)
+#target_link_libraries(${EXECUTABLE} ethcore)
+target_link_libraries(${EXECUTABLE} p2p)
 target_link_libraries(${EXECUTABLE} devcrypto)
 target_link_libraries(${EXECUTABLE} devcore)
-target_link_libraries(${EXECUTABLE} p2p)
 
 install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
 install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )
diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h
index f53cb17a7..21a1355f8 100644
--- a/libwhisper/Interface.h
+++ b/libwhisper/Interface.h
@@ -76,8 +76,8 @@ public:
 
 	void post(bytes const& _payload, Topics _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_topics, _ttl, _workToProve)); }
 	void post(Public _to, bytes const& _payload, Topics _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).sealTo(_to, _topics, _ttl, _workToProve)); }
-	void post(Secret _from, bytes const& _payload, Topics _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_from, _topics, _ttl, _workToProve)); }
-	void post(Secret _from, Public _to, bytes const& _payload, Topics _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).sealTo(_from, _to, _topics, _ttl, _workToProve)); }
+	void post(Secret const& _from, bytes const& _payload, Topics _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).seal(_from, _topics, _ttl, _workToProve)); }
+	void post(Secret const& _from, Public _to, bytes const& _payload, Topics _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { inject(Message(_payload).sealTo(_from, _to, _topics, _ttl, _workToProve)); }
 };
 
 struct WatshhChannel: public dev::LogChannel { static const char* name() { return "shh"; } static const int verbosity = 1; };
diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp
index dd72ff734..bf18835b6 100644
--- a/libwhisper/Message.cpp
+++ b/libwhisper/Message.cpp
@@ -97,7 +97,7 @@ bool Message::populate(bytes const& _data)
 	return true;
 }
 
-Envelope Message::seal(Secret _from, Topics const& _fullTopics, unsigned _ttl, unsigned _workToProve) const
+Envelope Message::seal(Secret const& _from, Topics const& _fullTopics, unsigned _ttl, unsigned _workToProve) const
 {
 	AbridgedTopics topics = abridge(_fullTopics);
 	Envelope ret(time(0) + _ttl, _ttl, topics);
diff --git a/libwhisper/Message.h b/libwhisper/Message.h
index 4d8b34548..1ec28ae01 100644
--- a/libwhisper/Message.h
+++ b/libwhisper/Message.h
@@ -118,11 +118,11 @@ public:
 	operator bool() const { return !!m_payload.size() || m_from || m_to; }
 
 	/// Turn this message into a ditributable Envelope.
-	Envelope seal(Secret _from, Topics const& _topics, unsigned _ttl = 50, unsigned _workToProve = 50) const;
+	Envelope seal(Secret const& _from, Topics const& _topics, unsigned _ttl = 50, unsigned _workToProve = 50) const;
 	// Overloads for skipping _from or specifying _to.
 	Envelope seal(Topics const& _topics, unsigned _ttl = 50, unsigned _workToProve = 50) const { return seal(Secret(), _topics, _ttl, _workToProve); }
 	Envelope sealTo(Public _to, Topics const& _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { m_to = _to; return seal(Secret(), _topics, _ttl, _workToProve); }
-	Envelope sealTo(Secret _from, Public _to, Topics const& _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { m_to = _to; return seal(_from, _topics, _ttl, _workToProve); }
+	Envelope sealTo(Secret const& _from, Public _to, Topics const& _topics, unsigned _ttl = 50, unsigned _workToProve = 50) { m_to = _to; return seal(_from, _topics, _ttl, _workToProve); }
 
 private:
 	bool populate(bytes const& _data);
diff --git a/mix/ClientModel.h b/mix/ClientModel.h
index bf88ad66a..cff767dad 100644
--- a/mix/ClientModel.h
+++ b/mix/ClientModel.h
@@ -55,7 +55,7 @@ struct SolidityType;
 struct TransactionSettings
 {
 	TransactionSettings() {}
-	TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, bool _isContractCreation, bool _isFunctionCall):
+	TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret const& _sender, bool _isContractCreation, bool _isFunctionCall):
 		contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCreation(_isContractCreation), isFunctionCall(_isFunctionCall)  {}
 	TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl):
 		contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCreation(true), isFunctionCall(true) {}
diff --git a/test/libdevcrypto/crypto.cpp b/test/libdevcrypto/crypto.cpp
index b70eae36e..c94cc4e8f 100644
--- a/test/libdevcrypto/crypto.cpp
+++ b/test/libdevcrypto/crypto.cpp
@@ -514,7 +514,7 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
 		bytes keyMaterialBytes(512);
 		bytesRef keyMaterial(&keyMaterialBytes);
 		
-		h256 ess;
+		Secret ess;
 		// todo: ecdh-agree should be able to output bytes
 		eA.agree(eBAck, ess);
 		ess.ref().copyTo(keyMaterial.cropped(0, h256::size));
@@ -581,7 +581,7 @@ BOOST_AUTO_TEST_CASE(handshakeNew)
 		bytes keyMaterialBytes(512);
 		bytesRef keyMaterial(&keyMaterialBytes);
 		
-		h256 ess;
+		Secret ess;
 		// todo: ecdh-agree should be able to output bytes
 		eB.agree(eAAuth, ess);
 //		s_secp256k1.agree(eB.seckey(), eAAuth, ess);
diff --git a/test/libethereum/stateOriginal.cpp b/test/libethereum/stateOriginal.cpp
index 163c89e50..9a806c7c4 100644
--- a/test/libethereum/stateOriginal.cpp
+++ b/test/libethereum/stateOriginal.cpp
@@ -54,8 +54,8 @@ BOOST_AUTO_TEST_CASE(Complex)
 
 	cnote << "Testing State...";
 
-	KeyPair me = sha3("Gav Wood");
-	KeyPair myMiner = sha3("Gav's Miner");
+	KeyPair me = Secret(sha3("Gav Wood"));
+	KeyPair myMiner = Secret(sha3("Gav's Miner"));
 //	KeyPair you = sha3("123");
 
 	Defaults::setDBPath(boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count()));