NavicatCrypto.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #pragma once
  2. #include <openssl/crypto.h>
  3. #include <openssl/blowfish.h>
  4. #include <openssl/sha.h>
  5. #include <string>
  6. #ifdef _DEBUG
  7. #pragma comment(lib, "libcryptoMTd.lib")
  8. #else
  9. #pragma comment(lib, "libcryptoMT.lib")
  10. #endif
  11. #pragma comment(lib, "WS2_32.lib") // some symbol are used in OpenSSL static lib
  12. #pragma comment(lib, "Crypt32.lib") // some symbol are used in OpenSSL static lib
  13. class Navicat11Crypto {
  14. protected:
  15. BF_KEY BlowfishKey;
  16. void BytesToHex(const void* src, size_t len, char* dst) {
  17. for (size_t i = 0; i < len; ++i) {
  18. char h = reinterpret_cast<const uint8_t*>(src)[i] >> 4;
  19. char l = reinterpret_cast<const uint8_t*>(src)[i] & 0x0F;
  20. h += h >= 10 ? 'A' - 10 : '0';
  21. l += l >= 10 ? 'A' - 10 : '0';
  22. dst[2 * i] = h;
  23. dst[2 * i + 1] = l;
  24. }
  25. }
  26. bool CheckHex(const char* src, size_t len) {
  27. if (len % 2 != 0)
  28. return false;
  29. for (size_t i = 0; i < len; i += 2) {
  30. char h = src[i];
  31. char l = src[i + 1];
  32. if (src[i] < '0' || src[i] > 'F')
  33. return false;
  34. if (src[i] < 'A' && src[i] > '9')
  35. return false;
  36. if (src[i + 1] < '0' || src[i + 1] > 'F')
  37. return false;
  38. if (src[i + 1] < 'A' && src[i + 1] > '9')
  39. return false;
  40. }
  41. return true;
  42. }
  43. void HexToBytes(const char* src, size_t len, void* dst) {
  44. for (size_t i = 0; i < len; i += 2) {
  45. uint8_t h = src[i];
  46. uint8_t l = src[i + 1];
  47. h -= h > '9' ? 'A' - 10 : '0';
  48. l -= l > '9' ? 'A' - 10 : '0';
  49. reinterpret_cast<uint8_t*>(dst)[i / 2] = (h << 4) ^ l;
  50. }
  51. }
  52. std::string EncryptString(const void* srcBytes, size_t srclen) {
  53. std::string ret;
  54. uint8_t CV[BF_BLOCK] = {
  55. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  56. };
  57. if (srclen == 0)
  58. return ret;
  59. ret.resize(2 * srclen);
  60. BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
  61. const uint64_t* blocks = reinterpret_cast<const uint64_t*>(srcBytes);
  62. size_t blocks_len = srclen / BF_BLOCK;
  63. for (size_t i = 0; i < blocks_len; ++i) {
  64. union {
  65. uint8_t byte[8];
  66. uint64_t qword;
  67. } temp;
  68. temp.qword = blocks[i];
  69. temp.qword ^= *reinterpret_cast<uint64_t*>(CV);
  70. BF_ecb_encrypt(temp.byte, temp.byte, &BlowfishKey, BF_ENCRYPT);
  71. *reinterpret_cast<uint64_t*>(CV) ^= temp.qword;
  72. BytesToHex(&temp, 8, ret.data() + 16 * i);
  73. }
  74. if (srclen % BF_BLOCK) {
  75. BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
  76. for (size_t i = 0; i < srclen % BF_BLOCK; ++i) {
  77. CV[i] ^= reinterpret_cast<const uint8_t*>(blocks + blocks_len)[i];
  78. }
  79. BytesToHex(CV, srclen % BF_BLOCK, ret.data() + 16 * blocks_len);
  80. }
  81. return ret;
  82. }
  83. std::string DecryptString(const char* srchex, size_t srclen) {
  84. std::string ret;
  85. uint8_t CV[BF_BLOCK] = {
  86. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  87. };
  88. if (CheckHex(srchex, srclen) == false)
  89. throw std::invalid_argument("Not hex string.");
  90. ret.resize(srclen / 2);
  91. BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
  92. const char(*blocks)[16] = reinterpret_cast<const char(*)[16]>(srchex);
  93. size_t blocks_len = srclen / 16;
  94. for (size_t i = 0; i < blocks_len; ++i) {
  95. union {
  96. uint8_t byte[8];
  97. uint64_t qword;
  98. } temp, temp2;
  99. HexToBytes(blocks[i], 16, temp.byte);
  100. temp2.qword = temp.qword;
  101. BF_ecb_encrypt(temp.byte, temp.byte, &BlowfishKey, BF_DECRYPT);
  102. temp.qword ^= *reinterpret_cast<uint64_t*>(CV);
  103. *reinterpret_cast<uint64_t*>(ret.data() + 8 * i) = temp.qword;
  104. *reinterpret_cast<uint64_t*>(CV) ^= temp2.qword;
  105. }
  106. if (srclen % 16) {
  107. union {
  108. uint8_t byte[8];
  109. uint64_t qword;
  110. } temp = { };
  111. HexToBytes(blocks[blocks_len], srclen % 16, temp.byte);
  112. BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
  113. for (size_t i = 0; i < (srclen % 16) / 2; ++i)
  114. ret[blocks_len * 8 + i] = temp.byte[i] ^ CV[i];
  115. }
  116. return ret;
  117. }
  118. public:
  119. Navicat11Crypto() {
  120. static const uint8_t PresetKey[20] = {
  121. 0x42, 0xCE, 0xB2, 0x71, 0xA5, 0xE4, 0x58, 0xB7,
  122. 0x4A, 0xEA, 0x93, 0x94, 0x79, 0x22, 0x35, 0x43,
  123. 0x91, 0x87, 0x33, 0x40
  124. };
  125. BF_set_key(&BlowfishKey, SHA_DIGEST_LENGTH, PresetKey);
  126. }
  127. Navicat11Crypto(const void* UserKey, size_t Length) {
  128. SetKey(UserKey, Length);
  129. }
  130. void SetKey(const void* UserKey, size_t Length) {
  131. unsigned char MessageDigest[SHA_DIGEST_LENGTH];
  132. SHA1(reinterpret_cast<const unsigned char*>(UserKey), Length, MessageDigest);
  133. BF_set_key(&BlowfishKey, SHA_DIGEST_LENGTH, MessageDigest);
  134. OPENSSL_cleanse(MessageDigest, SHA_DIGEST_LENGTH);
  135. }
  136. std::string EncryptString(const std::string& Plaintext) {
  137. return EncryptString(Plaintext.c_str(), Plaintext.length());
  138. }
  139. std::string DecryptString(const std::string& Ciphertext) {
  140. return DecryptString(Ciphertext.c_str(), Ciphertext.length());
  141. }
  142. void Clear() {
  143. OPENSSL_cleanse(&BlowfishKey, sizeof(BlowfishKey));
  144. }
  145. ~Navicat11Crypto() {
  146. Clear();
  147. }
  148. };