summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2024-01-25 03:01:21 +0100
committercyBerta <cyberta@riseup.net>2024-01-25 03:01:21 +0100
commitb85dc1b2ea68ab7ca7e11ab545bb88f4dbb59bdb (patch)
treef637bad97a571e32e69c27b173e02e0ee655fa2b
parent23278cefe308043228c9da9b4937d27888146206 (diff)
fix VpnCertificateValidatorTest, extract CertificateHelper (returns a fingerprint for a x509 cert) from ConfigHelper
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java64
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java2
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java21
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java14
4 files changed, 76 insertions, 25 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java
new file mode 100644
index 00000000..11202734
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java
@@ -0,0 +1,64 @@
+package se.leap.bitmaskclient.base.utils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+
+import de.blinkt.openvpn.core.NativeUtils;
+
+public class CertificateHelper {
+
+ public interface CertificateHelperInterface {
+ String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException;
+
+ }
+
+ public static class DefaultCertificateHelper implements CertificateHelperInterface {
+
+ public String byteArrayToHex(byte[] input) {
+ int readBytes = input.length;
+ StringBuffer hexData = new StringBuffer();
+ int onebyte;
+ for (int i = 0; i < readBytes; i++) {
+ onebyte = ((0x000000ff & input[i]) | 0xffffff00);
+ hexData.append(Integer.toHexString(onebyte).substring(6));
+ }
+ return hexData.toString();
+ }
+
+ /**
+ * Calculates the hexadecimal representation of a sha256/sha1 fingerprint of a certificate
+ *
+ * @param certificate
+ * @param encoding
+ * @return
+ * @throws NoSuchAlgorithmException
+ * @throws CertificateEncodingException
+ */
+ @Override
+ public String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException {
+ byte[] byteArray = MessageDigest.getInstance(encoding).digest(certificate.getEncoded());
+ return byteArrayToHex(byteArray);
+ }
+ }
+
+ private static CertificateHelperInterface instance = new DefaultCertificateHelper();
+
+ @VisibleForTesting
+ public CertificateHelper(CertificateHelperInterface helperInterface) {
+ if (!NativeUtils.isUnitTest()) {
+ throw new IllegalStateException("CertificateHelper injected with CertificateHelperInterface outside of an unit test");
+ }
+ instance = helperInterface;
+ }
+
+ @NonNull
+ public static String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException {
+ return instance.getFingerprintFromCertificate(certificate, encoding);
+ }
+
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java
index 08067d38..05c5448a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java
@@ -47,7 +47,7 @@ import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP;
import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP;
import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString;
import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.getFingerprintFromCertificate;
+import static se.leap.bitmaskclient.base.utils.CertificateHelper.getFingerprintFromCertificate;
import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider;
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
index 1cb47f43..a951f144 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
@@ -2,25 +2,20 @@ package se.leap.bitmaskclient.eip;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
import java.util.Calendar;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
+import se.leap.bitmaskclient.base.utils.CertificateHelper;
import se.leap.bitmaskclient.testutils.TestCalendarProvider;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockConfigHelper;
+import static se.leap.bitmaskclient.testutils.MockHelper.mockCertificateHelper;
import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ConfigHelper.class})
public class VpnCertificateValidatorTest {
@Before
@@ -31,7 +26,7 @@ public class VpnCertificateValidatorTest {
public void test_isValid() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
Calendar c = new Calendar.Builder().setDate(2018, 1, 1).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertTrue( validator.isValid());
@@ -41,7 +36,7 @@ public class VpnCertificateValidatorTest {
public void test_isValid_lessThan1day_returnFalse() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 28).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertFalse( validator.isValid());
@@ -51,7 +46,7 @@ public class VpnCertificateValidatorTest {
public void test_isValid_multipleCerts_failIfOneExpires() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 28).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertFalse(validator.isValid());
@@ -61,7 +56,7 @@ public class VpnCertificateValidatorTest {
public void test_isValid_multipleCerts_allValid() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 27).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertTrue(validator.isValid());
@@ -71,7 +66,7 @@ public class VpnCertificateValidatorTest {
public void test_shouldBeUpdated_lessThan8days_returnTrue() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 21).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertTrue(validator.shouldBeUpdated());
@@ -81,7 +76,7 @@ public class VpnCertificateValidatorTest {
public void test_shouldBeUpdated_moreThan8days_returnFalse() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 20).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertFalse(validator.shouldBeUpdated());
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
index daa67282..869e3190 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
@@ -50,7 +50,6 @@ import java.math.BigInteger;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.Arrays;
@@ -69,7 +68,7 @@ import okhttp3.OkHttpClient;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.base.models.Provider;
import se.leap.bitmaskclient.base.models.ProviderObservable;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
+import se.leap.bitmaskclient.base.utils.CertificateHelper;
import se.leap.bitmaskclient.base.utils.FileHelper;
import se.leap.bitmaskclient.base.utils.InputStreamHelper;
import se.leap.bitmaskclient.base.utils.ObfsVpnHelper;
@@ -473,15 +472,8 @@ public class MockHelper {
});
}
- public static void mockConfigHelper(String mockedFingerprint) throws CertificateEncodingException, NoSuchAlgorithmException {
- mockStatic(ConfigHelper.class);
- when(ConfigHelper.getFingerprintFromCertificate(any(X509Certificate.class), anyString())).thenReturn(mockedFingerprint);
- when(ConfigHelper.checkErroneousDownload(anyString())).thenCallRealMethod();
- when(ConfigHelper.parseX509CertificatesFromString(anyString())).thenCallRealMethod();
- when(ConfigHelper.getProviderFormattedString(any(Resources.class), anyInt())).thenCallRealMethod();
- when(ConfigHelper.isIPv4(anyString())).thenCallRealMethod();
- when(ConfigHelper.isDefaultBitmask()).thenReturn(true);
- when(ConfigHelper.getDomainFromMainURL(anyString())).thenCallRealMethod();
+ public static CertificateHelper mockCertificateHelper(String mockedFingerprint) {
+ return new CertificateHelper((certificate, encoding) -> mockedFingerprint);
}
public static void mockPreferenceHelper(final Provider providerFromPrefs) {