From b8e8cad2574d513d43c5d0b57e6a09e098537454 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 20 Jan 2017 09:23:00 +0100 Subject: [PATCH 1/7] increased time for session test --- src/test/java/me/figo/SessionTest.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/test/java/me/figo/SessionTest.java b/src/test/java/me/figo/SessionTest.java index b2d2bb8..ef02a10 100644 --- a/src/test/java/me/figo/SessionTest.java +++ b/src/test/java/me/figo/SessionTest.java @@ -35,6 +35,7 @@ import org.junit.Test; import me.figo.internal.FakeTrustManager; +import me.figo.internal.FigoTrustManager; import me.figo.models.Account; import me.figo.models.Notification; import me.figo.models.Payment; @@ -50,7 +51,10 @@ public class SessionTest { @Before public void setUp() throws Exception { - sut = new FigoSession("ASHWLIkouP2O6_bgA2wWReRhletgWKHYjLqDaqb0LFfamim9RjexTo22ujRIP_cjLiRiSyQXyt2kM1eXU2XLFZQ0Hro15HikJQT_eNeT_9XQ"); + sut = new FigoSession( + "ASHWLIkouP2O6_bgA2wWReRhletgWKHYjLqDaqb0LFfamim9RjexTo22ujRIP_cjLiRiSyQXyt2kM1eXU2XLFZQ0Hro15HikJQT_eNeT_9XQ", + 30000); + FigoTrustManager.addTrustedFingerprint("DBE2E9158FC9903084FE36CAA61138D85A205D93"); } @Test @@ -140,7 +144,7 @@ public void testGetErrorMessage() throws IOException { fail(acc.getName()); } catch(FigoException e) { - assertEquals("Entry not found.", e.getErrorMessage()); + assertEquals("Entry not found.", e.getErrorMessage()); assertEquals(null, e.getErrorDescription()); } } From 5cc1f9b062a4d196fbc6c1bce25677464b855b85 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 30 Jan 2017 16:46:45 +0100 Subject: [PATCH 2/7] static access --- src/main/java/me/figo/internal/FigoTrustManager.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/figo/internal/FigoTrustManager.java b/src/main/java/me/figo/internal/FigoTrustManager.java index fa0c1fd..de41b5c 100644 --- a/src/main/java/me/figo/internal/FigoTrustManager.java +++ b/src/main/java/me/figo/internal/FigoTrustManager.java @@ -32,6 +32,7 @@ import java.util.List; import javax.net.ssl.X509TrustManager; + import org.apache.commons.codec.binary.Hex; public class FigoTrustManager implements X509TrustManager { @@ -71,8 +72,9 @@ public void checkServerTrusted(X509Certificate[] certs, String authType) throws throw new CertificateException("No certificate found"); } else { String thumbprint = getThumbPrint(certs[0]); - if (!VALID_FINGERPRINTS.contains(thumbprint)) + if (!VALID_FINGERPRINTS.contains(thumbprint) && !getFingerprintsFromEnv().contains(thumbprint)) { throw new CertificateException(); + } } } @@ -89,4 +91,9 @@ private static String getThumbPrint(X509Certificate cert) { return ""; } } + + private static List getFingerprintsFromEnv() { + String fingerprintList = System.getenv("FIGO_API_FINGERPRINTS"); + return Arrays.asList(fingerprintList.split(":")); + } } From a3d381c28287b7bbb07d8927b16f60667d526536 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 30 Jan 2017 16:47:54 +0100 Subject: [PATCH 3/7] use constant --- src/main/java/me/figo/FigoApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/figo/FigoApi.java b/src/main/java/me/figo/FigoApi.java index 85dd4f3..e9a0299 100644 --- a/src/main/java/me/figo/FigoApi.java +++ b/src/main/java/me/figo/FigoApi.java @@ -80,7 +80,7 @@ public FigoApi(String authorization, int timeout) { this.apiEndpoint = endpointEnv; } else { - this.apiEndpoint = "https://api.figo.me"; + this.apiEndpoint = API_FIGO_LIVE; } } From a7132dad3938b9073a4d2a525360581f7bef1a6e Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 30 Jan 2017 16:49:00 +0100 Subject: [PATCH 4/7] version bump from master --- README.md | 7 ++++++- pom.xml | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8453b88..1966571 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Simply add to your pom.xml: me.figo sdk - 1.4.1 + 1.4.5 ``` @@ -56,6 +56,11 @@ session.setProxy(proxy); // now do your API calls ``` +You can add valid SSL fingerprints by adding them to the `FIGO_API_FINGERPRINTS` environment variable. Fingerprints +need to be added in HEX format without column delimiters. A column delimiter is used to indicate the next element in +the list of fingerprints. + + To disable the SSL certificate pinning (not recommended) do the following: ```java // first create the FigoSession object diff --git a/pom.xml b/pom.xml index 8452b3e..87dc019 100755 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ me.figo sdk - 1.4.3 + 1.4.5 jar Figo Java SDK From 584042b0436df45007b0867c08a490cac29134be Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 1 Feb 2017 23:29:34 +0100 Subject: [PATCH 5/7] included pull request #33 Force usage of TLSv1.2 protocol for HTTPS connections --- src/main/java/me/figo/FigoApi.java | 6 +- .../me/figo/internal/FigoSocketFactory.java | 64 +++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/main/java/me/figo/internal/FigoSocketFactory.java diff --git a/src/main/java/me/figo/FigoApi.java b/src/main/java/me/figo/FigoApi.java index e9a0299..4bd2545 100644 --- a/src/main/java/me/figo/FigoApi.java +++ b/src/main/java/me/figo/FigoApi.java @@ -41,6 +41,7 @@ import com.google.gson.Gson; +import me.figo.internal.FigoSocketFactory; import me.figo.internal.FigoTrustManager; import me.figo.internal.GsonAdapter; @@ -157,8 +158,9 @@ protected void setupTrustManager(HttpURLConnection connection, X509TrustManager try { final SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, new TrustManager[] { trustManager }, new java.security.SecureRandom()); - ((HttpsURLConnection) connection).setSSLSocketFactory(sc.getSocketFactory()); - } catch (NoSuchAlgorithmException e) { + FigoSocketFactory figoSocketFactory = new FigoSocketFactory(sc.getSocketFactory()); + ((HttpsURLConnection) connection).setSSLSocketFactory(figoSocketFactory); + } catch (NoSuchAlgorithmException e) { throw new IOException("Connection setup failed", e); } catch (KeyManagementException e) { throw new IOException("Connection setup failed", e); diff --git a/src/main/java/me/figo/internal/FigoSocketFactory.java b/src/main/java/me/figo/internal/FigoSocketFactory.java new file mode 100644 index 0000000..7ccc9d5 --- /dev/null +++ b/src/main/java/me/figo/internal/FigoSocketFactory.java @@ -0,0 +1,64 @@ +package me.figo.internal; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +public class FigoSocketFactory extends SSLSocketFactory { + + private static final String[] ENABLED_PROTOCOLS = { "TLSv1.2" }; + + private SSLSocketFactory isf; + + public FigoSocketFactory(SSLSocketFactory factory) { + isf = factory; + } + + @Override + public String[] getDefaultCipherSuites() { + return isf.getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return isf.getSupportedCipherSuites(); + } + + @Override + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { + return enableProtocols(isf.createSocket(socket, host, port, autoClose)); + } + + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + return enableProtocols(isf.createSocket(host, port)); + } + + @Override + public Socket createSocket(String remoteHost, int remotePort, InetAddress localHost, int localPort) + throws IOException, UnknownHostException { + return enableProtocols(isf.createSocket(remoteHost, remotePort, localHost, localPort)); + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + return enableProtocols(isf.createSocket(host, port)); + } + + @Override + public Socket createSocket(InetAddress remoteHost, int remotePort, InetAddress localHost, int localPort) + throws IOException { + return enableProtocols(isf.createSocket(remoteHost, remotePort, localHost, localPort)); + } + + private Socket enableProtocols(Socket socket) { + if (socket != null && socket instanceof SSLSocket) { + ((SSLSocket) socket).setEnabledProtocols(ENABLED_PROTOCOLS); + } + return socket; + } +} From 043202cebdca087baeb6951676dbfba6c1c9cb6a Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 17 Feb 2017 11:47:46 +0100 Subject: [PATCH 6/7] upgraded from SHA1 to SHA256 --- .../java/me/figo/internal/FigoTrustManager.java | 16 +++++++++------- src/test/java/me/figo/SessionTest.java | 8 +++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/me/figo/internal/FigoTrustManager.java b/src/main/java/me/figo/internal/FigoTrustManager.java index de41b5c..73c3232 100644 --- a/src/main/java/me/figo/internal/FigoTrustManager.java +++ b/src/main/java/me/figo/internal/FigoTrustManager.java @@ -38,11 +38,10 @@ public class FigoTrustManager implements X509TrustManager { private static final List VALID_FINGERPRINTS = new ArrayList(Arrays.asList( - "38AE4A326F16EA1581338BB0D8E4A635E727F107", - "DBE2E9158FC9903084FE36CAA61138D85A205D93")); + "070F14AEB94AFB3DF800E82B69A8515CEED2F5B1BA897BEF6432458F61CF9E33")); /** - * @return the list of trusted certificate fingerprints using SHA1 + * @return the list of trusted certificate fingerprints using SHA256 */ public static List getTrustedFingerprints() { return VALID_FINGERPRINTS; @@ -51,7 +50,7 @@ public static List getTrustedFingerprints() { /** * Add a fingerprint to the trusted list, e.g. when using a custom figo deployment. * - * @param fingerprint the SHA1 hash of the SSL certificate in upper case + * @param fingerprint the SHA256 hash of the SSL certificate in upper case */ public static void addTrustedFingerprint(String fingerprint) { VALID_FINGERPRINTS.add(fingerprint); @@ -73,14 +72,14 @@ public void checkServerTrusted(X509Certificate[] certs, String authType) throws } else { String thumbprint = getThumbPrint(certs[0]); if (!VALID_FINGERPRINTS.contains(thumbprint) && !getFingerprintsFromEnv().contains(thumbprint)) { - throw new CertificateException(); + throw new CertificateException("No valid certificate found"); } } } private static String getThumbPrint(X509Certificate cert) { try { - MessageDigest md = MessageDigest.getInstance("SHA-1"); + MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] der = cert.getEncoded(); md.update(der); byte[] digest = md.digest(); @@ -94,6 +93,9 @@ private static String getThumbPrint(X509Certificate cert) { private static List getFingerprintsFromEnv() { String fingerprintList = System.getenv("FIGO_API_FINGERPRINTS"); - return Arrays.asList(fingerprintList.split(":")); + if(fingerprintList!=null) + return Arrays.asList(fingerprintList.split(":")); + else + return new ArrayList<>(); } } diff --git a/src/test/java/me/figo/SessionTest.java b/src/test/java/me/figo/SessionTest.java index ef02a10..6aa9665 100644 --- a/src/test/java/me/figo/SessionTest.java +++ b/src/test/java/me/figo/SessionTest.java @@ -31,11 +31,7 @@ import java.util.HashMap; import java.util.List; -import org.junit.Before; -import org.junit.Test; - import me.figo.internal.FakeTrustManager; -import me.figo.internal.FigoTrustManager; import me.figo.models.Account; import me.figo.models.Notification; import me.figo.models.Payment; @@ -45,6 +41,9 @@ import me.figo.models.Transaction; import me.figo.models.User; +import org.junit.Before; +import org.junit.Test; + public class SessionTest { FigoSession sut = null; @@ -54,7 +53,6 @@ public void setUp() throws Exception { sut = new FigoSession( "ASHWLIkouP2O6_bgA2wWReRhletgWKHYjLqDaqb0LFfamim9RjexTo22ujRIP_cjLiRiSyQXyt2kM1eXU2XLFZQ0Hro15HikJQT_eNeT_9XQ", 30000); - FigoTrustManager.addTrustedFingerprint("DBE2E9158FC9903084FE36CAA61138D85A205D93"); } @Test From 8638a7d53e253a79c82da76361e05430a949e214 Mon Sep 17 00:00:00 2001 From: Berend Kapelle Date: Fri, 17 Feb 2017 14:01:21 +0100 Subject: [PATCH 7/7] message for fingerprint mismatch clarifed, staging fingerprint added to readme --- README.md | 3 +++ src/main/java/me/figo/internal/FigoTrustManager.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1966571..9f4d19a 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,9 @@ session.setTrustManager(trustManager); // now do your API calls ``` +To connect to the staging system of figo, you need to set the `FIGO_API_FINGERPRINTS` environment variable with the staging SHA256 fingerprint (`D0039EF08FBD48678671CE9DA554248163D7D94DEDF16A55F052C70AAB7BB89D`) + + A more detailed documentation of the figo connect API can be found at http://docs.figo.io. Demos diff --git a/src/main/java/me/figo/internal/FigoTrustManager.java b/src/main/java/me/figo/internal/FigoTrustManager.java index 73c3232..95be89b 100644 --- a/src/main/java/me/figo/internal/FigoTrustManager.java +++ b/src/main/java/me/figo/internal/FigoTrustManager.java @@ -72,7 +72,7 @@ public void checkServerTrusted(X509Certificate[] certs, String authType) throws } else { String thumbprint = getThumbPrint(certs[0]); if (!VALID_FINGERPRINTS.contains(thumbprint) && !getFingerprintsFromEnv().contains(thumbprint)) { - throw new CertificateException("No valid certificate found"); + throw new CertificateException("Fingerprint does not match certificate"); } } }