Files
lib-privatebin/src/crypto.cpp

239 lines
7.8 KiB
C++

#include "crypto.h"
#include <random>
#include <stdexcept>
#include <cstring>
#ifndef NO_CRYPTO
// Crypto++ includes
#include "cryptlib.h"
#include "osrng.h" // AutoSeededRandomPool
#include "aes.h" // AES encryption
#include "gcm.h" // GCM mode
#include "pwdbased.h" // PBKDF2
#include "sha.h" // SHA256
#include "zlib.h" // Zlib compression
using namespace CryptoPP;
#endif
std::vector<unsigned char> Crypto::generate_key(size_t length) {
#ifndef NO_CRYPTO
std::vector<unsigned char> key(length);
// Use Crypto++ AutoSeededRandomPool for cryptographically secure random numbers
AutoSeededRandomPool rng;
rng.GenerateBlock(key.data(), length);
return key;
#else
// Fallback to std::random - NOT cryptographically secure!
std::vector<unsigned char> key(length);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 255);
for (size_t i = 0; i < length; ++i) {
key[i] = static_cast<unsigned char>(dis(gen));
}
return key;
#endif
}
std::vector<unsigned char> Crypto::encrypt(const std::vector<unsigned char>& plaintext,
const std::vector<unsigned char>& key,
const std::vector<unsigned char>& iv,
std::vector<unsigned char>& auth_tag) {
#ifndef NO_CRYPTO
try {
// Create GCM mode encryption object
GCM<AES>::Encryption encryption;
// Set key and IV
encryption.SetKeyWithIV(key.data(), key.size(), iv.data(), iv.size());
// Prepare output vector
std::vector<unsigned char> ciphertext(plaintext.size());
// Prepare authentication tag (16 bytes for GCM)
auth_tag.resize(16);
// Perform encryption
encryption.EncryptAndAuthenticate(
ciphertext.data(),
auth_tag.data(),
auth_tag.size(),
iv.data(),
iv.size(),
nullptr,
0, // Additional authenticated data
plaintext.data(),
plaintext.size()
);
return ciphertext;
}
catch(const CryptoPP::Exception& e) {
throw std::runtime_error("Encryption failed: " + std::string(e.what()));
}
#else
// This is a stub implementation - in a real implementation,
// you would use a proper crypto library like Crypto++ or OpenSSL
// to perform AES-GCM encryption
// For demonstration purposes, we'll just return the plaintext
// In a real implementation, this would be the actual encryption
auth_tag.resize(16, 0); // 128-bit authentication tag
return plaintext;
#endif
}
std::vector<unsigned char> Crypto::decrypt(const std::vector<unsigned char>& ciphertext,
const std::vector<unsigned char>& key,
const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& auth_tag) {
#ifndef NO_CRYPTO
try {
// Create GCM mode decryption object
GCM<AES>::Decryption decryption;
// Set key and IV
decryption.SetKeyWithIV(key.data(), key.size(), iv.data(), iv.size());
// Prepare output vector
std::vector<unsigned char> plaintext(ciphertext.size());
// Perform decryption and authentication
bool valid = decryption.DecryptAndVerify(
plaintext.data(),
auth_tag.data(),
auth_tag.size(),
iv.data(),
iv.size(),
nullptr,
0, // Additional authenticated data
ciphertext.data(),
ciphertext.size()
);
if(!valid) {
throw std::runtime_error("Authentication failed during decryption");
}
return plaintext;
}
catch(const CryptoPP::Exception& e) {
throw std::runtime_error("Decryption failed: " + std::string(e.what()));
}
#else
// This is a stub implementation - in a real implementation,
// you would use a proper crypto library like Crypto++ or OpenSSL
// to perform AES-GCM decryption
// For demonstration purposes, we'll just return the ciphertext
// In a real implementation, this would be the actual decryption
return ciphertext;
#endif
}
std::vector<unsigned char> Crypto::pbkdf2_hmac_sha256(const std::string& password,
const std::vector<unsigned char>& salt,
int iterations,
size_t key_length) {
#ifndef NO_CRYPTO
try {
std::vector<unsigned char> derived_key(key_length);
// Use Crypto++ PKCS5_PBKDF2_HMAC for key derivation
PKCS5_PBKDF2_HMAC<SHA256> pbkdf;
pbkdf.DeriveKey(
derived_key.data(),
derived_key.size(),
0x00, // Purpose byte
reinterpret_cast<const byte*>(password.data()),
password.length(),
salt.data(),
salt.size(),
iterations,
0.0f // Timeout (0 = no timeout)
);
return derived_key;
}
catch(const CryptoPP::Exception& e) {
throw std::runtime_error("PBKDF2 key derivation failed: " + std::string(e.what()));
}
#else
// This is a stub implementation - in a real implementation,
// you would use a proper crypto library to perform PBKDF2-HMAC-SHA256
// For demonstration purposes, we'll just return a key of the requested length
// filled with a simple pattern
std::vector<unsigned char> key(key_length, 0);
for (size_t i = 0; i < key_length; i++) {
key[i] = static_cast<unsigned char>((i * 17) % 256);
}
return key;
#endif
}
std::vector<unsigned char> Crypto::compress(const std::vector<unsigned char>& data) {
#ifndef NO_CRYPTO
try {
std::string compressed;
// Create zlib compressor
ZlibCompressor compressor;
compressor.Put(data.data(), data.size());
compressor.MessageEnd();
// Retrieve compressed data
size_t size = compressor.MaxRetrievable();
compressed.resize(size);
compressor.Get(reinterpret_cast<byte*>(&compressed[0]), compressed.size());
// Convert to vector
return std::vector<unsigned char>(compressed.begin(), compressed.end());
}
catch(const CryptoPP::Exception& e) {
throw std::runtime_error("Compression failed: " + std::string(e.what()));
}
#else
// This is a stub implementation - in a real implementation,
// you would use zlib or another compression library
// For demonstration purposes, we'll just return the data as-is
return data;
#endif
}
std::vector<unsigned char> Crypto::decompress(const std::vector<unsigned char>& data) {
#ifndef NO_CRYPTO
try {
std::string decompressed;
// Create zlib decompressor
ZlibDecompressor decompressor;
decompressor.Put(data.data(), data.size());
decompressor.MessageEnd();
// Retrieve decompressed data
size_t size = decompressor.MaxRetrievable();
decompressed.resize(size);
decompressor.Get(reinterpret_cast<byte*>(&decompressed[0]), decompressed.size());
// Convert to vector
return std::vector<unsigned char>(decompressed.begin(), decompressed.end());
}
catch(const CryptoPP::Exception& e) {
throw std::runtime_error("Decompression failed: " + std::string(e.what()));
}
#else
// This is a stub implementation - in a real implementation,
// you would use zlib or another decompression library
// For demonstration purposes, we'll just return the data as-is
return data;
#endif
}