2014-01-29 3 views
6

Я в настоящее время внедряю Reddit OAuth2 для входа в мое веб-приложение. Рукопожатие и маркер обмен работает нормально при проверке на месте, но при запуске на сервере (размещено на DIY картриджа «OpenShift») я получаю следующее сообщение об ошибке:Java SSL DH Keypair Generation - Prime Size Error

java.security.InvalidAlgorithmParameterException: Prime size must be 
multiple of 64, and can only range from 512 to 1024 (inclusive) 

Что приводит

java.lang.RuntimeException: Could not generate DH keypair 

I мы искали большую часть дня и находили различные решения, начиная от изменения версии Java и заканчивая использованием BouncyCastle. Тем не менее, я использую библиотеку Scribe, поэтому я не думаю, что могу реализовать BouncyCastle без наложения и изменения базы писца, какой вид поражения это цель.

Установка JCE Unlimited Strength также появилась, но я не могу этого сделать на OpenShift, так как нет доступа root (возможно, она сможет заставить одну из их команды сделать это).

В версии Java в пользе (взяты из java -version):

локального тестирования машины:

java version "1.7.0_51" 
OpenJDK Runtime Environment (IcedTea 2.4.4) (7u51-2.4.4-1ubuntu1) 
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode) 

OpenShift Сервер:

java version "1.7.0_51" 
OpenJDK Runtime Environment (rhel-2.4.4.1.el6_5-i386 u51-b02) 
OpenJDK Server VM (build 24.45-b08, mixed mode) 

Я в недоумении относительно того, что Я могу это сделать. Надеюсь, я глуп или что-то не понимаю, поэтому любые возможные решения были бы замечательными!

-

EDIT 1

Запрос код, который возвращает ошибку (используя Scribe, как я уже говорил, так что не может быть много пользы). Конечная точка маркера равна https://ssl.reddit.com/api/v1/access_token с использованием POST. Как я сказал выше, это работает на моей тестовой машине.

OAuthRequest request = new OAuthRequest(getAccessTokenVerb(), getAccessTokenEndpoint()); 

request.addHeader("Authorization", "Basic" 
    +Base64.encode((config.getApiKey()+":"+config.getApiSecret()).getBytes())); 

request.addBodyParameter("state", "none"); 
request.addBodyParameter(OAuthConstants.SCOPE, config.getScope()); 
request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey()); 
request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback()); 
request.addBodyParameter(OAuthConstants.CODE, verifier.getValue()); 
request.addBodyParameter("grant_type", "authorization_code"); 

Response response = request.send(); // Errors here from Request.createConnection in the Scribe code 
return getAccessTokenExtractor().extract(response.getBody()); 
+0

Можете ли вы опубликовать код, который вы используете для создания ключевой пары, чтобы мы могли с ней проверить? –

+0

См. Также http://stackoverflow.com/questions/6851461/java-why-does-ssl-handshake-give-could-not-generate-dh-keypair-exception – Raedwald

ответ

6

Во-первых, «Безлимитный сила» здесь неуместна. Это исправит совершенно другую проблему, из-за которой вы не можете использовать шифровые наборы с использованием AES-256 (и если сторонник настаивает на них, это не может быть рукопожатием вообще). Кроме того, битрейт JVM не имеет значения; это (не совсем обоснованное) ограничение на DH находится в байт-коде «run-везде» в SunJCE.

Вы можете использовать BouncyCastle в качестве поставщика криптозащиты, не меняя код, который выполняет SSL-соединения (в вашем случае Scribe), но из того, что я прочитал, создавая BC, предпочтительный поставщик вызывает другие проблемы. Если вы все равно хотите попробовать, поместите bcprov-version.jar в JRE/lib/exit и отредактируйте JRE/lib/security/java.security; или поместите его куда-нибудь в свой путь к классу и получите код инициализации java.security.Security.insertProviderAt (новый org.bouncycastle.jce.provider.BouncyCastleProvider(), позиция);

Предлагаю начать с того, почему ваша местная система работает. Когда я пытаюсь ssl.reddit.com с openssl, он поддерживает как ECDHE-RSA (с P-256), так и DHE-RSA с dh 2048 бит. Suncle Java 7 поддерживает и предпочитает ECDHE, и я ожидал бы, что OpenJDK также будет работать, но, возможно, нет, а может быть, и нет; Я знаю, что RedHat до недавнего времени опустил ECC в своих rpms of openssl, и это не удивило бы меня, если бы они это сделали и в openjdk. Если вы скомпилируете и запустите следующую команду (с помощью ssl.reddit.com 443), она сообщит, какой пакет согласован в вашей системе, используя все настройки SSL по умолчанию для вашей JRE (что я ожидаю и надеюсь, что Scribe также использует):

//nopackage DThompson 2012.08.13b 
import java.net.InetSocketAddress; 
import java.net.Socket; 
import javax.net.ssl.SSLSocket; 
import javax.net.ssl.SSLSocketFactory; 

public class JustBConnectSSL { 

    /* (optionally bind and) just make SSL connection, for testing reach and trust 
    * uses default providers, truststore (normally JRE/lib/security/[jsse]cacerts), 
    * and keystore (normally none), override with -Djavax.net.ssl.{trust,key}Store* 
    */ 
    public static void main (String[] args) throws Exception { 
     if(args.length < 2){ System.out.println ("Usage: tohost port [fromaddr [fromport]]"); return; } 
     Socket sock = SSLSocketFactory.getDefault().createSocket(); 
     if(args.length > 2) 
      sock.bind (new InetSocketAddress (args[2], args.length>3? Integer.parseInt(args[3]): 0)); 
     sock.connect (new InetSocketAddress (args[0], Integer.parseInt(args[1]))); 
     System.out.println (sock.getInetAddress().getHostName() + " = " + sock.getInetAddress().getHostAddress()); 
     ((SSLSocket)sock).startHandshake(); 
     System.out.println ("connect okay " + ((SSLSocket)sock).getSession().getCipherSuite()); 
    } 
} 

Если тест получает _DHE_RSA_something, поставщики криптографии в вашей JRE должны отличаться от Suncle, либо измененными Ubuntu, либо некоторой настройкой или патчем в вашей системе. Если тест получает _ECDHE_RSA_something, но OpenShift этого не делает, они могут как-то отключить ECC/ECDHE. Если они позволят это лучше всего (ECDHE-P-256 по крайней мере безопасен и, вероятно, более эффективен, чем DH-2048). В противном случае, пока Oracle не исправляет это (видимо, в 8), единственный, на что я полагаю, можно полагаться, это отключить DHE-пакеты (и вернуться к простому RSA, что может быть небезопасно для NSA); это самый простой код, который фактически создает SSLSocket, но если Scribe (например, большинство веб-клиентов java) использует URL -> HttpsUrlConnection со своим SSLSocketFactory по умолчанию, вы можете заменить модифицированный завод, который изменяет список EnabledCiphers по строкам вопроса # 6851461 (хотя для хоста с хорошим общедоступным сертификатом вам не нужны части пользовательского доверия для этого решения).

+0

Большое спасибо за подробный ответ! Я запустил ваш код как на моем локальном компьютере, так и на OpenShift. Локально он возвращает «TLS_ECDHE_RSA_WITH_RC4_128_SHA», но в OpenShift я получаю сообщение «Не удалось создать DH keypair». Я также проверил его на ssllabs.com/ssltest, и он также возвращает ECDHE для рукопожатия. Считаете ли вы, что это случай, когда ECDHE отключен/нет по какой-либо причине OpenShift? Я мог бы попробовать BouncyCastle, хотя OpenShift допускает доступ только для чтения к файлам JRE, но ваше предложение пути к курсу является вариантом. Также нашел это https://bugzilla.redhat.com/show_bug.cgi?id=1052363 –

+0

(Извините за задержку). Это bugzilla для openssl и, видимо, серверная сторона (скорее всего, httpd?). Но это, безусловно, согласуется с отсутствием поддержки ECDHE. Да, поскольку сервер, как известно, поддерживает ECDHE, тогда OpenShift явно не запрашивает его - или не правильно: есть две ошибки, которые могут мешать здесь, если поставщик SSL в OpenShift/OpenJDK предлагает пакеты DHE перед пакетами ECDHE или он предлагает только ограниченные кривые. Но –

+0

(исправить, слишком медленно). Эта ошибка для opensl (C) и, видимо, на стороне сервера httpd, ваша проблема - это клиент Java. Но это, безусловно, не согласуется с отсутствием поддержки ECDHE. Поскольку сервер, который вы хотите, поддерживает ECDHE, OpenShift Java явно не запрашивает его (или не правильно, но это маловероятно). Попробуйте программу, которая просто выполняет javax.crypto.KeyAgreement.getInstance («ECDH»), и если это выбрасывает - нет провайдера - вы можете изменить сказанное выше и .addProvider (новый bouncy), чтобы стандартный (?) JSSE по-прежнему выбран, но получает ECC от Bouncy. Если нет, мне не хватает места в этом раунде. –

0

Не уверен, если это имеет значение, но версия OpenJDK работает на OpenShift составляет 32 бит, вы можете просматривать это с помощью System.getProperty («sun.arch.data.model») в вашем коде.

Я написал быстрый класс только выходной бит-Несс и скомпилирован на передаче OpenShift и запустил его и получил 32

class Test { 

public static void main(String[] args) { 

System.out.println(System.getProperty("sun.arch.data.model")); 

} 

} 
+0

Спасибо за ваш ответ! Я предположил, что OpenShift использует 32-битную Java, как показано выходом java -version. Может ли это быть проблема? Я не могу понять, как это повлияет на это, но я попытаюсь использовать 32-разрядную версию на своей тестовой машине. Я также добавил код, который вы просили, он использует Scribe, хотя, возможно, не так много пользы. –

+0

Возможно, эта ошибка (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6521495), но на сторона OpenJDK, не была исправлена ​​в 32-битной версии? –

+0

Вот что я подумал после того, как вы упомянули о версии, но я просто протестировал ее на своей локальной машине, используя 32-битную версию OpenJDK, и она отлично работала. –

2

Я знаю, что очень поздно ответить на это, но я боролся с подобной проблемой, а затем решил ее. Мое решение для MAC-OS.

  1. Установите Надувной замок баночку из http://www.bouncycastle.org/latest_releases.html, в /Library/Java/JavaVirtualMachines // Содержание/Начало/JRE/Библиотека/внутр
  2. редактировать java.security файл добавить следующую строку security.provider. 2 = org.bouncycastle.jce.provider.BouncyCastleProvider , а затем переупорядочить всех других поставщиков, которые у вас могут быть.
  3. вуаля
+0

Спасибо .. Это решение работает и для Linux-Mint (Java 1.6). – Roshan

+0

Я подтверждаю, что он работает с CentOS 7 и Java 1.6. –

1

Я решил проблему на оракула Java 8, переключаясь на BouncyCastle поставщика для SSL/TLS:

  1. Добавлена ​​BouncyCastle к моему проекту

    <dependency> 
        <groupId>org.bouncycastle</groupId> 
        <artifactId>bcprov-jdk15on</artifactId> 
        <version>1.54</version> 
    </dependency> 
    
  2. Перед тем, как делать какие-либо материалы SSL, я добавляю поставщика BouncyCastle в качестве первого провайдера в список:

    Security.insertProviderAt(new BouncyCastleProvider(),1); 
    

Это все. Теперь мои подключения к сайтам с 4096-разрядными параметрами DH работают как ожидалось (я использую Apache HTTP Client). Это также должно работать с jdk 7.

+0

Это отлично сработало для меня. Мне это нравится, потому что это одна строка кода и не требует никаких изменений в JVM. –