/* */ #include "InternalDHKeyExchange.h" #include #include "DlAbortEx.h" #include "LogFactory.h" #include "fmt.h" #include "util.h" namespace aria2 { void DHKeyExchange::init(const unsigned char* prime, size_t primeBits, const unsigned char* generator, size_t privateKeyBits) { std::string pr = reinterpret_cast(prime); if (pr.length() % 2) { pr = "0" + pr; } pr = util::fromHex(pr.begin(), pr.end()); if (pr.empty()) { throw DL_ABORT_EX("No valid prime supplied"); } prime_ = n(pr.c_str(), pr.length()); std::string gen = reinterpret_cast(generator); if (gen.length() % 2) { gen = "0" + gen; } gen = util::fromHex(gen.begin(), gen.end()); if (gen.empty()) { throw DL_ABORT_EX("No valid generator supplied"); } generator_ = n(gen.c_str(), gen.length()); size_t pbytes = (privateKeyBits + 7) / 8; unsigned char buf[pbytes]; util::generateRandomData(buf, pbytes); privateKey_ = n(reinterpret_cast(buf), pbytes); keyLength_ = (primeBits + 7) / 8; } void DHKeyExchange::generatePublicKey() { publicKey_ = generator_.mul_mod(privateKey_, prime_); } size_t DHKeyExchange::getPublicKey(unsigned char* out, size_t outLength) const { if (outLength < keyLength_) { throw DL_ABORT_EX( fmt("Insufficient buffer for public key. expect:%lu, actual:%lu", static_cast(keyLength_), static_cast(outLength))); } publicKey_.binary(reinterpret_cast(out), outLength); return keyLength_; } void DHKeyExchange::generateNonce(unsigned char* out, size_t outLength) const { util::generateRandomData(out, outLength); } size_t DHKeyExchange::computeSecret(unsigned char* out, size_t outLength, const unsigned char* peerPublicKeyData, size_t peerPublicKeyLength) const { if (outLength < keyLength_) { throw DL_ABORT_EX( fmt("Insufficient buffer for secret. expect:%lu, actual:%lu", static_cast(keyLength_), static_cast(outLength))); } if (prime_.length() < peerPublicKeyLength) { throw DL_ABORT_EX( fmt("peer public key overflows bignum. max:%lu, actual:%lu", static_cast(prime_.length()), static_cast(peerPublicKeyLength))); } n peerKey(reinterpret_cast(peerPublicKeyData), peerPublicKeyLength); n secret = peerKey.mul_mod(privateKey_, prime_); secret.binary(reinterpret_cast(out), outLength); return outLength; } } // namespace aria2