Browse Source

Merge pull request #8438 from nextcloud/checkKey

check e2e keys
Andy Scherzinger 3 years ago
parent
commit
377853190d

+ 29 - 0
src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java

@@ -52,6 +52,8 @@ import java.util.HashSet;
 import java.util.Random;
 import java.util.Random;
 import java.util.Set;
 import java.util.Set;
 
 
+import javax.crypto.BadPaddingException;
+
 import androidx.test.runner.AndroidJUnit4;
 import androidx.test.runner.AndroidJUnit4;
 
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -144,6 +146,33 @@ public class EncryptionTestIT {
         assertTrue(Arrays.equals(key1, key2));
         assertTrue(Arrays.equals(key1, key2));
     }
     }
 
 
+    @Test
+    public void encryptStringAsymmetricCorrectPublicKey() throws Exception {
+        KeyPair keyPair = EncryptionUtils.generateKeyPair();
+
+        byte[] key1 = generateKey();
+        String base64encodedKey = encodeBytesToBase64String(key1);
+
+        String encryptedString = EncryptionUtils.encryptStringAsymmetric(base64encodedKey, keyPair.getPublic());
+        String decryptedString = decryptStringAsymmetric(encryptedString, keyPair.getPrivate());
+
+        byte[] key2 = decodeStringToBase64Bytes(decryptedString);
+
+        assertTrue(Arrays.equals(key1, key2));
+    }
+
+    @Test(expected = BadPaddingException.class)
+    public void encryptStringAsymmetricWrongPublicKey() throws Exception {
+        KeyPair keyPair1 = EncryptionUtils.generateKeyPair();
+        KeyPair keyPair2 = EncryptionUtils.generateKeyPair();
+
+        byte[] key1 = generateKey();
+        String base64encodedKey = encodeBytesToBase64String(key1);
+
+        String encryptedString = EncryptionUtils.encryptStringAsymmetric(base64encodedKey, keyPair1.getPublic());
+        decryptStringAsymmetric(encryptedString, keyPair2.getPrivate());
+    }
+
     @Test
     @Test
     public void encryptStringSymmetricRandom() throws Exception {
     public void encryptStringSymmetricRandom() throws Exception {
         int max = 500;
         int max = 500;

+ 33 - 7
src/main/java/com/owncloud/android/ui/dialog/SetupEncryptionDialogFragment.java

@@ -52,6 +52,7 @@ import com.owncloud.android.utils.theme.ThemeColorUtils;
 import java.io.IOException;
 import java.io.IOException;
 import java.security.KeyPair;
 import java.security.KeyPair;
 import java.security.PrivateKey;
 import java.security.PrivateKey;
+import java.util.Arrays;
 import java.util.List;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 
 
@@ -61,6 +62,11 @@ import androidx.appcompat.app.AlertDialog;
 import androidx.core.graphics.drawable.DrawableCompat;
 import androidx.core.graphics.drawable.DrawableCompat;
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.DialogFragment;
 
 
+import static com.owncloud.android.utils.EncryptionUtils.decodeStringToBase64Bytes;
+import static com.owncloud.android.utils.EncryptionUtils.decryptStringAsymmetric;
+import static com.owncloud.android.utils.EncryptionUtils.encodeBytesToBase64String;
+import static com.owncloud.android.utils.EncryptionUtils.generateKey;
+
 /*
 /*
  *  Dialog to setup encryption
  *  Dialog to setup encryption
  */
  */
@@ -187,24 +193,43 @@ public class SetupEncryptionDialogFragment extends DialogFragment {
                                     String privateKey = task.get();
                                     String privateKey = task.get();
                                     String mnemonicUnchanged = passwordField.getText().toString();
                                     String mnemonicUnchanged = passwordField.getText().toString();
                                     String mnemonic = passwordField.getText().toString().replaceAll("\\s", "")
                                     String mnemonic = passwordField.getText().toString().replaceAll("\\s", "")
-                                            .toLowerCase(Locale.ROOT);
+                                        .toLowerCase(Locale.ROOT);
                                     String decryptedPrivateKey = EncryptionUtils.decryptPrivateKey(privateKey,
                                     String decryptedPrivateKey = EncryptionUtils.decryptPrivateKey(privateKey,
-                                            mnemonic);
+                                                                                                   mnemonic);
 
 
                                     arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
                                     arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
-                                            EncryptionUtils.PRIVATE_KEY, decryptedPrivateKey);
+                                                                                EncryptionUtils.PRIVATE_KEY, decryptedPrivateKey);
 
 
                                     dialog.dismiss();
                                     dialog.dismiss();
                                     Log_OC.d(TAG, "Private key successfully decrypted and stored");
                                     Log_OC.d(TAG, "Private key successfully decrypted and stored");
 
 
-                                    arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(), EncryptionUtils.MNEMONIC,
-                                            mnemonicUnchanged);
+                                    arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
+                                                                                EncryptionUtils.MNEMONIC,
+                                                                                mnemonicUnchanged);
+
+                                    // check if private key and public key match
+                                    String publicKey = arbitraryDataProvider.getValue(user.getAccountName(),
+                                                                                      EncryptionUtils.PUBLIC_KEY);
+
+                                    byte[] key1 = generateKey();
+                                    String base64encodedKey = encodeBytesToBase64String(key1);
+
+                                    String encryptedString = EncryptionUtils.encryptStringAsymmetric(base64encodedKey,
+                                                                                                     publicKey);
+                                    String decryptedString = decryptStringAsymmetric(encryptedString,
+                                                                                     decryptedPrivateKey);
+
+                                    byte[] key2 = decodeStringToBase64Bytes(decryptedString);
+
+                                    if (!Arrays.equals(key1, key2)) {
+                                        throw new Exception("Keys do not match");
+                                    }
 
 
                                     Intent intentExisting = new Intent();
                                     Intent intentExisting = new Intent();
                                     intentExisting.putExtra(SUCCESS, true);
                                     intentExisting.putExtra(SUCCESS, true);
                                     intentExisting.putExtra(ARG_POSITION, getArguments().getInt(ARG_POSITION));
                                     intentExisting.putExtra(ARG_POSITION, getArguments().getInt(ARG_POSITION));
                                     getTargetFragment().onActivityResult(getTargetRequestCode(),
                                     getTargetFragment().onActivityResult(getTargetRequestCode(),
-                                            SETUP_ENCRYPTION_RESULT_CODE, intentExisting);
+                                                                         SETUP_ENCRYPTION_RESULT_CODE, intentExisting);
 
 
                                 } catch (Exception e) {
                                 } catch (Exception e) {
                                     textView.setText(R.string.end_to_end_encryption_wrong_password);
                                     textView.setText(R.string.end_to_end_encryption_wrong_password);
@@ -257,7 +282,8 @@ public class SetupEncryptionDialogFragment extends DialogFragment {
                 Log_OC.d(TAG, "public key successful downloaded for " + user.getAccountName());
                 Log_OC.d(TAG, "public key successful downloaded for " + user.getAccountName());
 
 
                 String publicKeyFromServer = (String) publicKeyResult.getData().get(0);
                 String publicKeyFromServer = (String) publicKeyResult.getData().get(0);
-                arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(), EncryptionUtils.PUBLIC_KEY,
+                arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
+                                                            EncryptionUtils.PUBLIC_KEY,
                                                             publicKeyFromServer);
                                                             publicKeyFromServer);
             } else {
             } else {
                 return null;
                 return null;

+ 23 - 2
src/main/java/com/owncloud/android/utils/EncryptionUtils.java

@@ -384,7 +384,7 @@ public final class EncryptionUtils {
         Cipher cipher = Cipher.getInstance(RSA_CIPHER);
         Cipher cipher = Cipher.getInstance(RSA_CIPHER);
 
 
         String trimmedCert = cert.replace("-----BEGIN CERTIFICATE-----\n", "")
         String trimmedCert = cert.replace("-----BEGIN CERTIFICATE-----\n", "")
-                .replace("-----END CERTIFICATE-----\n", "");
+            .replace("-----END CERTIFICATE-----\n", "");
         byte[] encodedCert = trimmedCert.getBytes(StandardCharsets.UTF_8);
         byte[] encodedCert = trimmedCert.getBytes(StandardCharsets.UTF_8);
         byte[] decodedCert = org.apache.commons.codec.binary.Base64.decodeBase64(encodedCert);
         byte[] decodedCert = org.apache.commons.codec.binary.Base64.decodeBase64(encodedCert);
 
 
@@ -401,6 +401,17 @@ public final class EncryptionUtils {
         return encodeBytesToBase64String(cryptedBytes);
         return encodeBytesToBase64String(cryptedBytes);
     }
     }
 
 
+    public static String encryptStringAsymmetric(String string, PublicKey publicKey) throws NoSuchPaddingException,
+        NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        Cipher cipher = Cipher.getInstance(RSA_CIPHER);
+        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+
+        byte[] bytes = encodeStringToBase64Bytes(string);
+        byte[] cryptedBytes = cipher.doFinal(bytes);
+
+        return encodeBytesToBase64String(cryptedBytes);
+    }
+
 
 
     /**
     /**
      * Decrypt string with RSA algorithm, ECB mode, OAEPWithSHA-256AndMGF1 padding
      * Decrypt string with RSA algorithm, ECB mode, OAEPWithSHA-256AndMGF1 padding
@@ -414,7 +425,7 @@ public final class EncryptionUtils {
             throws NoSuchAlgorithmException,
             throws NoSuchAlgorithmException,
             NoSuchPaddingException, InvalidKeyException,
             NoSuchPaddingException, InvalidKeyException,
             BadPaddingException, IllegalBlockSizeException,
             BadPaddingException, IllegalBlockSizeException,
-            InvalidKeySpecException {
+        InvalidKeySpecException {
 
 
         Cipher cipher = Cipher.getInstance(RSA_CIPHER);
         Cipher cipher = Cipher.getInstance(RSA_CIPHER);
 
 
@@ -431,6 +442,16 @@ public final class EncryptionUtils {
         return decodeBase64BytesToString(encodedBytes);
         return decodeBase64BytesToString(encodedBytes);
     }
     }
 
 
+    public static String decryptStringAsymmetric(String string, PrivateKey privateKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        Cipher cipher = Cipher.getInstance(RSA_CIPHER);
+        cipher.init(Cipher.DECRYPT_MODE, privateKey);
+
+        byte[] bytes = decodeStringToBase64Bytes(string);
+        byte[] encodedBytes = cipher.doFinal(bytes);
+
+        return decodeBase64BytesToString(encodedBytes);
+    }
+
     /**
     /**
      * Encrypt string with RSA algorithm, ECB mode, OAEPWithSHA-256AndMGF1 padding Asymmetric encryption, with private
      * Encrypt string with RSA algorithm, ECB mode, OAEPWithSHA-256AndMGF1 padding Asymmetric encryption, with private
      * and public key
      * and public key