2016-07-07 3 views
2

현재 Java TLS 서버에서 작업하고 있습니다. 와이어 샤크에서 볼 수 있듯이 여기TLS 1.2 ECDHE_RSA 서명

140735242416208:error:1414D172:SSL routines:tls12_check_peer_sigalg:wrong signature type:t1_lib.c:1130:

TLS 메시지입니다 : 나는이를 ServerKeyExchange 메시지 후 다음과 같은 오류가 얻을하려면 openssl s_client가를 사용하여 테스트 할 때

TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA

을 : 나는하려면 다음 모두 CipherSuite를 얻으려고 The TLS message as seen in Wireshark

치명적 오류 인 decode_error에서 핸드 셰이크가 실패합니다.

그래서 클라이언트가 선택된 서명 알고리즘을 좋아하지 않는다고 생각합니다.

하지만 난 단지에 대한 기본 SignatureAndHashAlgorithm을 사용하고 이제 내가 ECDHE_RSA을

하고 있어요 때문에 (클라이언트가 비록 제안 논문의 기본값을 경우 난 아직 확인 해요) RFC 5246 Section-7.4.1.4.1

If the negotiated key exchange algorithm is one of (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), behave as if client had sent the value {sha1,rsa}.

당 나는 해시와 (:) 그래서 단지 2 링크 죄송 여기에 첫 번째 게시물) RFC에 따라

ServerKeyExchange.signed_params.sha_hash 
     SHA(ClientHello.random + ServerHello.random + 
              ServerKeyExchange.params); 
struct { 
    select (KeyExchangeAlgorithm) { 
     case ec_diffie_hellman: 
      ServerECDHParams params; 
      Signature signed_params; 
    }; 
} ServerKeyExchange; 

그리고 I을 4492 5.4 절을 serverECDHparams에 서명한다고 생각 RFC 2246 섹션에 따라이 작업을 수행해야한다 7.4.3

select (SignatureAlgorithm) { 
    case rsa: 
     digitally-signed struct { 
      opaque md5_hash[16]; 
      opaque sha_hash[20]; 
     }; 
} Signature; 


md5_hash 
MD5(ClientHello.random + ServerHello.random + ServerParams); 

sha_hash 
SHA(ClientHello.random + ServerHello.random + ServerParams); 

serverParams 서명에 대한 내 자바 코드 :

private byte[] getSignedParams(ChannelBuffer params) 
     throws NoSuchAlgorithmException, DigestException, 
     SignatureException, InvalidKeyException { 
    byte[] signedParams = null; 
    ChannelBuffer signAlg = ChannelBuffers.buffer(2); 
    MessageDigest md5 = MessageDigest.getInstance("MD5"); 
    MessageDigest sha = MessageDigest.getInstance("SHA-1"); 
    switch (session.cipherSuite.sign) { 
     case rsa: 
      signAlg.writeByte(2); // 2 for SHA1 
      sha.update(clientRandom); 
      sha.update(serverRandom); 
      sha.update(params.toByteBuffer()); 
      md5.update(clientRandom); 
      md5.update(serverRandom); 
      md5.update(params.toByteBuffer()); 
      signedParams = concat(md5.digest(), sha.digest()); 
     break; 
    } 
    signAlg.writeByte(session.cipherSuite.sign.value); // for RSA he byte is one 
    ChannelBuffer signLength = ChannelBuffers.buffer(2); 
    signLength.writeShort(signedParams.length); 
    return concat(signAlg.array(),concat(signLength.array(),signedParams)); 
} 

그래서 내 질문은 기본적으로 : 나는 모든 이것에 대해 잘못된 오전? 그렇다면 무엇이 잘못 되었습니까?

감사합니다. :)

+0

프로그래밍 관련 의심에 대한 stackoverflow 포럼에이 질문을 게시하는 것이 좋습니다. 당신은 거기에 신속하게 대답을 얻을 수 있습니다. – Limit

+0

고마워, 글쎄, 이건 내가 이해하지 못하는 순전히 문제인 RFC라고 생각했다. 나는 그 이후로 (?) 대답과 나는 사람들을 위해 오늘 나중에 찾을 수 있도록 게시 할 것이다 :) – Alpha4

+0

5246 7.1.4.1에서 인용 한 텍스트의 제목은 "클라이언트가 signature_algorithms 확장을 보내지 않으면"입니다. openssl s_client **는 ** 확장을 전송합니다. 추적에서 ClientHello를 살펴보십시오. 그러나 0201 SHA1 + RSA가 포함되어 있으므로이 이유로이 서명을 거부해서는 안됩니다. 그러나 발견 한대로 서명이 잘못되었습니다. MD5 + SHA1 + RSA 서명은 TLS 1.0 (2246) 및 1.1 (4346)에서 사용되지만 하나의 서버 선택 해시로 표준 PKCS1-v1_5로 1.2 변경됩니다. 1.246의 차이 목록에서 두 번째 항목은 5246 4.7을 참조하십시오. –

답변

0

내가 내 특정 문제 2 내가 언급 한 가지 고정 된 것 같다, 다시 나야 내 자바 코드에 대해서는

  1. 을의 MessageDigest 등의 클래스는 내가 지금 대신 서명 클래스를 사용하여 더 서명을 해싱하지 않습니다 .
  2. TLS1.2에서 SHA1을 사용하여 서명해야 할 것 같습니다. MD5를 전혀 할 필요가 없습니다.

두 번째 항목은 내가 RFC에서 찾을 수 있지만 (아마 어딘가에 기록, 나도 몰라) 나는이 그들이 아니더라도 사람들에게 도움이 될 수 있다고 생각하지 않았다해야 무엇인가 자바를하고, 내 코드는 지금 보이는 방법)

:

private byte[] getSignedParams(ChannelBuffer params) 
     throws NoSuchAlgorithmException, DigestException, 
     SignatureException, InvalidKeyException { 
    byte[] signedParams = null; 
    Signature signature = Signature.getInstance(selectedSignAndHash.toString()); 
    ChannelBuffer signAlg = ChannelBuffers.buffer(2); 
    signAlg.writeByte(selectedSignAndHash.hash.value); 
    signature.initSign(privateKey); 

    signature.update(clientRandom); 
    signature.update(serverRandom); 
    signature.update(params.toByteBuffer()); 

    signedParams = signature.sign(); 

    signAlg.writeByte(session.cipherSuite.sign.value); 
    ChannelBuffer signLength = ChannelBuffers.buffer(2); 
    signLength.writeShort(signedParams.length); 
    return concat(signAlg.array(), concat(signLength.array(), signedParams)); 
} 

코드 것은 내가 클라이언트가 제공하는 목록에서 사용할 SignatureAndHashAlgorithm를 선택할 수있는 기능을 추가하기 때문에 사이에 다릅니다. 그러나 이것이 기본 HashAndSignatureAlgorithm 인 것처럼 SHA1withRSA 만 사용하여 응답하도록 수정할 수 있습니다.