From 5beae18b5441417d8114320ba6edd70ee17ecd5d Mon Sep 17 00:00:00 2001 From: anonimal Date: Thu, 14 Apr 2016 15:43:43 +0000 Subject: [PATCH] Crypto: rewrite preexisting refactor. Fixes #164. * Redesign/refactor: the previous design was unnecessary in terms of organization and the logic was askew. Rewrite with maintainability in mind * Within the realm of Signature and ElGamal, refactor out the unfinished cryptopp * Finish the unfinished RNG-related refactor: - Swapout appropriate CryptoPP with Rand*-related calls - Creation of class DiffieHellman - Moving of CryptoConst into pimpl directory * Cleanup related files that still call cryptopp * C++11/style guideline refactor for touched files * Add Crypto++ CMake build option + related pimpl src dir handling * Various cleanups + add documentation --- CMakeLists.txt | 10 +- src/client/AddressBook.cpp | 7 +- src/client/Destination.cpp | 8 +- src/client/Destination.h | 1 - src/client/I2PControl/I2PControl.cpp | 9 +- src/core/CMakeLists.txt | 19 +- src/core/Garlic.cpp | 29 +- src/core/Garlic.h | 3 - src/core/Identity.cpp | 10 +- src/core/LeaseSet.cpp | 6 +- src/core/RouterContext.cpp | 1 - src/core/RouterInfo.cpp | 1 - .../cryptopp/Rand.h => DiffieHellman.h} | 45 +- src/core/crypto/EdDSA25519.cpp | 25 +- src/core/crypto/EdDSA25519.h | 54 +- src/core/crypto/ElGamal.h | 28 +- src/core/crypto/Rand.h | 34 +- src/core/crypto/Signature.cpp | 417 ---------- src/core/crypto/Signature.h | 407 +++++----- src/core/crypto/SignatureBase.h | 26 +- .../{ => pimpl/cryptopp}/CryptoConst.cpp | 6 +- .../crypto/{ => pimpl/cryptopp}/CryptoConst.h | 10 +- .../crypto/pimpl/cryptopp/DiffieHellman.cpp | 103 +++ .../crypto/{ => pimpl/cryptopp}/ElGamal.cpp | 162 ++-- src/core/crypto/{ => pimpl/cryptopp}/Rand.cpp | 7 +- src/core/crypto/pimpl/cryptopp/Signature.cpp | 753 ++++++++++++++++++ src/core/crypto/pimpl/cryptopp/Signature.h | 386 --------- src/core/crypto/pimpl/cryptopp/ZIP.cpp | 10 +- src/core/transport/NTCPSession.cpp | 7 +- src/core/transport/SSUSession.cpp | 12 +- src/core/transport/Transports.cpp | 14 +- src/core/transport/Transports.h | 3 - src/core/tunnel/TunnelPool.cpp | 1 - 33 files changed, 1331 insertions(+), 1283 deletions(-) rename src/core/crypto/{pimpl/cryptopp/Rand.h => DiffieHellman.h} (58%) delete mode 100644 src/core/crypto/Signature.cpp rename src/core/crypto/{ => pimpl/cryptopp}/CryptoConst.cpp (97%) rename src/core/crypto/{ => pimpl/cryptopp}/CryptoConst.h (91%) create mode 100644 src/core/crypto/pimpl/cryptopp/DiffieHellman.cpp rename src/core/crypto/{ => pimpl/cryptopp}/ElGamal.cpp (50%) rename src/core/crypto/{ => pimpl/cryptopp}/Rand.cpp (94%) create mode 100644 src/core/crypto/pimpl/cryptopp/Signature.cpp delete mode 100644 src/core/crypto/pimpl/cryptopp/Signature.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 243077cf..bd456c3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ option(KOVRI_DATA_PATH "The path to the kovri data folder") option(WITH_AESNI "Use AES-NI instructions set" OFF) option(WITH_BENCHMARKS "Build with benchmarks" OFF) option(WITH_BINARY "Build binary" ON) +option(WITH_CRYPTOPP "Build with Crypto++" ON) # Default ON unless we switch libraries option(WITH_DOXYGEN "Enable support for Doxygen" OFF) option(WITH_HARDENING "Use hardening compiler flags" OFF) option(WITH_LIBRARY "Build library" ON) @@ -133,9 +134,11 @@ else() add_definitions(-DBOOST_ALL_DYN_LINK) endif() -find_package(CryptoPP REQUIRED) -if(NOT DEFINED CRYPTO++_INCLUDE_DIR) - message(SEND_ERROR "Could not find Crypto++. Please download and install it first!") +if(WITH_CRYPTOPP) + find_package(CryptoPP REQUIRED) + if(NOT DEFINED CRYPTO++_INCLUDE_DIR) + message(SEND_ERROR "Could not find Crypto++. Please download and install it first!") + endif() endif() if(APPLE) @@ -190,6 +193,7 @@ message(STATUS "Options:") message(STATUS " AESNI : ${WITH_AESNI}") message(STATUS " BENCHMARKS : ${WITH_BENCHMARKS}") message(STATUS " BINARY : ${WITH_BINARY}") +message(STATUS " CRYPTOPP : ${WITH_CRYPTOPP}") message(STATUS " DOXYGEN : ${WITH_DOXYGEN}") message(STATUS " HARDENING : ${WITH_HARDENING}") message(STATUS " LIBRARY : ${WITH_LIBRARY}") diff --git a/src/client/AddressBook.cpp b/src/client/AddressBook.cpp index 742bceda..8f62426e 100644 --- a/src/client/AddressBook.cpp +++ b/src/client/AddressBook.cpp @@ -35,8 +35,6 @@ #include #include -#include - #include #include #include @@ -49,6 +47,7 @@ #include "Destination.h" #include "Identity.h" #include "NetworkDatabase.h" +#include "crypto/Rand.h" #include "util/HTTP.h" #include "util/Log.h" @@ -446,8 +445,8 @@ void AddressBook::HandleSubscriptionsUpdateTimer( if (m_IsLoaded && !m_IsDownloading && m_SharedLocalDestination->IsReady()) { // pick random subscription - CryptoPP::AutoSeededRandomPool rnd; - auto ind = rnd.GenerateWord32(0, m_Subscriptions.size() - 1); + auto ind = + i2p::crypto::RandInRange(0, m_Subscriptions.size() - 1); m_IsDownloading = true; m_Subscriptions[ind]->CheckSubscription(); } else { diff --git a/src/client/Destination.cpp b/src/client/Destination.cpp index 5b22c1ed..16d9e994 100644 --- a/src/client/Destination.cpp +++ b/src/client/Destination.cpp @@ -669,11 +669,9 @@ bool ClientDestination::SendLeaseSetRequest( request->excluded.insert(nextFloodfill->GetIdentHash()); request->requestTime = i2p::util::GetSecondsSinceEpoch(); request->requestTimeoutTimer.cancel(); - CryptoPP::AutoSeededRandomPool rnd; - uint8_t replyKey[32], - replyTag[32]; - rnd.GenerateBlock(replyKey, 32); // random session key - rnd.GenerateBlock(replyTag, 32); // random session tag + uint8_t replyKey[32], replyTag[32]; + i2p::crypto::RandBytes(replyKey, 32); // random session key + i2p::crypto::RandBytes(replyTag, 32); // random session tag AddSessionKey(replyKey, replyTag); auto msg = WrapMessage( diff --git a/src/client/Destination.h b/src/client/Destination.h index ad549aa4..b453166f 100644 --- a/src/client/Destination.h +++ b/src/client/Destination.h @@ -49,7 +49,6 @@ #include "NetworkDatabase.h" #include "Datagram.h" #include "Streaming.h" -#include "crypto/CryptoConst.h" #include "tunnel/TunnelPool.h" namespace i2p { diff --git a/src/client/I2PControl/I2PControl.cpp b/src/client/I2PControl/I2PControl.cpp index ed80edcf..e55d3d27 100644 --- a/src/client/I2PControl/I2PControl.cpp +++ b/src/client/I2PControl/I2PControl.cpp @@ -36,16 +36,16 @@ #include #include -#include #include #include #include -#include "core/RouterContext.h" -#include "core/NetworkDatabase.h" #include "client/ClientContext.h" +#include "core/NetworkDatabase.h" +#include "core/RouterContext.h" #include "core/Version.h" +#include "crypto/Rand.h" #include "transport/Transports.h" #include "tunnel/Tunnel.h" #include "util/Log.h" @@ -346,8 +346,7 @@ bool I2PControlSession::Authenticate( std::string I2PControlSession::GenerateToken() const { byte random_data[constants::TOKEN_SIZE] = {}; - CryptoPP::AutoSeededRandomPool rng; - rng.GenerateBlock(random_data, constants::TOKEN_SIZE); + i2p::crypto::RandBytes(random_data, constants::TOKEN_SIZE); std::string token; CryptoPP::StringSource ss( random_data, diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 87d2f745..826f877d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,5 +1,4 @@ set(CORE_SRC - "tunnel/TunnelConfig.cpp" "Garlic.cpp" "I2NPProtocol.cpp" "Identity.cpp" @@ -11,11 +10,7 @@ set(CORE_SRC "RouterContext.cpp" "RouterInfo.cpp" "crypto/AES.cpp" - "crypto/CryptoConst.cpp" "crypto/EdDSA25519.cpp" - "crypto/ElGamal.cpp" - "crypto/Rand.cpp" - "crypto/Signature.cpp" "crypto/Tunnel.cpp" "transport/NTCP.cpp" "transport/NTCPSession.cpp" @@ -26,6 +21,7 @@ set(CORE_SRC "transport/UPnP.cpp" "tunnel/TransitTunnel.cpp" "tunnel/Tunnel.cpp" + "tunnel/TunnelConfig.cpp" "tunnel/TunnelEndpoint.cpp" "tunnel/TunnelGateway.cpp" "tunnel/TunnelPool.cpp" @@ -36,9 +32,18 @@ set(CORE_SRC "util/Filesystem.cpp" "util/ZIP.cpp") +if(WITH_CRYPTOPP) + set(CRYPTO_PIMPL_DIR "crypto/pimpl/cryptopp") +endif() + set(CRYPTO_PIMPL_SRC - "crypto/pimpl/cryptopp/ZIP.cpp" - "crypto/pimpl/cryptopp/X509.cpp") + "${CRYPTO_PIMPL_DIR}/CryptoConst.cpp" + "${CRYPTO_PIMPL_DIR}/DiffieHellman.cpp" + "${CRYPTO_PIMPL_DIR}/ElGamal.cpp" + "${CRYPTO_PIMPL_DIR}/Rand.cpp" + "${CRYPTO_PIMPL_DIR}/Signature.cpp" + "${CRYPTO_PIMPL_DIR}/X509.cpp" + "${CRYPTO_PIMPL_DIR}/ZIP.cpp") set(EDDSA_SRC "crypto/ed25519/fe_0.cpp" diff --git a/src/core/Garlic.cpp b/src/core/Garlic.cpp index be5d1dac..86807caf 100644 --- a/src/core/Garlic.cpp +++ b/src/core/Garlic.cpp @@ -39,11 +39,12 @@ #include "I2NPProtocol.h" #include "RouterContext.h" #include "client/Destination.h" +#include "crypto/Rand.h" #include "tunnel/Tunnel.h" #include "tunnel/TunnelPool.h" #include "util/I2PEndian.h" -#include "util/Timestamp.h" #include "util/Log.h" +#include "util/Timestamp.h" namespace i2p { namespace garlic { @@ -59,7 +60,7 @@ GarlicRoutingSession::GarlicRoutingSession( m_LeaseSetUpdateStatus( attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend) { // create new session tags and session key - m_Rnd.GenerateBlock(m_SessionKey, 32); + i2p::crypto::RandBytes(m_SessionKey, 32); m_Encryption.SetKey(m_SessionKey); } @@ -87,7 +88,7 @@ GarlicRoutingSession::GenerateSessionTags() { auto tags = new UnconfirmedTags(m_NumTags); tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch(); for (int i = 0; i < m_NumTags; i++) { - m_Rnd.GenerateBlock(tags->sessionTags[i], 32); + i2p::crypto::RandBytes(tags->sessionTags[i], 32); tags->sessionTags[i].creationTime = tags->tagsCreationTime; } return tags; @@ -173,7 +174,7 @@ std::shared_ptr GarlicRoutingSession::WrapSingleMessage( // create ElGamal block ElGamalBlock elGamal; memcpy(elGamal.sessionKey, m_SessionKey, 32); - m_Rnd.GenerateBlock(elGamal.preIV, 32); // Pre-IV + i2p::crypto::RandBytes(elGamal.preIV, 32); // Pre-IV uint8_t iv[32]; // IV is first 16 bytes CryptoPP::SHA256().CalculateDigest(iv, elGamal.preIV, 32); m_Destination->GetElGamalEncryption()->Encrypt( @@ -236,9 +237,9 @@ size_t GarlicRoutingSession::CreateGarlicPayload( std::shared_ptr msg, UnconfirmedTags* newTags) { uint64_t ts = i2p::util::GetMillisecondsSinceEpoch() + 5000; // 5 sec - uint32_t msgID = m_Rnd.GenerateWord32(); + uint32_t msgID = i2p::crypto::Rand(); size_t size = 0; - uint8_t * numCloves = payload + size; + uint8_t* numCloves = payload + size; *numCloves = 0; size++; if (m_Owner) { @@ -307,7 +308,8 @@ size_t GarlicRoutingSession::CreateGarlicClove( } memcpy(buf + size, msg->GetBuffer(), msg->GetLength()); size += msg->GetLength(); - htobe32buf(buf + size, m_Rnd.GenerateWord32()); // CloveID + // CloveID + htobe32buf(buf + size, i2p::crypto::Rand()); size += 4; htobe64buf(buf + size, ts); // Expiration of clove size += 8; @@ -336,8 +338,8 @@ size_t GarlicRoutingSession::CreateDeliveryStatusClove( if (m_Owner) { // encrypt uint8_t key[32], tag[32]; - m_Rnd.GenerateBlock(key, 32); // random session key - m_Rnd.GenerateBlock(tag, 32); // random session tag + i2p::crypto::RandBytes(key, 32); // random session key + i2p::crypto::RandBytes(tag, 32); // random session tag m_Owner->SubmitSessionKey(key, tag); GarlicRoutingSession garlic(key, tag); msg = garlic.WrapSingleMessage(msg); @@ -346,7 +348,8 @@ size_t GarlicRoutingSession::CreateDeliveryStatusClove( size += msg->GetLength(); // fill clove uint64_t ts = i2p::util::GetMillisecondsSinceEpoch() + 5000; // 5 sec - htobe32buf(buf + size, m_Rnd.GenerateWord32()); // CloveID + // CloveID + htobe32buf(buf + size, i2p::crypto::Rand()); size += 4; htobe64buf(buf + size, ts); // Expiration of clove size += 8; @@ -411,8 +414,10 @@ void GarlicDestination::HandleGarlicMessage( ElGamalBlock elGamal; if (length >= 514 && i2p::crypto::ElGamalDecrypt( - GetEncryptionPrivateKey(), buf, - reinterpret_cast(&elGamal), true)) { + GetEncryptionPrivateKey(), + buf, + reinterpret_cast(&elGamal), + true)) { auto decryption = std::make_shared(); decryption->SetKey(elGamal.sessionKey); uint8_t iv[32]; // IV is first 16 bytes diff --git a/src/core/Garlic.h b/src/core/Garlic.h index 1d08d9b0..9e784278 100644 --- a/src/core/Garlic.h +++ b/src/core/Garlic.h @@ -33,8 +33,6 @@ #ifndef SRC_CORE_GARLIC_H_ #define SRC_CORE_GARLIC_H_ -#include - #include #include @@ -168,7 +166,6 @@ class GarlicRoutingSession uint64_t m_LeaseSetSubmissionTime; // in milliseconds i2p::crypto::CBCEncryption m_Encryption; - CryptoPP::AutoSeededRandomPool m_Rnd; }; class GarlicDestination : public i2p::data::LocalDestination { diff --git a/src/core/Identity.cpp b/src/core/Identity.cpp index 8e9a2a9c..6e6ac524 100644 --- a/src/core/Identity.cpp +++ b/src/core/Identity.cpp @@ -30,13 +30,6 @@ * Parts of the project are originally copyright (c) 2013-2015 The PurpleI2P Project */ -// TODO(unassigned): use crypto/DSA.h -#include -// TODO(unassigned): use crypto/SHA.h -#include - -#include - #include #include @@ -44,8 +37,7 @@ #include "Identity.h" #include "RouterContext.h" -#include "crypto/CryptoConst.h" -#include "crypto/pimpl/cryptopp/Rand.h" +#include "crypto/EdDSA25519.h" #include "crypto/ElGamal.h" #include "crypto/Rand.h" #include "crypto/Signature.h" diff --git a/src/core/LeaseSet.cpp b/src/core/LeaseSet.cpp index a8e99217..c74c573e 100644 --- a/src/core/LeaseSet.cpp +++ b/src/core/LeaseSet.cpp @@ -33,14 +33,13 @@ #include "LeaseSet.h" #include -#include #include #include #include "NetworkDatabase.h" -#include "crypto/CryptoConst.h" +#include "crypto/Rand.h" #include "tunnel/TunnelPool.h" #include "util/I2PEndian.h" #include "util/Log.h" @@ -88,7 +87,6 @@ LeaseSet::LeaseSet( m_Buffer[m_BufferLen] = tunnels.size(); // num leases m_BufferLen++; // leases - CryptoPP::AutoSeededRandomPool rnd; for (auto it : tunnels) { memcpy(m_Buffer + m_BufferLen, it->GetNextIdentHash(), 32); m_BufferLen += 32; // gateway id @@ -99,7 +97,7 @@ LeaseSet::LeaseSet( i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration ts *= 1000; // in milliseconds - ts += rnd.GenerateWord32(0, 5); // + random milliseconds + ts += i2p::crypto::RandInRange(0, 5); // + random milliseconds htobe64buf(m_Buffer + m_BufferLen, ts); m_BufferLen += 8; // end date } diff --git a/src/core/RouterContext.cpp b/src/core/RouterContext.cpp index 8426459d..f438ddc4 100644 --- a/src/core/RouterContext.cpp +++ b/src/core/RouterContext.cpp @@ -43,7 +43,6 @@ #include "I2NPProtocol.h" #include "NetworkDatabase.h" #include "Version.h" -#include "crypto/CryptoConst.h" #include "util/MTU.h" #include "util/Timestamp.h" #include "util/Filesystem.h" diff --git a/src/core/RouterInfo.cpp b/src/core/RouterInfo.cpp index 9728a653..89e20d52 100644 --- a/src/core/RouterInfo.cpp +++ b/src/core/RouterInfo.cpp @@ -45,7 +45,6 @@ #include #include "RouterContext.h" -#include "crypto/CryptoConst.h" #include "util/Base64.h" #include "util/I2PEndian.h" #include "util/Log.h" diff --git a/src/core/crypto/pimpl/cryptopp/Rand.h b/src/core/crypto/DiffieHellman.h similarity index 58% rename from src/core/crypto/pimpl/cryptopp/Rand.h rename to src/core/crypto/DiffieHellman.h index c434e0a9..e4b7cd6c 100644 --- a/src/core/crypto/pimpl/cryptopp/Rand.h +++ b/src/core/crypto/DiffieHellman.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2016, The Kovri I2P Router Project + * Copyright (c) 2013-2016, The Kovri I2P Router Project * * All rights reserved. * @@ -26,20 +26,51 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Parts of the project are originally copyright (c) 2013-2015 The PurpleI2P Project */ -#ifndef SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_RAND_H_ -#define SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_RAND_H_ +#ifndef SRC_CORE_CRYPTO_DIFFIEHELLMAN_H_ +#define SRC_CORE_CRYPTO_DIFFIEHELLMAN_H_ -#include +#include +#include namespace i2p { namespace crypto { -typedef CryptoPP::AutoSeededRandomPool PRNG; -static PRNG prng; +/** + * @brief Diffie-Hellman implemention + * @class Diffie-Hellman + */ +class DiffieHellman { + public: + DiffieHellman(); + ~DiffieHellman(); + + /// @brief Generate private/public key pair + /// @param private_key Private key + /// @param public_key Public key + void GenerateKeyPair( + std::uint8_t* private_key, + std::uint8_t* public_key); + + /// @brief Agreed value from your private key and other party's public key + /// @param agreed_value Agreed upon value + /// @param private_key Your private key + /// @param other_public_key Other party's public key + /// @return False on failure + bool Agree( + std::uint8_t* agreed_value, + const std::uint8_t* private_key, + const std::uint8_t* other_public_key); + + private: + class DiffieHellmanImpl; + std::unique_ptr m_DiffieHellmanPimpl; +}; } // namespace crypto } // namespace i2p -#endif // SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_RAND_H_ +#endif // SRC_CORE_CRYPTO_DIFFIEHELLMAN_H_ diff --git a/src/core/crypto/EdDSA25519.cpp b/src/core/crypto/EdDSA25519.cpp index 0066a398..fa4892f8 100644 --- a/src/core/crypto/EdDSA25519.cpp +++ b/src/core/crypto/EdDSA25519.cpp @@ -34,6 +34,7 @@ #include "Rand.h" #include +#include #include "ed25519/ed25519_ref10.h" @@ -41,7 +42,7 @@ namespace i2p { namespace crypto { EDDSA25519Verifier::EDDSA25519Verifier( - const uint8_t* signingKey) { + const std::uint8_t* signingKey) { std::memcpy( m_PublicKey, signingKey, @@ -49,9 +50,9 @@ EDDSA25519Verifier::EDDSA25519Verifier( } bool EDDSA25519Verifier::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { return ed25519_ref10_open( signature, buf, @@ -60,8 +61,8 @@ bool EDDSA25519Verifier::Verify( } EDDSA25519Signer::EDDSA25519Signer( - const uint8_t* signingPrivateKey, - const uint8_t* signingPublicKey) { + const std::uint8_t* signingPrivateKey, + const std::uint8_t* signingPublicKey) { std::memcpy( m_PrivateKey, signingPrivateKey, @@ -73,7 +74,7 @@ EDDSA25519Signer::EDDSA25519Signer( } EDDSA25519Signer::EDDSA25519Signer( - const uint8_t* signingPrivateKey) { + const std::uint8_t* signingPrivateKey) { std::memcpy( m_PrivateKey, signingPrivateKey, @@ -82,9 +83,9 @@ EDDSA25519Signer::EDDSA25519Signer( } void EDDSA25519Signer::Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { ed25519_ref10_sign( signature, buf, @@ -94,8 +95,8 @@ void EDDSA25519Signer::Sign( } void CreateEDDSARandomKeys( - uint8_t* privateKey, - uint8_t* publicKey) { + std::uint8_t* privateKey, + std::uint8_t* publicKey) { i2p::crypto::RandBytes( privateKey, EDDSA25519_PRIVATE_KEY_LENGTH); diff --git a/src/core/crypto/EdDSA25519.h b/src/core/crypto/EdDSA25519.h index 841780b2..353384da 100644 --- a/src/core/crypto/EdDSA25519.h +++ b/src/core/crypto/EdDSA25519.h @@ -33,66 +33,70 @@ #ifndef SRC_CORE_CRYPTO_EDDSA25519_H_ #define SRC_CORE_CRYPTO_EDDSA25519_H_ +#include + #include "SignatureBase.h" namespace i2p { namespace crypto { -// EdDSA -const size_t EDDSA25519_PUBLIC_KEY_LENGTH = 32; -const size_t EDDSA25519_SIGNATURE_LENGTH = 64; -const size_t EDDSA25519_PRIVATE_KEY_LENGTH = 32; +const std::size_t EDDSA25519_PUBLIC_KEY_LENGTH = 32; +const std::size_t EDDSA25519_SIGNATURE_LENGTH = 64; +const std::size_t EDDSA25519_PRIVATE_KEY_LENGTH = 32; +// Verifier class EDDSA25519Verifier : public Verifier { public: EDDSA25519Verifier( - const uint8_t* signingKey); + const std::uint8_t* signingKey); bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const; - size_t GetPublicKeyLen() const { + std::size_t GetPublicKeyLen() const { return EDDSA25519_PUBLIC_KEY_LENGTH; } - size_t GetSignatureLen() const { + std::size_t GetSignatureLen() const { return EDDSA25519_SIGNATURE_LENGTH; } - size_t GetPrivateKeyLen() const { + std::size_t GetPrivateKeyLen() const { return EDDSA25519_PRIVATE_KEY_LENGTH; } private: - uint8_t m_PublicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; + std::uint8_t m_PublicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; }; +// Signer class EDDSA25519Signer : public Signer { public: - // Construct from a key pair. + /// @brief Construct from a key pair. EDDSA25519Signer( - const uint8_t* signingPrivateKey, - const uint8_t* signingPublicKey); + const std::uint8_t* signingPrivateKey, + const std::uint8_t* signingPublicKey); - // Construct from a private key. - // The corresponding public key will be computed from it. + // @brief Construct from a private key. + // @details The corresponding public key will be computed from it. EDDSA25519Signer( - const uint8_t* signingPrivateKey); + const std::uint8_t* signingPrivateKey); void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const; - uint8_t m_PrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH]; - uint8_t m_PublicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; + std::uint8_t m_PrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH]; + std::uint8_t m_PublicKey[EDDSA25519_PUBLIC_KEY_LENGTH]; }; +// Create keys void CreateEDDSARandomKeys( - uint8_t* privateKey, - uint8_t* publicKey); + std::uint8_t* privateKey, + std::uint8_t* publicKey); } // namespace crypto } // namespace i2p diff --git a/src/core/crypto/ElGamal.h b/src/core/crypto/ElGamal.h index ac0c551c..30b141a8 100644 --- a/src/core/crypto/ElGamal.h +++ b/src/core/crypto/ElGamal.h @@ -33,39 +33,39 @@ #ifndef SRC_CORE_CRYPTO_ELGAMAL_H_ #define SRC_CORE_CRYPTO_ELGAMAL_H_ -#include -#include +#include +#include namespace i2p { namespace crypto { -class ElGamalEncryption_Pimpl; - +class ElGamalEncryptionImpl; class ElGamalEncryption { public: ElGamalEncryption( - const uint8_t* key); + const std::uint8_t* key); ~ElGamalEncryption(); void Encrypt( - const uint8_t* data, - size_t len, - uint8_t* encrypted, + const std::uint8_t* data, + std::size_t len, + std::uint8_t* encrypted, bool zeroPadding = false) const; private: - ElGamalEncryption_Pimpl* m_Impl; + // Pointer to implementation + std::unique_ptr m_ElGamalEncryptionPimpl; }; bool ElGamalDecrypt( - const uint8_t* key, - const uint8_t* encrypted, - uint8_t* data, + const std::uint8_t* key, + const std::uint8_t* encrypted, + std::uint8_t* data, bool zeroPadding = false); void GenerateElGamalKeyPair( - uint8_t* priv, - uint8_t* pub); + std::uint8_t* priv, + std::uint8_t* pub); } // namespace crypto } // namespace i2p diff --git a/src/core/crypto/Rand.h b/src/core/crypto/Rand.h index 7e318937..2e279df1 100644 --- a/src/core/crypto/Rand.h +++ b/src/core/crypto/Rand.h @@ -31,37 +31,39 @@ #ifndef SRC_CORE_CRYPTO_RAND_H_ #define SRC_CORE_CRYPTO_RAND_H_ -#include #include // imaxabs() +#include +#include #include namespace i2p { namespace crypto { - /// Generate random bytes - /// @param dataptr buffer to store result - /// @param datalen size of buffer + /// @brief Generates CSPRNG bytes + /// @param data Buffer to store result + /// @param length Size of buffer void RandBytes( - uint8_t* dataptr, - size_t datalen); + std::uint8_t* data, + std::size_t length); - /// Generate random of type T + /// @brief Generates a random of type T + /// @return template T Rand() { T ret; // TODO(unassigned): alignment - RandBytes((uint8_t*)&ret, sizeof(ret)); + RandBytes( + reinterpret_cast(&ret), + sizeof(ret)); return ret; } - /// Returns a random integer of type T from - /// a range of integers (signed or unsigned). - /// - /// @param T : integer type - /// @param min : lowerbound - /// @param max : upperbound - /// @return : random number in range [min, max] - /// (if (min < 0), results are undefined) + /// @brief Generates a random integer in range (signed or unsigned) of type T. + /// @param T Integer type + /// @param min Lowerbound + /// @param max Upperbound + /// @return Random number in range [min, max] + /// (if (min < 0), results are undefined) template T RandInRange(T min, T max) { if ((min > max) || (max < 0)) { diff --git a/src/core/crypto/Signature.cpp b/src/core/crypto/Signature.cpp deleted file mode 100644 index 6359e4b6..00000000 --- a/src/core/crypto/Signature.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/** - * Copyright (c) 2013-2016, The Kovri I2P Router Project - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of the project are originally copyright (c) 2013-2015 The PurpleI2P Project - */ - -#include "Signature.h" - -#include "CryptoConst.h" -#include "pimpl/cryptopp/Signature.h" -#include "Rand.h" - -#include - -#include "util/Log.h" - -namespace i2p { -namespace crypto { - -// DSA -DSAVerifier::DSAVerifier( - const uint8_t* signingKey) - : m_Impl( - new DSAVerifier_Pimpl(signingKey)) {} - -DSAVerifier::~DSAVerifier() { - delete m_Impl; -} - -bool DSAVerifier::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - return m_Impl->Verify(buf, len, signature); -} - -DSASigner::DSASigner( - const uint8_t* signingPrivateKey) - : m_Impl( - new DSASigner_Pimpl(signingPrivateKey)) {} - -DSASigner::~DSASigner() { - delete m_Impl; -} - -void DSASigner::Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - m_Impl->Sign(buf, len, signature); -} - -DSASigner_Pimpl::DSASigner_Pimpl( - const uint8_t* signingPrivateKey) { - m_PrivateKey.Initialize( - dsap, - dsaq, - dsag, - CryptoPP::Integer( - signingPrivateKey, - DSA_PRIVATE_KEY_LENGTH)); -} -DSASigner_Pimpl::~DSASigner_Pimpl() {} - -void DSASigner_Pimpl::Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - CryptoPP::DSA::Signer signer(m_PrivateKey); - PRNG& r = prng; - signer.SignMessage(r, buf, len, signature); -} - -void CreateDSARandomKeys( - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey) { - uint8_t keybuff[DSA_PRIVATE_KEY_LENGTH]; - CryptoPP::Integer dsax; - do { - i2p::crypto::RandBytes(keybuff, DSA_PRIVATE_KEY_LENGTH); - dsax = CryptoPP::Integer(keybuff, DSA_PRIVATE_KEY_LENGTH); - } while(dsax.IsZero() || dsax >= dsaq); - CryptoPP::DSA::PrivateKey privateKey; - CryptoPP::DSA::PublicKey publicKey; - privateKey.Initialize(dsap, dsaq, dsag, dsax); - privateKey.MakePublicKey(publicKey); - privateKey.GetPrivateExponent().Encode( - signingPrivateKey, - DSA_PRIVATE_KEY_LENGTH); - publicKey.GetPublicElement().Encode( - signingPublicKey, - DSA_PUBLIC_KEY_LENGTH); -} - -DSAVerifier_Pimpl::DSAVerifier_Pimpl( - const uint8_t* signingKey) { - m_PublicKey.Initialize( - dsap, - dsaq, - dsag, - CryptoPP::Integer( - signingKey, - DSA_PUBLIC_KEY_LENGTH)); -} - -bool DSAVerifier_Pimpl::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - CryptoPP::DSA::Verifier verifier(m_PublicKey); - return verifier.VerifyMessage(buf, len, signature, DSA_SIGNATURE_LENGTH); -} - -// ECDSAP256 -ECDSAP256Verifier::ECDSAP256Verifier( - const uint8_t* signingKey) - : m_Impl( - new ECDSAP256Verifier_Pimpl(signingKey)) {} - -ECDSAP256Verifier::~ECDSAP256Verifier() { - delete m_Impl; -} - -bool ECDSAP256Verifier::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - return m_Impl->Verify(buf, len, signature); -} - -ECDSAP256Signer::ECDSAP256Signer( - const uint8_t* signingPrivateKey) - : m_Impl( - new ECDSAP256Signer_Pimpl(signingPrivateKey)) {} - -ECDSAP256Signer::~ECDSAP256Signer() { - delete m_Impl; -} - -void ECDSAP256Signer::Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - m_Impl->Sign(buf, len, signature); -} - -// ECDSAP384 -ECDSAP384Verifier::ECDSAP384Verifier( - const uint8_t* signingKey) - : m_Impl( - new ECDSAP384Verifier_Pimpl(signingKey)) {} - -ECDSAP384Verifier::~ECDSAP384Verifier() { - delete m_Impl; -} - -bool ECDSAP384Verifier::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - return m_Impl->Verify(buf, len, signature); -} - -ECDSAP384Signer::ECDSAP384Signer( - const uint8_t* signingPrivateKey) - : m_Impl( - new ECDSAP384Signer_Pimpl(signingPrivateKey)) {} - -ECDSAP384Signer::~ECDSAP384Signer() { - delete m_Impl; -} - -void ECDSAP384Signer::Sign( - const uint8_t* buf, - size_t len, - uint8_t * signature) const { - m_Impl->Sign(buf, len, signature); -} - -// ECDSAP521 -ECDSAP521Verifier::ECDSAP521Verifier( - const uint8_t* signingKey) - : m_Impl( - new ECDSAP521Verifier_Pimpl(signingKey)) {} - -ECDSAP521Verifier::~ECDSAP521Verifier() { - delete m_Impl; -} - -bool ECDSAP521Verifier::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - return m_Impl->Verify(buf, len, signature); -} - -ECDSAP521Signer::ECDSAP521Signer( - const uint8_t* signingPrivateKey) - : m_Impl( - new ECDSAP521Signer_Pimpl(signingPrivateKey)) {} - -ECDSAP521Signer::~ECDSAP521Signer() { - delete m_Impl; -} - -void ECDSAP521Signer::Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - m_Impl->Sign(buf, len, signature); -} - -// ECDSAP256 -void CreateECDSAP256RandomKeys( - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey) { - CreateECDSARandomKeys( - CryptoPP::ASN1::secp256r1(), - ECDSAP256_KEY_LENGTH, - signingPrivateKey, - signingPublicKey); -} - -// ECDSAP384 -void CreateECDSAP384RandomKeys( - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey) { - CreateECDSARandomKeys( - CryptoPP::ASN1::secp384r1(), - ECDSAP384_KEY_LENGTH, - signingPrivateKey, - signingPublicKey); -} - -// ECDSAP521 -void CreateECDSAP521RandomKeys( - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey) { - CreateECDSARandomKeys( - CryptoPP::ASN1::secp521r1(), - ECDSAP521_KEY_LENGTH, - signingPrivateKey, - signingPublicKey); -} - -// RSA -void CreateRSARandomKeys( - size_t publicKeyLen, - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey) { - CryptoPP::RSA::PrivateKey privateKey; - privateKey.Initialize( - prng, - publicKeyLen * 8, - rsae); - privateKey.GetModulus().Encode( - signingPrivateKey, - publicKeyLen); - privateKey.GetPrivateExponent().Encode( - signingPrivateKey + publicKeyLen, - publicKeyLen); - privateKey.GetModulus().Encode( - signingPublicKey, - publicKeyLen); - } - -// RSASHA2562048 -RSASHA2562048Signer::RSASHA2562048Signer( - const uint8_t* privateKey) - : m_Impl( - new RSASHA2562048Signer_Pimpl(privateKey)) {} - -RSASHA2562048Signer::~RSASHA2562048Signer() { - delete m_Impl; -} - -void RSASHA2562048Signer::Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - m_Impl->Sign(buf, len, signature); -} - -// RSASHA3843072 -RSASHA3843072Signer::RSASHA3843072Signer( - const uint8_t* privateKey) - : m_Impl( - new RSASHA3843072Signer_Pimpl(privateKey)) {} - -RSASHA3843072Signer::~RSASHA3843072Signer() { - delete m_Impl; -} - -void RSASHA3843072Signer::Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - m_Impl->Sign(buf, len, signature); -} - -// RSASHA5124096 -RSASHA5124096Signer::RSASHA5124096Signer( - const uint8_t* privateKey) - : m_Impl( - new RSASHA5124096Signer_Pimpl(privateKey)) {} - -RSASHA5124096Signer::~RSASHA5124096Signer() { - delete m_Impl; -} - -void RSASHA5124096Signer::Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - m_Impl->Sign(buf, len, signature); -} - -// RSASHA2562048 -RSASHA2562048Verifier::RSASHA2562048Verifier( - const uint8_t* pubKey) - : m_Impl( - new RSASHA2562048Verifier_Pimpl(pubKey)) {} - -RSASHA2562048Verifier::~RSASHA2562048Verifier() { - delete m_Impl; -} - -bool RSASHA2562048Verifier::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - return m_Impl->Verify(buf, len, signature); -} - -// RSASHA3843072 -RSASHA3843072Verifier::RSASHA3843072Verifier( - const uint8_t* pubKey) - : m_Impl( - new RSASHA3843072Verifier_Pimpl(pubKey)) {} - -RSASHA3843072Verifier::~RSASHA3843072Verifier() { - delete m_Impl; -} - -bool RSASHA3843072Verifier::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - return m_Impl->Verify(buf, len, signature); -} - -// RSASHA5124096 -RSASHA5124096Verifier::RSASHA5124096Verifier( - const uint8_t* pubKey) - : m_Impl( - new RSASHA5124096Verifier_Pimpl(pubKey)) {} - -RSASHA5124096Verifier::~RSASHA5124096Verifier() { - delete m_Impl; -} - -bool RSASHA5124096Verifier::Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - return m_Impl->Verify(buf, len, signature); -} - -// RSASHA5124096 -RSASHA5124096RawVerifier::RSASHA5124096RawVerifier( - const uint8_t* signingKey) - : m_Impl( - new RSASHA5124096RawVerifier_Pimpl(signingKey)) {} - -RSASHA5124096RawVerifier::~RSASHA5124096RawVerifier() { - delete m_Impl; -} - -void RSASHA5124096RawVerifier::Update( - const uint8_t* buf, - size_t len) { - m_Impl->Update(buf, len); -} - -bool RSASHA5124096RawVerifier::Verify( - const uint8_t* signature) { - return m_Impl->Verify(signature); -} - -} // namespace crypto -} // namespace i2p diff --git a/src/core/crypto/Signature.h b/src/core/crypto/Signature.h index 1af6bab0..3aa6decd 100644 --- a/src/core/crypto/Signature.h +++ b/src/core/crypto/Signature.h @@ -33,447 +33,422 @@ #ifndef SRC_CORE_CRYPTO_SIGNATURE_H_ #define SRC_CORE_CRYPTO_SIGNATURE_H_ -#include +#include +#include -#include "EdDSA25519.h" #include "SignatureBase.h" namespace i2p { namespace crypto { -const size_t DSA_PUBLIC_KEY_LENGTH = 128; -const size_t DSA_SIGNATURE_LENGTH = 40; -const size_t DSA_PRIVATE_KEY_LENGTH = DSA_SIGNATURE_LENGTH/2; +/** + * + * DSA + * + */ + +const std::size_t DSA_PUBLIC_KEY_LENGTH = 128; +const std::size_t DSA_SIGNATURE_LENGTH = 40; +const std::size_t DSA_PRIVATE_KEY_LENGTH = DSA_SIGNATURE_LENGTH / 2; -// DSAVerifier -class DSAVerifier_Pimpl; class DSAVerifier : public Verifier { public: DSAVerifier( - const uint8_t* signingKey); - + const std::uint8_t* signing_key); ~DSAVerifier(); + bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const; - size_t GetPublicKeyLen() const { + std::size_t GetPublicKeyLen() const { return DSA_PUBLIC_KEY_LENGTH; } - size_t GetSignatureLen() const { + std::size_t GetSignatureLen() const { return DSA_SIGNATURE_LENGTH; } - size_t GetPrivateKeyLen() const { + std::size_t GetPrivateKeyLen() const { return DSA_PRIVATE_KEY_LENGTH; } private: - DSAVerifier_Pimpl* m_Impl; + class DSAVerifierImpl; + std::unique_ptr m_DSAVerifierPimpl; }; -// DSASigner -class DSASigner_Pimpl; class DSASigner : public Signer { public: explicit DSASigner( - const uint8_t* signingPrivateKey); + const std::uint8_t* private_signing_key); ~DSASigner(); void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const; private: - DSASigner_Pimpl* m_Impl; + class DSASignerImpl; + std::unique_ptr m_DSASignerPimpl; }; void CreateDSARandomKeys( - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey); + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key); + +/** + * + * ECDSAP256 + * + */ -// ECDSA_SHA256_P256 -const size_t ECDSAP256_KEY_LENGTH = 64; -// ECDSAP256Verifier -class ECDSAP256Verifier_Pimpl; +const std::size_t ECDSAP256_KEY_LENGTH = 64; + +class ECDSAP256VerifierImpl; class ECDSAP256Verifier : public Verifier { public: ECDSAP256Verifier( - const uint8_t * signingKey); + const std::uint8_t* signing_key); ~ECDSAP256Verifier(); bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const; - size_t GetPublicKeyLen() const { + std::size_t GetPublicKeyLen() const { return ECDSAP256_KEY_LENGTH; } - size_t GetSignatureLen() const { + std::size_t GetSignatureLen() const { return ECDSAP256_KEY_LENGTH; } - size_t GetPrivateKeyLen() const { + std::size_t GetPrivateKeyLen() const { return ECDSAP256_KEY_LENGTH / 2; } private: - ECDSAP256Verifier_Pimpl* m_Impl; + std::unique_ptr m_ECDSAP256VerifierPimpl; }; -// ECDSAP256Signer -class ECDSAP256Signer_Pimpl; -struct ECDSAP256Signer : public Signer { +class ECDSAP256SignerImpl; +class ECDSAP256Signer : public Signer { + public: explicit ECDSAP256Signer( - const uint8_t* signingPrivateKey); + const std::uint8_t* private_signing_key); ~ECDSAP256Signer(); void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const; private: - ECDSAP256Signer_Pimpl* m_Impl; + std::unique_ptr m_ECDSAP256SignerPimpl; }; void CreateECDSAP256RandomKeys( - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey); + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key); + +/** + * + * ECDSAP384 + * + */ + +const std::size_t ECDSAP384_KEY_LENGTH = 96; -// ECDSA_SHA384_P384 -const size_t ECDSAP384_KEY_LENGTH = 96; -// ECDSAP384Verifier -class ECDSAP384Verifier_Pimpl; +class ECDSAP384VerifierImpl; class ECDSAP384Verifier : public Verifier { public: ECDSAP384Verifier( - const uint8_t * signingKey); + const std::uint8_t * signing_key); ~ECDSAP384Verifier(); bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const; - size_t GetPublicKeyLen() const { + std::size_t GetPublicKeyLen() const { return ECDSAP384_KEY_LENGTH; } - size_t GetSignatureLen() const { + std::size_t GetSignatureLen() const { return ECDSAP384_KEY_LENGTH; } - size_t GetPrivateKeyLen() const { + std::size_t GetPrivateKeyLen() const { return ECDSAP384_KEY_LENGTH / 2; } private: - ECDSAP384Verifier_Pimpl* m_Impl; + std::unique_ptr m_ECDSAP384VerifierPimpl; }; -// ECDSAP384Signer -class ECDSAP384Signer_Pimpl; -struct ECDSAP384Signer : public Signer { +class ECDSAP384SignerImpl; +class ECDSAP384Signer : public Signer { + public: explicit ECDSAP384Signer( - const uint8_t* signingPrivateKey); + const uint8_t* private_signing_key); ~ECDSAP384Signer(); void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const; private: - ECDSAP384Signer_Pimpl* m_Impl; + std::unique_ptr m_ECDSAP384SignerPimpl; }; void CreateECDSAP384RandomKeys( - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey); + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key); + +/** + * + * ECDSAP521 + * + */ -// ECDSA_SHA512_P521 -const size_t ECDSAP521_KEY_LENGTH = 132; -// ECDSAP521Verifier -class ECDSAP521Verifier_Pimpl; +const std::size_t ECDSAP521_KEY_LENGTH = 132; + +class ECDSAP521VerifierImpl; class ECDSAP521Verifier : public Verifier { public: ECDSAP521Verifier( - const uint8_t* signingKey); + const std::uint8_t* signing_key); ~ECDSAP521Verifier(); bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const; - size_t GetPublicKeyLen() const { + std::size_t GetPublicKeyLen() const { return ECDSAP521_KEY_LENGTH; } - size_t GetSignatureLen() const { + std::size_t GetSignatureLen() const { return ECDSAP521_KEY_LENGTH; } - size_t GetPrivateKeyLen() const { + std::size_t GetPrivateKeyLen() const { return ECDSAP521_KEY_LENGTH / 2; } private: - ECDSAP521Verifier_Pimpl* m_Impl; + std::unique_ptr m_ECDSAP521VerifierPimpl; }; -// ECDSAP521Signer -class ECDSAP521Signer_Pimpl; +class ECDSAP521SignerImpl; struct ECDSAP521Signer : public Signer { explicit ECDSAP521Signer( - const uint8_t* signingPrivateKey); + const uint8_t* private_signing_key); ~ECDSAP521Signer(); void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const; private: - ECDSAP521Signer_Pimpl* m_Impl; + std::unique_ptr m_ECDSAP521SignerPimpl; }; void CreateECDSAP521RandomKeys( - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey); + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key); + +/** + * + * RSASHA2562048 + * + */ -// RSA_SHA256_2048 -const size_t RSASHA2562048_KEY_LENGTH = 256; -// RSASHA2562048Verifier -class RSASHA2562048Verifier_Pimpl; +const std::size_t RSASHA2562048_KEY_LENGTH = 256; + +class RSASHA2562048VerifierImpl; class RSASHA2562048Verifier : public Verifier { public: explicit RSASHA2562048Verifier( - const uint8_t* signingKey); + const std::uint8_t* signing_key); ~RSASHA2562048Verifier(); - size_t GetPublicKeyLen() const { + std::size_t GetPublicKeyLen() const { return RSASHA2562048_KEY_LENGTH; } - size_t GetSignatureLen() const { + std::size_t GetSignatureLen() const { return RSASHA2562048_KEY_LENGTH; } - size_t GetPrivateKeyLen() const { + std::size_t GetPrivateKeyLen() const { return RSASHA2562048_KEY_LENGTH * 2; } bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const; private: - RSASHA2562048Verifier_Pimpl* m_Impl; + std::unique_ptr m_RSASHA2562048VerifierPimpl; }; -// RSASHA2562048Signer -class RSASHA2562048Signer_Pimpl; +class RSASHA2562048SignerImpl; class RSASHA2562048Signer : public Signer { public: explicit RSASHA2562048Signer( - const uint8_t* signingPrivateKey); + const std::uint8_t* private_signing_key); ~RSASHA2562048Signer(); void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const; private: - RSASHA2562048Signer_Pimpl* m_Impl; + std::unique_ptr m_RSASHA2562048SignerPimpl; }; -// RSA_SHA384_3072 -const size_t RSASHA3843072_KEY_LENGTH = 384; -// RSASHA3843072Verifier -class RSASHA3843072Verifier_Pimpl; +/** + * + * RSASHA3843072 + * + */ + +const std::size_t RSASHA3843072_KEY_LENGTH = 384; + +class RSASHA3843072VerifierImpl; class RSASHA3843072Verifier : public Verifier { public: explicit RSASHA3843072Verifier( - const uint8_t* signingKey); + const std::uint8_t* signing_key); ~RSASHA3843072Verifier(); - size_t GetPublicKeyLen() const { + std::size_t GetPublicKeyLen() const { return RSASHA3843072_KEY_LENGTH; } - size_t GetSignatureLen() const { + std::size_t GetSignatureLen() const { return RSASHA3843072_KEY_LENGTH; } - size_t GetPrivateKeyLen() const { + std::size_t GetPrivateKeyLen() const { return RSASHA3843072_KEY_LENGTH * 2; } bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const; private: - RSASHA3843072Verifier_Pimpl* m_Impl; + std::unique_ptr m_RSASHA3843072VerifierPimpl; }; -// RSASHA3843072Signer -class RSASHA3843072Signer_Pimpl; +class RSASHA3843072SignerImpl; class RSASHA3843072Signer : public Signer { public: explicit RSASHA3843072Signer( - const uint8_t* signingPrivateKey); + const std::uint8_t* private_signing_key); ~RSASHA3843072Signer(); void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const; private: - RSASHA3843072Signer_Pimpl* m_Impl; + std::unique_ptr m_RSASHA3843072SignerPimpl; }; -// RSA_SHA512_4096 -const size_t RSASHA5124096_KEY_LENGTH = 512; -// RSASHA5124096Verifier -class RSASHA5124096Verifier_Pimpl; +/** + * + * RSASHA5124096 + * + */ + +const std::size_t RSASHA5124096_KEY_LENGTH = 512; + +class RSASHA5124096VerifierImpl; class RSASHA5124096Verifier : public Verifier { public: explicit RSASHA5124096Verifier( - const uint8_t* signingKey); + const std::uint8_t* signing_key); ~RSASHA5124096Verifier(); - size_t GetPublicKeyLen() const { + std::size_t GetPublicKeyLen() const { return RSASHA5124096_KEY_LENGTH; } - size_t GetSignatureLen() const { + std::size_t GetSignatureLen() const { return RSASHA5124096_KEY_LENGTH; } - size_t GetPrivateKeyLen() const { + std::size_t GetPrivateKeyLen() const { return RSASHA5124096_KEY_LENGTH * 2; } bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const; private: - RSASHA5124096Verifier_Pimpl* m_Impl; + std::unique_ptr m_RSASHA5124096VerifierPimpl; }; -// RSASHA5124096Signer -class RSASHA5124096Signer_Pimpl; +class RSASHA5124096SignerImpl; class RSASHA5124096Signer : public Signer { public: explicit RSASHA5124096Signer( - const uint8_t* signingPrivateKey); + const std::uint8_t* private_signing_key); ~RSASHA5124096Signer(); void Sign( - const uint8_t* buf, - size_t len, - uint8_t * signature) const; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const; private: - RSASHA5124096Signer_Pimpl* m_Impl; + std::unique_ptr m_RSASHA5124096SignerPimpl; }; void CreateRSARandomKeys( - size_t publicKeyLen, - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey); - -// TODO(unassigned): ??? -/* -// Raw verifiers -class RawVerifier { - public: - virtual ~RawVerifier() {} + std::size_t public_key_length, + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key); - virtual void Update( - const uint8_t* buf, - size_t len) = 0; - - virtual bool Verify( - const uint8_t* signature) = 0; -}; - -template -class RSARawVerifier - : public RawVerifier { - public: - RSARawVerifier( - const uint8_t* signingKey) - : n(signingKey, keyLen) {} - - void Update( - const uint8_t* buf, - size_t len) { - m_Hash.Update(buf, len); - } - - bool Verify( - const uint8_t* signature) { - // RSA encryption first - CryptoPP::Integer enSig( - a_exp_b_mod_c( - CryptoPP::Integer( - signature, - keyLen), - CryptoPP::Integer( - i2p::crypto::rsae), - n)); // s^e mod n - uint8_t EnSigBuf[keyLen]; - enSig.Encode(EnSigBuf, keyLen); - uint8_t digest[Hash::DIGESTSIZE]; - m_Hash.Final(digest); - if (static_cast(keyLen) < Hash::DIGESTSIZE) - return false; // can't verify digest longer than key - // we assume digest is right aligned, at least for PKCS#1 v1.5 padding - return !memcmp( - EnSigBuf + (keyLen - Hash::DIGESTSIZE), - digest, - Hash::DIGESTSIZE); - } - - private: - CryptoPP::Integer n; // RSA modulus - Hash m_Hash; -}; -*/ +/** + * + * RSASHA5124096Raw + * + */ -// RSASHA5124096RawVerifier -class RSASHA5124096RawVerifier_Pimpl; +class RSASHA5124096RawVerifierImpl; class RSASHA5124096RawVerifier : public RawVerifier { -// public RSARawVerifier { public: explicit RSASHA5124096RawVerifier( - const uint8_t* signingKey); + const std::uint8_t* signing_key); ~RSASHA5124096RawVerifier(); bool Verify( - const uint8_t* signature); + const std::uint8_t* signature); void Update( - const uint8_t* signature, - size_t len); + const std::uint8_t* signature, + std::size_t len); private: - RSASHA5124096RawVerifier_Pimpl* m_Impl; + std::unique_ptr m_RSASHA5124096RawVerifierPimpl; }; } // namespace crypto diff --git a/src/core/crypto/SignatureBase.h b/src/core/crypto/SignatureBase.h index ac804fe2..6564f236 100644 --- a/src/core/crypto/SignatureBase.h +++ b/src/core/crypto/SignatureBase.h @@ -33,7 +33,7 @@ #ifndef SRC_CORE_CRYPTO_SIGNATUREBASE_H_ #define SRC_CORE_CRYPTO_SIGNATUREBASE_H_ -#include +#include namespace i2p { namespace crypto { @@ -42,21 +42,21 @@ class Verifier { public: virtual ~Verifier() {} virtual bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const = 0; - virtual size_t GetPublicKeyLen() const = 0; - virtual size_t GetSignatureLen() const = 0; - virtual size_t GetPrivateKeyLen() const = 0; + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const = 0; + virtual std::size_t GetPublicKeyLen() const = 0; + virtual std::size_t GetSignatureLen() const = 0; + virtual std::size_t GetPrivateKeyLen() const = 0; }; class Signer { public: virtual ~Signer() {} virtual void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const = 0; + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const = 0; }; class RawVerifier { @@ -64,11 +64,11 @@ class RawVerifier { virtual ~RawVerifier() {} virtual void Update( - const uint8_t* buf, - size_t len) = 0; + const std::uint8_t* buf, + std::size_t len) = 0; virtual bool Verify( - const uint8_t* signature) = 0; + const std::uint8_t* signature) = 0; }; } // namespace crypto diff --git a/src/core/crypto/CryptoConst.cpp b/src/core/crypto/pimpl/cryptopp/CryptoConst.cpp similarity index 97% rename from src/core/crypto/CryptoConst.cpp rename to src/core/crypto/pimpl/cryptopp/CryptoConst.cpp index 0bd9c51b..0260da39 100644 --- a/src/core/crypto/CryptoConst.cpp +++ b/src/core/crypto/pimpl/cryptopp/CryptoConst.cpp @@ -86,10 +86,10 @@ const uint8_t dsag_[128]= { const CryptoConstants& GetCryptoConstants() { static CryptoConstants cryptoConstants = { CryptoPP::Integer(elgp_, 256), // elgp - CryptoPP::Integer(2), // elgg + CryptoPP::Integer(2), // elgg CryptoPP::Integer(dsap_, 128), // dsap - CryptoPP::Integer(dsaq_, 20), // dsaq - CryptoPP::Integer(dsag_, 128) // dsag + CryptoPP::Integer(dsaq_, 20), // dsaq + CryptoPP::Integer(dsag_, 128) // dsag }; return cryptoConstants; } diff --git a/src/core/crypto/CryptoConst.h b/src/core/crypto/pimpl/cryptopp/CryptoConst.h similarity index 91% rename from src/core/crypto/CryptoConst.h rename to src/core/crypto/pimpl/cryptopp/CryptoConst.h index c22ca7f4..335f2c88 100644 --- a/src/core/crypto/CryptoConst.h +++ b/src/core/crypto/pimpl/cryptopp/CryptoConst.h @@ -30,8 +30,8 @@ * Parts of the project are originally copyright (c) 2013-2015 The PurpleI2P Project */ -#ifndef SRC_CORE_CRYPTO_CRYPTOCONST_H_ -#define SRC_CORE_CRYPTO_CRYPTOCONST_H_ +#ifndef SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_CRYPTOCONST_H_ +#define SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_CRYPTOCONST_H_ #include @@ -39,7 +39,7 @@ namespace i2p { namespace crypto { struct CryptoConstants { - // DH/ElGamal + // ElGamal/Diffie-Hellman const CryptoPP::Integer elgp; const CryptoPP::Integer elgg; @@ -51,7 +51,7 @@ struct CryptoConstants { const CryptoConstants& GetCryptoConstants(); -// DH/ElGamal +// ElGamal/Diffie-Hellman #define elgp GetCryptoConstants().elgp #define elgg GetCryptoConstants().elgg @@ -66,4 +66,4 @@ const int rsae = 65537; } // namespace crypto } // namespace i2p -#endif // SRC_CORE_CRYPTO_CRYPTOCONST_H_ +#endif // SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_CRYPTOCONST_H_ diff --git a/src/core/crypto/pimpl/cryptopp/DiffieHellman.cpp b/src/core/crypto/pimpl/cryptopp/DiffieHellman.cpp new file mode 100644 index 00000000..35e95a46 --- /dev/null +++ b/src/core/crypto/pimpl/cryptopp/DiffieHellman.cpp @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2015-2016, The Kovri I2P Router Project + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "crypto/DiffieHellman.h" + +#include +#include + +#include + +#include "CryptoConst.h" + +namespace i2p { +namespace crypto { + +class DiffieHellman::DiffieHellmanImpl { + public: + /// @brief Initializes with ElGamal constants on construction + DiffieHellmanImpl() + : dh(i2p::crypto::elgp, i2p::crypto::elgg) {} + + /// @brief Generate private/public key pair + /// @param private_key Private key + /// @param public_key Public key + void GenerateKeyPair( + std::uint8_t* private_key, + std::uint8_t* public_key) { + dh.GenerateKeyPair( + prng, + private_key, + public_key); + } + + /// @brief Agreed value from your private key and other party's public key + /// @param agreed_value Agreed upon value + /// @param private_key Your private key + /// @param other_public_key Other party's public key + /// @return False on failure + bool Agree( + std::uint8_t* agreed_value, + const std::uint8_t* private_key, + const std::uint8_t* other_public_key) { + return dh.Agree( + agreed_value, + private_key, + other_public_key); + } + + private: + CryptoPP::DH dh; + CryptoPP::AutoSeededRandomPool prng; +}; + +DiffieHellman::DiffieHellman() : m_DiffieHellmanPimpl(new DiffieHellmanImpl()) {} +DiffieHellman::~DiffieHellman() {} + +void DiffieHellman::GenerateKeyPair( + std::uint8_t* private_key, + std::uint8_t* public_key) { + m_DiffieHellmanPimpl->GenerateKeyPair( + private_key, + public_key); +} + +bool DiffieHellman::Agree( + std::uint8_t* agreed_value, + const std::uint8_t* private_key, + const std::uint8_t* other_public_key) { + return m_DiffieHellmanPimpl->Agree( + agreed_value, + private_key, + other_public_key); +} + +} // namespace crypto +} // namespace i2p diff --git a/src/core/crypto/ElGamal.cpp b/src/core/crypto/pimpl/cryptopp/ElGamal.cpp similarity index 50% rename from src/core/crypto/ElGamal.cpp rename to src/core/crypto/pimpl/cryptopp/ElGamal.cpp index 3366c0e2..09c964db 100644 --- a/src/core/crypto/ElGamal.cpp +++ b/src/core/crypto/pimpl/cryptopp/ElGamal.cpp @@ -30,122 +30,130 @@ * Parts of the project are originally copyright (c) 2013-2015 The PurpleI2P Project */ -#include "ElGamal.h" +#include "crypto/ElGamal.h" -#include #include #include #include +#include + #include "CryptoConst.h" -#include "pimpl/cryptopp/Rand.h" -#include "Rand.h" -#include "util/Log.h" +#include "crypto/DiffieHellman.h" +#include "crypto/Rand.h" namespace i2p { namespace crypto { -class ElGamalEncryption_Pimpl { +// Encryption +class ElGamalEncryptionImpl { public: - ElGamalEncryption_Pimpl( - const uint8_t* key); + ElGamalEncryptionImpl( + const std::uint8_t* key) { + CryptoPP::AutoSeededRandomPool prng; + CryptoPP::Integer + y(key, 256), + k(prng, CryptoPP::Integer::One(), elgp - 1); + a = a_exp_b_mod_c(elgg, k, elgp); + b1 = a_exp_b_mod_c(y, k, elgp); + } void Encrypt( - const uint8_t* data, - size_t len, - uint8_t* encrypted, - bool zeroPadding) const; + const std::uint8_t* data, + std::size_t len, + std::uint8_t* encrypted, + bool zeroPadding) const { + if (len > 222) { + // Bad size, will overflow + throw std::logic_error( + "ElGamal: bad size for encryption: " + std::to_string(len)); + } + std::array memory; + // Don't pad with uninitialized memory + RandBytes(memory.data(), 255); + memory.at(0) = 0xFF; + memcpy(memory.data() + 33, data, len); + CryptoPP::SHA256().CalculateDigest( + memory.data() + 1, + memory.data() + 33, + 222); + CryptoPP::Integer b( + a_times_b_mod_c( + b1, + CryptoPP::Integer(memory.data(), 255), + elgp)); + // Copy a and b + if (zeroPadding) { + encrypted[0] = 0; + a.Encode(encrypted + 1, 256); + encrypted[257] = 0; + b.Encode(encrypted + 258, 256); + } else { + a.Encode(encrypted, 256); + b.Encode(encrypted + 256, 256); + } + } private: - CryptoPP::Integer a, - b1; + CryptoPP::Integer a, b1; }; -ElGamalEncryption::ElGamalEncryption( - const uint8_t* key) - : m_Impl( - new ElGamalEncryption_Pimpl(key)) {} +ElGamalEncryption::ElGamalEncryption(const std::uint8_t* key) + : m_ElGamalEncryptionPimpl(new ElGamalEncryptionImpl(key)) {} -ElGamalEncryption::~ElGamalEncryption() { - delete m_Impl; -} +ElGamalEncryption::~ElGamalEncryption() {} void ElGamalEncryption::Encrypt( - const uint8_t* data, - size_t len, - uint8_t* encrypted, - bool zeroPadding) const { - m_Impl->Encrypt(data, len, encrypted, zeroPadding); -} - -ElGamalEncryption_Pimpl::ElGamalEncryption_Pimpl( - const uint8_t* key) { - PRNG rnd; - CryptoPP::Integer y(key, 256), - k(rnd, CryptoPP::Integer::One(), elgp-1); - a = a_exp_b_mod_c(elgg, k, elgp); - b1 = a_exp_b_mod_c(y, k, elgp); -} - -void ElGamalEncryption_Pimpl::Encrypt( - const uint8_t* data, - size_t len, - uint8_t* encrypted, + const std::uint8_t* data, + std::size_t len, + std::uint8_t* encrypted, bool zeroPadding) const { - if (len > 222) { - // bad size, will cause an overflow - throw std::logic_error( - "bad size for ElGamal encryption: " + std::to_string(len)); - } - uint8_t m[255]; - // don't use uninitialized memory as padding - RandBytes(m, 255); - m[0] = 0xFF; - memcpy(m + 33, data, len); - CryptoPP::SHA256().CalculateDigest(m + 1, m + 33, 222); - CryptoPP::Integer b(a_times_b_mod_c(b1, CryptoPP::Integer(m, 255), elgp)); - // copy a and b - if (zeroPadding) { - encrypted[0] = 0; - a.Encode(encrypted + 1, 256); - encrypted[257] = 0; - b.Encode(encrypted + 258, 256); - } else { - a.Encode(encrypted, 256); - b.Encode(encrypted + 256, 256); - } + m_ElGamalEncryptionPimpl->Encrypt(data, len, encrypted, zeroPadding); } +// Decryption bool ElGamalDecrypt( - const uint8_t* key, - const uint8_t* encrypted, - uint8_t* data, + const std::uint8_t* key, + const std::uint8_t* encrypted, + std::uint8_t* data, bool zeroPadding) { if (zeroPadding && (encrypted[0] || encrypted[257])) - return false; // bad padding - + return false; // Bad padding CryptoPP::Integer x(key, 256), a(zeroPadding ? encrypted + 1 : encrypted, 256), b(zeroPadding ? encrypted + 258 : encrypted + 256, 256); - uint8_t m[255]; - a_times_b_mod_c(b, a_exp_b_mod_c(a, elgp - x - 1, elgp), elgp).Encode(m, 255); - if (!CryptoPP::SHA256().VerifyDigest(m + 1, m + 33, 222)) { + std::array memory; + a_times_b_mod_c( + b, + a_exp_b_mod_c( + a, + elgp - x - 1, + elgp), + elgp).Encode(memory.data(), 255); + if (!CryptoPP::SHA256().VerifyDigest( + memory.data() + 1, + memory.data() + 33, + 222)) { return false; } - memcpy(data, m + 33, 222); + memcpy(data, memory.data() + 33, 222); return true; } +// Create keypair void GenerateElGamalKeyPair( - uint8_t* priv, - uint8_t* pub) { + std::uint8_t* priv, + std::uint8_t* pub) { #if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER) RandBytes(priv, 256); - a_exp_b_mod_c(elgg, CryptoPP::Integer(priv, 256), elgp).Encode(pub, 256); + a_exp_b_mod_c( + elgg, + CryptoPP::Integer(priv, 256), + elgp).Encode(pub, 256); #else - CryptoPP::DH dh(elgp, elgg); - dh.GenerateKeyPair(prng, priv, pub); + DiffieHellman dh; + dh.GenerateKeyPair(priv, pub); #endif } diff --git a/src/core/crypto/Rand.cpp b/src/core/crypto/pimpl/cryptopp/Rand.cpp similarity index 94% rename from src/core/crypto/Rand.cpp rename to src/core/crypto/pimpl/cryptopp/Rand.cpp index 241d6789..df2b3509 100644 --- a/src/core/crypto/Rand.cpp +++ b/src/core/crypto/pimpl/cryptopp/Rand.cpp @@ -28,11 +28,9 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "Rand.h" +#include "crypto/Rand.h" -#include "pimpl/cryptopp/Rand.h" - -// implementation of crypto::Rand* functions +#include namespace i2p { namespace crypto { @@ -40,6 +38,7 @@ namespace crypto { void RandBytes( uint8_t* dataptr, size_t datalen) { + CryptoPP::AutoSeededRandomPool prng; prng.GenerateBlock(dataptr, datalen); } diff --git a/src/core/crypto/pimpl/cryptopp/Signature.cpp b/src/core/crypto/pimpl/cryptopp/Signature.cpp new file mode 100644 index 00000000..5e722eff --- /dev/null +++ b/src/core/crypto/pimpl/cryptopp/Signature.cpp @@ -0,0 +1,753 @@ +/** + * Copyright (c) 2013-2016, The Kovri I2P Router Project + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Parts of the project are originally copyright (c) 2013-2015 The PurpleI2P Project + */ + +#include "crypto/Signature.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "CryptoConst.h" +#include "crypto/Rand.h" + +namespace i2p { +namespace crypto { + +/** + * + * DSA + * + */ + +// Verifier +class DSAVerifier::DSAVerifierImpl { + public: + DSAVerifierImpl( + const std::uint8_t* signing_key) { + m_PublicKey.Initialize( + dsap, + dsaq, + dsag, + CryptoPP::Integer( + signing_key, + DSA_PUBLIC_KEY_LENGTH)); + } + + bool Verify( + const uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + CryptoPP::DSA::Verifier verifier(m_PublicKey); + return verifier.VerifyMessage(buf, len, signature, DSA_SIGNATURE_LENGTH); + } + + private: + CryptoPP::DSA::PublicKey m_PublicKey; +}; + +DSAVerifier::DSAVerifier(const std::uint8_t* signing_key) + : m_DSAVerifierPimpl(new DSAVerifierImpl(signing_key)) {} + +DSAVerifier::~DSAVerifier() {} + +bool DSAVerifier::Verify( + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + return m_DSAVerifierPimpl->Verify(buf, len, signature); +} + +// Signer +class DSASigner::DSASignerImpl { + public: + DSASignerImpl( + const std::uint8_t* private_signing_key) { + m_PrivateKey.Initialize( + dsap, + dsaq, + dsag, + CryptoPP::Integer( + private_signing_key, + DSA_PRIVATE_KEY_LENGTH)); + } + + void Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + CryptoPP::DSA::Signer signer(m_PrivateKey); + CryptoPP::AutoSeededRandomPool prng; + signer.SignMessage(prng, buf, len, signature); + } + + private: + CryptoPP::DSA::PrivateKey m_PrivateKey; +}; + +DSASigner::DSASigner(const std::uint8_t* private_signing_key) + : m_DSASignerPimpl(new DSASignerImpl(private_signing_key)) {} + +DSASigner::~DSASigner() {} + +void DSASigner::Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + m_DSASignerPimpl->Sign(buf, len, signature); +} + +// Create keys +void CreateDSARandomKeys( + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key) { + std::array key_buf; + CryptoPP::Integer dsax; + do { + i2p::crypto::RandBytes(key_buf.data(), DSA_PRIVATE_KEY_LENGTH); + dsax = CryptoPP::Integer(key_buf.data(), DSA_PRIVATE_KEY_LENGTH); + } while (dsax.IsZero() || dsax >= dsaq); + CryptoPP::DSA::PrivateKey private_key; + CryptoPP::DSA::PublicKey public_key; + private_key.Initialize(dsap, dsaq, dsag, dsax); + private_key.MakePublicKey(public_key); + private_key.GetPrivateExponent().Encode( + private_signing_key, + DSA_PRIVATE_KEY_LENGTH); + public_key.GetPublicElement().Encode( + public_signing_key, + DSA_PUBLIC_KEY_LENGTH); +} + +/** + * + * ECDSA + * + */ + +// Verifier +template +class ECDSAVerifier { + public: + template + ECDSAVerifier( + Curve curve, + const std::uint8_t* signing_key) { + m_PublicKey.Initialize( + curve, + CryptoPP::ECP::Point( + CryptoPP::Integer( + signing_key, + KeyLen / 2), + CryptoPP::Integer( + signing_key + KeyLen / 2, + KeyLen / 2))); + } + + bool Verify( + const std::uint8_t* buf, + std::size_t len, + const uint8_t * signature) const { + typename CryptoPP::ECDSA::Verifier + verifier(m_PublicKey); + return verifier.VerifyMessage( + buf, len, signature, KeyLen); // Signature length + } + + private: + typename CryptoPP::ECDSA::PublicKey m_PublicKey; +}; + +// Signer +template +class ECDSASigner : public Signer { + public: + typedef typename CryptoPP::ECDSA::PrivateKey SignKey; + template + ECDSASigner( + Curve curve, + const std::uint8_t* private_signing_key, + std::size_t key_length) { + m_PrivateKey.Initialize( + curve, + CryptoPP::Integer( + private_signing_key, + key_length / 2)); // Private key length + } + + void Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + typename CryptoPP::ECDSA::Signer + signer(m_PrivateKey); + CryptoPP::AutoSeededRandomPool prng; + signer.SignMessage(prng, buf, len, signature); + } + + private: + SignKey m_PrivateKey; +}; + +// Create keys +template +inline void CreateECDSARandomKeys( + Curve curve, + std::size_t key_length, + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key) { + typename CryptoPP::ECDSA::PrivateKey + private_key; + typename CryptoPP::ECDSA::PublicKey + public_key; + CryptoPP::AutoSeededRandomPool prng; + private_key.Initialize(prng, curve); + private_key.MakePublicKey(public_key); + private_key.GetPrivateExponent().Encode(private_signing_key, key_length / 2); + auto q = public_key.GetPublicElement(); + q.x.Encode(public_signing_key, key_length / 2); + q.y.Encode(public_signing_key + key_length / 2, key_length / 2); +} + +/** + * + * ECDSAP256 + * + */ + +// Verifier +class ECDSAP256VerifierImpl + : public ECDSAVerifier { + public: + ECDSAP256VerifierImpl( + const std::uint8_t* signing_key) + : ECDSAVerifier( + CryptoPP::ASN1::secp256r1(), + signing_key) {} +}; + +ECDSAP256Verifier::ECDSAP256Verifier(const std::uint8_t* signing_key) + : m_ECDSAP256VerifierPimpl(new ECDSAP256VerifierImpl(signing_key)) {} + +ECDSAP256Verifier::~ECDSAP256Verifier() {} + +bool ECDSAP256Verifier::Verify( + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + return m_ECDSAP256VerifierPimpl->Verify(buf, len, signature); +} + +// Signer +class ECDSAP256SignerImpl + : public ECDSASigner { + public: + ECDSAP256SignerImpl( + const std::uint8_t* private_signing_key) + : ECDSASigner( + CryptoPP::ASN1::secp256r1(), + private_signing_key, + ECDSAP256_KEY_LENGTH) {} +}; + +ECDSAP256Signer::ECDSAP256Signer(const std::uint8_t* private_signing_key) + : m_ECDSAP256SignerPimpl(new ECDSAP256SignerImpl(private_signing_key)) {} + +ECDSAP256Signer::~ECDSAP256Signer() {} + +void ECDSAP256Signer::Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + m_ECDSAP256SignerPimpl->Sign(buf, len, signature); +} + +// Create keys +void CreateECDSAP256RandomKeys( + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key) { + CreateECDSARandomKeys( + CryptoPP::ASN1::secp256r1(), + ECDSAP256_KEY_LENGTH, + private_signing_key, + public_signing_key); +} + +/** + * + * ECDSAP384 + * + */ + +// Verifier +class ECDSAP384VerifierImpl + : public ECDSAVerifier { + public: + ECDSAP384VerifierImpl( + const std::uint8_t* signing_key) + : ECDSAVerifier( + CryptoPP::ASN1::secp384r1(), + signing_key) {} +}; + +ECDSAP384Verifier::ECDSAP384Verifier(const std::uint8_t* signing_key) + : m_ECDSAP384VerifierPimpl(new ECDSAP384VerifierImpl(signing_key)) {} + +ECDSAP384Verifier::~ECDSAP384Verifier() {} + +bool ECDSAP384Verifier::Verify( + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + return m_ECDSAP384VerifierPimpl->Verify(buf, len, signature); +} + +// Signer +class ECDSAP384SignerImpl + : public ECDSASigner { + public: + ECDSAP384SignerImpl( + const std::uint8_t* private_signing_key) + : ECDSASigner( + CryptoPP::ASN1::secp384r1(), + private_signing_key, + ECDSAP384_KEY_LENGTH) {} +}; + +ECDSAP384Signer::ECDSAP384Signer(const std::uint8_t* private_signing_key) + : m_ECDSAP384SignerPimpl(new ECDSAP384SignerImpl(private_signing_key)) {} + +ECDSAP384Signer::~ECDSAP384Signer() {} + +void ECDSAP384Signer::Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t * signature) const { + m_ECDSAP384SignerPimpl->Sign(buf, len, signature); +} + +// Create keys +void CreateECDSAP384RandomKeys( + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key) { + CreateECDSARandomKeys( + CryptoPP::ASN1::secp384r1(), + ECDSAP384_KEY_LENGTH, + private_signing_key, + public_signing_key); +} + +/** + * + * ECDSAP521 + * + */ + +// Verifier +class ECDSAP521VerifierImpl + : public ECDSAVerifier { + public: + ECDSAP521VerifierImpl( + const std::uint8_t* signing_key) + : ECDSAVerifier( + CryptoPP::ASN1::secp521r1(), + signing_key) {} +}; + +ECDSAP521Verifier::ECDSAP521Verifier(const std::uint8_t* signing_key) + : m_ECDSAP521VerifierPimpl(new ECDSAP521VerifierImpl(signing_key)) {} + +ECDSAP521Verifier::~ECDSAP521Verifier() {} + +bool ECDSAP521Verifier::Verify( + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + return m_ECDSAP521VerifierPimpl->Verify(buf, len, signature); +} + +// Signer +class ECDSAP521SignerImpl + : public ECDSASigner { + public: + ECDSAP521SignerImpl( + const std::uint8_t* private_signing_key) + : ECDSASigner( + CryptoPP::ASN1::secp521r1(), + private_signing_key, + ECDSAP521_KEY_LENGTH) {} +}; + +ECDSAP521Signer::ECDSAP521Signer(const std::uint8_t* private_signing_key) + : m_ECDSAP521SignerPimpl(new ECDSAP521SignerImpl(private_signing_key)) {} + +ECDSAP521Signer::~ECDSAP521Signer() {} + +void ECDSAP521Signer::Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + m_ECDSAP521SignerPimpl->Sign(buf, len, signature); +} + +// Create keys +void CreateECDSAP521RandomKeys( + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key) { + CreateECDSARandomKeys( + CryptoPP::ASN1::secp521r1(), + ECDSAP521_KEY_LENGTH, + private_signing_key, + public_signing_key); +} + +/** + * + * RSA + * + */ + +// Verifier +template +class RSAVerifier { + public: + explicit RSAVerifier( + const std::uint8_t* signing_key) { + m_PublicKey.Initialize( + CryptoPP::Integer( + signing_key, + key_length), + CryptoPP::Integer( + rsae)); + } + bool Verify( + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + typename CryptoPP::RSASS::Verifier + verifier(m_PublicKey); + // Signature length + return verifier.VerifyMessage(buf, len, signature, key_length); + } + + private: + CryptoPP::RSA::PublicKey m_PublicKey; +}; + +// Signer +template +class RSASigner { + public: + RSASigner( + const std::uint8_t* private_signing_key, + std::size_t key_length) { + m_PrivateKey.Initialize( + CryptoPP::Integer( + private_signing_key, + key_length / 2), + rsae, + CryptoPP::Integer( + private_signing_key + key_length / 2, + key_length / 2)); + } + + void Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + CryptoPP::AutoSeededRandomPool prng; + typename CryptoPP::RSASS::Signer + signer(m_PrivateKey); + signer.SignMessage(prng, buf, len, signature); + } + + private: + CryptoPP::RSA::PrivateKey m_PrivateKey; +}; + +// Create keys +void CreateRSARandomKeys( + std::size_t public_key_length, + std::uint8_t* private_signing_key, + std::uint8_t* public_signing_key) { + CryptoPP::RSA::PrivateKey private_key; + CryptoPP::AutoSeededRandomPool prng; + private_key.Initialize( + prng, + public_key_length * 8, + rsae); + private_key.GetModulus().Encode( + private_signing_key, + public_key_length); + private_key.GetPrivateExponent().Encode( + private_signing_key + public_key_length, + public_key_length); + private_key.GetModulus().Encode( + public_signing_key, + public_key_length); + } + +/** + * + * RSASHA2562048 + * + */ + +// Verifier +class RSASHA2562048VerifierImpl + : public RSAVerifier { + public: + explicit RSASHA2562048VerifierImpl( + const std::uint8_t* public_key) + : RSAVerifier(public_key) {} +}; + +RSASHA2562048Verifier::RSASHA2562048Verifier(const std::uint8_t* pubKey) + : m_RSASHA2562048VerifierPimpl(new RSASHA2562048VerifierImpl(pubKey)) {} + +RSASHA2562048Verifier::~RSASHA2562048Verifier() {} + +bool RSASHA2562048Verifier::Verify( + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + return m_RSASHA2562048VerifierPimpl->Verify(buf, len, signature); +} + +// Signer +class RSASHA2562048SignerImpl + : public RSASigner { + public: + RSASHA2562048SignerImpl( + const std::uint8_t* privkey) + : RSASigner(privkey, RSASHA2562048_KEY_LENGTH * 2) {} +}; + +RSASHA2562048Signer::RSASHA2562048Signer(const std::uint8_t* private_key) + : m_RSASHA2562048SignerPimpl(new RSASHA2562048SignerImpl(private_key)) {} + +RSASHA2562048Signer::~RSASHA2562048Signer() {} + +void RSASHA2562048Signer::Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + m_RSASHA2562048SignerPimpl->Sign(buf, len, signature); +} + +/** + * + * RSASHA3843072 + * + */ + +// Verifier +class RSASHA3843072VerifierImpl + : public RSAVerifier { + public: + explicit RSASHA3843072VerifierImpl( + const std::uint8_t* public_key) + : RSAVerifier(public_key) {} +}; + +RSASHA3843072Verifier::RSASHA3843072Verifier(const std::uint8_t* pubKey) + : m_RSASHA3843072VerifierPimpl(new RSASHA3843072VerifierImpl(pubKey)) {} + +RSASHA3843072Verifier::~RSASHA3843072Verifier() {} + +bool RSASHA3843072Verifier::Verify( + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + return m_RSASHA3843072VerifierPimpl->Verify(buf, len, signature); +} + +// Signer +class RSASHA3843072SignerImpl + : public RSASigner { + public: + RSASHA3843072SignerImpl( + const uint8_t* privkey) + : RSASigner(privkey, RSASHA3843072_KEY_LENGTH * 2) {} +}; + +RSASHA3843072Signer::RSASHA3843072Signer(const std::uint8_t* private_key) + : m_RSASHA3843072SignerPimpl(new RSASHA3843072SignerImpl(private_key)) {} + +RSASHA3843072Signer::~RSASHA3843072Signer() {} + +void RSASHA3843072Signer::Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + m_RSASHA3843072SignerPimpl->Sign(buf, len, signature); +} + +/** + * + * RSASHA5124096 + * + */ + +// Verifier +class RSASHA5124096VerifierImpl + : public RSAVerifier { + public: + RSASHA5124096VerifierImpl( + const std::uint8_t* public_key) + : RSAVerifier(public_key) {} +}; + +RSASHA5124096Verifier::RSASHA5124096Verifier(const std::uint8_t* pubKey) + : m_RSASHA5124096VerifierPimpl(new RSASHA5124096VerifierImpl(pubKey)) {} + +RSASHA5124096Verifier::~RSASHA5124096Verifier() {} + +bool RSASHA5124096Verifier::Verify( + const std::uint8_t* buf, + std::size_t len, + const std::uint8_t* signature) const { + return m_RSASHA5124096VerifierPimpl->Verify(buf, len, signature); +} + +// Signer +class RSASHA5124096SignerImpl + : public RSASigner { + public: + RSASHA5124096SignerImpl( + const std::uint8_t* privkey) + : RSASigner(privkey, RSASHA5124096_KEY_LENGTH * 2) {} +}; + +RSASHA5124096Signer::RSASHA5124096Signer(const std::uint8_t* private_key) + : m_RSASHA5124096SignerPimpl(new RSASHA5124096SignerImpl(private_key)) {} + +RSASHA5124096Signer::~RSASHA5124096Signer() {} + +void RSASHA5124096Signer::Sign( + const std::uint8_t* buf, + std::size_t len, + std::uint8_t* signature) const { + m_RSASHA5124096SignerPimpl->Sign(buf, len, signature); +} + +/** + * + * RSARaw + * + */ + +// Verifier +template +class RSARawVerifier { + public: + RSARawVerifier( + const std::uint8_t* signing_key) + : n(signing_key, key_length) {} + + void Update( + const std::uint8_t* buf, + std::size_t len) { + m_Hash.Update(buf, len); + } + + bool Verify( + const std::uint8_t* signature) { + // RSA encryption first + CryptoPP::Integer enSig( + a_exp_b_mod_c( + CryptoPP::Integer( + signature, + key_length), + CryptoPP::Integer( + i2p::crypto::rsae), + n)); // s^e mod n + + std::uint8_t EnSigBuf[key_length]; + enSig.Encode(EnSigBuf, key_length); + std::uint8_t digest[Hash::DIGESTSIZE]; + m_Hash.Final(digest); + + if (static_cast(key_length) < Hash::DIGESTSIZE) + return false; // Can't verify digest longer than key + // We assume digest is right aligned, at least for PKCS#1 v1.5 padding + return !memcmp( + EnSigBuf + (key_length - Hash::DIGESTSIZE), + digest, + Hash::DIGESTSIZE); + } + + private: + CryptoPP::Integer n; // RSA modulus + Hash m_Hash; +}; + +/** + * + * RSASHA5124096Raw + * + */ + +// Verifier +class RSASHA5124096RawVerifierImpl + : public RSARawVerifier { + public: + RSASHA5124096RawVerifierImpl( + const std::uint8_t* signing_key) + : RSARawVerifier(signing_key) {} +}; + +RSASHA5124096RawVerifier::RSASHA5124096RawVerifier(const std::uint8_t* signing_key) + : m_RSASHA5124096RawVerifierPimpl(new RSASHA5124096RawVerifierImpl(signing_key)) {} + +RSASHA5124096RawVerifier::~RSASHA5124096RawVerifier() {} + +void RSASHA5124096RawVerifier::Update( + const std::uint8_t* buf, + std::size_t len) { + m_RSASHA5124096RawVerifierPimpl->Update(buf, len); +} + +bool RSASHA5124096RawVerifier::Verify( + const std::uint8_t* signature) { + return m_RSASHA5124096RawVerifierPimpl->Verify(signature); +} + +} // namespace crypto +} // namespace i2p diff --git a/src/core/crypto/pimpl/cryptopp/Signature.h b/src/core/crypto/pimpl/cryptopp/Signature.h deleted file mode 100644 index 8ca267c5..00000000 --- a/src/core/crypto/pimpl/cryptopp/Signature.h +++ /dev/null @@ -1,386 +0,0 @@ -/** - * Copyright (c) 2013-2016, The Kovri I2P Router Project - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of the project are originally copyright (c) 2013-2015 The PurpleI2P Project - */ - -#ifndef SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_SIGNATURE_H_ -#define SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_SIGNATURE_H_ - -#include -#include -#include -#include -#include -#include - -#include "Rand.h" -#include "crypto/Signature.h" - -namespace i2p { -namespace crypto { - -class DSAVerifier_Pimpl { - public: - DSAVerifier_Pimpl( - const uint8_t* signingKey); - - bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const; - - private: - CryptoPP::DSA::PublicKey m_PublicKey; -}; - -class DSASigner_Pimpl { - public: - DSASigner_Pimpl( - const uint8_t* signingPrivateKey); - ~DSASigner_Pimpl(); - - void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const; - - private: - CryptoPP::DSA::PrivateKey m_PrivateKey; - uint8_t* m_PrivateKeyBuff; -}; - -template -class ECDSAVerifier { - public: - template - ECDSAVerifier( - Curve curve, - const uint8_t* signingKey) { - m_PublicKey.Initialize( - curve, - CryptoPP::ECP::Point( - CryptoPP::Integer( - signingKey, - keyLen / 2), - CryptoPP::Integer( - signingKey + keyLen / 2, - keyLen / 2))); - } - - bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t * signature) const { - typename CryptoPP::ECDSA::Verifier - verifier(m_PublicKey); - return verifier.VerifyMessage( - buf, len, signature, keyLen); // signature length - } - - private: - typename CryptoPP::ECDSA::PublicKey m_PublicKey; -}; - - -template -class ECDSASigner : public Signer { - public: - typedef typename CryptoPP::ECDSA::PrivateKey SignKey; - template - ECDSASigner( - Curve curve, - const uint8_t* signingPrivateKey, - size_t keyLen) { - m_PrivateKey.Initialize( - curve, - CryptoPP::Integer( - signingPrivateKey, - keyLen / 2)); // private key length - } - - void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - typename CryptoPP::ECDSA::Signer - signer(m_PrivateKey); - PRNG& r = prng; - signer.SignMessage(r, buf, len, signature); - } - - private: - SignKey m_PrivateKey; -}; - -template -inline void CreateECDSARandomKeys( - Curve curve, - size_t keyLen, - uint8_t* signingPrivateKey, - uint8_t* signingPublicKey) { - typename CryptoPP::ECDSA::PrivateKey - privateKey; - typename CryptoPP::ECDSA::PublicKey - publicKey; - PRNG& r = prng; - privateKey.Initialize(r, curve); - privateKey.MakePublicKey(publicKey); - privateKey.GetPrivateExponent().Encode(signingPrivateKey, keyLen / 2); - auto q = publicKey.GetPublicElement(); - q.x.Encode(signingPublicKey, keyLen / 2); - q.y.Encode(signingPublicKey + keyLen / 2, keyLen / 2); -} - -class ECDSAP256Verifier_Pimpl - : public ECDSAVerifier { - public: - ECDSAP256Verifier_Pimpl( - const uint8_t* signingKey) - : ECDSAVerifier( - CryptoPP::ASN1::secp256r1(), - signingKey) {} -}; - -class ECDSAP256Signer_Pimpl - : public ECDSASigner { - public: - ECDSAP256Signer_Pimpl( - const uint8_t* signingPrivateKey) - : ECDSASigner( - CryptoPP::ASN1::secp256r1(), - signingPrivateKey, - ECDSAP256_KEY_LENGTH) {} -}; - -class ECDSAP384Verifier_Pimpl - : public ECDSAVerifier { - public: - ECDSAP384Verifier_Pimpl( - const uint8_t* signingKey) - : ECDSAVerifier( - CryptoPP::ASN1::secp384r1(), - signingKey) {} -}; - -class ECDSAP384Signer_Pimpl - : public ECDSASigner { - public: - ECDSAP384Signer_Pimpl( - const uint8_t* signingPrivateKey) - : ECDSASigner( - CryptoPP::ASN1::secp384r1(), - signingPrivateKey, - ECDSAP384_KEY_LENGTH) {} -}; - -class ECDSAP521Verifier_Pimpl - : public ECDSAVerifier { - public: - ECDSAP521Verifier_Pimpl( - const uint8_t* signingKey) - : ECDSAVerifier( - CryptoPP::ASN1::secp521r1(), - signingKey) {} -}; - -class ECDSAP521Signer_Pimpl - : public ECDSASigner { - public: - ECDSAP521Signer_Pimpl( - const uint8_t* signingPrivateKey) - : ECDSASigner( - CryptoPP::ASN1::secp521r1(), - signingPrivateKey, - ECDSAP521_KEY_LENGTH) {} -}; - -template -class RSAVerifier { - public: - explicit RSAVerifier( - const uint8_t* signingKey) { - m_PublicKey.Initialize( - CryptoPP::Integer( - signingKey, - keyLen), - CryptoPP::Integer( - rsae)); - } - bool Verify( - const uint8_t* buf, - size_t len, - const uint8_t* signature) const { - typename CryptoPP::RSASS::Verifier - verifier(m_PublicKey); - // signature length - return verifier.VerifyMessage(buf, len, signature, keyLen); - } - - private: - CryptoPP::RSA::PublicKey m_PublicKey; -}; - - -template -class RSASigner { - public: - RSASigner( - const uint8_t* signingPrivateKey, - size_t keyLen) { - m_PrivateKey.Initialize( - CryptoPP::Integer( - signingPrivateKey, - keyLen / 2), - rsae, - CryptoPP::Integer( - signingPrivateKey + keyLen / 2, - keyLen / 2)); - } - - void Sign( - const uint8_t* buf, - size_t len, - uint8_t* signature) const { - PRNG rnd; - typename CryptoPP::RSASS::Signer - signer(m_PrivateKey); - signer.SignMessage(rnd, buf, len, signature); - } - - private: - CryptoPP::RSA::PrivateKey m_PrivateKey; -}; - - -class RSASHA2562048Verifier_Pimpl - : public RSAVerifier { - public: - explicit RSASHA2562048Verifier_Pimpl( - const uint8_t* pubkey) - : RSAVerifier(pubkey) {} -}; - -class RSASHA3843072Verifier_Pimpl - : public RSAVerifier { - public: - explicit RSASHA3843072Verifier_Pimpl( - const uint8_t* pubkey) - : RSAVerifier(pubkey) {} -}; - -class RSASHA5124096Verifier_Pimpl - : public RSAVerifier { - public: - RSASHA5124096Verifier_Pimpl( - const uint8_t* pubkey) - : RSAVerifier(pubkey) {} -}; - -class RSASHA2562048Signer_Pimpl - : public RSASigner { - public: - RSASHA2562048Signer_Pimpl( - const uint8_t* privkey) - : RSASigner(privkey, RSASHA2562048_KEY_LENGTH * 2) {} -}; - -class RSASHA3843072Signer_Pimpl - : public RSASigner { - public: - RSASHA3843072Signer_Pimpl( - const uint8_t* privkey) - : RSASigner(privkey, RSASHA3843072_KEY_LENGTH * 2) {} -}; - -class RSASHA5124096Signer_Pimpl - : public RSASigner { - public: - RSASHA5124096Signer_Pimpl( - const uint8_t* privkey) - : RSASigner(privkey, RSASHA5124096_KEY_LENGTH * 2) {} -}; - -template -class RSARawVerifier { - public: - RSARawVerifier( - const uint8_t* signingKey) - : n(signingKey, keyLen) {} - - void Update( - const uint8_t* buf, - size_t len) { - m_Hash.Update(buf, len); - } - - bool Verify( - const uint8_t* signature) { - // RSA encryption first - CryptoPP::Integer enSig( - a_exp_b_mod_c( - CryptoPP::Integer( - signature, - keyLen), - CryptoPP::Integer( - i2p::crypto::rsae), - n)); // s^e mod n - - uint8_t EnSigBuf[keyLen]; - enSig.Encode(EnSigBuf, keyLen); - uint8_t digest[Hash::DIGESTSIZE]; - m_Hash.Final(digest); - - if (static_cast(keyLen) < Hash::DIGESTSIZE) - return false; // can't verify digest longer than key - // we assume digest is right aligned, at least for PKCS#1 v1.5 padding - return !memcmp( - EnSigBuf + (keyLen - Hash::DIGESTSIZE), - digest, - Hash::DIGESTSIZE); - } - - private: - CryptoPP::Integer n; // RSA modulus - Hash m_Hash; -}; - - -class RSASHA5124096RawVerifier_Pimpl - : public RSARawVerifier { - public: - RSASHA5124096RawVerifier_Pimpl( - const uint8_t* signingKey) - : RSARawVerifier(signingKey) {} -}; - -} // namespace crypto -} // namespace i2p - -#endif // SRC_CORE_CRYPTO_PIMPL_CRYPTOPP_SIGNATURE_H_ diff --git a/src/core/crypto/pimpl/cryptopp/ZIP.cpp b/src/core/crypto/pimpl/cryptopp/ZIP.cpp index a9072abc..0ec85418 100644 --- a/src/core/crypto/pimpl/cryptopp/ZIP.cpp +++ b/src/core/crypto/pimpl/cryptopp/ZIP.cpp @@ -42,6 +42,8 @@ namespace i2p { namespace crypto { +// TODO(unassigned): we should create a base class to interface Put()/Get(), etc. + class Decompressor::DecompressorImpl { public: /// @brief Puts data into decompressor (inflator) @@ -60,7 +62,7 @@ class Decompressor::DecompressorImpl { m_Inflator.MessageEnd(); } catch (CryptoPP::Exception& e) { LogPrint(eLogError, - "Decompressor: could not put data. Exception: '", e.what(), "'"); + "Decompressor: could not put data. '", e.what(), "'"); return false; } return true; @@ -77,7 +79,7 @@ class Decompressor::DecompressorImpl { m_Inflator.Get(buffer, length); } catch (CryptoPP::Exception& e) { LogPrint(eLogError, - "Decompressor: could not get data. Exception: '", e.what(), "'"); + "Decompressor: could not get data. '", e.what(), "'"); return false; } return true; @@ -91,7 +93,7 @@ class Decompressor::DecompressorImpl { max = m_Inflator.MaxRetrievable(); } catch (CryptoPP::Exception& e) { LogPrint(eLogError, - "Decompressor: could not get max. Exception: '", e.what(), "'"); + "Decompressor: could not get max. '", e.what(), "'"); max = 0; } return max; @@ -111,7 +113,7 @@ class Decompressor::DecompressorImpl { verify = CryptoPP::CRC32().VerifyDigest(hash, data, length); } catch (CryptoPP::Exception& e) { LogPrint(eLogError, - "Decompressor: could not verify digest. Exception: '", e.what(), "'"); + "Decompressor: could not verify digest. '", e.what(), "'"); return false; } return verify; diff --git a/src/core/transport/NTCPSession.cpp b/src/core/transport/NTCPSession.cpp index 727f4f6e..dad9eaab 100644 --- a/src/core/transport/NTCPSession.cpp +++ b/src/core/transport/NTCPSession.cpp @@ -33,7 +33,6 @@ #include "NTCPSession.h" #include -#include #include #include @@ -45,8 +44,8 @@ #include "NetworkDatabase.h" #include "RouterContext.h" #include "Transports.h" +#include "crypto/DiffieHellman.h" #include "crypto/Rand.h" -#include "crypto/CryptoConst.h" #include "util/Base64.h" #include "util/I2PEndian.h" #include "util/Log.h" @@ -78,9 +77,7 @@ NTCPSession::~NTCPSession() { void NTCPSession::CreateAESKey( std::uint8_t* pubKey, i2p::crypto::AESKey& key) { - CryptoPP::DH dh( - i2p::crypto::elgp, - i2p::crypto::elgg); + i2p::crypto::DiffieHellman dh; std::uint8_t sharedKey[NTCP_PUBKEY_SIZE]; if (!dh.Agree(sharedKey, m_DHKeysPair->privateKey, pubKey)) { LogPrint(eLogError, "Couldn't create shared key"); diff --git a/src/core/transport/SSUSession.cpp b/src/core/transport/SSUSession.cpp index df4ec6f5..7138916f 100644 --- a/src/core/transport/SSUSession.cpp +++ b/src/core/transport/SSUSession.cpp @@ -34,7 +34,6 @@ #include -#include #include #include @@ -42,8 +41,8 @@ #include "RouterContext.h" #include "SSU.h" #include "Transports.h" +#include "crypto/DiffieHellman.h" #include "crypto/Rand.h" -#include "crypto/CryptoConst.h" #include "util/Log.h" #include "util/Timestamp.h" @@ -170,14 +169,9 @@ boost::asio::io_service& SSUSession::GetService() { void SSUSession::CreateAESandMacKey( const uint8_t* pubKey) { - CryptoPP::DH dh( - i2p::crypto::elgp, - i2p::crypto::elgg); + i2p::crypto::DiffieHellman dh; uint8_t sharedKey[256]; - if (!dh.Agree( - sharedKey, - m_DHKeysPair->privateKey, - pubKey)) { + if (!dh.Agree(sharedKey, m_DHKeysPair->privateKey, pubKey)) { LogPrint(eLogError, "Couldn't create shared key"); return; } diff --git a/src/core/transport/Transports.cpp b/src/core/transport/Transports.cpp index 93ca5397..b3f0ecfc 100644 --- a/src/core/transport/Transports.cpp +++ b/src/core/transport/Transports.cpp @@ -32,8 +32,6 @@ #include "Transports.h" -#include - #include #include #include @@ -41,7 +39,7 @@ #include "I2NPProtocol.h" #include "NetworkDatabase.h" #include "RouterContext.h" -#include "crypto/CryptoConst.h" +#include "crypto/DiffieHellman.h" #include "crypto/Rand.h" #include "util/Log.h" @@ -90,14 +88,11 @@ void DHKeysPairSupplier::Run() { void DHKeysPairSupplier::CreateDHKeysPairs( int num) { if (num > 0) { - CryptoPP::DH dh( - i2p::crypto::elgp, - i2p::crypto::elgg); + i2p::crypto::DiffieHellman dh; for (int i = 0; i < num; i++) { i2p::transport::DHKeysPair* pair = new i2p::transport::DHKeysPair(); dh.GenerateKeyPair( - m_Rnd, pair->privateKey, pair->publicKey); std::unique_lock l(m_AcquiredMutex); @@ -118,11 +113,8 @@ DHKeysPair* DHKeysPairSupplier::Acquire() { // queue is empty, create new key pair DHKeysPair* pair = new DHKeysPair(); - CryptoPP::DH dh( - i2p::crypto::elgp, - i2p::crypto::elgg); + i2p::crypto::DiffieHellman dh; dh.GenerateKeyPair( - m_Rnd, pair->privateKey, pair->publicKey); return pair; diff --git a/src/core/transport/Transports.h b/src/core/transport/Transports.h index 91281181..54087e08 100644 --- a/src/core/transport/Transports.h +++ b/src/core/transport/Transports.h @@ -35,8 +35,6 @@ #include -#include - #include #include #include @@ -92,7 +90,6 @@ class DHKeysPairSupplier { std::thread* m_Thread; std::condition_variable m_Acquired; std::mutex m_AcquiredMutex; - CryptoPP::AutoSeededRandomPool m_Rnd; }; struct Peer { diff --git a/src/core/tunnel/TunnelPool.cpp b/src/core/tunnel/TunnelPool.cpp index 81ecee3a..14b130ae 100644 --- a/src/core/tunnel/TunnelPool.cpp +++ b/src/core/tunnel/TunnelPool.cpp @@ -38,7 +38,6 @@ #include "Garlic.h" #include "NetworkDatabase.h" #include "Tunnel.h" -#include "crypto/CryptoConst.h" #include "crypto/Rand.h" #include "transport/Transports.h" #include "util/I2PEndian.h"