2016-07-07 26 views
2

Я сейчас работаю на сервере Java TLS. Я пытаюсь получить следующую CipherSuite работать: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHATLS 1.2 ECDHE_RSA подпись

Когда я проверить его с помощью OpenSSL s_client я получаю следующее сообщение об ошибке после сообщения ServerKeyExchange:

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

Вот сообщение TLS, как показано в Wireshark The TLS message as seen in Wireshark

Рукопожатие терпит неудачу при фатальной ошибке decode_error.

Таким образом, я думаю, что клиенту не нравится выбранный алгоритм подписи.

Но я только использую по умолчанию SignatureAndHashAlgorithm на сейчас, как на 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}.

(я до сих пор проверки, если клиент предлагают тезисы значения по умолчанию, хотя)

Поскольку я делаю ECDHE_RSA Я считаю, что я должен хэширования и подписать serverECDHparams в соответствии с RFC 4492 Раздел 5.4 (первый пост здесь, так только 2 ссылки извините :))

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; 

и Я должен делать это в соответствии с 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); 

Мой Java-код относительно подписания 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), но 1.2 изменяется на стандартный PKCS1-v1_5 с одним выбранным сервером хешем; см. 5246 4.7 и второй пункт в списке различий в 1.2. –

ответ

0

Это снова я, я, кажется, исправили свою особую проблему 2 вещи, которые я заметил:

  1. Что касается моего Java кода, класс MessageDigest только не делает хэширования не подписания, так что я теперь использовать класс подписи вместо ,
  2. Кажется, мне нужно только подписать SHA1 в TLS1.2. Мне вообще не нужно делать MD5.

Второй пункт это то, что я должен был найти в RFC, но не сделал (может быть написано где-то, я не знаю), я думаю, что это может быть полезным для людей, даже если они не являются делает Java;)

Как мой код выглядит сейчас:

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 использовать из списка клиент предоставляет. Но вы можете изменить это, чтобы отвечать только с помощью SHA1withRSA, поскольку это, по-видимому, является HashAndSignatureAlgorithm по умолчанию.

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

  • Нет связанных вопросов^_^