123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- #pragma once
- #include <openssl/crypto.h>
- #include <openssl/blowfish.h>
- #include <openssl/sha.h>
- #include <string>
- #ifdef _DEBUG
- #pragma comment(lib, "libcryptoMTd.lib")
- #else
- #pragma comment(lib, "libcryptoMT.lib")
- #endif
- #pragma comment(lib, "WS2_32.lib") // some symbol are used in OpenSSL static lib
- #pragma comment(lib, "Crypt32.lib") // some symbol are used in OpenSSL static lib
- class Navicat11Crypto {
- protected:
- BF_KEY BlowfishKey;
- void BytesToHex(const void* src, size_t len, char* dst) {
- for (size_t i = 0; i < len; ++i) {
- char h = reinterpret_cast<const uint8_t*>(src)[i] >> 4;
- char l = reinterpret_cast<const uint8_t*>(src)[i] & 0x0F;
- h += h >= 10 ? 'A' - 10 : '0';
- l += l >= 10 ? 'A' - 10 : '0';
- dst[2 * i] = h;
- dst[2 * i + 1] = l;
- }
- }
- bool CheckHex(const char* src, size_t len) {
- if (len % 2 != 0)
- return false;
- for (size_t i = 0; i < len; i += 2) {
- char h = src[i];
- char l = src[i + 1];
- if (src[i] < '0' || src[i] > 'F')
- return false;
- if (src[i] < 'A' && src[i] > '9')
- return false;
- if (src[i + 1] < '0' || src[i + 1] > 'F')
- return false;
- if (src[i + 1] < 'A' && src[i + 1] > '9')
- return false;
- }
- return true;
- }
- void HexToBytes(const char* src, size_t len, void* dst) {
- for (size_t i = 0; i < len; i += 2) {
- uint8_t h = src[i];
- uint8_t l = src[i + 1];
- h -= h > '9' ? 'A' - 10 : '0';
- l -= l > '9' ? 'A' - 10 : '0';
- reinterpret_cast<uint8_t*>(dst)[i / 2] = (h << 4) ^ l;
- }
- }
- std::string EncryptString(const void* srcBytes, size_t srclen) {
- std::string ret;
- uint8_t CV[BF_BLOCK] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- };
- if (srclen == 0)
- return ret;
- ret.resize(2 * srclen);
- BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
- const uint64_t* blocks = reinterpret_cast<const uint64_t*>(srcBytes);
- size_t blocks_len = srclen / BF_BLOCK;
- for (size_t i = 0; i < blocks_len; ++i) {
- union {
- uint8_t byte[8];
- uint64_t qword;
- } temp;
- temp.qword = blocks[i];
- temp.qword ^= *reinterpret_cast<uint64_t*>(CV);
- BF_ecb_encrypt(temp.byte, temp.byte, &BlowfishKey, BF_ENCRYPT);
- *reinterpret_cast<uint64_t*>(CV) ^= temp.qword;
- BytesToHex(&temp, 8, ret.data() + 16 * i);
- }
- if (srclen % BF_BLOCK) {
- BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
- for (size_t i = 0; i < srclen % BF_BLOCK; ++i) {
- CV[i] ^= reinterpret_cast<const uint8_t*>(blocks + blocks_len)[i];
- }
- BytesToHex(CV, srclen % BF_BLOCK, ret.data() + 16 * blocks_len);
- }
- return ret;
- }
- std::string DecryptString(const char* srchex, size_t srclen) {
- std::string ret;
- uint8_t CV[BF_BLOCK] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- };
- if (CheckHex(srchex, srclen) == false)
- throw std::invalid_argument("Not hex string.");
- ret.resize(srclen / 2);
- BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
- const char(*blocks)[16] = reinterpret_cast<const char(*)[16]>(srchex);
- size_t blocks_len = srclen / 16;
- for (size_t i = 0; i < blocks_len; ++i) {
- union {
- uint8_t byte[8];
- uint64_t qword;
- } temp, temp2;
- HexToBytes(blocks[i], 16, temp.byte);
- temp2.qword = temp.qword;
- BF_ecb_encrypt(temp.byte, temp.byte, &BlowfishKey, BF_DECRYPT);
- temp.qword ^= *reinterpret_cast<uint64_t*>(CV);
- *reinterpret_cast<uint64_t*>(ret.data() + 8 * i) = temp.qword;
- *reinterpret_cast<uint64_t*>(CV) ^= temp2.qword;
- }
- if (srclen % 16) {
- union {
- uint8_t byte[8];
- uint64_t qword;
- } temp = { };
- HexToBytes(blocks[blocks_len], srclen % 16, temp.byte);
- BF_ecb_encrypt(CV, CV, &BlowfishKey, BF_ENCRYPT);
- for (size_t i = 0; i < (srclen % 16) / 2; ++i)
- ret[blocks_len * 8 + i] = temp.byte[i] ^ CV[i];
- }
- return ret;
- }
- public:
- Navicat11Crypto() {
- static const uint8_t PresetKey[20] = {
- 0x42, 0xCE, 0xB2, 0x71, 0xA5, 0xE4, 0x58, 0xB7,
- 0x4A, 0xEA, 0x93, 0x94, 0x79, 0x22, 0x35, 0x43,
- 0x91, 0x87, 0x33, 0x40
- };
- BF_set_key(&BlowfishKey, SHA_DIGEST_LENGTH, PresetKey);
- }
- Navicat11Crypto(const void* UserKey, size_t Length) {
- SetKey(UserKey, Length);
- }
- void SetKey(const void* UserKey, size_t Length) {
- unsigned char MessageDigest[SHA_DIGEST_LENGTH];
- SHA1(reinterpret_cast<const unsigned char*>(UserKey), Length, MessageDigest);
- BF_set_key(&BlowfishKey, SHA_DIGEST_LENGTH, MessageDigest);
- OPENSSL_cleanse(MessageDigest, SHA_DIGEST_LENGTH);
- }
- std::string EncryptString(const std::string& Plaintext) {
- return EncryptString(Plaintext.c_str(), Plaintext.length());
- }
- std::string DecryptString(const std::string& Ciphertext) {
- return DecryptString(Ciphertext.c_str(), Ciphertext.length());
- }
- void Clear() {
- OPENSSL_cleanse(&BlowfishKey, sizeof(BlowfishKey));
- }
- ~Navicat11Crypto() {
- Clear();
- }
- };
|