From 40d7a8b9da9faffccc388527dfd4885470b9cab6 Mon Sep 17 00:00:00 2001
From: COM8 <sauter.fabian@mailbox.org>
Date: Tue, 5 Mar 2019 16:13:39 +0100
Subject: [PATCH] Fixed the OMEMO fingerprint! #5

---
 .../Classes/Crypto/Test_CryptoUtils.cs        | 17 +++++++++++-
 XMPP_API/Classes/Crypto/CryptoUtils.cs        | 27 ++++++++++++-------
 XMPP_API/Classes/Network/XMPPAccount.cs       | 10 -------
 3 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/Component_Tests/Classes/Crypto/Test_CryptoUtils.cs b/Component_Tests/Classes/Crypto/Test_CryptoUtils.cs
index d6836dbc4..eaab68e12 100644
--- a/Component_Tests/Classes/Crypto/Test_CryptoUtils.cs
+++ b/Component_Tests/Classes/Crypto/Test_CryptoUtils.cs
@@ -1,4 +1,5 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using libsignal;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
 using System;
 using System.Linq;
 using System.Text;
@@ -123,5 +124,19 @@ public void Test_CryptoUtils_HexToByteArray()
             string saltStringHex = CryptoUtils.byteArrayToHexString(salt);
             Assert.IsTrue(saltStringHex.Equals(saltStringHexRef));
         }
+
+        [TestCategory("Crypto")]
+        [TestMethod]
+        public void Test_CryptoUtils_GenOmemoFingerprint()
+        {
+            string identKeyPairSerializedHex = "0a210511dbad7fcece74492f390f0a2a8387c543e802ab7f2176e303e28840559c41521220a082ae07fd8941536457cb2f3e4b560a87991d380f02af460b5204e46ca7b15a";
+            byte[] identKeyPairSerialized = CryptoUtils.hexStringToByteArray(identKeyPairSerializedHex);
+            IdentityKeyPair identKeyPair = new IdentityKeyPair(identKeyPairSerialized);
+
+            string outputRef = "11dbad7f cece7449 2f390f0a 2a8387c5 43e802ab 7f2176e3 03e28840 559c4152";
+            string output = CryptoUtils.genOmemoFingerprint(identKeyPair.getPublicKey());
+
+            Assert.AreEqual(outputRef, output);
+        }
     }
 }
diff --git a/XMPP_API/Classes/Crypto/CryptoUtils.cs b/XMPP_API/Classes/Crypto/CryptoUtils.cs
index f18bc4278..3be01265b 100644
--- a/XMPP_API/Classes/Crypto/CryptoUtils.cs
+++ b/XMPP_API/Classes/Crypto/CryptoUtils.cs
@@ -1,7 +1,7 @@
 using libsignal;
+using libsignal.ecc;
 using libsignal.state;
 using libsignal.util;
-using org.whispersystems.libsignal.fingerprint;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -20,7 +20,7 @@ public static class CryptoUtils
     {
         //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\
         #region --Attributes--
-        private static readonly NumericFingerprintGenerator FINGERPRINT_GENERATOR = new NumericFingerprintGenerator(5200);
+
 
         #endregion
         //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
@@ -30,7 +30,20 @@ public static class CryptoUtils
         #endregion
         //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\
         #region --Set-, Get- Methods--
+        /// <summary>
+        /// Reads the raw key from the given ECPublicKey.
+        /// Based on: https://github.com/langboost/libsignal-protocol-pcl/blob/ef9dece1283948f89c7cc4c5825f944f77ed2c3e/signal-protocol-pcl/ecc/Curve.cs#L37
+        /// </summary>
+        /// <param name="key">The public key you want to retrieve the raw key from.</param>
+        /// <returns>Returns the raw key from the given ECPublicKey.</returns>
+        public static byte[] getRawFromECPublicKey(ECPublicKey key)
+        {
+            byte[] keySerialized = key.serialize();
+            byte[] keyRaw = new byte[32];
+            System.Buffer.BlockCopy(keySerialized, 1, keyRaw, 0, keySerialized.Length - 1);
 
+            return keyRaw;
+        }
 
         #endregion
         //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\
@@ -122,11 +135,6 @@ public static uint generateOmemoDeviceIds(IList<uint> usedDeviceIds)
             throw new InvalidOperationException("Failed to generate unique device id! " + nameof(usedDeviceIds) + ". Count = " + usedDeviceIds.Count);
         }
 
-        public static Fingerprint generateOmemoFingerprint(string accountId, IdentityKey key)
-        {
-            return FINGERPRINT_GENERATOR.createFor(accountId, key, accountId, key);
-        }
-
         public static byte[] hexStringToByteArray(string hex)
         {
             return Enumerable.Range(0, hex.Length)
@@ -150,8 +158,9 @@ public static string byteArrayToHexString(byte[] data)
         /// <returns>A hex string representing the given OMEMO identity public key. Split up in blocks of 8 characters separated by a whitespace.</returns>
         public static string genOmemoFingerprint(IdentityKey key)
         {
-            string fingerprint = byteArrayToHexString(key.serialize());
-            return Regex.Replace(fingerprint, ".{8}", "$0 ");
+            byte[] keyRaw = getRawFromECPublicKey(key.getPublicKey());
+            string fingerprint = byteArrayToHexString(keyRaw);
+            return Regex.Replace(fingerprint, ".{8}", "$0 ").TrimEnd();
         }
 
         /// <summary>
diff --git a/XMPP_API/Classes/Network/XMPPAccount.cs b/XMPP_API/Classes/Network/XMPPAccount.cs
index fb4914631..70e0e1a7e 100644
--- a/XMPP_API/Classes/Network/XMPPAccount.cs
+++ b/XMPP_API/Classes/Network/XMPPAccount.cs
@@ -3,7 +3,6 @@
 using libsignal.state;
 using libsignal.util;
 using Logging;
-using org.whispersystems.libsignal.fingerprint;
 using Shared.Classes;
 using Shared.Classes.Collections;
 using System;
@@ -176,15 +175,6 @@ public OmemoBundleInformation getOmemoBundleInformation()
             return new OmemoBundleInformation(omemoIdentityKeyPair.getPublicKey(), omemoSignedPreKeyPair.getKeyPair().getPublicKey(), omemoSignedPreKeyId, omemoSignedPreKeyPair.getSignature(), pubPreKeys);
         }
 
-        public Fingerprint getOmemoFingerprint()
-        {
-            if (omemoIdentityKeyPair != null)
-            {
-                return CryptoUtils.generateOmemoFingerprint(getIdAndDomain(), omemoIdentityKeyPair.getPublicKey());
-            }
-            return null;
-        }
-
         private void setXMPPUserProperty(XMPPUser value)
         {
             if (!(user is null))