rsa_cipher.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #pragma once
  2. #include <string>
  3. #include <filesystem>
  4. #include <openssl/err.h>
  5. #include <openssl/rsa.h>
  6. #include "resource_wrapper.hpp"
  7. #if (OPENSSL_VERSION_NUMBER & 0xf0000000) < 0x30000000 // for openssl < 3.0.0
  8. #include "resource_traits/openssl/rsa.hpp"
  9. #elif (OPENSSL_VERSION_NUMBER & 0xf0000000) == 0x30000000 // for openssl 3.x.x
  10. #include "resource_traits/openssl/evp_pkey_ctx.hpp"
  11. #include "resource_traits/openssl/evp_pkey.hpp"
  12. #else
  13. #error "rsa_cipher.hpp: Unexpected OpenSSL version."
  14. #endif
  15. #include "exception.hpp"
  16. #define NKG_CURRENT_SOURCE_FILE() u8".\\common\\rsa_cipher.hpp"
  17. #define NKG_CURRENT_SOURCE_LINE() __LINE__
  18. namespace nkg {
  19. class rsa_cipher {
  20. public:
  21. class backend_error;
  22. class no_key_assigned_error;
  23. private:
  24. #if (OPENSSL_VERSION_NUMBER & 0xf0000000) < 0x30000000 // for openssl < 3.0.0
  25. resource_wrapper<resource_traits::openssl::rsa> m_rsa;
  26. [[nodiscard]]
  27. static RSA* _read_private_key_from_bio(BIO* p_bio);
  28. [[nodiscard]]
  29. static RSA* _read_public_key_pem_from_bio(BIO* p_bio);
  30. [[nodiscard]]
  31. static RSA* _read_public_key_pkcs1_from_bio(BIO* p_bio);
  32. static void _write_private_key_to_bio(RSA* p_rsa, BIO* p_bio);
  33. static void _write_public_key_pem_to_bio(RSA* p_rsa, BIO* p_bio);
  34. static void _write_public_key_pkcs1_to_bio(RSA* p_rsa, BIO* p_bio);
  35. #elif (OPENSSL_VERSION_NUMBER & 0xf0000000) == 0x30000000 // for openssl 3.x.x
  36. resource_wrapper<resource_traits::openssl::evp_pkey> m_rsa;
  37. [[nodiscard]]
  38. static EVP_PKEY* _read_private_key_from_bio(BIO* p_bio);
  39. [[nodiscard]]
  40. static EVP_PKEY* _read_public_key_pem_from_bio(BIO* p_bio);
  41. [[nodiscard]]
  42. static EVP_PKEY* _read_public_key_pkcs1_from_bio(BIO* p_bio);
  43. static void _write_private_key_to_bio(EVP_PKEY* p_rsa, BIO* p_bio);
  44. static void _write_public_key_pem_to_bio(EVP_PKEY* p_rsa, BIO* p_bio);
  45. static void _write_public_key_pkcs1_to_bio(EVP_PKEY* p_rsa, BIO* p_bio);
  46. #else
  47. #error "rsa_cipher.hpp: Unexpected OpenSSL version."
  48. #endif
  49. public:
  50. rsa_cipher();
  51. [[nodiscard]]
  52. size_t bits() const;
  53. void generate_key(int bits, unsigned int e = RSA_F4);
  54. void export_private_key_file(std::wstring_view file_path) const;
  55. void export_private_key_file(const std::filesystem::path& file_path) const;
  56. void export_public_key_file_pem(std::wstring_view file_path) const;
  57. void export_public_key_file_pem(const std::filesystem::path& file_path) const;
  58. void export_public_key_file_pkcs1(std::wstring_view file_path) const;
  59. void export_public_key_file_pkcs1(const std::filesystem::path& file_path) const;
  60. void import_private_key_file(std::wstring_view file_path);
  61. void import_private_key_file(const std::filesystem::path& file_path);
  62. void import_public_key_file_pem(std::wstring_view file_path);
  63. void import_public_key_file_pem(const std::filesystem::path& file_path);
  64. void import_public_key_file_pkcs1(std::wstring_view file_path);
  65. void import_public_key_file_pkcs1(const std::filesystem::path& file_path);
  66. [[nodiscard]]
  67. std::string export_private_key_string() const;
  68. [[nodiscard]]
  69. std::string export_public_key_string_pem() const;
  70. [[nodiscard]]
  71. std::string export_public_key_string_pkcs1() const;
  72. void import_private_key_string(std::string_view key_string);
  73. void import_public_key_string_pem(std::string_view key_string);
  74. void import_public_key_string_pkcs1(std::string_view key_string);
  75. size_t public_encrypt(const void* plaintext, size_t plaintext_size, void* ciphertext, int padding) const;
  76. size_t private_encrypt(const void* plaintext, size_t plaintext_size, void* ciphertext, int padding) const;
  77. size_t public_decrypt(const void* ciphertext, size_t ciphertext_size, void* plaintext, int padding) const;
  78. size_t private_decrypt(const void* ciphertext, size_t ciphertext_size, void* plaintext, int padding) const;
  79. };
  80. class rsa_cipher::backend_error : public ::nkg::exception {
  81. public:
  82. using error_code_t = decltype(ERR_get_error());
  83. private:
  84. error_code_t m_error_code;
  85. std::string m_error_string;
  86. public:
  87. backend_error(std::string_view file, int line, std::string_view message) noexcept;
  88. backend_error(std::string_view file, int line, error_code_t openssl_errno, std::string_view message) noexcept;
  89. [[nodiscard]]
  90. virtual bool error_code_exists() const noexcept override {
  91. return m_error_code != 0;
  92. }
  93. [[nodiscard]]
  94. virtual intptr_t error_code() const noexcept override {
  95. if (error_code_exists()) { return m_error_code; } else { trap_then_terminate(); }
  96. }
  97. [[nodiscard]]
  98. virtual const std::string& error_string() const noexcept override {
  99. if (error_code_exists()) { return m_error_string; } else { trap_then_terminate(); }
  100. }
  101. };
  102. class rsa_cipher::no_key_assigned_error : public ::nkg::exception {
  103. using ::nkg::exception::exception;
  104. };
  105. }
  106. #undef NKG_CURRENT_SOURCE_FILE
  107. #undef NKG_CURRENT_SOURCE_LINE