Assinatura TLS 1.2 ECDHE_RSA
Atualmente, estou trabalhando em um servidor Java TLS. Estou tentando fazer com que o seguinte CipherSuite funcione: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Ao testá-lo usando o openssl s_client, recebo o seguinte erro após a mensagem ServerKeyExchange:
140735242416208: erro: 1414D172: rotinas SSL: tls12_check_peer_sigalg: tipo de assinatura incorreto: t1_lib.c: 1130:
Aqui está a mensagem TLS como vista em Wireshark
O Handshake falha em um erro fatal decode_error.
Acho que o cliente não gosta do algoritmo de assinatura escolhido.
Mas só estou usando o SignatureAndHashAlgorithm padrão por enquanto, conformeSeção RFC 5246 - 7.4.1.4.1
Se o algoritmo de troca de chaves negociado for um (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), comporte-se como se o cliente tivesse enviado o valor {sha1, rsa}.
(Ainda estou verificando se o cliente oferece esses valores padrão)
Desde que eu estou fazendo ECDHE_RSA, acredito que devo fazer o hash e assinar o serverECDHparams conforme a RFC 4492, seção 5.4 (primeiro post aqui, apenas 2 links, desculpe :))
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;
E devo fazer isso de acordo com a Seção 7.4.3 da RFC 2246
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);
Meu código Java sobre a assinatura do 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));
}
Então, minha pergunta é basicamente: estou errado sobre tudo isso? e se sim, o que estou fazendo de errado?
Obrigado pelo seu tempo! :)