mirror of
https://github.com/anope/anope.git
synced 2026-06-12 15:44:46 +02:00
151 lines
4.4 KiB
C++
151 lines
4.4 KiB
C++
// Anope IRC Services <https://www.anope.org/>
|
|
//
|
|
// Copyright (C) 2003-2026 Anope Contributors
|
|
//
|
|
// Anope is free software. You can use, modify, and/or distribute it under the
|
|
// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt
|
|
// for the complete terms of this license and docs/AUTHORS.txt for a list of
|
|
// contributors.
|
|
//
|
|
// Based on the original code of Epona by Lara
|
|
// Based on the original code of Services by Andy Church
|
|
//
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
#pragma once
|
|
|
|
namespace Encryption
|
|
{
|
|
/** Base class for encryption contexts. */
|
|
class Context
|
|
{
|
|
public:
|
|
virtual ~Context() = default;
|
|
|
|
/** Updates the encryption context with the specified data.
|
|
* @param str The data to update the context with.
|
|
*/
|
|
inline void Update(const Anope::string &str)
|
|
{
|
|
Update(reinterpret_cast<const unsigned char *>(str.c_str()), str.length());
|
|
}
|
|
|
|
/** Updates the encryption context with the specified data.
|
|
* @param data The data to update the context with.
|
|
* @param len The length of the data.
|
|
*/
|
|
virtual void Update(const unsigned char *data, size_t len) = 0;
|
|
|
|
/** Finalises the encryption context and returns the digest. */
|
|
virtual Anope::string Finalize() = 0;
|
|
};
|
|
|
|
/** Provider of encryption contexts. */
|
|
class Provider
|
|
: public Service
|
|
{
|
|
public:
|
|
/** The byte size of the block cipher. */
|
|
const size_t block_size;
|
|
|
|
/** The byte size of the resulting digest. */
|
|
const size_t digest_size;
|
|
|
|
/** Creates a provider of encryption contexts.
|
|
* @param creator The module that created this provider.
|
|
* @param algorithm The name of the encryption algorithm.
|
|
* @param bs The byte size of the block cipher.
|
|
* @param ds The byte size of the resulting digest.
|
|
*/
|
|
Provider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds)
|
|
: Service(creator, "Encryption::Provider", algorithm)
|
|
, block_size(bs)
|
|
, digest_size(ds)
|
|
{
|
|
}
|
|
|
|
virtual ~Provider() = default;
|
|
|
|
/** Checks whether a plain text value matches a hash created by this provider. */
|
|
virtual bool Compare(const Anope::string &hash, const Anope::string &plain)
|
|
{
|
|
return !hash.empty() && hash.equals_cs(ToPrintable(Encrypt(plain)));
|
|
}
|
|
|
|
/** Called on initialising a encryption provider to check it works properly. */
|
|
void Check(const Anope::map<Anope::string> &checks)
|
|
{
|
|
for (const auto &[hash, plain] : checks)
|
|
{
|
|
if (!Compare(hash, plain))
|
|
throw ModuleException("BUG: unable to generate " + this->name + " hashes safely! Please report this!");
|
|
}
|
|
Log(LOG_DEBUG) << "The " << this->name << " encryption provider appears to be working correctly.";
|
|
}
|
|
|
|
/** Creates a new encryption context. */
|
|
virtual std::unique_ptr<Context> CreateContext() = 0;
|
|
|
|
/** Quickly encrypts the specified values and returns the digest. */
|
|
template<typename... Args>
|
|
Anope::string Encrypt(Args &&...args)
|
|
{
|
|
auto context = CreateContext();
|
|
context->Update(std::forward<Args>(args)...);
|
|
return context->Finalize();
|
|
}
|
|
|
|
/** Calculates the RFC 2104 hash-based message authentication code for the specified data. */
|
|
inline Anope::string HMAC(const Anope::string &key, const Anope::string &data)
|
|
{
|
|
if (!block_size)
|
|
return {};
|
|
|
|
auto keybuf = key.length() > block_size ? Encrypt(key) : key;
|
|
keybuf.resize(block_size);
|
|
|
|
Anope::string hmac1;
|
|
Anope::string hmac2;
|
|
for (size_t i = 0; i < block_size; ++i)
|
|
{
|
|
hmac1.push_back(static_cast<char>(keybuf[i] ^ 0x5C));
|
|
hmac2.push_back(static_cast<char>(keybuf[i] ^ 0x36));
|
|
}
|
|
hmac2.append(data);
|
|
hmac1.append(Encrypt(hmac2));
|
|
|
|
return Encrypt(hmac1);
|
|
}
|
|
|
|
/** Converts a hash to its printable form. */
|
|
virtual Anope::string ToPrintable(const Anope::string &hash)
|
|
{
|
|
return Anope::Hex(hash);
|
|
}
|
|
};
|
|
|
|
/** Helper template for creating simple providers of encryption contexts. */
|
|
template <typename T>
|
|
class SimpleProvider final
|
|
: public Provider
|
|
{
|
|
public:
|
|
/** Creates a simple provider of encryption contexts.
|
|
* @param creator The module that created this provider.
|
|
* @param algorithm The name of the encryption algorithm.
|
|
* @param bs The byte size of the block cipher.
|
|
* @param ds The byte size of the resulting digest.
|
|
*/
|
|
SimpleProvider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds)
|
|
: Provider(creator, algorithm, bs, ds)
|
|
{
|
|
}
|
|
|
|
/** @copydoc Encryption::Provider::CreateContext. */
|
|
std::unique_ptr<Context> CreateContext() override
|
|
{
|
|
return std::make_unique<T>();
|
|
}
|
|
};
|
|
}
|