From 7fb09a81632de6066e55def20308d6e61cadbc48 Mon Sep 17 00:00:00 2001
From: Matthieu Gallien <matthieu_gallien@yahoo.fr>
Date: Wed, 19 May 2021 15:36:47 +0200
Subject: [PATCH] check e2ee public key against private one

should ensure we have matching private/public keys

Signed-off-by: Matthieu Gallien <matthieu_gallien@yahoo.fr>
---
 src/libsync/clientsideencryption.cpp | 30 +++++++++++++++++++++++++++-
 src/libsync/clientsideencryption.h   |  1 +
 2 files changed, 30 insertions(+), 1 deletion(-)

--- a/src/libsync/clientsideencryption.cpp
+++ b/src/libsync/clientsideencryption.cpp
@@ -16,6 +16,7 @@
 
 #include <map>
 #include <string>
+#include <algorithm>
 
 #include <cstdio>
 
@@ -32,6 +33,7 @@
 #include <QIODevice>
 #include <QUuid>
 #include <QScopeGuard>
+#include <QRandomGenerator>
 
 #include <qt5keychain/keychain.h>
 #include "common/utility.h"
@@ -797,6 +799,32 @@ void ClientSideEncryption::fetchFromKeyC
     job->start();
 }
 
+ bool ClientSideEncryption::checkPublicKeyValidity() const
+ {
+     QByteArray data = EncryptionHelper::generateRandom(64);
+
+     Bio publicKeyBio;
+     QByteArray publicKeyPem = _account->e2e()->_publicKey.toPem();
+     BIO_write(publicKeyBio, publicKeyPem.constData(), publicKeyPem.size());
+     auto publicKey = PKey::readPublicKey(publicKeyBio);
+
+     auto encryptedData = EncryptionHelper::encryptStringAsymmetric(publicKey, data.toBase64());
+
+     Bio privateKeyBio;
+     QByteArray privateKeyPem = _account->e2e()->_privateKey;
+     BIO_write(privateKeyBio, privateKeyPem.constData(), privateKeyPem.size());
+     auto key = PKey::readPrivateKey(privateKeyBio);
+
+     QByteArray decryptResult = QByteArray::fromBase64(EncryptionHelper::decryptStringAsymmetric( key, QByteArray::fromBase64(encryptedData)));
+
+     if (data != decryptResult) {
+         qCInfo(lcCse()) << "invalid private key";
+         return false;
+     }
+
+     return true;
+ }
+
 void ClientSideEncryption::publicKeyFetched(Job *incoming) {
     auto *readJob = static_cast<ReadPasswordJob *>(incoming);
 
@@ -1183,7 +1211,7 @@ void ClientSideEncryption::decryptPrivat
 
             qCInfo(lcCse()) << "Private key: " << _privateKey;
 
-            if (!_privateKey.isNull()) {
+            if (!_privateKey.isNull() && checkPublicKeyValidity()) {
                 writePrivateKey();
                 writeCertificate();
                 writeMnemonic();
--- a/src/libsync/clientsideencryption.h
+++ b/src/libsync/clientsideencryption.h
@@ -118,6 +118,7 @@ private:
 
     void fetchFromKeyChain();
 
+    bool checkPublicKeyValidity() const;
     void writePrivateKey();
     void writeCertificate();
     void writeMnemonic();
