2014-01-29 5 views
6

현재 웹 앱에 Reddit OAuth2 로그인을 구현 중입니다. 핸드 쉐이크 및 토큰 교환이 잘 작동 할 때 로컬 테스트하지만 ('OpenShift'DIY 카트리지에서 호스팅) 나는 다음과 같은 오류 얻을 서버에서 실행하는 경우 :자바 SSL DH 키 쌍 생성 - 프라임 크기 오류

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의 결과입니다 자바의 버전을 바꿀 때부터 BouncyCastle을 사용할 때까지 다양한 솔루션을 찾아 냈습니다. 그러나 나는라이브러리를 사용하고 있으므로 BouncyCastle을 fork하고 스크라이브의베이스를 변경하지 않고 구현할 수 있다고 생각하지 않습니다.

JCE Unlimited Strength도 설치되었지만 루트 액세스 권한이 없으므로 OpenShift에서이를 수행 할 수 없습니다 (팀 중 하나를 수행 할 수 있음). 사용

자바 버전 (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

오류를 반환 요청 코드 (내가 언급 한 바와 같이, 스크라이브를 사용하여, 너무 많이 사용하지 않을 수도 있습니다). 토큰 엔드 포인트는 POST를 사용하여 https://ssl.reddit.com/api/v1/access_token입니다. 위에서 말했듯이 이것은 내 테스트 머신에서 작동합니다. 그것은 중요한 확실하지만, 오픈 JDK는 OpenShift에서 실행중인 버전하지

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

첫째, "무제한 힘"(32)을 얻었다. 그러면 AES-256을 사용하는 암호 스위트를 사용할 수 없다는 완전히 다른 문제가 해결 될 것입니다. (그리고 상대방이 주장하는대로 핸드 셰이크를 할 수 없다고 주장하는 경우) 또한 JVM의 비트 화는 중요하지 않습니다. DH에 대한이 (실제로 정당화되지는 않은) 제한은 SunJCE의 "run-everywhere"바이트 코드에 있습니다.

BouncyCastle은 SSL 연결을 사용하는 코드 (예 : Scribe)를 변경하지 않고도 암호화 공급자로 사용할 수 있지만 BC를 읽음으로써 선호 공급자가 다른 문제를 일으키는 것으로 보았습니다. 어쨌든 시도하려면 bcprov-version.jar을 JRE/lib/exit에 넣고 JRE/lib/security/java.security를 ​​편집하십시오. 또는 클래스 패스의 어느 곳에 나 넣고 init 코드를 호출한다. java.security.Security.insertProviderAt (new org.bouncycastle.jce.provider.BouncyCastleProvider(), position);

로컬 시스템이 작동하는 이유부터 시작하는 것이 좋습니다. ssl.reddit을 시도 할 때.com과 openssl을 지원하며, ECDHE-RSA (P-256 포함)와 dh 2048 비트가있는 DHE-RSA를 모두 지원합니다. Suncle Java 7은 ECDHE를 지원하고 선호하지만, OpenJDK도 그렇지만 어쩌면 그렇지 않을 수도 있고 때로는 그렇지 않을 수도 있습니다. 나는 Redhat이 최근까지 opensl의 rpms에서 ECC를 고결하게 할 때까지 알고 있으며 openjdk에서도 그렇게한다면 놀라지 않을 것입니다. 다음을 컴파일하고 실행하면 (ssl.reddit.com 443을 사용하여) JRE의 모든 기본 SSL 설정을 사용하여 시스템에서 협상 할 제품군을 알 수 있습니다 (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보다 안전하고 아마 더 효율적입니다). 그렇지 않으면 오라클이 이것을 수정하기 전까지 (분명히 8), DHE Suite를 사용하지 않도록 설정하고 NSA에 대해 안전하지 않을 수있는 일반 RSA로 되돌려 놓아야합니다. 그것은 SSLSocket을 실제로 생성하는 코드에서 가장 단순하지만, Scribe (대부분의 자바 웹 클라이언트와 마찬가지로)가 기본 SSLSocketFactory와 함께 URL -> HttpsUrlConnection을 사용하면 문제의 라인을 따라 EnabledCiphers 목록을 변경하는 조정 된 팩터 리로 대체 할 수 있습니다. # 6851461 좋은 공용 인증서가있는 호스트의 경우 해당 솔루션의 custom-trustmanager 부분은 필요하지 않습니다.

+0

답장을 보내 주셔서 감사합니다. 로컬 컴퓨터와 OpenShift에서 코드를 실행했습니다. 로컬에서는 'TLS_ECDHE_RSA_WITH_RC4_128_SHA'를 반환하지만 OpenShift에서는 'DH 키 쌍을 생성 할 수 없습니다.'오류가 발생합니다. 나는 ssllabs.com/ssltest에서도 확인했으며 핸드 셰이크를 위해 ECDHE를 리턴한다. OpenShift에서 ECDHE가 무효화되고있는 이유는 무엇입니까? OpenShift는 JRE 파일에 대한 읽기 전용 액세스를 허용하지만 클래스 경로 제안은 옵션입니다. BouncyCastle을 시도해 볼 수 있습니다. 또한 발견이 https://bugzilla.redhat.com/show_bug.cgi?id=1052363 –

+0

(지연 죄송합니다) 그 bugzilla는 openssl 및 분명히 서버 쪽 (가능성이 httpd?)입니다. 그러나 그것은 확실히 ECDHE에 대한 지원이 부족한 것과 일치합니다. 예, 서버가 ECDHE를 지원하는 것으로 알려져 있으므로 OpenShift가 명확하게 요청하지 않거나 올바르지 않은 경우 : OpenShift/OpenJDK의 SSL 공급자가 ECDHE Suite 전 DHE 제품군을 제공하는 경우 여기에 간섭 할 수있는 두 가지 문제점이 있습니다. 제한된 곡선만을 제공합니다. 그러나 –

+0

(너무 느리다.) 그 bugzilla는 openssl (C)이고 분명히 httpd 서버 쪽이다. 문제는 자바 클라이언트 다. 그러나 ECDHE를지지하려는 열망은 분명히 일치합니다. 원하는 서버가 ECDHE를 지원하기 때문에 OpenShift Java가이를 분명히 요구하지 않고 있습니다 (그렇지 않을 수도 있지만 그럴 것 같지 않습니다). javax.crypto.KeyAgreement.getInstance ("ECDH")를 실행하는 프로그램을 실행 해보고 공급자가없는 경우 - 위에서 말한 내용과 .addProvider (새로운 탄력성)를 수정하여 표준 (?) JSSE는 여전히 선택되었지만 Bouncy로부터 ECC를 얻습니다. 그렇지 않다면 나는이 라운드에서 우주를 벗어났다. –

0

32 비트, 당신은 당신의 코드에서 System.getProperty를 ("sun.arch.data.model")를 사용하여이 작업을 볼 수 있습니다.

나는 단지 출력 빠른 클래스 비트 다움을 작성하고 OpenShift 기어에 컴파일하고 실행하고 여기에 무관

class Test { 

public static void main(String[] args) { 

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

} 

} 
+0

답장을 보내 주셔서 감사합니다! 나는 OpenShift가 java -version 출력에 나타난 것처럼 32 비트 Java를 사용한다고 가정했습니다. 그것이 문제일까요? 어떻게 영향을 주는지 실제로 알 수는 없지만 테스트 머신에서 32 비트 버전을 사용해 보겠습니다. 당신이 요청한 코드도 첨부했습니다. 그래도 Scribe를 사용하기 때문에 많이 사용하지 않을 수도 있습니다. –

+0

아마도이 버그 (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6521495)가 있지만 OpenJDK 측은 32 비트 버전에서 수정되지 않았습니까? –

+0

그건 내가 당신이 버전을 언급 한 후에 생각한거야,하지만 난 그냥 내 로컬 컴퓨터에서 32 비트 OpenJDK 버전을 사용하여 테스트하고 괜찮 았어. –

2

나는이 답변에 매우 늦었지만 비슷한 문제로 고민하고 해결했습니다. 내 솔루션은 MAC-OS 용입니다.

  1. 은 아래 라인을 security.provider를 추가 /라이브러리/자바/JavaVirtualMachines // 내용/홈/JRE/lib 디렉토리/내선
  2. 편집 java.security 파일 에 http://www.bouncycastle.org/latest_releases.html에서 탄력 성 항아리를 설치합니다. 2 = org.bouncycastle.jce.provider.BouncyCastleProvider 그리고 다른 모든 제공자를 재정렬하십시오.
+0

감사합니다 ...이 솔루션은 Linux-Mint (Java 1.6)에서도 작동합니다. – Roshan

+0

CentOS 7 및 Java 1.6에서도 작동하는지 확인합니다. –

1

짜잔 내가 SSL/TLS에 대한 제공을 bouncycastle로 전환하여 오라클 자바 8 문제를 해결 :

  1. 추가 된 bouncycastle 내 프로젝트에

    <dependency> 
        <groupId>org.bouncycastle</groupId> 
        <artifactId>bcprov-jdk15on</artifactId> 
        <version>1.54</version> 
    </dependency> 
    
  2. 전에 I 모든 SSL 작업을 수행하려면 목록에 첫 번째 공급자로 BouncyCastle 공급자를 추가하십시오.

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

그게 전부입니다. 이제 4096 비트 DH 매개 변수가있는 사이트에 대한 연결이 예상대로 작동합니다 (Apache HTTP 클라이언트를 사용하고 있습니다). 또한 jdk 7에서도 작동해야합니다.

+0

이것은 나를 위해 완벽하게 작동했습니다. 코드가 한 줄이기 때문에 JVM을 변경하지 않아도됩니다. –

관련 문제