#pragma once #include #include #include namespace Leonetienne::GCrypt { /** Wrapper for std::bitset that zeroes memory upon deletion. * This does not include ALL methods, but the ones needed. * * Just creating a specialization of std::bitset does not work. */ template class SecureBitset { public: explicit SecureBitset(); explicit SecureBitset(const std::string& str); explicit SecureBitset(const long long int i); ~SecureBitset(); bool operator==(const SecureBitset& other) const; bool operator!=(const SecureBitset& other) const; bool operator[](const std::size_t) const; bool test(const std::size_t index) const; bool all() const; bool any() const; bool none() const; std::size_t count() const; std::size_t size() const; SecureBitset& operator&=(const SecureBitset& other); SecureBitset& operator|=(const SecureBitset& other); SecureBitset& operator^=(const SecureBitset& other); SecureBitset operator&(const SecureBitset& other); SecureBitset operator|(const SecureBitset& other); SecureBitset operator^(const SecureBitset& other); SecureBitset operator~() const; SecureBitset& operator<<=(const std::size_t offset); SecureBitset& operator>>=(const std::size_t offset); SecureBitset operator<<(const std::size_t offset) const; SecureBitset operator>>(const std::size_t offset) const; SecureBitset& set(); SecureBitset& set(const std::size_t index, bool value = true); SecureBitset& reset(); SecureBitset& reset(const std::size_t index); SecureBitset& flip(); SecureBitset& flip(const std::size_t index); std::string to_string() const; unsigned long to_ulong() const; unsigned long long to_ullong() const; std::bitset& Get(); const std::bitset& Get() const; private: std::bitset bitset; }; template inline SecureBitset::SecureBitset() : bitset() { return; } template inline SecureBitset::SecureBitset(const std::string& str) : bitset(str) { return; } template inline SecureBitset::SecureBitset(const long long int i) : bitset(i) { return; } // Don't optimize the destructor out!!! // These pragmas only work for MSVC and g++, as far as i know. Beware!!! #if defined _WIN32 || defined _WIN64 #pragma optimize("", off ) #elif defined __GNUG__ #pragma GCC push_options #pragma GCC optimize ("O0") #endif template inline SecureBitset::~SecureBitset() { bitset.reset(); return; } #if defined _WIN32 || defined _WIN64 #pragma optimize("", on ) #elif defined __GNUG__ #pragma GCC pop_options #endif template inline bool SecureBitset::operator==(const SecureBitset& other) const { return bitset == other.bitset; } template inline bool SecureBitset::operator!=(const SecureBitset& other) const { return bitset != other.bitset; } template inline bool SecureBitset::operator[](const std::size_t index) const { return bitset[index]; } template inline bool SecureBitset::test(const std::size_t index) const { return bitset.test(index); } template inline bool SecureBitset::all() const { return bitset.all(); } template inline bool SecureBitset::any() const { return bitset.any(); } template inline bool SecureBitset::none() const { return bitset.none(); } template inline std::size_t SecureBitset::count() const { return bitset.count(); } template inline std::size_t SecureBitset::size() const { return bitset.count(); } template inline SecureBitset& SecureBitset::operator&=(const SecureBitset& other) { bitset &= other.bitset; return *this; } template inline SecureBitset& SecureBitset::operator|=(const SecureBitset& other) { bitset |= other.bitset; return *this; } template inline SecureBitset& SecureBitset::operator^=(const SecureBitset& other) { bitset ^= other.bitset; return *this; } template inline SecureBitset SecureBitset::operator&(const SecureBitset& other) { SecureBitset bs; bs.bitset = bitset & other.bitset; return bs; } template inline SecureBitset SecureBitset::operator|(const SecureBitset& other) { SecureBitset bs; bs.bitset = bitset | other.bitset; return bs; } template inline SecureBitset SecureBitset::operator^(const SecureBitset& other) { SecureBitset bs; bs.bitset = bitset ^ other.bitset; return bs; } template inline SecureBitset SecureBitset::operator~() const { SecureBitset bs; bs.bitset = ~bitset; return bs; } template inline SecureBitset& SecureBitset::operator<<=(const std::size_t offset) { bitset <<= offset; return *this; } template inline SecureBitset& SecureBitset::operator>>=(const std::size_t offset) { bitset >>= offset; return *this; } template inline SecureBitset SecureBitset::operator<<(const std::size_t offset) const { SecureBitset bs; bs.bitset = bitset << offset; return bs; } template inline SecureBitset SecureBitset::operator>>(const std::size_t offset) const { SecureBitset bs; bs.bitset = bitset >> offset; return bs; } template inline SecureBitset& SecureBitset::set() { bitset.set(); return *this; } template inline SecureBitset& SecureBitset::set(const std::size_t index, bool value) { bitset.set(index, value); return *this; } template inline SecureBitset& SecureBitset::reset() { bitset.reset(); return *this; } template inline SecureBitset& SecureBitset::reset(const std::size_t index) { bitset.reset(index); return *this; } template inline SecureBitset& SecureBitset::flip() { bitset.flip(); return *this; } template inline SecureBitset& SecureBitset::flip(const std::size_t index) { bitset.flip(index); return *this; } template inline std::string SecureBitset::to_string() const { return bitset.to_string(); } template inline unsigned long SecureBitset::to_ulong() const { return bitset.to_ulong(); } template inline unsigned long long SecureBitset::to_ullong() const { return bitset.to_ullong(); } template inline std::bitset& SecureBitset::Get() { return bitset; } template inline const std::bitset& SecureBitset::Get() const { return bitset; } template inline std::ostream& operator<<(std::ostream& ofs, const SecureBitset& bs) { return ofs << bs.Get(); } template inline std::istream& operator>>(std::istream& ifs, const SecureBitset& bs) { return ifs >> bs.Get(); } }