mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
add Crypto/AuthenticatedEncryption to move code from model/User into own class, add app secret to server config
This commit is contained in:
parent
4a93b26e9a
commit
ea18b3ca0a
137
src/cpp/Crypto/AuthenticatedEncryption.cpp
Normal file
137
src/cpp/Crypto/AuthenticatedEncryption.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include "AuthenticatedEncryption.h"
|
||||
|
||||
#include "sodium.h"
|
||||
#include "../ServerConfig.h"
|
||||
#include <assert.h>
|
||||
|
||||
AuthenticatedEncryption::AuthenticatedEncryption()
|
||||
: mOpsLimit(10), mMemLimit(33554432), mAlgo(2), mEncryptionKey(nullptr), mEncryptionKeyHash(0)
|
||||
{
|
||||
}
|
||||
|
||||
AuthenticatedEncryption::AuthenticatedEncryption(unsigned long long opslimit, size_t memlimit, int algo)
|
||||
: mOpsLimit(opslimit), mMemLimit(memlimit), mAlgo(algo), mEncryptionKey(nullptr), mEncryptionKeyHash(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AuthenticatedEncryption::~AuthenticatedEncryption()
|
||||
{
|
||||
if (mEncryptionKey) {
|
||||
MemoryManager::getInstance()->releaseMemory(mEncryptionKey);
|
||||
mEncryptionKey = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AuthenticatedEncryption::ResultType AuthenticatedEncryption::createKey(const std::string& salt_parameter, const std::string& passwd)
|
||||
{
|
||||
assert(crypto_hash_sha512_BYTES >= crypto_pwhash_SALTBYTES);
|
||||
|
||||
auto mm = MemoryManager::getInstance();
|
||||
auto app_secret = ServerConfig::g_CryptoAppSecret;
|
||||
|
||||
std::unique_lock<std::shared_mutex> _lock(mWorkingMutex);
|
||||
|
||||
// use hash512 because existing data where calculated with that, but could be also changed to hash256
|
||||
auto hash512_salt = mm->getFreeMemory(crypto_hash_sha512_BYTES); // need at least crypto_pwhash_SALTBYTES 16U
|
||||
|
||||
crypto_hash_sha512_state state;
|
||||
crypto_hash_sha512_init(&state);
|
||||
//crypto_hash_sha512_update
|
||||
crypto_hash_sha512_update(&state, (const unsigned char*)salt_parameter.data(), salt_parameter.size());
|
||||
crypto_hash_sha512_update(&state, *app_secret, app_secret->size());
|
||||
crypto_hash_sha512_final(&state, *hash512_salt);
|
||||
|
||||
|
||||
//unsigned char* key = (unsigned char *)malloc(crypto_box_SEEDBYTES); // 32U
|
||||
//ObfusArray* key = new ObfusArray(crypto_box_SEEDBYTES);
|
||||
auto mEncryptionKey = mm->getFreeMemory(crypto_box_SEEDBYTES);
|
||||
//Bin32Bytes* key = mm->get32Bytes();
|
||||
|
||||
// generate encryption key, should take a bit longer to make brute force attacks hard
|
||||
if (crypto_pwhash(*mEncryptionKey, mEncryptionKey->size(), passwd.data(), passwd.size(), *hash512_salt, mOpsLimit, mMemLimit, mAlgo) != 0) {
|
||||
mm->releaseMemory(mEncryptionKey);
|
||||
mEncryptionKey = nullptr;
|
||||
|
||||
return AUTH_CREATE_ENCRYPTION_KEY_FAILED;
|
||||
}
|
||||
|
||||
// generate hash from key for compare
|
||||
assert(sizeof(KeyHashed) >= crypto_shorthash_BYTES);
|
||||
crypto_shorthash((unsigned char*)&mEncryptionKeyHash, *mEncryptionKey, crypto_box_SEEDBYTES, *ServerConfig::g_ServerCryptoKey);
|
||||
|
||||
return AUTH_ENCRYPT_OK;
|
||||
}
|
||||
|
||||
AuthenticatedEncryption::ResultType AuthenticatedEncryption::encrypt(const MemoryBin* message, MemoryBin** encryptedMessage)
|
||||
{
|
||||
assert(message && encryptedMessage);
|
||||
std::shared_lock<std::shared_mutex> _lock(mWorkingMutex);
|
||||
|
||||
if (!mEncryptionKey) {
|
||||
return AUTH_NO_KEY;
|
||||
}
|
||||
|
||||
size_t message_len = message->size();
|
||||
size_t ciphertext_len = crypto_secretbox_MACBYTES + message_len;
|
||||
|
||||
unsigned char nonce[crypto_secretbox_NONCEBYTES];
|
||||
// we use a hardcoded value for nonce
|
||||
// TODO: use a dynamic value, save it along with the other parameters
|
||||
memset(nonce, 31, crypto_secretbox_NONCEBYTES);
|
||||
|
||||
auto mm = MemoryManager::getInstance();
|
||||
auto ciphertext = mm->getFreeMemory(ciphertext_len);
|
||||
memset(*ciphertext, 0, ciphertext_len);
|
||||
|
||||
if (0 != crypto_secretbox_easy(*ciphertext, *message, message_len, nonce, *mEncryptionKey)) {
|
||||
mm->releaseMemory(ciphertext);
|
||||
|
||||
return AUTH_ENCRYPT_MESSAGE_FAILED;
|
||||
}
|
||||
|
||||
*encryptedMessage = ciphertext;
|
||||
|
||||
return AUTH_ENCRYPT_OK;
|
||||
}
|
||||
|
||||
AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const MemoryBin* encryptedMessage, MemoryBin** message)
|
||||
{
|
||||
assert(message && encryptedMessage);
|
||||
std::shared_lock<std::shared_mutex> _lock(mWorkingMutex);
|
||||
|
||||
if (!mEncryptionKey) {
|
||||
return AUTH_NO_KEY;
|
||||
}
|
||||
|
||||
size_t decryptSize = encryptedMessage->size() - crypto_secretbox_MACBYTES;
|
||||
//unsigned char* decryptBuffer = (unsigned char*)malloc(decryptSize);
|
||||
auto mm = MemoryManager::getInstance();
|
||||
//ObfusArray* decryptedData = new ObfusArray(decryptSize);
|
||||
auto decryptedData = mm->getFreeMemory(decryptSize);
|
||||
unsigned char nonce[crypto_secretbox_NONCEBYTES];
|
||||
// we use a hardcoded value for nonce
|
||||
// TODO: use a dynamic value, save it along with the other parameters
|
||||
memset(nonce, 31, crypto_secretbox_NONCEBYTES);
|
||||
|
||||
if (crypto_secretbox_open_easy(*decryptedData, *encryptedMessage, encryptedMessage->size(), nonce, *mEncryptionKey)) {
|
||||
mm->releaseMemory(decryptedData);
|
||||
return AUTH_DECRYPT_MESSAGE_FAILED;
|
||||
}
|
||||
*message = decryptedData;
|
||||
|
||||
return AUTH_DECRYPT_OK;
|
||||
}
|
||||
|
||||
const char* AuthenticatedEncryption::getErrorMessage(ResultType type)
|
||||
{
|
||||
switch (type) {
|
||||
case AUTH_ENCRYPT_OK: return "everything is ok";
|
||||
//case AUTH_ENCRYPT_SHA2_TO_SMALL: return "libsodium crypto_hash_sha512_BYTES is to small to use as crypto_pwhash_SALTBYTES";
|
||||
case AUTH_CREATE_ENCRYPTION_KEY_FAILED: return "error creating encryption key, maybe to much memory requested?";
|
||||
case AUTH_NO_KEY: return "no encryption key generated";
|
||||
case AUTH_ENCRYPT_MESSAGE_FAILED: return "message encryption failed";
|
||||
case AUTH_DECRYPT_MESSAGE_FAILED: return "message decryption failed";
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
78
src/cpp/Crypto/AuthenticatedEncryption.h
Normal file
78
src/cpp/Crypto/AuthenticatedEncryption.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef __GRADIDO_LOGIN_SERVER_CRYPTO_AUTHENTICATED_ENCRYPTION_H
|
||||
#define __GRADIDO_LOGIN_SERVER_CRYPTO_AUTHENTICATED_ENCRYPTION_H
|
||||
|
||||
|
||||
#include "../SingletonManager/MemoryManager.h"
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
/*!
|
||||
*
|
||||
* \author: Dario Rekowski
|
||||
*
|
||||
* \date: 07-06-2020
|
||||
*
|
||||
* \brief: Wrapper Class for make using libsodium authenticated encryption easy, used for encrypt private keys for user
|
||||
*
|
||||
*/
|
||||
|
||||
typedef Poco::UInt64 KeyHashed;
|
||||
|
||||
class AuthenticatedEncryption
|
||||
{
|
||||
public:
|
||||
|
||||
enum ResultType {
|
||||
AUTH_ENCRYPT_OK,
|
||||
AUTH_DECRYPT_OK,
|
||||
AUTH_CREATE_ENCRYPTION_KEY_FAILED,
|
||||
AUTH_NO_KEY,
|
||||
AUTH_ENCRYPT_MESSAGE_FAILED,
|
||||
AUTH_DECRYPT_MESSAGE_FAILED
|
||||
};
|
||||
|
||||
//! \brief init with default algorithms parameter
|
||||
AuthenticatedEncryption();
|
||||
//! \brief init with custom algorithms parameter
|
||||
//!
|
||||
//! details see in libsodium crypto_pwhash
|
||||
AuthenticatedEncryption(unsigned long long opslimit, size_t memlimit, int algo);
|
||||
|
||||
~AuthenticatedEncryption();
|
||||
|
||||
|
||||
inline KeyHashed getKeyHashed() const { std::shared_lock<std::shared_mutex> _lock(mWorkingMutex); return mEncryptionKeyHash; }
|
||||
inline bool operator == (const AuthenticatedEncryption& b) const {
|
||||
std::shared_lock<std::shared_mutex> _lock(mWorkingMutex);
|
||||
return mEncryptionKeyHash == b.getKeyHashed();
|
||||
}
|
||||
|
||||
inline bool hasKey() const { std::shared_lock<std::shared_mutex> _lock(mWorkingMutex); return !mEncryptionKey; }
|
||||
|
||||
//! \brief generate encryption key, with default parameter use ca. 300 ms
|
||||
//!
|
||||
//! should be call from task, running in g_CryptoCPUScheduler, lock shared mutex for writing
|
||||
//! \param salt_parameter for example email
|
||||
//! \return AUTH_CREATE_ENCRYPTION_KEY_FAILED call strerror(errno) for more details
|
||||
ResultType createKey(const std::string& salt_parameter, const std::string& passwd);
|
||||
|
||||
ResultType encrypt(const MemoryBin* message, MemoryBin** encryptedMessage);
|
||||
|
||||
ResultType decrypt(const MemoryBin* encryptedMessage, MemoryBin** message);
|
||||
|
||||
const char* getErrorMessage(ResultType type);
|
||||
|
||||
protected:
|
||||
// algorithms parameter
|
||||
unsigned long long mOpsLimit;
|
||||
size_t mMemLimit;
|
||||
int mAlgo;
|
||||
|
||||
// encryption key and hash
|
||||
MemoryBin* mEncryptionKey;
|
||||
KeyHashed mEncryptionKeyHash;
|
||||
|
||||
mutable std::shared_mutex mWorkingMutex;
|
||||
};
|
||||
|
||||
#endif //__GRADIDO_LOGIN_SERVER_CRYPTO_AUTHENTICATED_ENCRYPTION_H
|
||||
@ -3,6 +3,7 @@
|
||||
#include "Crypto/mnemonic_german2.h"
|
||||
#include "Crypto/mnemonic_bip0039.h"
|
||||
#include "Crypto/DRRandom.h"
|
||||
#include "lib/DataTypeConverter.h"
|
||||
#include "sodium.h"
|
||||
|
||||
|
||||
@ -51,6 +52,7 @@ namespace ServerConfig {
|
||||
bool g_disableEmail = false;
|
||||
ServerSetupType g_ServerSetupType = SERVER_TYPE_PRODUCTION;
|
||||
std::string g_gRPCRelayServerFullURL;
|
||||
MemoryBin* g_CryptoAppSecret = nullptr;
|
||||
|
||||
#ifdef __linux__
|
||||
#include <stdio.h>
|
||||
@ -217,6 +219,14 @@ namespace ServerConfig {
|
||||
auto serverSetupTypeString = cfg.getString("ServerSetupType", "");
|
||||
g_ServerSetupType = getServerSetupTypeFromString(serverSetupTypeString);
|
||||
|
||||
// app secret for encrypt user private keys
|
||||
// TODO: encrypt with server admin key
|
||||
auto app_secret_string = cfg.getString("crypto.app_secret", "");
|
||||
if ("" != app_secret_string) {
|
||||
g_CryptoAppSecret = DataTypeConverter::hexToBin(app_secret_string);
|
||||
}
|
||||
//g_CryptoAppSecret
|
||||
|
||||
g_gRPCRelayServerFullURL = cfg.getString("grpc.server", "");
|
||||
|
||||
return true;
|
||||
@ -283,6 +293,10 @@ namespace ServerConfig {
|
||||
if (g_CryptoCPUScheduler) {
|
||||
delete g_CryptoCPUScheduler;
|
||||
}
|
||||
if (g_CryptoAppSecret) {
|
||||
MemoryManager::getInstance()->releaseMemory(g_CryptoAppSecret);
|
||||
g_CryptoAppSecret = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void writeToFile(std::istream& datas, std::string fileName)
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "tasks/CPUSheduler.h"
|
||||
|
||||
#include "SingletonManager/LanguageManager.h"
|
||||
|
||||
#include "SingletonManager/MemoryManager.h"
|
||||
|
||||
#define DISABLE_EMAIL
|
||||
|
||||
@ -60,6 +60,7 @@ namespace ServerConfig {
|
||||
extern bool g_disableEmail;
|
||||
extern ServerSetupType g_ServerSetupType;
|
||||
extern std::string g_gRPCRelayServerFullURL;
|
||||
extern MemoryBin* g_CryptoAppSecret;
|
||||
|
||||
bool loadMnemonicWordLists();
|
||||
bool initServerCrypto(const Poco::Util::LayeredConfiguration& cfg);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user