aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-05-16 09:47:31 +0200
committerdec05eba <dec05eba@protonmail.com>2020-08-18 23:25:46 +0200
commit97c9ff702f002925dcd33869d0e22eda18390e2e (patch)
tree88096d36e2b20d63ff3e5add42a7053c5b85c8a5 /src
parent2326b2da65624e921ee79b56324c59de4a885fde (diff)
Store node encryption key with user data, fix encryption bug when using additional data
Diffstat (limited to 'src')
-rw-r--r--src/Database.cpp12
-rw-r--r--src/DatabaseStorage.cpp44
-rw-r--r--src/Encryption.cpp4
3 files changed, 34 insertions, 26 deletions
diff --git a/src/Database.cpp b/src/Database.cpp
index fff74f4..df11b3c 100644
--- a/src/Database.cpp
+++ b/src/Database.cpp
@@ -90,10 +90,10 @@ namespace odhtdb
}
Database::Database(const char *bootstrapNodeAddr, u16 port, const boost::filesystem::path &storageDir, DatabaseCallbackFuncs callbackFuncs) :
+ databaseStorage(this, storageDir),
onCreateNodeCallbackFunc(callbackFuncs.createNodeCallbackFunc),
onAddNodeCallbackFunc(callbackFuncs.addNodeCallbackFunc),
onAddUserCallbackFunc(callbackFuncs.addUserCallbackFunc),
- databaseStorage(this, storageDir),
shuttingDown(false)
{
node.run(port , {
@@ -443,7 +443,7 @@ namespace odhtdb
serializer.add(newActionCounter);
DataView encryptionKey(nodeInfo.getNodeEncryptionKey()->data, ENCRYPTION_KEY_BYTE_SIZE);
- Encryption encryptedBody(dataToAdd, DataView(), encryptionKey);
+ Encryption encryptedBody(dataToAdd, encryptionKey);
OwnedMemory requestData = combine(serializer, encryptedBody);
string signedRequestData = userToPerformActionWith.getPrivateKey().sign(requestData.getView());
OwnedMemory stagedAddObject = combine(userToPerformActionWith.getPublicKey(), signedRequestData);
@@ -643,14 +643,14 @@ namespace odhtdb
return databaseStorage.storeUserWithoutNodes(username, password);
}
- void Database::storeUserPasswordEncrypted(const Hash &nodeHash, const string &username, const string &password, const Signature::KeyPair &keyPair)
+ void Database::storeNodeInfoForUserEncrypted(const DatabaseNode &nodeInfo, const string &username, const string &password, const Signature::KeyPair &keyPair)
{
- return databaseStorage.storeUserPasswordEncrypted(nodeHash, username, password, keyPair);
+ return databaseStorage.storeNodeInfoForUserEncrypted(nodeInfo, username, password, keyPair);
}
- MapHash<Signature::KeyPair> Database::getStoredUserNodeDataDecrypted(const string &username, const string &password)
+ MapHash<StoredNodeInfo> Database::getStoredNodeUserInfoDecrypted(const string &username, const string &password) const
{
- return databaseStorage.getStoredUserNodeDataDecrypted(username, password);
+ return databaseStorage.getStoredNodeUserInfoDecrypted(username, password);
}
vector<OwnedMemory> Database::getUserGroups(const Hash &nodeHash, const Signature::PublicKey &userPublicKey) const
diff --git a/src/DatabaseStorage.cpp b/src/DatabaseStorage.cpp
index 7b316f7..016c498 100644
--- a/src/DatabaseStorage.cpp
+++ b/src/DatabaseStorage.cpp
@@ -117,7 +117,7 @@ namespace odhtdb
"CREATE TABLE IF NOT EXISTS NodeUserActionGap(id INTEGER PRIMARY KEY, nodeUserId INTEGER NOT NULL, start INTEGER NOT NULL, range INTEGER NOT NULL, FOREIGN KEY(nodeUserId) REFERENCES NodeUser(id));"
"CREATE TABLE IF NOT EXISTS NodeEncryptedUser(id INTEGER PRIMARY KEY, username BLOB UNIQUE NOT NULL, nonce BLOB NOT NULL, encryptedPassword BLOB NOT NULL);"
- "CREATE TABLE IF NOT EXISTS NodeEncryptedUserData(node INTEGER NOT NULL, usernameId INTEGER NOT NULL, userPublicKey BLOB NOT NULL, nonce BLOB NOT NULL, userPrivateKeyEncrypted BLOB NOT NULL, FOREIGN KEY(usernameId) REFERENCES NodeEncryptedUser(id), FOREIGN KEY(node, userPublicKey) REFERENCES NodeUser(node, publicKey));"
+ "CREATE TABLE IF NOT EXISTS NodeEncryptedUserData(node INTEGER NOT NULL, usernameId INTEGER NOT NULL, userPublicKey BLOB NOT NULL, nonce BLOB NOT NULL, nodeAndUserPrivateKeyEncrypted BLOB NOT NULL, FOREIGN KEY(usernameId) REFERENCES NodeEncryptedUser(id), FOREIGN KEY(node, userPublicKey) REFERENCES NodeUser(node, publicKey));"
"CREATE UNIQUE INDEX IF NOT EXISTS UniqueUserInNode ON NodeUser(node, publicKey);"
"CREATE UNIQUE INDEX IF NOT EXISTS UniqueUserGroupAssoc ON NodeUserGroupAssoc(node, userPublicKey, groupId);"
@@ -851,12 +851,12 @@ namespace odhtdb
DataView usernameView((void*)username.data(), username.size());
DataView saltView((void*)passwordSalt, PASSWORD_SALT_LEN);
- Encryption encryptedPassword(saltView, {}, hashedPasswordView);
+ Encryption encryptedPassword(saltView, hashedPasswordView);
SqlExec addUserSql(sqliteDb, "INSERT INTO NodeEncryptedUser(username, nonce, encryptedPassword) VALUES(?, ?, ?)");
addUserSql.execWithArgs({ usernameView, encryptedPassword.getNonce(), encryptedPassword.getCipherText() });
}
- i64 DatabaseStorage::getStoredUserId(const string &username, const DataView &hashedPassword)
+ i64 DatabaseStorage::getStoredUserId(const string &username, const DataView &hashedPassword) const
{
DataView usernameView((void*)username.data(), username.size());
SqlQuery userQuery(sqliteDb, "SELECT id, nonce, encryptedPassword FROM NodeEncryptedUser WHERE username = ?", { usernameView });
@@ -882,12 +882,16 @@ namespace odhtdb
}
}
- void DatabaseStorage::storeUserPasswordEncrypted(const Hash &nodeHash, const string &username, const string &password, const Signature::KeyPair &keyPair)
+ void DatabaseStorage::storeNodeInfoForUserEncrypted(const DatabaseNode &nodeInfo, const string &username, const string &password, const Signature::KeyPair &keyPair)
{
OwnedMemory hashedPassword = hashPassword(DataView((void*)password.data(), password.size()), DataView((void*)passwordSalt, PASSWORD_SALT_LEN));
DataView hashedPasswordView(hashedPassword.data, hashedPassword.size);
DataView privateKeyView((void*)keyPair.getPrivateKey().getData(), PRIVATE_KEY_NUM_BYTES);
- Encryption encryptedPrivateKey(privateKeyView, {}, hashedPasswordView);
+
+ sibs::SafeSerializer serializer;
+ serializer.add((const u8*)privateKeyView.data, privateKeyView.size);
+ serializer.add((const u8*)nodeInfo.getNodeEncryptionKey()->data, nodeInfo.getNodeEncryptionKey()->size);
+ Encryption encryptedNodeUserPrivateKey(DataView(serializer.getBuffer().data(), serializer.getBuffer().size()), hashedPasswordView);
SqlTransaction transaction(sqliteDb);
DataView usernameView((void*)username.data(), username.size());
@@ -900,7 +904,7 @@ namespace odhtdb
catch(DatabaseStorageNoSuchStoredUser &e)
{
DataView saltView((void*)passwordSalt, PASSWORD_SALT_LEN);
- Encryption encryptedPassword(saltView, {}, hashedPasswordView);
+ Encryption encryptedPassword(saltView, hashedPasswordView);
SqlExec addUserSql(sqliteDb, "INSERT INTO NodeEncryptedUser(username, nonce, encryptedPassword) VALUES(?, ?, ?)");
addUserSql.execWithArgs({ usernameView, encryptedPassword.getNonce(), encryptedPassword.getCipherText() });
@@ -912,25 +916,25 @@ namespace odhtdb
encryptedUserRowId = userQuery.getInt64(0);
}
- SqlExec sqlExec(sqliteDb, "INSERT INTO NodeEncryptedUserData(node, usernameId, userPublicKey, nonce, userPrivateKeyEncrypted) VALUES(?, ?, ?, ?, ?)");
+ SqlExec sqlExec(sqliteDb, "INSERT INTO NodeEncryptedUserData(node, usernameId, userPublicKey, nonce, nodeAndUserPrivateKeyEncrypted) VALUES(?, ?, ?, ?, ?)");
sqlExec.execWithArgs({
- DataView(nodeHash.getData(), nodeHash.getSize()),
+ DataView(nodeInfo.getRequestHash()->getData(), nodeInfo.getRequestHash()->getSize()),
encryptedUserRowId,
DataView((void*)keyPair.getPublicKey().getData(), PUBLIC_KEY_NUM_BYTES),
- encryptedPrivateKey.getNonce(),
- encryptedPrivateKey.getCipherText()
+ encryptedNodeUserPrivateKey.getNonce(),
+ encryptedNodeUserPrivateKey.getCipherText()
});
transaction.commit();
}
- MapHash<Signature::KeyPair> DatabaseStorage::getStoredUserNodeDataDecrypted(const string &username, const string &password)
+ MapHash<StoredNodeInfo> DatabaseStorage::getStoredNodeUserInfoDecrypted(const string &username, const string &password) const
{
OwnedMemory hashedPassword = hashPassword(DataView((void*)password.data(), password.size()), DataView((void*)passwordSalt, PASSWORD_SALT_LEN));
DataView hashedPasswordView(hashedPassword.data, hashedPassword.size);
i64 encryptedUserRowId = getStoredUserId(username, hashedPasswordView);
- MapHash<Signature::KeyPair> result;
- SqlQuery query(sqliteDb, "SELECT node, userPublicKey, nonce, userPrivateKeyEncrypted FROM NodeEncryptedUserData WHERE usernameId = ?", { encryptedUserRowId });
+ MapHash<StoredNodeInfo> result;
+ SqlQuery query(sqliteDb, "SELECT node, userPublicKey, nonce, nodeAndUserPrivateKeyEncrypted FROM NodeEncryptedUserData WHERE usernameId = ?", { encryptedUserRowId });
while(query.next())
{
Hash nodeHash;
@@ -940,14 +944,18 @@ namespace odhtdb
const DataView storedUserPublicKey = query.getBlob(1);
Signature::PublicKey userPublicKey((const char*)storedUserPublicKey.data, storedUserPublicKey.size);
const DataView storedNonce = query.getBlob(2);
- const DataView storedPrivateKeyEncrypted = query.getBlob(3);
+ const DataView storedNodeUserPrivateKeyEncrypted = query.getBlob(3);
try
{
// TODO: We can bypass decrypting several times by storing several nodes private key user the same field (as a blob)
- Decryption decryptedStoredPrivateKey(storedPrivateKeyEncrypted, storedNonce, hashedPasswordView);
- Signature::PrivateKey userPrivateKey((const char*)decryptedStoredPrivateKey.getDecryptedText().data, decryptedStoredPrivateKey.getDecryptedText().size);
- Signature::KeyPair keyPair(userPublicKey, userPrivateKey);
- result[nodeHash] = keyPair;
+ Decryption decryptedStoredNodeUserPrivateKey(storedNodeUserPrivateKeyEncrypted, storedNonce, hashedPasswordView);
+ if(decryptedStoredNodeUserPrivateKey.getDecryptedText().size != PRIVATE_KEY_NUM_BYTES + ENCRYPTION_KEY_BYTE_SIZE)
+ throw DatabaseStorageException("Encrypted data size is of unexpected size");
+ Signature::PrivateKey userPrivateKey((const char*)decryptedStoredNodeUserPrivateKey.getDecryptedText().data, PRIVATE_KEY_NUM_BYTES);
+ shared_ptr<Signature::KeyPair> keyPair = make_shared<Signature::KeyPair>(userPublicKey, userPrivateKey);
+ shared_ptr<OwnedMemory> nodeEncryptionKey = make_shared<OwnedMemory>(new u8[ENCRYPTION_KEY_BYTE_SIZE], ENCRYPTION_KEY_BYTE_SIZE);
+ memcpy(nodeEncryptionKey->data, (char*)decryptedStoredNodeUserPrivateKey.getDecryptedText().data + PRIVATE_KEY_NUM_BYTES, ENCRYPTION_KEY_BYTE_SIZE);
+ result[nodeHash] = { nodeEncryptionKey, keyPair };
}
catch(DecryptionException &e)
{
diff --git a/src/Encryption.cpp b/src/Encryption.cpp
index ff37270..d4763b8 100644
--- a/src/Encryption.cpp
+++ b/src/Encryption.cpp
@@ -7,7 +7,7 @@ namespace odhtdb
{
static_assert(ENCRYPTION_CHECKSUM_BYTE_SIZE == crypto_aead_xchacha20poly1305_ietf_ABYTES, "Encryption checksum key size has changed for some reason, oops...");
- Encryption::Encryption(const DataView &data, const DataView &additionalData, const DataView &_key)
+ Encryption::Encryption(const DataView &data, const DataView &_key)
{
cipherTextLength = crypto_aead_xchacha20poly1305_ietf_ABYTES + data.size;
cipherText = new unsigned char[cipherTextLength];
@@ -22,7 +22,7 @@ namespace odhtdb
generateKey(key);
randombytes_buf(nonce, ENCRYPTION_NONCE_BYTE_SIZE);
- if(crypto_aead_xchacha20poly1305_ietf_encrypt(cipherText, &cipherTextLength, (const unsigned char*)data.data, data.size, (const unsigned char*)additionalData.data, additionalData.size, nullptr, nonce, key) < 0)
+ if(crypto_aead_xchacha20poly1305_ietf_encrypt(cipherText, &cipherTextLength, (const unsigned char*)data.data, data.size, nullptr, 0, nullptr, nonce, key) < 0)
throw EncryptionException("Failed to encrypt data");
}