NavicatCrypto.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. public:
  53. Navicat11Crypto() {
  54. static const uint8_t PresetKey[20] = {
  55. 0x42, 0xCE, 0xB2, 0x71, 0xA5, 0xE4, 0x58, 0xB7,
  56. 0x4A, 0xEA, 0x93, 0x94, 0x79, 0x22, 0x35, 0x43,
  57. 0x91, 0x87, 0x33, 0x40
  58. };
  59. BF_set_key(&BlowfishKey, SHA_DIGEST_LENGTH, PresetKey);
  60. }
  61. Navicat11Crypto(const void* UserKey, size_t Length) {
  62. SetKey(UserKey, Length);
  63. }
  64. void SetKey(const void* UserKey, size_t Length) {
  65. unsigned char MessageDigest[SHA_DIGEST_LENGTH];
  66. SHA1(reinterpret_cast<const unsigned char*>(UserKey), Length, MessageDigest);
  67. BF_set_key(&BlowfishKey, SHA_DIGEST_LENGTH, MessageDigest);
  68. OPENSSL_cleanse(MessageDigest, SHA_DIGEST_LENGTH);
  69. }
  70. std::string EncryptString(const void* srcBytes, size_t srclen) {
  71. std::string ret;
  72. uint8_t CV[BF_BLOCK] = {
  73. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  74. };
  75. if (srclen == 0)
  76. return ret;
  77. ret.resize(2 * srclen);
  78. BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
  79. const uint64_t* blocks = reinterpret_cast<const uint64_t*>(srcBytes);
  80. size_t blocks_len = srclen / BF_BLOCK;
  81. for (size_t i = 0; i < blocks_len; ++i) {
  82. union {
  83. uint8_t byte[8];
  84. uint64_t qword;
  85. } temp;
  86. temp.qword = blocks[i];
  87. temp.qword ^= *reinterpret_cast<uint64_t*>(CV);
  88. BF_ecb_encrypt(temp.byte, temp.byte, &BlowfishKey, BF_ENCRYPT);
  89. *reinterpret_cast<uint64_t*>(CV) ^= temp.qword;
  90. BytesToHex(&temp, 8, ret.data() + 16 * i);
  91. }
  92. if (srclen % BF_BLOCK) {
  93. BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
  94. for (size_t i = 0; i < srclen % BF_BLOCK; ++i) {
  95. CV[i] ^= reinterpret_cast<const uint8_t*>(blocks + blocks_len)[i];
  96. }
  97. BytesToHex(CV, srclen % BF_BLOCK, ret.data() + 16 * blocks_len);
  98. }
  99. return ret;
  100. }
  101. std::string DecryptString(const char* srchex, size_t srclen) {
  102. std::string ret;
  103. uint8_t CV[BF_BLOCK] = {
  104. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  105. };
  106. if (CheckHex(srchex, srclen) == false)
  107. return ret;
  108. ret.resize(srclen / 2);
  109. BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
  110. const char(*blocks)[16] = reinterpret_cast<const char(*)[16]>(srchex);
  111. size_t blocks_len = srclen / 16;
  112. for (size_t i = 0; i < blocks_len; ++i) {
  113. union {
  114. uint8_t byte[8];
  115. uint64_t qword;
  116. } temp, temp2;
  117. HexToBytes(blocks[i], 16, temp.byte);
  118. temp2.qword = temp.qword;
  119. BF_ecb_encrypt(temp.byte, temp.byte, &BlowfishKey, BF_DECRYPT);
  120. temp.qword ^= *reinterpret_cast<uint64_t*>(CV);
  121. *reinterpret_cast<uint64_t*>(ret.data() + 8 * i) = temp.qword;
  122. *reinterpret_cast<uint64_t*>(CV) ^= temp2.qword;
  123. }
  124. if (srclen % 16) {
  125. union {
  126. uint8_t byte[8];
  127. uint64_t qword;
  128. } temp = { };
  129. HexToBytes(blocks[blocks_len], srclen % 16, temp.byte);
  130. BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
  131. for (size_t i = 0; i < (srclen % 16) / 2; ++i)
  132. ret[blocks_len * 8 + i] = temp.byte[i] ^ CV[i];
  133. }
  134. return ret;
  135. }
  136. void Clear() {
  137. OPENSSL_cleanse(&BlowfishKey, sizeof(BlowfishKey));
  138. }
  139. ~Navicat11Crypto() {
  140. Clear();
  141. }
  142. };