mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-03 16:59:04 +00:00
221 lines
7.2 KiB
C++
221 lines
7.2 KiB
C++
/**
|
|
* @file Md5Generator.h
|
|
* @brief Declarations for API resources for MD5 calculations.
|
|
* @author Jack (jakcron)
|
|
* @version 0.2
|
|
* @date 2020/06/01
|
|
**/
|
|
#pragma once
|
|
#include <tc/types.h>
|
|
#include <tc/crypto/detail/Md5Impl.h>
|
|
|
|
namespace tc { namespace crypto {
|
|
|
|
/**
|
|
* @class Md5Generator
|
|
* @brief Class for calculating MD5 hash.
|
|
*
|
|
* @warning MD5 is considered a weak message digest and its use constitutes a security risk. It should only be used to maintain compatibility with legacy systems.
|
|
*
|
|
* @details
|
|
* This class has three states:
|
|
* - None : Not ready
|
|
* - Initialized : Ready to process input data
|
|
* - Done : Hash value is calculated
|
|
*
|
|
* General usage of this class is as follows:
|
|
* - Initialize Hash Generator state with @ref initialize().
|
|
* - Update hash value with input data with @ref update().
|
|
* - Complete hash calculation and export hash value with @ref getHash().
|
|
*
|
|
* Below is code sample for calculating hash value with one call to @ref update():
|
|
* @code
|
|
* // open file stream
|
|
* auto stream = tc::io::FileStream("a_file.bin", tc::io::FileMode::Open, tc::io::FileAccess::Read);
|
|
*
|
|
* // create array to store hash value
|
|
* std::array<byte_t, tc::crypto::Md5Generator::kHashSize> hash;
|
|
*
|
|
* // initialize generator. Md5Generator is now in a ready state.
|
|
* tc::crypto::Md5Generator impl;
|
|
* impl.initialize();
|
|
*
|
|
* // reset stream position to beginning (not strictly necessary for an unused tc::io::FileStream)
|
|
* stream.seek(0, tc::io::SeekOrigin::Begin);
|
|
*
|
|
* // read whole file into memory. This is unsafe for large file sizes especially on 32-bit systems.
|
|
* tc::ByteData data = tc::ByteData((size_t)stream.length());
|
|
* stream.read(data.data(), data.size());
|
|
*
|
|
* // update generator state with stream data
|
|
* impl.update(data.data(), data.size());
|
|
*
|
|
* // complete generator state and write hash value to hash
|
|
* impl.getHash(hash.data());
|
|
* @endcode
|
|
*
|
|
* Below is code sample for calculating hash value with sequential calls to @ref update():
|
|
* @code
|
|
* // open file stream
|
|
* auto stream = tc::io::FileStream("a_file.bin", tc::io::FileMode::Open, tc::io::FileAccess::Read);
|
|
*
|
|
* // create read block (size 512)
|
|
* static const size_t kReadBlockSize = 0x200;
|
|
* std::array<byte_t, kReadBlockSize> block;
|
|
*
|
|
* // create array to store hash value
|
|
* std::array<byte_t, tc::crypto::Md5Generator::kHashSize> hash;
|
|
*
|
|
* // initialize generator. Md5Generator is now in a ready state.
|
|
* tc::crypto::Md5Generator impl;
|
|
* impl.initialize();
|
|
*
|
|
* // reset stream position to beginning (not strictly necessary for an unused tc::io::FileStream)
|
|
* stream.seek(0, tc::io::SeekOrigin::Begin);
|
|
*
|
|
* // iterate over blocks in stream until no more data can be read
|
|
* size_t read_count = 0;
|
|
* while ( 0 != (read_count = tc::io::IOUtil::getReadableCount(stream.position(), stream.length(), block.size())) )
|
|
* {
|
|
* // read block from stream
|
|
* stream.read(block.data(), read_count);
|
|
*
|
|
* // update generator state with stream data
|
|
* impl.update(block.data(), read_count);
|
|
* }
|
|
*
|
|
* // complete generator state and write hash value to hash
|
|
* impl.getHash(hash.data());
|
|
* @endcode
|
|
*/
|
|
class Md5Generator
|
|
{
|
|
public:
|
|
static const size_t kAsn1OidDataSize = 18; /**< MD5 ASN.1 Encoded OID length */
|
|
static const std::array<byte_t, kAsn1OidDataSize> kAsn1OidData; /**< MD5 ASN.1 Encoded OID */
|
|
|
|
static const size_t kHashSize = 16; /**< MD5 hash size */
|
|
static const size_t kBlockSize = 64; /**< MD5 processing block size */
|
|
|
|
/**
|
|
* @brief Default constructor.
|
|
*
|
|
* @post
|
|
* - State is None. @ref initialize() must be called before use.
|
|
*/
|
|
Md5Generator() :
|
|
mImpl()
|
|
{}
|
|
|
|
/**
|
|
* @brief Initializes the hash calculation.
|
|
*
|
|
* @post
|
|
* - Instance is now in a Initialized state
|
|
*
|
|
* @details
|
|
* Resets the hash calculation state to the begin state.
|
|
*
|
|
* @note
|
|
* - This must be called before calculating a new hash.
|
|
*/
|
|
void initialize()
|
|
{
|
|
mImpl.initialize();
|
|
}
|
|
|
|
/**
|
|
* @brief Update hash value with specified data.
|
|
*
|
|
* @param[in] data Pointer to input data.
|
|
* @param[in] data_size Size of input data.
|
|
*
|
|
* @details
|
|
* Data can be input to the generator in one @ref update() call or split across multiple sequential calls.
|
|
*
|
|
* For example the following scenarios all generate the same hash value.
|
|
* @code
|
|
* // generate data to be hashed
|
|
* tc::ByteData data = tc::ByteData(0x30);
|
|
* memset(data.data(), 0xff, data.size());
|
|
*
|
|
* // create generator instance
|
|
* tc::crypto::Md5Generator impl;
|
|
*
|
|
* // scenario 1 (one call to update() 0x30 bytes, totaling 0x30 bytes inputted)
|
|
* std::array<byte_t, tc::crypto::Md5Generator::kHashSize> hash1;
|
|
* impl.initialize();
|
|
* impl.update(data.data(), data.size());
|
|
* impl.getHash(hash1.data());
|
|
*
|
|
* // scenario 2 (three calls to update() 0x10 bytes each, totaling 0x30 bytes inputted)
|
|
* std::array<byte_t, tc::crypto::Md5Generator::kHashSize> hash2;
|
|
* impl.initialize();
|
|
* impl.update(data.data() + 0x00, 0x10);
|
|
* impl.update(data.data() + 0x10, 0x10);
|
|
* impl.update(data.data() + 0x20, 0x10);
|
|
* impl.getHash(hash2.data());
|
|
*
|
|
* // scenario 3 (two calls to update() one 0x10 bytes, the second 0x20 bytes, totaling 0x30 bytes inputted)
|
|
* std::array<byte_t, tc::crypto::Md5Generator::kHashSize> hash3;
|
|
* impl.initialize();
|
|
* impl.update(data.data() + 0x00, 0x10);
|
|
* impl.update(data.data() + 0x10, 0x20);
|
|
* impl.getHash(hash3.data());
|
|
* @endcode
|
|
*
|
|
* @note
|
|
* - If input data is broken up into blocks and supplied via multiple @ref update() calls, the order must be consistent with the original input data.
|
|
*/
|
|
void update(const byte_t* data, size_t data_size)
|
|
{
|
|
mImpl.update(data, data_size);
|
|
}
|
|
|
|
/**
|
|
* @brief Completes hash calculation and output hash value.
|
|
*
|
|
* @param[out] hash Pointer to buffer storing hash value.
|
|
*
|
|
* @pre
|
|
* - Instance is in either Initialized or Done state.
|
|
* - The size of the <tt><var>hash</var></tt> buffer must be >= @ref kHashSize.
|
|
*
|
|
* @post
|
|
* - Instance is now in a Done state.
|
|
* - The calculated hash value is written to <tt><var>hash</var></tt>.
|
|
*
|
|
* @note
|
|
* - If the instance is in a None state, then this call does nothing.
|
|
*/
|
|
void getHash(byte_t* hash)
|
|
{
|
|
mImpl.getHash(hash);
|
|
}
|
|
|
|
private:
|
|
detail::Md5Impl mImpl;
|
|
};
|
|
|
|
/**
|
|
* @brief Utility function for calculating the MD5 hash.
|
|
*
|
|
* @warning MD5 is considered a weak message digest and its use constitutes a security risk. It should only be used to maintain compatibility with legacy systems.
|
|
*
|
|
* @param[out] hash Pointer to buffer storing hash value.
|
|
* @param[in] data Pointer to input data.
|
|
* @param[in] data_size Size of input data.
|
|
*
|
|
* @pre
|
|
* - The size of the <tt><var>hash</var></tt> buffer must be >= @ref Md5Generator::kHashSize.
|
|
*
|
|
* @post
|
|
* - The calculated hash value is written to <tt><var>hash</var></tt>.
|
|
*
|
|
* @details
|
|
* This function calculates the hash value for input passed in the <tt><var>data</var></tt> array.
|
|
* To calculate the hash value for input split across multiple arrays, use the @ref Md5Generator class.
|
|
*/
|
|
void GenerateMd5Hash(byte_t* hash, const byte_t* data, size_t data_size);
|
|
|
|
}} // namespace tc::crypto
|