Archived
1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
trinity/src/encryption.cpp

338 lines
11 KiB
C++
Raw Normal View History

#include "encryption.h"
#include <stdlib.h>
#include <QDebug>
#include <unistd.h>
#include <fcntl.h>
#include <QJsonDocument>
#include <cstring>
void Encryption::createNewDeviceKeys() {
initAccount();
// create account
auto length = olm_create_account_random_length(account);
void* memory = malloc(length);
int fd = open("/dev/random", O_RDONLY);
read(fd, memory, length);
olm_create_account(account, memory, length);
qDebug() << olm_account_last_error(account);
qDebug() << "Created new device keys!";
// retrieve identity keys
length = olm_account_identity_keys_length(account);
char* identity_memory = (char*)malloc(length + 1);
identity_memory[length] = '\0';
olm_account_identity_keys(account, identity_memory, length);
QJsonDocument doc = QJsonDocument::fromJson((char*)identity_memory);
identityKey = doc.object();
qDebug() << "identity keys: " << (char*)identity_memory;
qDebug() << "identity keys (parsed): " << identityKey;
}
QString Encryption::saveDeviceKeys() {
auto length = olm_pickle_account_length(account);
char* identity_memory = (char*)malloc(length + 1);
identity_memory[length] = '\0';
auto err = olm_pickle_account(account, "secret_key", 10, identity_memory, length);
qDebug() << olm_account_last_error(account);
qDebug() << err << " = " << olm_error();
qDebug() << "Save: " << identity_memory;
return identity_memory;
}
void Encryption::loadDeviceKeys(QString bytes) {
initAccount();
qDebug() << "load: " << bytes;
auto length = bytes.length();
std::string key = bytes.toStdString();
olm_unpickle_account(account, "secret_key", 10, key.data(), key.length());
qDebug() << olm_account_last_error(account);
length = olm_account_identity_keys_length(account);
char* identity_memory = (char*)malloc(length + 1);
identity_memory[length] = '\0';
olm_account_identity_keys(account, identity_memory, length);
qDebug() << identity_memory;
QJsonDocument doc = QJsonDocument::fromJson(identity_memory);
qDebug() << doc;
identityKey = doc.object();
}
QJsonObject Encryption::generateOneTimeKeys(int number_of_keys) {
int fd = open("/dev/random", O_RDONLY);
// generate random data
auto length = olm_account_generate_one_time_keys_random_length(account, number_of_keys);
auto memory = malloc(length);
read(fd, memory, length);
olm_account_generate_one_time_keys(account, number_of_keys, memory, length);
// retrieve one time keys
length = olm_account_one_time_keys_length(account);
memory = malloc(length);
olm_account_one_time_keys(account, memory, length);
olm_account_mark_keys_as_published(account);
QJsonDocument doc = QJsonDocument::fromJson((char*)memory);
return doc.object();
}
int Encryption::getRecommendedNumberOfOneTimeKeys() {
return olm_account_max_number_of_one_time_keys(account) / 2;
}
QString Encryption::signMessage(QString message) {
auto length = olm_account_signature_length(account);
void* memory = malloc(length);
olm_account_sign(
account,
message.data(), message.length(),
memory, length
);
qDebug() << "Signed: " << (char*)memory;
return (char*)memory;
}
void Encryption::initAccount() {
void* memory = malloc(olm_account_size());
account = olm_account(memory);
}
OlmOutboundGroupSession* Encryption::beginOutboundSession() {
void* outboundMemory = malloc(olm_outbound_group_session_size());
auto outboundSession = olm_outbound_group_session(outboundMemory);
auto length = olm_init_outbound_group_session_random_length(outboundSession);
void* memory = malloc(length);
int fd = open("/dev/random", O_RDONLY);
read(fd, memory, length);
olm_init_outbound_group_session(outboundSession, (uint8_t*)memory, length);
return outboundSession;
}
std::string Encryption::getGroupSessionId(OlmOutboundGroupSession* session) {
auto encryptedLength = olm_outbound_group_session_id_length(session);
char* encryptedMemory = (char*)malloc(encryptedLength + 1);
olm_outbound_group_session_id(session, (uint8_t*)encryptedMemory, encryptedLength);
return encryptedMemory;
}
std::string Encryption::getGroupSessionKey(OlmOutboundGroupSession* session) {
auto encryptedLength = olm_outbound_group_session_key_length(session);
char* encryptedMemory = (char*)malloc(encryptedLength + 1);
olm_outbound_group_session_key(session, (uint8_t*)encryptedMemory, encryptedLength);
return encryptedMemory;
}
OlmSession* Encryption::beginOutboundOlmSession(std::string identityKey, std::string oneTimeKey) {
void* outboundMemory = malloc(olm_session_size());
auto outboundSession = olm_session(outboundMemory);
auto length = olm_create_outbound_session_random_length(outboundSession);
void* memory = malloc(length);
int fd = open("/dev/random", O_RDONLY);
read(fd, memory, length);
olm_create_outbound_session(outboundSession, account, identityKey.data(), identityKey.length(), oneTimeKey.data(), oneTimeKey.length(), (uint8_t*)memory, length);
//qDebug() << "ERR: " << olm_session_last_error(outboundSession);
return outboundSession;
/*size_t olm_create_outbound_session(
OlmSession * session,
OlmAccount * account,
void const * their_identity_key, size_t their_identity_key_length,
void const * their_one_time_key, size_t their_one_time_key_length,
void * random, size_t random_length
);*/
}
std::string Encryption::getSessionId(OlmSession* session) {
auto length = olm_session_id_length(session);
char* memory = (char*)malloc(length + 1);
memory[length] = '\0';
/** An identifier for this session. Will be the same for both ends of the
* conversation. If the id buffer is too small then olm_session_last_error()
* will be "OUTPUT_BUFFER_TOO_SMALL". */
olm_session_id(
session,
memory, length
);
return memory;
}
std::string Encryption::encrypt(OlmSession* session, std::string message) {
auto length = olm_encrypt_random_length(session);
void* memory = malloc(length);
int fd = open("/dev/random", O_RDONLY);
read(fd, memory, length);
auto encryptedLength = olm_encrypt_message_length(session, message.length());
char* encryptedMemory = (char*)malloc(encryptedLength + 1);
olm_encrypt(session, message.data(), message.length(), memory, length, encryptedMemory, encryptedLength);
return encryptedMemory;
}
std::string Encryption::encryptGroup(OlmOutboundGroupSession* session, std::string message) {
auto encryptedLength = olm_group_encrypt_message_length(session, message.length());
char* encryptedMemory = (char*)malloc(encryptedLength + 1);
olm_group_encrypt(session, (uint8_t*)message.data(), message.length(), (uint8_t*)encryptedMemory, encryptedLength);
return encryptedMemory;
}
OlmSession* Encryption::createInboundSession(std::string senderKey, std::string body) {
void* inboundMemory = malloc(olm_session_size());
auto inboundSession = olm_session(inboundMemory);
olm_create_inbound_session_from(inboundSession, account, (void*)senderKey.c_str(), senderKey.length(), (void*)body.c_str(), body.length());
return inboundSession;
}
std::vector<std::uint8_t> Encryption::decrypt(OlmSession* session, int msgType, std::string cipherText) {
/*std::string maxPlaintextLengthBuffer = cipherText;
size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(session, msgType, (void*)maxPlaintextLengthBuffer.data(), maxPlaintextLengthBuffer.length());;
qDebug() << "THE ERROR YOU ARE LOOKING FOR " << olm_session_last_error(session);
if(maxPlaintextLength == olm_error())
return "";
char* plaintext = new char[maxPlaintextLength];
//plaintext[maxPlaintextLength] = '\0';
memset(plaintext, '\0', maxPlaintextLength);
int size = olm_decrypt(session, msgType, (void*)cipherText.data(), cipherText.length(), (void*)plaintext, maxPlaintextLength);
//plaintext[size] = '\0';
plaintext[size + 1] = '\0';
return plaintext;*/
// because olm_group_decrypt_max_plaintext_length DESTROYS the buffer, why?
auto tmp_plaintext_buffer = std::vector<std::uint8_t>(cipherText.size());
std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin());
// create the result buffer
size_t length = olm_decrypt_max_plaintext_length(session, msgType, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size());
if(length == olm_error())
return {};
auto result_buffer = std::vector<std::uint8_t>(length);
// now create another buffer for olm_group_decrypt
auto tmp_buffer = std::vector<std::uint8_t>(cipherText.size());
std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin());
auto size = olm_decrypt(session, msgType, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size());
if(size == olm_error())
return {};
auto output = std::vector<std::uint8_t>(size);
std::memcpy(output.data(), result_buffer.data(), size);
return output;
}
QString Encryption::saveSession(OlmOutboundGroupSession* session) {
auto length = olm_pickle_outbound_group_session_length(session);
char* identity_memory = (char*)malloc(length + 1);
identity_memory[length] = '\0';
auto err = olm_pickle_outbound_group_session(session, "secret_key", 10, identity_memory, length);
return identity_memory;
}
OlmOutboundGroupSession* Encryption::loadSession(QString bytes) {
void* outboundMemory = malloc(olm_outbound_group_session_size());
auto outboundSession = olm_outbound_group_session(outboundMemory);
auto length = bytes.length();
std::string key = bytes.toStdString();
olm_unpickle_outbound_group_session(outboundSession, "secret_key", 10, (void*)key.data(), key.length());
return outboundSession;
}
OlmInboundGroupSession* Encryption::beginInboundSession(std::string sessionKey) {
void* inboundMemory = malloc(olm_inbound_group_session_size());
auto inboundSession = olm_inbound_group_session(inboundMemory);
olm_init_inbound_group_session(inboundSession, (uint8_t*)sessionKey.data(), sessionKey.size());
return inboundSession;
}
std::vector<std::uint8_t> Encryption::decrypt(OlmInboundGroupSession* session, std::string cipherText) {
// because olm_group_decrypt_max_plaintext_length DESTROYS the buffer, why?
auto tmp_plaintext_buffer = std::vector<std::uint8_t>(cipherText.size());
std::copy(cipherText.begin(), cipherText.end(), tmp_plaintext_buffer.begin());
// create the result buffer
size_t length = olm_group_decrypt_max_plaintext_length(session, tmp_plaintext_buffer.data(), tmp_plaintext_buffer.size());
if(length == olm_error())
return {};
auto result_buffer = std::vector<std::uint8_t>(length);
// now create another buffer for olm_group_decrypt
auto tmp_buffer = std::vector<std::uint8_t>(cipherText.size());
std::copy(cipherText.begin(), cipherText.end(), tmp_buffer.begin());
uint32_t msgIndex;
auto size = olm_group_decrypt(session, tmp_buffer.data(), tmp_buffer.size(), result_buffer.data(), result_buffer.size(), &msgIndex);
if(size == olm_error())
return {};
auto output = std::vector<std::uint8_t>(size);
std::memcpy(output.data(), result_buffer.data(), size);
return output;
}