Hush has not been subjected to a formal third-party security review! But the
Zcash source code has. For security
@ -14,17 +12,13 @@ to our own code, such as audits on ZecWallet that apply to SilentDragon.
Hush also reports many new bugs and issues to upstream Zcash and many other
Zcash Protocol coins.
Additionally, Hush itself finds many CVE's and things-that-should-be-CVE's
in Zcash internals. Since Zcash community treats Hush people so poorly, we
keep these bugs and fixes to ourselves. If you want to know some of them,
let us know and bring your wallet.
x86-64 Linux Only
-----------------------
There are [known bugs](https://github.com/scipr-lab/libsnark/issues/26) which
make proving keys generated on 64-bit systems unusable on 32-bit and big-endian
systems. It's unclear if a warning will be issued in this case, or if the
proving system will be silently compromised.
Wallet Encryption
-----------------
## Wallet Encryption
Wallet encryption is disabled, for several reasons:
@ -51,12 +45,11 @@ You should use full-disk encryption (or encryption of your home directory) to
protect your wallet at rest, and should assume (even unprivileged) users who are
running on your OS can read your wallet.dat file.
Side-Channel Attacks
--------------------
## Side-Channel Attacks
This implementation of Hush is not resistant to side-channel attacks. You
should assume (even unprivileged) users who are running on the hardware, or who
are physically near the hardware, that your `zcashd` process is running on will
are physically near the hardware, that your `hushd` process is running on will
be able to:
- Determine the values of your secret spending keys, as well as which notes you
@ -74,29 +67,23 @@ You should ensure no other users have the ability to execute code (even
unprivileged) on the hardware your `hushd` process runs on until these
vulnerabilities are fully analyzed and fixed.
REST Interface
--------------
## REST Interface
The REST interface is a feature inherited from upstream Bitcoin. By default,
it is disabled. We do not recommend you enable it until it has undergone a
security review.
RPC Interface
---------------
## RPC Interface
Users should choose a strong RPC password. If no RPC username and password are set, hush will not start and will print an error message with a suggestion for a strong random password. If the client knows the RPC password, they have at least full access to the node. In addition, certain RPC commands can be misused to overwrite files and/or take over the account that is running hushd. (In the future we may restrict these commands, but full node access – including the ability to spend from and export keys held by the wallet – would still be possible unless wallet methods are disabled.)
Users should also refrain from changing the default setting that only allows RPC connections from localhost. Allowing connections from remote hosts would enable a MITM to execute arbitrary RPC commands, which could lead to compromise of the account running hushd and loss of funds. For multi-user services that use one or more hushd instances on the backend, the parameters passed in by users should be controlled to prevent confused-deputy attacks which could spend from any keys held by that zcashd.
Block Chain Reorganization: Major Differences
-------------------------------------------------
Users should be aware of new behavior in Hush that differs significantly from Bitcoin: in the case of a block chain reorganization, Bitcoin's coinbase maturity rule helps to ensure that any reorganization shorter than the maturity interval will not invalidate any of the rolled-back transactions. Hush keeps Bitcoin's 100-block maturity interval for generation transactions, but because JoinSplits must be anchored within a block, this provides more limited protection against transactions becoming invalidated. In the case of a block chain reorganization for Hush, all JoinSplits which were anchored within the reorganization interval and any transactions that depend on them will become invalid, rolling back transactions and reverting funds to the original owner. The transaction rebroadcast mechanism inherited from Bitcoin will not successfully rebroadcast transactions depending on invalidated JoinSplits if the anchor needs to change. The creator of an invalidated JoinSplit, as well as the creators of all transactions dependent on it, must rebroadcast the transactions themselves.
## Block Chain Reorganization: Major Differences
Receivers of funds from a JoinSplit can mitigate the risk of relying on funds received from transactions that may be rolled back by using a higher minconf (minimum number of confirmations).
Hush has Delayed-Proof-of-Work, which drastically improves the Zcash rule-of-thumb of "re-organize 100 blocks to crash all ZEC full nodes in the world".
Logging z_* RPC calls
---------------------
## Logging z_* RPC calls
The option `-debug=zrpc` covers logging of the z_* calls. This will reveal information about private notes which you might prefer not to disclose. For example, when calling `z_sendmany` to create a shielded transaction, input notes are consumed and new output notes are created.
@ -104,12 +91,10 @@ The option `-debug=zrpcunsafe` covers logging of sensitive information in z_* ca
Private spending keys for z addresses are never logged.
Potentially-Missing Required Modifications
------------------------------------------
## Potentially-Missing Required Modifications
In addition to potential mistakes in code we added to Bitcoin Core, Zcash
and Komodo and
potential mistakes in our modifications to Bitcoin Core, Zcash and Komodo, it is also possible
and Komodo and potential mistakes in our modifications to Bitcoin Core, Zcash and Komodo, it is also possible
that there were potential changes we were supposed to make to Bitcoin Core, Zcash and Komodo but
didn't, either because we didn't even consider making those changes or have not found out about
them. Submitting Github issues is highly appreciated!
if(nRet!=SSL_ERROR_WANT_READ&&nRet!=SSL_ERROR_WANT_WRITE)// SSL_read() operation has to be repeated because of SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE (https://wiki.openssl.org/index.php/Manual:SSL_read(3)#NOTES)
if(RAND_poll()&&// The pseudo-random number generator must be seeded prior to calling RSA_generate_key_ex(). (https://www.openssl.org/docs/man1.1.0/crypto/RSA_generate_key.html)
// Generates public key pair and the self-signed certificate for it, and then stores them by the specified paths 'keyPath' and 'certPath' respectively.
//
boolGenerateCredentials(
constboost::filesystem::path&keyPath,
constboost::filesystem::path&certPath,
conststd::string&passphrase)
{
boolbGenerated=false;
EVP_PKEY*key=NULL;
X509*cert=NULL;
// Generating RSA key and the self-signed certificate for it
//
key=GenerateRsaKey(TLS_RSA_KEY_SIZE,RSA_F4);
if(key)
{
cert=GenerateCertificate(key);
if(cert)
{
if(StoreKey(key,keyPath,passphrase)&&
StoreCertificate(cert,certPath))
{
bGenerated=true;
LogPrintStr("TLS: New private key and self-signed certificate were generated successfully\n");
}
X509_free(cert);
}
EVP_PKEY_free(key);
}
returnbGenerated;
}
// Checks if certificate of a peer is valid (by internal means of the TLS protocol)
//
// Validates peer certificate using a chain of CA certificates.
// If some of intermediate CA certificates are absent in the trusted certificates store, then validation status will be 'false')
//
boolValidatePeerCertificate(SSL*ssl)
{
if(!ssl)
returnfalse;
boolbIsOk=false;
X509*cert=SSL_get_peer_certificate(ssl);
if(cert)
{
// NOTE: SSL_get_verify_result() is only useful in connection with SSL_get_peer_certificate (https://www.openssl.org/docs/man1.0.2/ssl/SSL_get_verify_result.html)
//
bIsOk=(SSL_get_verify_result(ssl)==X509_V_OK);
X509_free(cert);
}
else
{
LogPrint("net","TLS: Peer does not have certificate\n");
bIsOk=false;
}
returnbIsOk;
}
// Check if a given context is set up with a cert that can be validated by this context
// Verifies credentials (a private key, a certificate for public key and a correspondence between the private and the public key)
//
CredentialsStatusVerifyCredentials(
constboost::filesystem::path&keyPath,
constboost::filesystem::path&certPath,
conststd::string&passphrase);
// Generates public key pair and the self-signed certificate for it, and then stores them by the specified paths 'keyPath' and 'certPath' respectively.
//
boolGenerateCredentials(
constboost::filesystem::path&keyPath,
constboost::filesystem::path&certPath,
conststd::string&passphrase);
// Checks if certificate of a peer is valid (by internal means of the TLS protocol)
//
// Validates peer certificate using a chain of CA certificates.
// If some of intermediate CA certificates are absent in the trusted certificates store, then validation status will be 'false')
//
boolValidatePeerCertificate(SSL*ssl);
// Check if a given context is set up with a cert that can be validated by this context
//
boolValidateCertificate(SSL_CTX*ssl_ctx);
// Creates the list of available OpenSSL default directories for trusted certificates storage
strUsage+=HelpMessageOpt("-torcontrol=<ip>:<port>",strprintf(_("Tor control port to use if onion listening enabled (default: %s)"),DEFAULT_TOR_CONTROL));
strUsage+=HelpMessageOpt("-torpassword=<pass>",_("Tor control port password (default: empty)"));
strUsage+=HelpMessageOpt("-tls=<option>",_("Specify TLS usage (default: 1 => enabled and preferred, yet compatible); other options are -tls=0 to disable TLS and -tls=only to enforce it"));
strUsage+=HelpMessageOpt("-tlsfallbacknontls=<0 or 1>",_("If a TLS connection fails, the next connection attempt of the same peer (based on IP address) takes place without TLS (default: 1)"));
strUsage+=HelpMessageOpt("-tlsvalidate=<0 or 1>",_("Connect to peers only with valid certificates (default: 0)"));
strUsage+=HelpMessageOpt("-tlskeypath=<path>",_("Full path to a private key"));
strUsage+=HelpMessageOpt("-tlskeypwd=<password>",_("Password for a private key encryption (default: not set, i.e. private key will be stored unencrypted)"));
strUsage+=HelpMessageOpt("-tlscertpath=<path>",_("Full path to a certificate"));
// one time only setting of static class attribute
if(GetBoolArg("-tlsvalidate",false))
{
LogPrint("tls","%s():%d - TLS certificates will be validated\n",
__func__,__LINE__);
tlsValidate=eTlsOption::FALLBACK_TRUE;
}
else
{
LogPrint("tls","%s():%d - TLS certificates will NOT be validated\n",
__func__,__LINE__);
tlsValidate=eTlsOption::FALLBACK_FALSE;
}
}
return(tlsValidate==eTlsOption::FALLBACK_TRUE);
}
CNode::~CNode()
{
// No need to make a lock on cs_hSocket, because before deletion CNode object is removed from the vNodes vector, so any other thread hasn't access to it.
// Removal is synchronized with read and write routines, so all of them will be completed to this moment.
// Work around clang compilation problem in Boost 1.46:
// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup
FormatParagraph(_("This is experimental software!!!"))+"\n"+
"\n"+
FormatParagraph(_("Distributed under the GPLv3 software license, see the accompanying file COPYING or <https://www.gnu.org/licenses/gpl-3.0.en.html>."))+"\n"+
"\n"+
FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young."))+