mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
[3.3.5] Core/Authserver: TOTP rewrite: (PR #23633)
- Proper management commands (.account 2fa)
- Secrets can now be encrypted (set TOTPTokenSecret in .conf)
- Secret now stored in binary
- Argon2 and AES primitives
- Base32/64 support
(cherry picked from commit 4211645834)
This commit is contained in:
54
src/common/Encoding/Base32.cpp
Normal file
54
src/common/Encoding/Base32.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Base32.h"
|
||||
#include "BaseEncoding.h"
|
||||
#include "Errors.h"
|
||||
|
||||
struct B32Impl
|
||||
{
|
||||
static constexpr std::size_t BITS_PER_CHAR = 5;
|
||||
|
||||
static constexpr char PADDING = '=';
|
||||
static constexpr char Encode(uint8 v)
|
||||
{
|
||||
ASSERT(v < 0x20);
|
||||
if (v < 26) return 'A'+v;
|
||||
else return '2' + (v-26);
|
||||
}
|
||||
|
||||
static constexpr uint8 DECODE_ERROR = 0xff;
|
||||
static constexpr uint8 Decode(uint8 v)
|
||||
{
|
||||
if (v == '0') return Decode('O');
|
||||
if (v == '1') return Decode('l');
|
||||
if (('A' <= v) && (v <= 'Z')) return (v-'A');
|
||||
if (('a' <= v) && (v <= 'z')) return (v-'a');
|
||||
if (('2' <= v) && (v <= '8')) return (v-'2')+26;
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
/*static*/ std::string Trinity::Encoding::Base32::Encode(std::vector<uint8> const& data)
|
||||
{
|
||||
return Trinity::Impl::GenericBaseEncoding<B32Impl>::Encode(data);
|
||||
}
|
||||
|
||||
/*static*/ Optional<std::vector<uint8>> Trinity::Encoding::Base32::Decode(std::string const& data)
|
||||
{
|
||||
return Trinity::Impl::GenericBaseEncoding<B32Impl>::Decode(data);
|
||||
}
|
||||
38
src/common/Encoding/Base32.h
Normal file
38
src/common/Encoding/Base32.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_BASE32_H
|
||||
#define TRINITY_BASE32_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "Optional.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
namespace Encoding
|
||||
{
|
||||
struct TC_COMMON_API Base32
|
||||
{
|
||||
static std::string Encode(std::vector<uint8> const& data);
|
||||
static Optional<std::vector<uint8>> Decode(std::string const& data);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
57
src/common/Encoding/Base64.cpp
Normal file
57
src/common/Encoding/Base64.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Base64.h"
|
||||
#include "BaseEncoding.h"
|
||||
#include "Errors.h"
|
||||
|
||||
struct B64Impl
|
||||
{
|
||||
static constexpr std::size_t BITS_PER_CHAR = 6;
|
||||
|
||||
static constexpr char PADDING = '=';
|
||||
static constexpr char Encode(uint8 v)
|
||||
{
|
||||
ASSERT(v < 0x40);
|
||||
if (v < 26) return 'A' + v;
|
||||
if (v < 52) return 'a' + (v - 26);
|
||||
if (v < 62) return '0' + (v - 52);
|
||||
if (v == 62) return '+';
|
||||
else return '/';
|
||||
}
|
||||
|
||||
static constexpr uint8 DECODE_ERROR = 0xff;
|
||||
static constexpr uint8 Decode(uint8 v)
|
||||
{
|
||||
if (('A' <= v) && (v <= 'Z')) return (v - 'A');
|
||||
if (('a' <= v) && (v <= 'z')) return (v - 'a') + 26;
|
||||
if (('0' <= v) && (v <= '9')) return (v - '0') + 52;
|
||||
if (v == '+') return 62;
|
||||
if (v == '/') return 63;
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
/*static*/ std::string Trinity::Encoding::Base64::Encode(std::vector<uint8> const& data)
|
||||
{
|
||||
return Trinity::Impl::GenericBaseEncoding<B64Impl>::Encode(data);
|
||||
}
|
||||
|
||||
/*static*/ Optional<std::vector<uint8>> Trinity::Encoding::Base64::Decode(std::string const& data)
|
||||
{
|
||||
return Trinity::Impl::GenericBaseEncoding<B64Impl>::Decode(data);
|
||||
}
|
||||
38
src/common/Encoding/Base64.h
Normal file
38
src/common/Encoding/Base64.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_BASE64_H
|
||||
#define TRINITY_BASE64_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "Optional.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
namespace Encoding
|
||||
{
|
||||
struct TC_COMMON_API Base64
|
||||
{
|
||||
static std::string Encode(std::vector<uint8> const& data);
|
||||
static Optional<std::vector<uint8>> Decode(std::string const& data);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
160
src/common/Encoding/BaseEncoding.h
Normal file
160
src/common/Encoding/BaseEncoding.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_BASE_ENCODING_HPP
|
||||
#define TRINITY_BASE_ENCODING_HPP
|
||||
|
||||
#include "advstd.h"
|
||||
#include "Define.h"
|
||||
#include "Optional.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
namespace Impl
|
||||
{
|
||||
template <typename Encoding>
|
||||
struct GenericBaseEncoding
|
||||
{
|
||||
static constexpr std::size_t BITS_PER_CHAR = Encoding::BITS_PER_CHAR;
|
||||
static constexpr std::size_t PAD_TO = advstd::lcm(8u, BITS_PER_CHAR);
|
||||
|
||||
static_assert(BITS_PER_CHAR < 8, "Encoding parameters are invalid");
|
||||
|
||||
static constexpr uint8 DECODE_ERROR = Encoding::DECODE_ERROR;
|
||||
static constexpr char PADDING = Encoding::PADDING;
|
||||
|
||||
static constexpr std::size_t EncodedSize(std::size_t size)
|
||||
{
|
||||
size *= 8; // bits in input
|
||||
if (size % PAD_TO) // pad to boundary
|
||||
size += (PAD_TO - (size % PAD_TO));
|
||||
return (size / BITS_PER_CHAR);
|
||||
}
|
||||
|
||||
static constexpr std::size_t DecodedSize(std::size_t size)
|
||||
{
|
||||
size *= BITS_PER_CHAR; // bits in input
|
||||
if (size % PAD_TO) // pad to boundary
|
||||
size += (PAD_TO - (size % PAD_TO));
|
||||
return (size / 8);
|
||||
}
|
||||
|
||||
static std::string Encode(std::vector<uint8> const& data)
|
||||
{
|
||||
auto it = data.begin(), end = data.end();
|
||||
if (it == end)
|
||||
return "";
|
||||
|
||||
std::string s;
|
||||
s.reserve(EncodedSize(data.size()));
|
||||
|
||||
uint8 bitsLeft = 8; // in current byte
|
||||
do
|
||||
{
|
||||
uint8 thisC = 0;
|
||||
if (bitsLeft >= BITS_PER_CHAR)
|
||||
{
|
||||
bitsLeft -= BITS_PER_CHAR;
|
||||
thisC = ((*it >> bitsLeft) & ((1 << BITS_PER_CHAR)-1));
|
||||
if (!bitsLeft)
|
||||
{
|
||||
++it;
|
||||
bitsLeft = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thisC = (*it & ((1 << bitsLeft) - 1)) << (BITS_PER_CHAR - bitsLeft);
|
||||
bitsLeft += (8 - BITS_PER_CHAR);
|
||||
if ((++it) != end)
|
||||
thisC |= (*it >> bitsLeft);
|
||||
}
|
||||
s.append(1, Encoding::Encode(thisC));
|
||||
} while (it != end);
|
||||
|
||||
while (bitsLeft != 8)
|
||||
{
|
||||
if (bitsLeft > BITS_PER_CHAR)
|
||||
bitsLeft -= BITS_PER_CHAR;
|
||||
else
|
||||
bitsLeft += (8 - BITS_PER_CHAR);
|
||||
s.append(1, PADDING);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static Optional<std::vector<uint8>> Decode(std::string const& data)
|
||||
{
|
||||
auto it = data.begin(), end = data.end();
|
||||
if (it == end)
|
||||
return std::vector<uint8>();
|
||||
|
||||
std::vector<uint8> v;
|
||||
v.reserve(DecodedSize(data.size()));
|
||||
|
||||
uint8 currentByte = 0;
|
||||
uint8 bitsLeft = 8; // in current byte
|
||||
while ((it != end) && (*it != PADDING))
|
||||
{
|
||||
uint8 cur = Encoding::Decode(*(it++));
|
||||
if (cur == DECODE_ERROR)
|
||||
return {};
|
||||
|
||||
if (bitsLeft > BITS_PER_CHAR)
|
||||
{
|
||||
bitsLeft -= BITS_PER_CHAR;
|
||||
currentByte |= (cur << bitsLeft);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitsLeft = BITS_PER_CHAR - bitsLeft; // in encoded char
|
||||
currentByte |= (cur >> bitsLeft);
|
||||
v.push_back(currentByte);
|
||||
currentByte = (cur & ((1 << bitsLeft) - 1));
|
||||
bitsLeft = 8 - bitsLeft; // in byte again
|
||||
currentByte <<= bitsLeft;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentByte)
|
||||
return {}; // decode error, trailing non-zero bits
|
||||
|
||||
// process padding
|
||||
while ((it != end) && (*it == PADDING) && (bitsLeft != 8))
|
||||
{
|
||||
if (bitsLeft > BITS_PER_CHAR)
|
||||
bitsLeft -= BITS_PER_CHAR;
|
||||
else
|
||||
bitsLeft += (8 - BITS_PER_CHAR);
|
||||
++it;
|
||||
}
|
||||
|
||||
// ok, all padding should be consumed, and we should be at end of string
|
||||
if (it == end)
|
||||
return v;
|
||||
|
||||
// anything else is an error
|
||||
return {};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user