Cryptography.h 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #pragma once
  2. #include <Cafe/ErrorHandling/ErrorHandling.h>
  3. #include <Cafe/Io/Streams/StreamBase.h>
  4. #include "Utility.h"
  5. #include <charconv>
  6. namespace YumeBot::Cryptography
  7. {
  8. CAFE_DEFINE_GENERAL_EXCEPTION(CryptoException);
  9. namespace Tea
  10. {
  11. constexpr std::size_t TeaProcessUnitSize = 8;
  12. constexpr std::size_t CalculateOutputSize(std::size_t inputSize)
  13. {
  14. return Utility::AlignTo(inputSize + 10, TeaProcessUnitSize);
  15. }
  16. std::array<std::uint32_t, 4> FormatKey(gsl::span<const std::byte> const& key);
  17. std::size_t Encrypt(gsl::span<const std::byte> const& input, gsl::span<std::byte> const& output,
  18. gsl::span<const std::uint32_t, 4> const& key);
  19. std::size_t Decrypt(gsl::span<const std::byte> const& input, gsl::span<std::byte> const& output,
  20. gsl::span<const std::uint32_t, 4> const& key);
  21. /// @see https://baike.baidu.com/item/TEA%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95
  22. /// @return 应当写入的字节数,用户应检查是否成功写入指定数量的字节到 outputStream 内
  23. /// 若 outputStream 在写入开始前具有不少于 Tea::CalculateOutputSize(key.size())
  24. /// 的可用空间,则保证写入一定成功
  25. std::size_t Encrypt(gsl::span<const std::byte> const& input,
  26. Cafe::Io::OutputStream* outputStream,
  27. gsl::span<const std::uint32_t, 4> const& key);
  28. std::size_t Decrypt(gsl::span<const std::byte> const& input,
  29. Cafe::Io::OutputStream* outputStream,
  30. gsl::span<const std::uint32_t, 4> const& key);
  31. } // namespace Tea
  32. namespace Md5
  33. {
  34. void Calculate(gsl::span<const std::byte> const& input, gsl::span<std::byte, 16> const& output);
  35. template <typename Receiver>
  36. decltype(auto) Md5ToHexString(gsl::span<const std::byte, 16> const& md5, Receiver&& receiver)
  37. {
  38. #if __cpp_char8_t >= 201811L
  39. char8_t
  40. #else
  41. char
  42. #endif
  43. result[32]{ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
  44. '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
  45. '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' };
  46. for (std::size_t i = 0; i < 32; i += 2)
  47. {
  48. const auto value = static_cast<std::uint8_t>(md5[i / 2]);
  49. const auto toCharResult =
  50. std::to_chars(reinterpret_cast<char*>(result + i + (value <= 0x0F)),
  51. reinterpret_cast<char*>(result + i + 2), value, 16);
  52. assert(toCharResult.ec == std::errc{});
  53. }
  54. return std::invoke(std::forward<Receiver>(receiver),
  55. Cafe::Encoding::StringView<Cafe::Encoding::CodePage::Utf8>{ result });
  56. }
  57. } // namespace Md5
  58. namespace Ecdh
  59. {
  60. void GenerateKeyPair(gsl::span<std::byte, 25> const& pubKey,
  61. gsl::span<std::byte, 16> const& shareKey);
  62. } // namespace Ecdh
  63. } // namespace YumeBot::Cryptography