HasherSha1Traits.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #pragma once
  2. #ifndef _WIN32
  3. #include <string.h>
  4. #include <openssl/crypto.h>
  5. #include <openssl/sha.h>
  6. //ndef _WIN32
  7. struct HasherSha1Traits {
  8. public:
  9. static constexpr size_t BlockSize = 512 / 8;
  10. static constexpr size_t DigestSize = 160 / 8;
  11. struct DigestType {
  12. unsigned char Bytes[DigestSize];
  13. };
  14. using ContextType = SHA_CTX;
  15. public:
  16. static inline ContextType ContextCreate() {
  17. ContextType Ctx;
  18. SHA1_Init(&Ctx);
  19. return Ctx;
  20. }
  21. static inline ContextType ContextCreate(const void* lpBuffer, size_t cbBuffer) {
  22. ContextType Ctx = ContextCreate();
  23. ContextUpdate(Ctx, lpBuffer, cbBuffer);
  24. return Ctx;
  25. }
  26. static inline ContextType ContextCopy(const ContextType& Ctx) {
  27. return Ctx;
  28. }
  29. static inline void ContextUpdate(ContextType& Ctx, const void* lpBuffer, size_t cbBuffer) {
  30. SHA1_Update(&Ctx, lpBuffer, cbBuffer);
  31. }
  32. static inline void ContextEvaluate(const ContextType& Ctx, DigestType& Digest) {
  33. auto ForkedCtx = ContextCopy(Ctx);
  34. SHA1_Final(Digest.Bytes, &ForkedCtx);
  35. }
  36. static inline void ContextDestroy(ContextType& Ctx) noexcept {
  37. OPENSSL_cleanse(&Ctx, sizeof(Ctx));
  38. }
  39. };
  40. #else
  41. #include <windows.h>
  42. #include <wincrypt.h>
  43. #include <system_error>
  44. struct HasherSha1Traits {
  45. public:
  46. static constexpr size_t BlockSize = 512 / 8;
  47. static constexpr size_t DigestSize = 160 / 8;
  48. struct DigestType {
  49. BYTE Bytes[DigestSize];
  50. };
  51. struct ContextType {
  52. HCRYPTHASH hHash;
  53. ContextType() noexcept :
  54. hHash(NULL) {}
  55. ContextType(const ContextType& Other) noexcept = default;
  56. ContextType(ContextType&& Other) noexcept : hHash(Other.hHash) {
  57. Other.hHash = NULL;
  58. }
  59. ContextType& operator=(const ContextType& Other) noexcept = default;
  60. ContextType& operator=(ContextType&& Other) noexcept {
  61. hHash = Other.hHash;
  62. Other.hHash = NULL;
  63. return *this;
  64. }
  65. };
  66. private:
  67. static inline struct ContextProvider {
  68. HCRYPTPROV Handle;
  69. ~ContextProvider() {
  70. if (Handle) {
  71. CryptReleaseContext(Handle, 0);
  72. Handle = NULL;
  73. }
  74. }
  75. } CryptProvider;
  76. public:
  77. static inline ContextType ContextCreate() {
  78. ContextType Ctx;
  79. if (CryptProvider.Handle == NULL) {
  80. if (!CryptAcquireContext(&CryptProvider.Handle, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)) {
  81. auto err = GetLastError();
  82. if (err == NTE_BAD_KEYSET) {
  83. if (!CryptAcquireContext(&CryptProvider.Handle, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_NEWKEYSET)) {
  84. err = GetLastError();
  85. throw std::system_error(err, std::system_category());
  86. }
  87. } else {
  88. throw std::system_error(err, std::system_category());
  89. }
  90. }
  91. }
  92. if (!CryptCreateHash(CryptProvider.Handle, CALG_SHA1, NULL, 0, &Ctx.hHash)) {
  93. auto err = GetLastError();
  94. throw std::system_error(err, std::system_category());
  95. }
  96. return Ctx;
  97. }
  98. static inline ContextType ContextCreate(const void* lpBuffer, size_t cbBuffer) {
  99. ContextType Ctx = ContextCreate();
  100. ContextUpdate(Ctx, lpBuffer, cbBuffer);
  101. return Ctx;
  102. }
  103. static inline ContextType ContextCopy(const ContextType& Ctx) {
  104. ContextType NewCtx;
  105. if (!CryptDuplicateHash(Ctx.hHash, NULL, 0, &NewCtx.hHash)) {
  106. auto err = GetLastError();
  107. throw std::system_error(err, std::system_category());
  108. }
  109. return NewCtx;
  110. }
  111. static inline void ContextUpdate(ContextType& Ctx, const void* lpBuffer, size_t cbBuffer) {
  112. if constexpr (sizeof(size_t) <= sizeof(DWORD)) {
  113. if (!CryptHashData(Ctx.hHash, reinterpret_cast<const BYTE*>(lpBuffer), static_cast<DWORD>(cbBuffer), 0)) {
  114. auto err = GetLastError();
  115. throw std::system_error(err, std::system_category());
  116. }
  117. } else {
  118. size_t BytesRead = 0;
  119. DWORD BytesToRead = cbBuffer - BytesRead > MAXDWORD ? MAXDWORD : static_cast<DWORD>(cbBuffer - BytesRead);
  120. do {
  121. if (!CryptHashData(Ctx.hHash, reinterpret_cast<const BYTE*>(lpBuffer) + BytesRead, BytesToRead, 0)) {
  122. auto err = GetLastError();
  123. throw std::system_error(err, std::system_category());
  124. }
  125. BytesRead += BytesToRead;
  126. BytesToRead = cbBuffer - BytesRead > MAXDWORD ? MAXDWORD : static_cast<DWORD>(cbBuffer - BytesRead);
  127. } while (BytesToRead);
  128. }
  129. }
  130. static inline void ContextEvaluate(const ContextType& Ctx, DigestType& Digest) {
  131. DWORD SizeOfDigest = sizeof(Digest.Bytes);
  132. if (!CryptGetHashParam(Ctx.hHash, HP_HASHVAL, Digest.Bytes, &SizeOfDigest, 0)) {
  133. auto err = GetLastError();
  134. throw std::system_error(err, std::system_category());
  135. }
  136. }
  137. static inline void ContextDestroy(ContextType& Ctx) noexcept {
  138. if (Ctx.hHash) {
  139. CryptDestroyHash(Ctx.hHash);
  140. Ctx.hHash = NULL;
  141. }
  142. }
  143. };
  144. #endif