/* * Kontalk Java client * Copyright (C) 2016 Kontalk Devteam <devteam@kontalk.org> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kontalk.util; import javax.crypto.Cipher; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.security.NoSuchAlgorithmException; import java.security.Permission; import java.security.PermissionCollection; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author Alexander Bikadorov {@literal <bikaejkb@mail.tu-berlin.de>} */ public class CryptoUtils { private static final Logger LOGGER = Logger.getLogger(CryptoUtils.class.getName()); /** * Ugly hack to get “unlimited strength” for the Java Encryption Extension. * Source: https://stackoverflow.com/a/22492582 * And even more evil: http://stackoverflow.com/a/3301720/6286694 */ public static boolean removeCryptographyRestrictions() { try { if (Cipher.getMaxAllowedKeyLength("RC5") >= 256) { LOGGER.config("cryptography restrictions removal not needed"); return true; } } catch (NoSuchAlgorithmException ex) { LOGGER.log(Level.WARNING, "can't check for crypto restriction", ex); } try { /* * Do the following, but with reflection to bypass access checks: * * JceSecurity.isRestricted = false; * JceSecurity.defaultPolicy.perms.clear(); * JceSecurity.defaultPolicy.add(CryptoAllPermission.INSTANCE); */ Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity"); Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions"); Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission"); Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted"); isRestrictedField.setAccessible(true); // "isRestricted" field is final now, remove this Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(isRestrictedField, isRestrictedField.getModifiers() & ~Modifier.FINAL); isRestrictedField.set(null, false); Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy"); defaultPolicyField.setAccessible(true); PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null); Field perms = cryptoPermissions.getDeclaredField("perms"); perms.setAccessible(true); ((Map<?, ?>) perms.get(defaultPolicy)).clear(); Field instance = cryptoAllPermission.getDeclaredField("INSTANCE"); instance.setAccessible(true); defaultPolicy.add((Permission) instance.get(null)); LOGGER.info("removed cryptography restrictions"); } catch (ClassNotFoundException | NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) { LOGGER.log(Level.WARNING, "can't remove cryptography restrictions", ex); return false; } return true; } }