From 2f5c1a926a0ced370100e80c196e37a785b23a06 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Thu, 20 Oct 2016 01:45:19 +0200 Subject: [PATCH] Check if supported crypto key length is > 128 (security policy adopted in Oracel JDK) --- .../util/LimitedKeyStrengthException.java | 24 ++++++++++ .../io/bitsquare/common/util/Utilities.java | 47 +++---------------- .../java/io/bitsquare/app/BitsquareApp.java | 15 ++++-- .../java/io/bitsquare/headless/Headless.java | 10 +++- .../java/io/bitsquare/monitor/Monitor.java | 10 +++- .../java/io/bitsquare/seednode/SeedNode.java | 10 +++- .../io/bitsquare/statistics/Statistics.java | 10 +++- 7 files changed, 74 insertions(+), 52 deletions(-) create mode 100644 common/src/main/java/io/bitsquare/common/util/LimitedKeyStrengthException.java diff --git a/common/src/main/java/io/bitsquare/common/util/LimitedKeyStrengthException.java b/common/src/main/java/io/bitsquare/common/util/LimitedKeyStrengthException.java new file mode 100644 index 00000000000..3a668168362 --- /dev/null +++ b/common/src/main/java/io/bitsquare/common/util/LimitedKeyStrengthException.java @@ -0,0 +1,24 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.common.util; + +public class LimitedKeyStrengthException extends Exception { + public LimitedKeyStrengthException() { + super("Default crypto policy has not been changed. Only weak keys with length 128 are allowed by the default policy."); + } +} diff --git a/common/src/main/java/io/bitsquare/common/util/Utilities.java b/common/src/main/java/io/bitsquare/common/util/Utilities.java index 3c15be69072..47fabc77404 100644 --- a/common/src/main/java/io/bitsquare/common/util/Utilities.java +++ b/common/src/main/java/io/bitsquare/common/util/Utilities.java @@ -30,15 +30,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.crypto.Cipher; import java.awt.*; import java.io.*; -import java.lang.reflect.Field; import java.net.URI; import java.net.URLConnection; -import java.security.Permission; -import java.security.PermissionCollection; +import java.security.NoSuchAlgorithmException; import java.util.Locale; -import java.util.Map; import java.util.Random; import java.util.concurrent.*; @@ -408,42 +406,11 @@ public boolean shouldSkipClass(Class clazz) { } } - // See: https://stackoverflow.com/questions/1179672/how-to-avoid-installing-unlimited-strength-jce-policy-files-when-deploying-an - public static void removeCryptographyRestrictions() { - if (!isRestrictedCryptography()) { - log.debug("Cryptography restrictions removal not needed"); - return; - } - try { - final Class jceSecurity = Class.forName("javax.crypto.JceSecurity"); - final Class cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions"); - final Class cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission"); - - final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted"); - isRestrictedField.setAccessible(true); - isRestrictedField.set(null, false); - - final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy"); - defaultPolicyField.setAccessible(true); - final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null); - - final Field perms = cryptoPermissions.getDeclaredField("perms"); - perms.setAccessible(true); - ((Map) perms.get(defaultPolicy)).clear(); - - final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE"); - instance.setAccessible(true); - defaultPolicy.add((Permission) instance.get(null)); - - log.debug("Successfully removed cryptography restrictions"); - } catch (Exception e) { - log.warn("Failed to remove cryptography restrictions", e); - } - } - - public static boolean isRestrictedCryptography() { - // This simply matches the Oracle JRE, but not OpenJDK. - return "Java(TM) SE Runtime Environment".equals(System.getProperty("java.runtime.name")); + public static void checkCryptoPolicySetup() throws NoSuchAlgorithmException, LimitedKeyStrengthException { + if (Cipher.getMaxAllowedKeyLength("AES") > 128) + log.debug("Congratulations, you have unlimited key length support!"); + else + throw new LimitedKeyStrengthException(); } public static String toTruncatedString(Object message, int maxLenght) { diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java index 2f98060a943..8816ee29f4f 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -27,6 +27,7 @@ import io.bitsquare.common.CommonOptionKeys; import io.bitsquare.common.UserThread; import io.bitsquare.common.handlers.ResultHandler; +import io.bitsquare.common.util.LimitedKeyStrengthException; import io.bitsquare.common.util.Profiler; import io.bitsquare.common.util.Utilities; import io.bitsquare.filter.FilterManager; @@ -74,6 +75,7 @@ import java.io.IOException; import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; import java.security.Security; import java.util.ArrayList; import java.util.List; @@ -118,6 +120,8 @@ public void start(Stage stage) throws IOException { UserThread.setExecutor(Platform::runLater); UserThread.setTimerClass(UITimer.class); + shutDownHandler = this::stop; + // setup UncaughtExceptionHandler Thread.UncaughtExceptionHandler handler = (thread, throwable) -> { // Might come from another thread @@ -136,12 +140,15 @@ public void start(Stage stage) throws IOException { Thread.setDefaultUncaughtExceptionHandler(handler); Thread.currentThread().setUncaughtExceptionHandler(handler); - if (Utilities.isRestrictedCryptography()) - Utilities.removeCryptographyRestrictions(); + try { + Utilities.checkCryptoPolicySetup(); + } catch (NoSuchAlgorithmException | LimitedKeyStrengthException e) { + e.printStackTrace(); + UserThread.execute(() -> showErrorPopup(e, true)); + } + Security.addProvider(new BouncyCastleProvider()); - shutDownHandler = this::stop; - try { // Guice bitsquareAppModule = new BitsquareAppModule(env, primaryStage); diff --git a/headless/src/main/java/io/bitsquare/headless/Headless.java b/headless/src/main/java/io/bitsquare/headless/Headless.java index 967787838a8..b233b32455b 100644 --- a/headless/src/main/java/io/bitsquare/headless/Headless.java +++ b/headless/src/main/java/io/bitsquare/headless/Headless.java @@ -12,6 +12,7 @@ import io.bitsquare.common.CommonOptionKeys; import io.bitsquare.common.UserThread; import io.bitsquare.common.handlers.ResultHandler; +import io.bitsquare.common.util.LimitedKeyStrengthException; import io.bitsquare.common.util.Utilities; import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.P2PServiceListener; @@ -25,6 +26,7 @@ import org.springframework.core.env.Environment; import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; import java.security.Security; public class Headless { @@ -66,8 +68,12 @@ public Headless() { Thread.setDefaultUncaughtExceptionHandler(handler); Thread.currentThread().setUncaughtExceptionHandler(handler); - if (Utilities.isRestrictedCryptography()) - Utilities.removeCryptographyRestrictions(); + try { + Utilities.checkCryptoPolicySetup(); + } catch (NoSuchAlgorithmException | LimitedKeyStrengthException e) { + e.printStackTrace(); + UserThread.execute(this::shutDown); + } Security.addProvider(new BouncyCastleProvider()); diff --git a/monitor/src/main/java/io/bitsquare/monitor/Monitor.java b/monitor/src/main/java/io/bitsquare/monitor/Monitor.java index f61461bf633..066e70bcb54 100644 --- a/monitor/src/main/java/io/bitsquare/monitor/Monitor.java +++ b/monitor/src/main/java/io/bitsquare/monitor/Monitor.java @@ -12,6 +12,7 @@ import io.bitsquare.common.CommonOptionKeys; import io.bitsquare.common.UserThread; import io.bitsquare.common.handlers.ResultHandler; +import io.bitsquare.common.util.LimitedKeyStrengthException; import io.bitsquare.common.util.Utilities; import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.P2PServiceListener; @@ -25,6 +26,7 @@ import org.springframework.core.env.Environment; import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; import java.security.Security; public class Monitor { @@ -67,8 +69,12 @@ public Monitor() { Thread.setDefaultUncaughtExceptionHandler(handler); Thread.currentThread().setUncaughtExceptionHandler(handler); - if (Utilities.isRestrictedCryptography()) - Utilities.removeCryptographyRestrictions(); + try { + Utilities.checkCryptoPolicySetup(); + } catch (NoSuchAlgorithmException | LimitedKeyStrengthException e) { + e.printStackTrace(); + UserThread.execute(this::shutDown); + } Security.addProvider(new BouncyCastleProvider()); diff --git a/seednode/src/main/java/io/bitsquare/seednode/SeedNode.java b/seednode/src/main/java/io/bitsquare/seednode/SeedNode.java index 4ea1783af13..c0dc204da0d 100644 --- a/seednode/src/main/java/io/bitsquare/seednode/SeedNode.java +++ b/seednode/src/main/java/io/bitsquare/seednode/SeedNode.java @@ -12,6 +12,7 @@ import io.bitsquare.common.CommonOptionKeys; import io.bitsquare.common.UserThread; import io.bitsquare.common.handlers.ResultHandler; +import io.bitsquare.common.util.LimitedKeyStrengthException; import io.bitsquare.common.util.Utilities; import io.bitsquare.p2p.BootstrapListener; import io.bitsquare.p2p.P2PService; @@ -25,6 +26,7 @@ import org.springframework.core.env.Environment; import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; import java.security.Security; public class SeedNode { @@ -65,8 +67,12 @@ public SeedNode() { Thread.setDefaultUncaughtExceptionHandler(handler); Thread.currentThread().setUncaughtExceptionHandler(handler); - if (Utilities.isRestrictedCryptography()) - Utilities.removeCryptographyRestrictions(); + try { + Utilities.checkCryptoPolicySetup(); + } catch (NoSuchAlgorithmException | LimitedKeyStrengthException e) { + e.printStackTrace(); + UserThread.execute(this::shutDown); + } Security.addProvider(new BouncyCastleProvider()); diff --git a/statistics/src/main/java/io/bitsquare/statistics/Statistics.java b/statistics/src/main/java/io/bitsquare/statistics/Statistics.java index 2a4b79d04ff..57138984ec1 100644 --- a/statistics/src/main/java/io/bitsquare/statistics/Statistics.java +++ b/statistics/src/main/java/io/bitsquare/statistics/Statistics.java @@ -13,6 +13,7 @@ import io.bitsquare.common.CommonOptionKeys; import io.bitsquare.common.UserThread; import io.bitsquare.common.handlers.ResultHandler; +import io.bitsquare.common.util.LimitedKeyStrengthException; import io.bitsquare.common.util.Utilities; import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.p2p.BootstrapListener; @@ -28,6 +29,7 @@ import org.springframework.core.env.Environment; import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; import java.security.Security; public class Statistics { @@ -70,8 +72,12 @@ public Statistics() { Thread.setDefaultUncaughtExceptionHandler(handler); Thread.currentThread().setUncaughtExceptionHandler(handler); - if (Utilities.isRestrictedCryptography()) - Utilities.removeCryptographyRestrictions(); + try { + Utilities.checkCryptoPolicySetup(); + } catch (NoSuchAlgorithmException | LimitedKeyStrengthException e) { + e.printStackTrace(); + UserThread.execute(this::shutDown); + } Security.addProvider(new BouncyCastleProvider());