CryptoOpenSSL.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include "CryptoOpenSSL.h"
  2. namespace
  3. {
  4. struct BIOFreeAll
  5. {
  6. void operator()(BIO *p) { BIO_free_all(p); }
  7. };
  8. } // namespace
  9. CryptoOpenSSL::CryptoOpenSSL()
  10. {
  11. // OpenSSL init
  12. ENGINE_load_builtin_engines();
  13. ENGINE_register_all_complete();
  14. this->publicKey = std::vector<uint8_t>(DH_KEY_SIZE);
  15. this->privateKey = generateVectorWithRandomData(DH_KEY_SIZE);
  16. }
  17. CryptoOpenSSL::~CryptoOpenSSL()
  18. {
  19. if (this->dhContext != nullptr)
  20. {
  21. DH_free(this->dhContext);
  22. }
  23. }
  24. std::vector<uint8_t> CryptoOpenSSL::base64Decode(const std::string& data)
  25. {
  26. // base64 in openssl is an absolute mess lmao
  27. std::unique_ptr<BIO, BIOFreeAll> b64(BIO_new(BIO_f_base64()));
  28. BIO_set_flags(b64.get(), BIO_FLAGS_BASE64_NO_NL);
  29. BIO *source = BIO_new_mem_buf(data.c_str(), -1); // read-only source
  30. BIO_push(b64.get(), source);
  31. const int maxlen = data.size() / 4 * 3 + 1;
  32. std::vector<uint8_t> decoded(maxlen);
  33. const int len = BIO_read(b64.get(), decoded.data(), maxlen);
  34. decoded.resize(len);
  35. return decoded;
  36. }
  37. std::string CryptoOpenSSL::base64Encode(const std::vector<uint8_t>& data)
  38. {
  39. // base64 in openssl is an absolute mess lmao x 2
  40. std::unique_ptr<BIO, BIOFreeAll> b64(BIO_new(BIO_f_base64()));
  41. // No newline mode, put all the data into sink
  42. BIO_set_flags(b64.get(), BIO_FLAGS_BASE64_NO_NL);
  43. BIO *sink = BIO_new(BIO_s_mem());
  44. BIO_push(b64.get(), sink);
  45. BIO_write(b64.get(), data.data(), data.size());
  46. BIO_flush(b64.get());
  47. const char *encoded;
  48. const long len = BIO_get_mem_data(sink, &encoded);
  49. return std::string(encoded, len);
  50. }
  51. // Sha1
  52. void CryptoOpenSSL::sha1Init()
  53. {
  54. SHA1_Init(&sha1Context);
  55. }
  56. void CryptoOpenSSL::sha1Update(const std::string& s)
  57. {
  58. sha1Update(std::vector<uint8_t>(s.begin(), s.end()));
  59. }
  60. void CryptoOpenSSL::sha1Update(const std::vector<uint8_t>& vec)
  61. {
  62. SHA1_Update(&sha1Context, vec.data(), vec.size());
  63. }
  64. std::vector<uint8_t> CryptoOpenSSL::sha1FinalBytes()
  65. {
  66. std::vector<uint8_t> digest(20); // 20 is 160 bits
  67. SHA1_Final(digest.data(), &sha1Context);
  68. return digest;
  69. }
  70. std::string CryptoOpenSSL::sha1Final()
  71. {
  72. auto digest = sha1FinalBytes();
  73. return std::string(digest.begin(), digest.end());
  74. }
  75. // HMAC SHA1
  76. std::vector<uint8_t> CryptoOpenSSL::sha1HMAC(const std::vector<uint8_t>& inputKey, const std::vector<uint8_t>& message)
  77. {
  78. std::vector<uint8_t> digest(20); // 20 is 160 bits
  79. auto hmacContext = HMAC_CTX_new();
  80. HMAC_Init_ex(hmacContext, inputKey.data(), inputKey.size(), EVP_sha1(), NULL);
  81. HMAC_Update(hmacContext, message.data(), message.size());
  82. unsigned int resLen = 0;
  83. HMAC_Final(hmacContext, digest.data(), &resLen);
  84. HMAC_CTX_free(hmacContext);
  85. return digest;
  86. }
  87. // AES CTR
  88. void CryptoOpenSSL::aesCTRXcrypt(const std::vector<uint8_t>& key, std::vector<uint8_t>& iv, std::vector<uint8_t> &data)
  89. {
  90. // Prepare AES_KEY
  91. auto cryptoKey = AES_KEY();
  92. AES_set_encrypt_key(key.data(), 128, &cryptoKey);
  93. // Needed for openssl internal cache
  94. unsigned char ecountBuf[16] = {0};
  95. unsigned int offsetInBlock = 0;
  96. CRYPTO_ctr128_encrypt(
  97. data.data(),
  98. data.data(),
  99. data.size(),
  100. &cryptoKey,
  101. iv.data(),
  102. ecountBuf,
  103. &offsetInBlock,
  104. block128_f(AES_encrypt));
  105. }
  106. void CryptoOpenSSL::aesECBdecrypt(const std::vector<uint8_t>& key, std::vector<uint8_t>& data)
  107. {
  108. EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  109. EVP_CIPHER_CTX_init(ctx);
  110. int len = 0;
  111. EVP_DecryptInit_ex(ctx, EVP_aes_192_ecb(), NULL, key.data(), NULL);
  112. EVP_DecryptUpdate(ctx, data.data(), &len, data.data(), data.size());
  113. EVP_DecryptFinal_ex(ctx, data.data() + len, &len);
  114. EVP_CIPHER_CTX_free(ctx);
  115. }
  116. // PBKDF2
  117. std::vector<uint8_t> CryptoOpenSSL::pbkdf2HmacSha1(const std::vector<uint8_t>& password, const std::vector<uint8_t>& salt, int iterations, int digestSize)
  118. {
  119. std::vector<uint8_t> digest(digestSize);
  120. // Generate PKDF2 digest
  121. PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.size(),
  122. (const unsigned char *)salt.data(), salt.size(), iterations,
  123. digestSize, digest.data());
  124. return digest;
  125. }
  126. void CryptoOpenSSL::dhInit()
  127. {
  128. // Free old context
  129. if (this->dhContext != nullptr)
  130. {
  131. DH_free(this->dhContext);
  132. }
  133. this->dhContext = DH_new();
  134. // Set prime and the generator
  135. DH_set0_pqg(this->dhContext, BN_bin2bn(DHPrime, DH_KEY_SIZE, NULL), NULL, BN_bin2bn(DHGenerator, 1, NULL));
  136. // Generate public and private keys and copy them to vectors
  137. DH_generate_key(this->dhContext);
  138. BN_bn2bin(DH_get0_pub_key(dhContext), this->publicKey.data());
  139. }
  140. std::vector<uint8_t> CryptoOpenSSL::dhCalculateShared(const std::vector<uint8_t>& remoteKey)
  141. {
  142. auto sharedKey = std::vector<uint8_t>(DH_KEY_SIZE);
  143. // Convert remote key to bignum and compute shared key
  144. auto pubKey = BN_bin2bn(&remoteKey[0], DH_KEY_SIZE, NULL);
  145. DH_compute_key(sharedKey.data(), pubKey, this->dhContext);
  146. BN_free(pubKey);
  147. return sharedKey;
  148. }
  149. // Random stuff
  150. std::vector<uint8_t> CryptoOpenSSL::generateVectorWithRandomData(size_t length)
  151. {
  152. std::vector<uint8_t> randomVec(length);
  153. if(RAND_bytes(randomVec.data(), length) == 0)
  154. {
  155. }
  156. return randomVec;
  157. }