«java.io.IOException: неверный формат секретного ключа» при открытии хранилища ключей JCEKS с Oracle Java 8 JRE 172 - PullRequest
0 голосов
/ 17 мая 2018

При попытке открыть хранилище ключей типа JCEKS с помощью Oracle Java 8 JRE 172 в Windows я получаю следующее исключение.Это работало нормально с более ранними версиями JRE:

INFO: ObjectInputFilter REJECTED: null, array length: -1, nRefs: 1, depth: 1, bytes: 70, ex: n/a
[...call stacks omitted to protect the innocent...]
Caused by: java.io.IOException: Invalid secret key format
        at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:856)
        at java.security.KeyStore.load(Unknown Source)
[...]

Это очень похоже на JDK-8202506 , но я использую Java 8 и получаю null в исходном сообщении INFO.

Это та же проблема?

Мне кажется, что проблема JDK-8202506 в настоящее время не устранена ни в одном публичном выпуске JRE.Я прав?

ОБНОВЛЕНИЕ 1

Это выглядит похоже, и они также не имеют решения: ATLAS-2642

ОБНОВЛЕНИЕ 2

По какой-то причине Equinox не видит класс com.sun.crypto.provider.SealedObjectForKeyProtector после обновления, хотя он явно находится в JRE, поставляемом с новым JDK:

BundleClassLoader[foo.bar.baz.crypto].loadClass(com.sun.crypto.provider.SealedObjectForKeyProtector) failed.
java.lang.ClassNotFoundException: com.sun.crypto.provider.SealedObjectForKeyProtector
    at org.eclipse.osgi.framework.internal.core.BundleLoader.findClassInternal(BundleLoader.java:481)
    at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:397)
    at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:385)
    at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:87)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:686)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1866)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1749)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2040)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1571)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
    at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:850)
    at java.security.KeyStore.load(KeyStore.java:1445)

UPDATE 3

Класс SealedObjectForKeyProtector.class несколько отличается от остальных классов в sunjce_provider.jar.Когда мы пытаемся декомпилировать его с помощью JD-GUI, происходит сбой из-за внутренней ошибки, в отличие от остальных классов:

JD-GUI failure to decompile SealedObjectForKeyProtector.class

Ответы [ 3 ]

0 голосов
/ 01 октября 2018

Я встречаю эту проблему в эти дни. И в соответствии с моим устранением неполадок, это вызвано различным значением возврата этого метода:

sun.misc.VM.latestUserDefinedLoader()

Ранее (до 8u171) этот метод возвращает sun.misc.Launcher$ExtClassLoader, в то время как он возвращает загрузчик классов приложения после обновления. В ObjectInputStream оба загрузчика классов могут успешно загружать com.sun.crypto.provider.SealedObjectForKeyProtector, это просто потому, что ExtClassLoader является родителем загрузчика классов приложения (или родителем родителя). Однако, как только SealedObjectForKeyProtector загружен загрузчиком классов приложения, его загрузчик классов больше не равен ExtClassLoader.

С другой стороны, в пределах com.sun.crypto.provider.JceKeyStore, в отличие от ObjectInputStream, SealedObjectForKeyProtector всегда загружается ExtClassLoader. Таким образом, проверка ниже JceKeyStore.java: 932 завершится сбоем из-за того, что класс не равен:

932            if (info.serialClass() != SealedObjectForKeyProtector.class))
934                return Status.REJECTED;

Тогда, в конце концов, мы получим ниже log и IOException: ObjectInputFilter ОТКАЗАНО: класс com.sun.crypto.provider.SealedObjectForKeyProtector

Решение: убедитесь, что класс com.sun.crypto.provider.SealedObjectForKeyProtector не загружен ContextClassLoader с определенной конфигурацией. Детали зависят от ContextClassLoader. Например, для org.powermock.core.classloader.MockClassLoader конкретное решение добавляет добавленную ниже аннотацию к участвующим тестовым классам:

@PowerMockIgnore("com.sun.*")

0 голосов
/ 26 марта 2019

Я выполнил полный анализ проблемы и отладил часть кода, которая связана с хранилищем ключей JCEKS. Всякий раз, когда приложение использует пользовательский загрузчик классов, вы наверняка столкнетесь с этой проблемой, если будете использовать хранилище ключей JCEKS из более старых версий Java, чем JDK 8 Update 151.

 private static class DeserializationChecker implements ObjectInputFilter {
    private static final int MAX_NESTED_DEPTH = 2;

    @Override
    public ObjectInputFilter.Status
        checkInput(ObjectInputFilter.FilterInfo info) {

        // First run a custom filter
        long nestedDepth = info.depth();
        if ((nestedDepth == 1 &&
                    info.serialClass() != SealedObjectForKeyProtector.class) ||
                (nestedDepth > MAX_NESTED_DEPTH &&
                    info.serialClass() != null &&
                    info.serialClass() != Object.class)) {
            return Status.REJECTED;
        }

        // Next run the default filter, if available
        ObjectInputFilter defaultFilter =
            ObjectInputFilter.Config.getSerialFilter();
        if (defaultFilter != null) {
            return defaultFilter.checkInput(info);
        }

        return Status.UNDECIDED;
    }
}

В приведенном выше коде из JceKeyStore.class информация фильтра всегда будет нулевой, поэтому проверка info.serialClass ()! = SealedObjectForKeyProtector.class завершится неудачей. Делегирование загрузки классов не происходит должным образом в случае пользовательского загрузчика классов, такого как плагин Equinox - Eclipse.

Существует два шага решения

  1. Сначала обновите хранилище ключей с JCEKS до PKCS12, как упомянуто в JDK 151 https://www.oracle.com/technetwork/java/javase/8u151-relnotes-3850493.html в разделе «Примечания: более эффективная работа с хранилищем ключей». В большинстве случаев это решит проблему. Далее получите доступ к хранилищу ключей со значением типа хранилища ключей PKCS12 после изменений.
  2. Заставьте классы из провайдера sun_jce загружаться раньше, даже раньше, чем ваша область загрузки пользовательских классов. Используйте эту конфигурацию, чтобы ваш пользовательский загрузчик классов делегировал загрузку классов jar sun_jce в ExtClassLoader. Например: с помощью Eclipse-BuddyPolicy: ext в META-INF проектов подключаемых модулей eclipse.
0 голосов
/ 29 июля 2018

В настоящее время я работаю над поддержкой Oracle JRE и у меня открыта личная ошибка. Информация, которую я получил до сих пор:

  1. Это не то же самое, что JDK-8202506.
  2. Да, это проблема загрузки классов в SealedObjectForKeyProtector с Equinox.

Решения:

Обходной путь - добавить следующую строку в пакет OSGi MANIFEST.MF.

Eclipse-BuddyPolicy: ext

Я лично проверил этот обходной путь с JRE 1.8_181, и, похоже, он работает.

Мне также сказали, что для Java 9 параметр JVM -Dosgi.compatibility.bootdelegation = true может выполнять работу (без необходимости обновления MANIFEST.MF), но у меня нет среды Java 9 для проверьте это. Цените, если кто-то может попробовать это, и сообщите нам результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...