Как указать ciphersuite для использования в сеансе SSL
Я создал сокет на порту 443, как в следующей строке:
socket = (SSLSocket) factory.createSocket(hostName, port);
Затем я хотел увидеть активированные ciphersuites в этом сокете, я использовал:
String[] enCiphersuite=socket.getEnabledCipherSuites();
System.out.println("Enabled ciphersuites are: "+Arrays.toString(enCiphersuite));
Затем я хочу выбрать только один ciphersuite, который хочу, чтобы мое приложение использовалось при создании рукопожатия с удаленным сервером. Я сделал следующее:
String pickedCipher[] ={"TLS_RSA_WITH_AES_128_CBC_SHA"};
socket.setEnabledCipherSuites(pickedCipher);
System.out.println("ciphersuite set to: "+Arrays.toString(pickedCipher));
Затем я сделал рукопожатие и проверил сеанс ciphersuite:
socket.startHandshake();
System.out.println("Session ciphersuite is"+socket.getSession().getCipherSuite() );
Но я обнаружил, что имя шифра, напечатанного в предыдущем заявлении распечатки после рукопожатия (как я понимаю, это фактически используемый шифр в сеансе), не то, что я установил раньше, используя setEnabledCipherSuites()
Почему я все еще не вижу, что мой выбранный ciphersuite используется? а также, я также попытался getEnabledCipherSuites()
и распечатать его после я setEnabledCipherSuites
и нашел, что список не изменился до того, что я установил. Я не уверен, когда я печатаю разрешенный ciphersuite, этот список ciphersuites зависит от Java и всегда одного и того же списка, или зависит от клиента или от сервера? Может ли какой-нибудь орган объяснить?
EDIT:
Перед рукопожатием у меня есть только следующие строки:
SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();
SSLSocket socket=null;
try {
socket = (SSLSocket) factory.createSocket(hostName, port);
socket.setSoTimeout(15000);
socket.startHandshake(); //handshake
.
.
Ответы
Ответ 1
Я узнал, что добавил socket.getsession() до setEnableCipherSuite(), чтобы распечатать разрешенные шифры перед установкой. Когда я его удалю, шифр был установлен. Зачем что?
Как описано в SSLSocket
JavaDoc:
Первоначальное рукопожатие на этом соединении может быть инициировано в одном из тремя способами:
- вызов startHandshake, который явно начинает рукопожатие, или
- любая попытка чтения или записи данных приложения в этом сокете вызывает неявное рукопожатие или
- вызов getSession пытается настроить сеанс, если в настоящий момент нет действующего сеанса, а неявное рукопожатие выполняется.
Если вы вызываете getSession()
перед вызовом setEnabledCipherSuite()
, рукопожатие уже выполнено, когда вы пытаетесь установить разрешенные комплекты шифрования, поэтому этот набор шифрования сеанса уже выбран.