2016-04-26 2 views
2

Я использую АОH 0.1.53 для подключения к удаленному SSH-серверу, который использует 1024-битный ключ RSA. Мы можем успешно подключиться к удаленному серверу, когда мы также используем 1024-битный ключ RSA, но когда мы создали более мощные 2048-битные ключи, мы перестали быть в состоянии подключиться. Мы получили сообщение об ошибке, которое гласит: «Основной размер должен быть кратным 64 и может варьироваться от 512 до 2048», и это происходит от вызова DHGEX.java (Diffie-Hellman Group EXchange).DHGEX не работает с 2048-битным ключом под Java 8, но с использованием 1024-битного ключа

Мы запускаем Java 1.8, и сообщение об ошибке правильно указывает максимальный размер бита 2048, поэтому проблема не в ограничении ключа JCE 1024 бит в Java 1.6 и 1.7. И мы подтвердили, что и наш частный, и наш открытый ключ на самом деле составляют 2048 бит, через openssl rsa -text -noout -in id_rsa и ssh-keygen -lf id_rsa.pub.

Поскольку на нашем конце все выглядело хорошо, я начал добавлять строки отладки в код АОХ и перекомпилировать JAR, и в конечном итоге я смог определить, что модуль, передаваемый нам во время обмена ключами, на самом деле был длиной 2047 бит , Теперь 2047 бит в длину не означает, что вы не генерировали 2048-битный ключ или что он менее силен, чем ключ, который фактически содержит 2048 бит, это просто означает, что вам удалось получить два простых числа, которые умножились вместе к чему-то, чей первый бит равен 0. Поэтому ожидается, что поведение (часть времени) и проверка JCE должны быть (n% 64 == 0 || n% 64 == 63). Но JCE является приверженцем точки, поэтому он отвергает этот ключ для того, чтобы он не считался допустимым.

Основываясь на этом, я думал, что нашел проблему: на удаленном сервере был сформирован 2048-битный ключ, который содержал только 2047 бит, поэтому им просто нужно было создать новый (и продолжать делать это до тех пор, пока они не получили тот, который действительно был 2048 бит). Но когда я спросил об этом своих администраторов, они настаивали на том, что они используют 1024-битный ключ, и именно это вы получаете в файле known_hosts, когда вы используете SSH. Так что, похоже, это не причина.

Итак, я начал регистрировать содержимое буфера, содержащего то, что они нам отправили, и вытащил значения p и g (модуль и группу), и я обнаружил, что всего за несколько коротких периодов тестирования в течение нескольких дней , было 33 разных значения модуля, и все они отличались только на последние несколько символов при кодировании в базе 64 или base 10. Значения Modulii были повторно использованы, иногда только один раз, а иногда и десяток раз, но было много разных значений , поэтому ключи не генерируются для одноразового использования и не генерируются один раз и не используются повторно.

Это (при условии, что сервер отправляет множество разных ключей, которые очень близки по размеру, с некоторым повторным использованием, но много уникальных значений) ожидаемое поведение при любых условиях, и особенно это ожидаемое поведение, когда клиент использует 2048-битный ключ, но сервер использует 1024-битный ключ? Я ничего не знаю об обмене группой Диффи-Хеллмана, кроме того, что я читал с тех пор, как начал изучать на прошлой неделе, так что, возможно, это именно то, как это работает, но мне кажется странным.

Кроме того, указывает ли стандарт SSH что-либо о том, как ключи должны генерироваться в таких случаях? Я еще не выяснил, какой сервер SSH используется на стороне (я подозреваю OpenSSH, но не знаю точно и не знаю, какую версию), но я надеюсь, что может быть какой-то стандарт, который заставляет использование ключей, которые имеют тот же размер, который был запрошен (между 1^(n-1) и 1^n - 1), и что на удаленном сервере может быть возможность принудительно заставить тот или иной я могу подать ошибку против них чтобы заставить их изменить поведение. Я, вероятно, также отправлю ошибку JDK, чтобы разрешить ключи из n-1 бит, с 0-padding для первого бита.

Любое руководство, которое может дать любой человек, было бы весьма полезно.

Я также отвечал на этот вопрос в список рассылки JSch: https://sourceforge.net/p/jsch/mailman/message/35042955/

UPDATE:

После дальнейшего чтения, я считаю, что вперед секретность характеристика Диффи-Хеллмана означает, что различные простые числа (часто из предварительно сгенерированный набор, который хранится где-то вроде/etc/ssl/moduli) будет использоваться для каждого сеанса (источник: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange#Forward_secrecy) и что используемое основное значение фактически не является ключом RSA (источник: https://stackoverflow.com/a/23346185/1247705), поэтому тот факт, что много разных p ценности уже не кажется проблемой. Я все еще удивляюсь, что они так близки по стоимости, но, возможно, это тоже ожидается.

Далекая сторона использует Solaris SSH 1.1.4 (который, как я понимаю, основан на OpenSSH), как демон SSH. Ожидается ли, что этот демон пройдет 2047-битные простые числа как часть обмена ключами Диффи-Хеллмана, и есть ли что-нибудь, что можно сделать, чтобы заставить его отправлять 2048-битные простые числа?

+0

У вас есть [Unlimited Strength Policy for Java 8] (http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) файлы установлены? –

+0

Я этого не делаю, и я не видел ничего, что заставило бы меня поверить, что это необходимо. Используя тест JUnit, я могу запустить код, который генерирует исключение (заполнение p и g на объекте com.jcraft.jsch.jce.DH, а затем вызов getE() на нем) с использованием нашего 2048-битного ключа, и он работает без проблем, но он не работает, когда я запускаю ключ с 2047 бит, полученный с удаленного сервера. Если бы была необходима политика без ограничений, я бы ожидал, что вызов будет неудачным для нашего 2048-битного ключа. Но если у вас есть информация, которая указывает, что это поможет в моем конкретном сценарии, пожалуйста, поделитесь. – Tim

+1

Как вы обновили, модуль DHgex (простое) не имеет ничего общего с каким-либо модулем RSA (произведение двух простых чисел). Java JCE, по-видимому, применительно к параметрам DH указывает на ограничение DSA на размер группы, потому что (re) использует свою логику генерации параметров DSS для параметров DH, но нет веских оснований для применения этого ограничения к внешним/полученным параметрам. OpenSSH 'sshd' определенно использует модули DHgex из файла; если * сгенерирован * с 'ssh-keygen', этот файл включает в себя пучок простых чисел из ограниченного диапазона (высокие биты одинаковые) и необъяснимо один бит меньше указанного .... –

ответ

2

Мы зафиксировали подобные симптомы с:

Security.insertProviderAt(new BouncyCastleProvider(), 1) 

мы использовали JSch 0.1.54 и увидел:

java.security.InvalidAlgorithmParameterException: DH размер ключа должен быть кратен 64, и может только от 512 до 4096 (включительно). Конкретный размер ключа 2047 не поддерживается

, возможно, связано это JDK-8164963: InvalidAlgorithmParameterException prime size issue after JDK upgrade with JSCH libraries

+0

Это хорошая информация, и интересно посмотреть, что ошибка, на которую вы ссылались, ссылается на этот вопрос. Люди OpenJDK, похоже, решили, что это не их проблема (и то, что они написали, подразумевает, что они считают, что это проблема OpenSSH). – Tim

0

Я закончил работать вокруг этого вопроса путем отключения алгоритмов обмена ключами, которые использовали вариант обмена ключами Диффи-Хеллмана Group. Похоже, что @Brian Low работал вокруг него, используя BouncyCastle вместо встроенного поставщика безопасности JDK.

Я считаю, что оба из них являются обходными решениями, которые не решают основной проблемы (которая, как представляется, является ошибкой в ​​JDK, для каких размеров ключей они принимают или в OpenSSH, для каких размеров ключей они генерируют), но ни Я ни мой проект не заботился о том, чтобы тратить время и деньги, пытаясь заставить одного или другого взять на себя ответственность за проблему.

Смежные вопросы