2016-07-07 12 views
2

Ich arbeite gerade an einem Java-TLS-Server. Ich versuche, die folgende CipherSuite an der Arbeit: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHATLS 1.2 ECDHE_RSA-Signatur

Als ich es testen openssl s_client ich mit dem folgenden Fehler nach der ServerKeyExchange Meldung:

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

Hier ist die TLS-Nachricht wie in Wireshark gesehen The TLS message as seen in Wireshark

Der Handshake schlägt bei einem schwerwiegenden decode_error-Fehler fehl.

Also ich schätze, dass der Client den gewählten Signaturalgorithmus nicht mag.

Aber ich bin nur die Standard-SignatureAndHashAlgorithm mit jetzt per 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}.

(Ich überprüfe noch, wenn der Kunde es jedoch Standardwerte bieten Thesen)

Da ich ECDHE_RSA mache ich glaube, ich Hash sollte und unterschreiben die serverECDHparams gemäß RFC 4492 Abschnitt 5.4 (erster Beitrag hier so nur 2 Links leid :))

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; 

und ich tun dies gemäß RFC 2246 Abschnitt sollte 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); 

Mein Java-Code in Bezug auf die serverParams Unterzeichnung:

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)); 
} 

Also meine Frage ist im Grunde: Bin ich falsch über alles? und wenn ja, was mache ich falsch?

Vielen Dank für Ihre Zeit! :)

+0

Ich würde vorschlagen, diese Frage auf dem Stackoverflow-Forum für Ihre Programmierung im Zusammenhang Zweifel zu stellen. Sie können schnell Antworten bekommen – Limit

+0

Danke, nun dachte ich, das war ein reines Problem von mir nicht verstehen, die RFCs. Ich habe seitdem ein (das?) antworte und ich poste es dort, damit Leute es später noch finden können :) – Alpha4

+0

Der Text, den du aus 5246 7.1.4.1 zitierst, lautet "Wenn der Client die signature_algorithms-Erweiterung nicht sendet". openssl s_client ** sendet ** die Erweiterung; Schauen Sie sich den ClientHallo in Ihrem Trace an - aber er enthält 0201 SHA1 + RSA und sollte diese Unterschrift deshalb nicht ablehnen. Ihre Signatur ist jedoch falsch, wie Sie festgestellt haben; die MD5 + SHA1 + RSA-Signatur wird in TLS 1.0 (2246) und 1.1 (4346) verwendet, aber 1.2 ändert sich zu Standard PKCS1-v1_5 mit einem einzigen, vom Server ausgewählten Hash; siehe 5246 4.7 und der zweite Punkt in der Liste der Unterschiede in 1.2. –

Antwort

0

Es ist mir wieder, ich scheine 2 Dinge, die mein besonderes Problem zu haben feste ich gemerkt:

  1. In Bezug auf mein Java-Code, nur die Message Klasse nicht Hashing keine Unterzeichnung so dass ich jetzt stattdessen die Signature-Klasse verwenden .
  2. Es scheint, dass ich nur unter Verwendung von SHA1 in TLS1.2 unterschreiben muss. Ich brauche MD5 überhaupt nicht zu tun.

Der zweite Punkt ist, was ich in der RFC gefunden habe, sollte aber nicht (vielleicht ist es irgendwo geschrieben, ich weiß es nicht) Ich denke, dies auch für Menschen nützlich sein könnte, wenn sie nicht tun Java;)

Wie mein Code sieht jetzt:

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)); 
} 

den Code ist anders, weil zwischen mir eine Funktion hinzugefügt, um die SignatureAndHashAlgorithm zu wählen aus der Liste zu verwenden, der Client zur Verfügung stellt. Aber Sie könnten dies ändern, um nur mit SHA1withRSA zu antworten, da dies der Standard-HashAndSignatureAlgorithm zu sein scheint.