This commit is contained in:
justuser-31 2025-07-26 16:21:32 +03:00
parent 1ade51f4ef
commit f3743942ee
7 changed files with 2171 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
__pycache__
*.pem
example

19
Makefile Normal file
View File

@ -0,0 +1,19 @@
CXX = g++
CXXFLAGS = -std=c++17 -I/usr/local/include/botan-2/ -lbotan-2
RUN = ./
LD_LIBRARY_PATH = /usr/local/lib
.PHONY: all clean build run
all: build run
build: example.cpp
$(CXX) example.cpp $(CXXFLAGS) -o example
run:
$(RUN)example
run_python:
LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) python example.py
clean:
rm -f *.pem

1789
botan2.py Normal file

File diff suppressed because it is too large Load Diff

152
crypto_lib.cpp Normal file
View File

@ -0,0 +1,152 @@
#include <botan/auto_rng.h>
#include <botan/rsa.h>
#include <botan/pkcs8.h>
#include <botan/x509_key.h>
#include <botan/pubkey.h>
#include <botan/data_src.h>
#include <fstream>
#include <iostream>
namespace CryptoLib {
std::pair<std::unique_ptr<Botan::Private_Key>, std::unique_ptr<Botan::Public_Key>>
generate_keys(int key_size = 2048);
std::pair<std::unique_ptr<Botan::Private_Key>, std::unique_ptr<Botan::Public_Key>>
generate_keys(int key_size) {
Botan::AutoSeeded_RNG rng;
std::unique_ptr<Botan::RSA_PrivateKey> private_key(new Botan::RSA_PrivateKey(rng, key_size));
std::unique_ptr<Botan::RSA_PublicKey> public_key(new Botan::RSA_PublicKey(*private_key));
return std::make_pair(std::move(private_key), std::move(public_key));
}
std::vector<uint8_t> encrypt(const Botan::Public_Key& public_key, const std::string& data) {
std::vector<uint8_t> data_vector(data.begin(), data.end());
Botan::AutoSeeded_RNG rng;
Botan::PK_Encryptor_EME encryptor(public_key, rng, "OAEP(SHA-256)");
return encryptor.encrypt(data_vector, rng);
}
std::string decrypt(const Botan::Private_Key& private_key, const std::vector<uint8_t>& encrypted_data) {
std::vector<uint8_t> encrypted_vector(encrypted_data.begin(), encrypted_data.end());
Botan::AutoSeeded_RNG rng;
Botan::PK_Decryptor_EME decryptor(private_key, rng, "OAEP(SHA-256)");
auto result = decryptor.decrypt(encrypted_vector);
return std::string(result.begin(), result.end());
}
std::string public_key_to_string(const Botan::Public_Key& public_key) {
return Botan::X509::PEM_encode(public_key);
}
std::unique_ptr<Botan::Public_Key> public_key_from_string(const std::string& key_string) {
Botan::DataSource_Memory ds(key_string);
return std::unique_ptr<Botan::Public_Key>(Botan::X509::load_key(ds));
}
std::string private_key_to_string(const Botan::Private_Key& private_key) {
return Botan::PKCS8::PEM_encode(private_key);
}
std::unique_ptr<Botan::Private_Key> private_key_from_string(const std::string& key_string) {
Botan::DataSource_Memory ds(key_string);
return std::unique_ptr<Botan::Private_Key>(Botan::PKCS8::load_key(ds));
}
void save_private_key(const Botan::Private_Key& private_key, const std::string& filename) {
std::ofstream file(filename);
if (file.is_open()) {
file << Botan::PKCS8::PEM_encode(private_key);
file.close();
} else {
throw std::runtime_error("Cannot open file for writing: " + filename);
}
}
void save_public_key(const Botan::Public_Key& public_key, const std::string& filename) {
std::ofstream file(filename);
if (file.is_open()) {
file << Botan::X509::PEM_encode(public_key);
file.close();
} else {
throw std::runtime_error("Cannot open file for writing: " + filename);
}
}
std::unique_ptr<Botan::Private_Key> load_private_key(const std::string& filename) {
std::ifstream file(filename);
if (file.is_open()) {
std::string content((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
file.close();
Botan::DataSource_Memory ds(content);
return std::unique_ptr<Botan::Private_Key>(Botan::PKCS8::load_key(ds));
} else {
throw std::runtime_error("Cannot open file for reading: " + filename);
}
}
std::unique_ptr<Botan::Public_Key> load_public_key(const std::string& filename) {
std::ifstream file(filename);
if (file.is_open()) {
std::string content((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
file.close();
Botan::DataSource_Memory ds(content);
return std::unique_ptr<Botan::Public_Key>(Botan::X509::load_key(ds));
} else {
throw std::runtime_error("Cannot open file for reading: " + filename);
}
}
std::string bytes_to_base64(const std::vector<unsigned char>& data) {
static const char* const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string result;
size_t i = 0;
while (i < data.size()) {
uint32_t octet_a = i < data.size() ? data[i++] : 0;
uint32_t octet_b = i < data.size() ? data[i++] : 0;
uint32_t octet_c = i < data.size() ? data[i++] : 0;
uint32_t triple = (octet_a << 16) + (octet_b << 8) + octet_c;
result += chars[(triple >> 18) & 63];
result += chars[(triple >> 12) & 63];
result += chars[(triple >> 6) & 63];
result += chars[triple & 63];
}
// Add padding
switch (data.size() % 3) {
case 1:
result[result.size() - 2] = '=';
result[result.size() - 1] = '=';
break;
case 2:
result[result.size() - 1] = '=';
break;
}
return result;
}
std::vector<unsigned char> base64_to_bytes(const std::string& input) {
static const std::string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::vector<unsigned char> result;
int val = 0, valb = -8;
for (unsigned char c : input) {
if (c == '=') break;
if (chars.find(c) == std::string::npos) continue;
val = (val << 6) + chars.find(c);
valb += 6;
if (valb >= 0) {
result.push_back((val >> valb) & 0xFF);
valb -= 8;
}
}
return result;
}
};

86
crypto_lib.py Normal file
View File

@ -0,0 +1,86 @@
import botan2 as botan
import base64
class CryptoLib:
@staticmethod
def generate_keys(key_size=2048):
"""Generate RSA key pair"""
rng = botan.RandomNumberGenerator()
private_key = botan.PrivateKey.create("RSA", str(key_size), rng)
public_key = private_key.get_public_key()
return private_key, public_key
@staticmethod
def encrypt(public_key, data):
"""Encrypt data with public key"""
if isinstance(data, str):
data = data.encode('utf-8')
rng = botan.RandomNumberGenerator()
encryptor = botan.PKEncrypt(public_key, "OAEP(SHA-256)")
return encryptor.encrypt(data, rng)
@staticmethod
def decrypt(private_key, encrypted_data):
"""Decrypt data with private key"""
decryptor = botan.PKDecrypt(private_key, "OAEP(SHA-256)")
return decryptor.decrypt(encrypted_data)
@staticmethod
def public_key_to_string(public_key):
"""Convert public key to PEM string"""
return public_key.to_pem().encode('utf-8')
@staticmethod
def public_key_from_string(key_string):
"""Load public key from PEM string"""
if isinstance(key_string, str):
key_string = key_string.encode('utf-8')
return botan.PublicKey.load(key_string)
@staticmethod
def private_key_to_string(private_key):
"""Convert private key to PEM string"""
return private_key.to_pem().decode('utf-8')
@staticmethod
def private_key_from_string(key_string):
"""Load private key from PEM string"""
if isinstance(key_string, str):
key_string = key_string.encode('utf-8')
return botan.PrivateKey.load(key_string)
@staticmethod
def save_private_key(private_key, filename):
"""Save private key to file"""
with open(filename, 'w') as f:
# f.write(private_key.to_pem().encode('utf-8'))
f.write(private_key.to_pem())
@staticmethod
def save_public_key(public_key, filename):
"""Save public key to file"""
with open(filename, 'w') as f:
# f.write(public_key.to_pem().decode('utf-8'))
f.write(public_key.to_pem())
@staticmethod
def load_private_key(filename):
"""Load private key from file"""
with open(filename, 'r') as f:
pem_data = f.read()
return botan.PrivateKey.load(pem_data.encode('utf-8'))
@staticmethod
def load_public_key(filename):
"""Load public key from file"""
with open(filename, 'r') as f:
pem_data = f.read()
return botan.PublicKey.load(pem_data.encode('utf-8'))
@staticmethod
def bytes_to_base64(public_key: bytes) -> str:
return base64.b64encode(public_key).decode('utf-8')
@staticmethod
def base64_to_bytes(key_string: str) -> bytes:
return base64.b64decode(key_string.encode('utf-8'))

75
example.cpp Normal file
View File

@ -0,0 +1,75 @@
#include "crypto_lib.cpp"
#include <iostream>
#include <vector>
#include <string>
int main() {
try {
std::cout << "=== Asymmetric Cryptography Example ===" << std::endl;
std::string generate_new_keys;
std::cout << "Generate new keys? (y/n): ";
std::cin >> generate_new_keys;
std::string message;
std::vector<uint8_t> encrypted;
if (generate_new_keys == "y") {
// 1. Generate keys
std::cout << "1. Generating key pair...\n\n";
auto keys = CryptoLib::generate_keys(2048);
auto& private_key = keys.first;
auto& public_key = keys.second;
// 2. Save keys to files
std::cout << "2. Saving keys to files...\n\n";
CryptoLib::save_private_key(*private_key, "private_key.pem");
CryptoLib::save_public_key(*public_key, "public_key.pem");
message = "Hello, this is a secret message!";
} else {
std::cout << "Enter message to decrypt (if exists): ";
std::cin.ignore();
std::getline(std::cin, message);
if (!message.empty()) {
encrypted = CryptoLib::base64_to_bytes(message);
} else {
message = "Hello, this is a secret message!";
}
}
// 3. Load keys from files
std::cout << "3. Loading keys from files...\n\n";
auto loaded_private_key = CryptoLib::load_private_key("private_key.pem");
auto loaded_public_key = CryptoLib::load_public_key("public_key.pem");
// 4. Convert public key to string and back
std::cout << "4. Loaded keys:\n";
std::string private_key_str = CryptoLib::private_key_to_string(*loaded_private_key);
std::string public_key_str = CryptoLib::public_key_to_string(*loaded_public_key);
std::cout << "Private key string as: " << private_key_str.substr(0, 50) << "...\n";
std::cout << "Public key string as: " << public_key_str.substr(0, 50) << "...\n\n";
std::cout << "5. Convert public key from string...\n\n";
auto restored_public_key = CryptoLib::public_key_from_string(public_key_str);
if (encrypted.empty()) {
// 6. Encrypt data
std::cout << "6. Testing ecnryption..." << std::endl;
std::cout << "Original message: " << message << std::endl;
encrypted = CryptoLib::encrypt(*loaded_public_key, message);
std::cout << "Encrypted (base64): " << CryptoLib::bytes_to_base64(encrypted) << std::endl;
std::cout << "Encrypted data size: " << encrypted.size() << " bytes\n\n";
}
// 7. Decrypt data
std::string decrypted_message = CryptoLib::decrypt(*loaded_private_key, encrypted);
std::cout << "7. Decrypted message: " << decrypted_message << "\n";
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}

47
example.py Normal file
View File

@ -0,0 +1,47 @@
from crypto_lib import *
# Example usage
if __name__ == "__main__":
generate_new_keys = input('Generate new keys? (y/n): ')
if generate_new_keys == 'y':
# 1. Generate keys
print("1. Generating key pair...\n")
private_key, public_key = CryptoLib.generate_keys(2048)
# 2. Save keys to files
print("2. Saving keys to files...\n")
CryptoLib.save_private_key(private_key, "private_key.pem")
CryptoLib.save_public_key(public_key, "public_key.pem")
encrypted = ''
else:
encrypted = CryptoLib.base64_to_bytes(input('Enter message (if exist): '))
# 6. Load keys from files
print("3. Loading keys from files...\n")
loaded_private_key = CryptoLib.load_private_key("private_key.pem")
loaded_public_key = CryptoLib.load_public_key("public_key.pem")
# 3. Convert public key to string and back
print("4. Loaded keys:.")
private_key_str = CryptoLib.public_key_to_string(loaded_private_key)
public_key_str = CryptoLib.public_key_to_string(loaded_public_key)
print(f'Private key as string: {private_key_str[:50]}...')
print(f'Public key as string: {public_key_str[:50]}...\n')
print(f'5. Convert public key from string...\n')
restored_public_key = CryptoLib.public_key_from_string(public_key_str)
if not encrypted:
# 6. Encrypt data
print("6. Encrypting data...")
message = "Hello, this is a secret message from Python!"
print(f'Original message: {message}')
encrypted = CryptoLib.encrypt(loaded_public_key, message)
print(f'Encrypted (base64): {CryptoLib.bytes_to_base64(encrypted)}')
print(f"Encrypted data size: {len(encrypted)} bytes\n")
# 7. Decrypt data
decrypted_data = CryptoLib.decrypt(loaded_private_key, encrypted)
decrypted_message = decrypted_data.decode('utf-8')
print(f"7. Decrypted message: {decrypted_message}")