mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
update code to work together for setting new password and update encrypted privkey and password hash in db
This commit is contained in:
parent
e7624382ae
commit
c44184f823
@ -128,6 +128,34 @@ AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const Memor
|
||||
return AUTH_DECRYPT_OK;
|
||||
}
|
||||
|
||||
AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const std::vector<unsigned char>& encryptedMessage, MemoryBin** message) const
|
||||
{
|
||||
assert(message);
|
||||
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.data(), 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) {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "../SingletonManager/MemoryManager.h"
|
||||
|
||||
#include <shared_mutex>
|
||||
#include <vector>
|
||||
|
||||
/*!
|
||||
*
|
||||
@ -59,6 +60,11 @@ public:
|
||||
ResultType encrypt(const MemoryBin* message, MemoryBin** encryptedMessage) const;
|
||||
|
||||
ResultType decrypt(const MemoryBin* encryptedMessage, MemoryBin** message) const;
|
||||
//! \brief same as the other decrypt only in other format
|
||||
//! \param encryptedMessage format from Poco Binary Data from DB, like returned from model/table/user for encrypted private key
|
||||
//!
|
||||
//! double code, I don't know how to prevent without unnecessary copy of encryptedMessage
|
||||
ResultType decrypt(const std::vector<unsigned char>& encryptedMessage, MemoryBin** message) const;
|
||||
|
||||
static const char* getErrorMessage(ResultType type);
|
||||
|
||||
|
||||
@ -8,10 +8,12 @@
|
||||
|
||||
#include "Passphrase.h"
|
||||
|
||||
KeyPairEd25519::KeyPairEd25519(MemoryBin* privateKey, const unsigned char* publicKey)
|
||||
KeyPairEd25519::KeyPairEd25519(MemoryBin* privateKey)
|
||||
: mSodiumSecret(privateKey)
|
||||
{
|
||||
memcpy(mSodiumPublic, publicKey, crypto_sign_PUBLICKEYBYTES);
|
||||
//memcpy(mSodiumPublic, publicKey, crypto_sign_PUBLICKEYBYTES);
|
||||
// read pubkey from private key, so we are sure it is the correct pubkey for the private key
|
||||
crypto_sign_ed25519_sk_to_pk(*privateKey, mSodiumPublic);
|
||||
}
|
||||
|
||||
KeyPairEd25519::KeyPairEd25519(const unsigned char* publicKey)
|
||||
|
||||
@ -21,7 +21,7 @@ class KeyPairEd25519 : public IKeyPair
|
||||
public:
|
||||
//! \param privateKey: take ownership, release after object destruction
|
||||
//! \param publicKey: copy
|
||||
KeyPairEd25519(MemoryBin* privateKey, const unsigned char* publicKey);
|
||||
KeyPairEd25519(MemoryBin* privateKey);
|
||||
KeyPairEd25519(const unsigned char* publicKey);
|
||||
|
||||
~KeyPairEd25519();
|
||||
@ -38,10 +38,16 @@ public:
|
||||
inline bool isTheSame(const KeyPairEd25519& b) const {
|
||||
return 0 == sodium_memcmp(mSodiumPublic, b.mSodiumPublic, crypto_sign_PUBLICKEYBYTES);
|
||||
}
|
||||
inline bool isTheSame(const unsigned char* pubkey) const {
|
||||
return 0 == sodium_memcmp(mSodiumPublic, pubkey, crypto_sign_PUBLICKEYBYTES);
|
||||
}
|
||||
|
||||
inline bool operator == (const KeyPairEd25519& b) const { return isTheSame(b); }
|
||||
inline bool operator != (const KeyPairEd25519& b) const { return !isTheSame(b); }
|
||||
|
||||
inline bool operator == (const unsigned char* b) const { return isTheSame(b); }
|
||||
inline bool operator != (const unsigned char* b) const { return !isTheSame(b); }
|
||||
|
||||
inline bool hasPrivateKey() const { return mSodiumSecret != nullptr; }
|
||||
|
||||
//! \brief only way to get a private key.. encrypted
|
||||
|
||||
@ -207,7 +207,7 @@ void AdminUserPasswordReset::handleRequest(Poco::Net::HTTPServerRequest& request
|
||||
responseStream << "</li>\n";
|
||||
responseStream << "\t\t\t<li>Private Key verschlüsselt: ";
|
||||
#line 92 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminUserPasswordReset.cpsp"
|
||||
responseStream << ( std::to_string(userModel->existPrivateKeyCrypted()) );
|
||||
responseStream << ( std::to_string(userModel->hasPrivateKeyEncrypted()) );
|
||||
responseStream << "</li>\n";
|
||||
responseStream << "\t\t\t<li>Passwort gesetzt: ";
|
||||
#line 93 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminUserPasswordReset.cpsp"
|
||||
|
||||
@ -3,10 +3,12 @@
|
||||
#include "sodium.h"
|
||||
|
||||
#include "../SingletonManager/SessionManager.h"
|
||||
#include "../lib/DataTypeConverter.h"
|
||||
|
||||
|
||||
namespace controller {
|
||||
User::User(model::table::User* dbModel)
|
||||
: mPassword(nullptr)
|
||||
: mPassword(nullptr), mGradidoKeyPair(nullptr)
|
||||
{
|
||||
mDBModel = dbModel;
|
||||
}
|
||||
@ -15,6 +17,11 @@ namespace controller {
|
||||
{
|
||||
if (mPassword) {
|
||||
delete mPassword;
|
||||
mPassword = nullptr;
|
||||
}
|
||||
if (mGradidoKeyPair) {
|
||||
delete mGradidoKeyPair;
|
||||
mGradidoKeyPair = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,4 +122,45 @@ namespace controller {
|
||||
return json;
|
||||
}
|
||||
|
||||
int User::setPassword(AuthenticatedEncryption* passwd)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
auto model = getModel();
|
||||
const static char* function_name = "controller::User::setPassword";
|
||||
|
||||
if (mPassword)
|
||||
{
|
||||
if (mPassword == passwd) return 0;
|
||||
// if password exist but gradido key pair not, try to load key pair
|
||||
if ((!mGradidoKeyPair || !mGradidoKeyPair->hasPrivateKey()) && model->hasPrivateKeyEncrypted()) {
|
||||
//if (!mGradidoKeyPair) mGradidoKeyPair = new KeyPairEd25519;
|
||||
MemoryBin* clear_private_key = nullptr;
|
||||
if (AuthenticatedEncryption::AUTH_DECRYPT_OK == mPassword->decrypt(model->getPrivateKeyEncrypted(), &clear_private_key)) {
|
||||
if (mGradidoKeyPair) delete mGradidoKeyPair;
|
||||
mGradidoKeyPair = new KeyPairEd25519(clear_private_key);
|
||||
|
||||
// check if saved pubkey and from private key extracted pubkey match
|
||||
if (*mGradidoKeyPair != model->getPublicKey()) {
|
||||
delete mGradidoKeyPair;
|
||||
mGradidoKeyPair = nullptr;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete passwd;
|
||||
}
|
||||
// replace old password with new
|
||||
mPassword = passwd;
|
||||
|
||||
// set new encrypted password and hash
|
||||
model->setPasswordHashed(mPassword->getKeyHashed());
|
||||
auto encryptedPrivateKey = mGradidoKeyPair->getCryptedPrivKey(mPassword);
|
||||
model->setPrivateKey(encryptedPrivateKey);
|
||||
MemoryManager::getInstance()->releaseMemory(encryptedPrivateKey);
|
||||
|
||||
// save changes to db
|
||||
return model->updatePrivkeyAndPasswordHash();
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,8 @@
|
||||
#define GRADIDO_LOGIN_SERVER_CONTROLLER_USER_INCLUDE
|
||||
|
||||
#include "../model/table/User.h"
|
||||
#include "../Crypto/AuthenticatedEncryption.h"
|
||||
//#include "../Crypto/AuthenticatedEncryption.h"
|
||||
#include "../Crypto/KeyPairEd25519.h"
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
@ -42,13 +43,12 @@ namespace controller {
|
||||
|
||||
// ***********************************************************************************
|
||||
// password related
|
||||
//! \brief
|
||||
//! \brief set authenticated encryption and save hash in db, should also re encrypt private key if exist
|
||||
//! \param passwd take owner ship
|
||||
inline void setPassword(AuthenticatedEncryption* passwd) {
|
||||
std::unique_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
if (mPassword) delete passwd;
|
||||
mPassword = passwd;
|
||||
}
|
||||
//! \return 0 = new and current passwords are the same
|
||||
//! \return 1 = password changed, private key re-encrypted and saved into db
|
||||
//! \return -1 = stored pubkey and private key didn't match
|
||||
int setPassword(AuthenticatedEncryption* passwd);
|
||||
|
||||
inline const AuthenticatedEncryption* getPassword() {
|
||||
std::shared_lock<std::shared_mutex> _lock(mSharedMutex);
|
||||
@ -60,6 +60,7 @@ namespace controller {
|
||||
std::string mPublicHex;
|
||||
|
||||
AuthenticatedEncryption* mPassword;
|
||||
KeyPairEd25519* mGradidoKeyPair;
|
||||
|
||||
mutable std::shared_mutex mSharedMutex;
|
||||
};
|
||||
|
||||
@ -426,8 +426,8 @@ User::User(Poco::AutoPtr<controller::User> ctrl_user)
|
||||
mPublicHex = std::string((char*)(*hexStringTemp));
|
||||
mm->releaseMemory(hexStringTemp);
|
||||
}
|
||||
if (model->existPrivateKeyCrypted()) {
|
||||
auto privKeyVetor = model->getPrivateKeyCrypted();
|
||||
if (model->hasPrivateKeyEncrypted()) {
|
||||
auto privKeyVetor = model->getPrivateKeyEncrypted();
|
||||
mPrivateKey = mm->getFreeMemory(privKeyVetor.size());
|
||||
memcpy(*mPrivateKey, privKeyVetor.data(), privKeyVetor.size());
|
||||
}
|
||||
|
||||
@ -143,7 +143,10 @@ namespace model {
|
||||
size_t User::updatePrivkey()
|
||||
{
|
||||
lock();
|
||||
if (mPrivateKey.isNull()) return 0;
|
||||
if (mPrivateKey.isNull()) {
|
||||
unlock();
|
||||
return 0;
|
||||
}
|
||||
auto result = updateIntoDB("privkey", mPrivateKey.value());
|
||||
unlock();
|
||||
return result;
|
||||
@ -151,12 +154,45 @@ namespace model {
|
||||
size_t User::updatePublickey()
|
||||
{
|
||||
lock();
|
||||
if (mPublicKey.isNull()) return 0;
|
||||
if (mPublicKey.isNull()) {
|
||||
unlock();
|
||||
return 0;
|
||||
}
|
||||
auto result = updateIntoDB("pubkey", mPublicKey.value());
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t User::updatePrivkeyAndPasswordHash()
|
||||
{
|
||||
lock();
|
||||
if (mPrivateKey.isNull() || !mPasswordHashed || !mID) {
|
||||
unlock();
|
||||
return 0;
|
||||
}
|
||||
auto cm = ConnectionManager::getInstance();
|
||||
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
|
||||
|
||||
Poco::Data::Statement update(session);
|
||||
|
||||
update << "UPDATE users SET password = ?, privkey = ? where id = ?;",
|
||||
bind(mPasswordHashed), use(mPrivateKey), use(mID);
|
||||
|
||||
|
||||
size_t resultCount = 0;
|
||||
try {
|
||||
return update.execute();
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
lock("User::updatePrivkeyAndPasswordHash");
|
||||
addError(new ParamError(getTableName(), "mysql error by insert", ex.displayText().data()));
|
||||
addError(new ParamError(getTableName(), "data set: ", toString().data()));
|
||||
unlock();
|
||||
}
|
||||
//printf("data valid: %s\n", toString().data());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
std::string mEmail;
|
||||
|
||||
@ -45,7 +45,7 @@ namespace model {
|
||||
// specific db operation
|
||||
size_t updatePrivkey();
|
||||
size_t updatePublickey();
|
||||
|
||||
size_t updatePrivkeyAndPasswordHash();
|
||||
|
||||
// default getter unlocked
|
||||
inline const std::string& getEmail() const { return mEmail; }
|
||||
@ -56,8 +56,8 @@ namespace model {
|
||||
inline const unsigned char* getPublicKey() const { if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); }
|
||||
std::string getPublicKeyHex() const;
|
||||
|
||||
inline bool existPrivateKeyCrypted() const { return !mPrivateKey.isNull(); }
|
||||
inline const std::vector<unsigned char>& getPrivateKeyCrypted() const { return mPrivateKey.value().content(); }
|
||||
inline bool hasPrivateKeyEncrypted() const { return !mPrivateKey.isNull(); }
|
||||
inline const std::vector<unsigned char>& getPrivateKeyEncrypted() const { return mPrivateKey.value().content(); }
|
||||
inline bool isEmailChecked() const { return mEmailChecked; }
|
||||
inline const std::string& getLanguageKey() const { return mLanguageKey; }
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
#include "../SingletonManager/SingletonTaskObserver.h"
|
||||
#include "../SingletonManager/ErrorManager.h"
|
||||
|
||||
#include "../lib/Profiler.h"
|
||||
|
||||
AuthenticatedEncryptionCreateKeyTask::AuthenticatedEncryptionCreateKeyTask(Poco::AutoPtr<controller::User> user, const std::string& passwd)
|
||||
: UniLib::controller::CPUTask(ServerConfig::g_CryptoCPUScheduler), mUser(user), mPassword(passwd)
|
||||
{
|
||||
@ -20,6 +22,7 @@ int AuthenticatedEncryptionCreateKeyTask::run()
|
||||
auto em = ErrorManager::getInstance();
|
||||
const static char* function_name = "AuthenticatedEncryptionCreateKeyTask::run";
|
||||
auto authenticated_encryption = new AuthenticatedEncryption;
|
||||
Profiler timeUsed;
|
||||
if (AuthenticatedEncryption::AUTH_ENCRYPT_OK != authenticated_encryption->createKey(mUser->getModel()->getEmail(), mPassword)) {
|
||||
em->addError(new Error(function_name, "error creating key"));
|
||||
em->addError(new ParamError(function_name, "for email", mUser->getModel()->getEmail()));
|
||||
@ -27,7 +30,10 @@ int AuthenticatedEncryptionCreateKeyTask::run()
|
||||
em->sendErrorsAsEmail();
|
||||
return -1;
|
||||
}
|
||||
printf("create password time: %s\n", timeUsed.string().data());
|
||||
timeUsed.reset();
|
||||
mUser->setPassword(authenticated_encryption);
|
||||
printf("set password time: %s\n", timeUsed.string().data());
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -89,7 +89,7 @@ enum PageState
|
||||
<li><%= userModel->getEmail() %></li>
|
||||
<li>Public Key: <%= userModel->getPublicKeyHex() %></li>
|
||||
<li>E-Mail überprüft: <%= std::to_string(userModel->isEmailChecked()) %></li>
|
||||
<li>Private Key verschlüsselt: <%= std::to_string(userModel->existPrivateKeyCrypted()) %></li>
|
||||
<li>Private Key verschlüsselt: <%= std::to_string(userModel->hasPrivateKeyEncrypted()) %></li>
|
||||
<li>Passwort gesetzt: <%= std::to_string(userModel->getPasswordHashed() != 0) %></li>
|
||||
</ul>
|
||||
<% } %>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user