Когда я получил эту ошибку, это было связано с тем, что поддерживаемые сервером протоколы (версии TLS) и / или шифрованные версии не были включены (и, возможно, даже не поддерживаются) устройством. Для API 16-19 TLSv1.1 и TLSv1.2 поддерживаются, но не включены по умолчанию. Как только я включил их для этих версий, я все еще получил ошибку, потому что эти версии не поддерживают ни один из шифров нашего экземпляра AWS CloudFront.
Так как невозможно добавить шифры в Android, мы для переключения нашей версии CloudFront с TLSv1.2_2018 на TLSv1.1_2016 (которая все еще поддерживает TLSv1.2, она просто не требует этого), которая имеет четыре из шифров, поддерживаемых более ранними версиями Android, две из которых по-прежнему считаются сильными .
В этот момент ошибка исчезла, и вызовы прошли (с TLSv1.2), потому что был хотя бы один протокол и по крайней мере один шифр, который разделял устройство и сервер.
Обратитесь к таблицам на этой странице , чтобы узнать, какие протоколы и шифры поддерживаются и разрешены в каких версиях Android.
Теперь Android действительно пытался использовать SSLv3 как подразумеваемый по ошибке «sslv3 alert handshake failure» в сообщении об ошибке? Я сомневаюсь в этом; Я подозреваю, что это старая паутина в библиотеке SSL, которая не была очищена, но я не могу сказать точно.
Чтобы включить TLSv1.2 (и TLSv1.1), я был способный использовать гораздо более простой SSLSocketFactory
, чем тот, который можно найти в другом месте (например, NoSSLv3SocketFactory
). Он просто гарантирует, что включенные протоколы включают все поддерживаемые протоколы и что включенные шифры включают в себя все поддерживаемые шифры (последнее для меня не было необходимым, но это могло быть для других) - см. configure()
внизу. Если вы предпочитаете использовать только самые последние протоколы, вы можете заменить socket.supportedProtocols
на что-то вроде arrayOf("TLSv1.1", "TLSv1.2")
(аналогично для шифров):
class TLSSocketFactory : SSLSocketFactory() {
private val socketFactory: SSLSocketFactory
init {
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, null, null)
socketFactory = sslContext.socketFactory
}
override fun getDefaultCipherSuites(): Array {
return socketFactory.defaultCipherSuites
}
override fun getSupportedCipherSuites(): Array {
return socketFactory.supportedCipherSuites
}
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket {
return configure(socketFactory.createSocket(s, host, port, autoClose) as SSLSocket)
}
override fun createSocket(host: String, port: Int): Socket {
return configure(socketFactory.createSocket(host, port) as SSLSocket)
}
override fun createSocket(host: InetAddress, port: Int): Socket {
return configure(socketFactory.createSocket(host, port) as SSLSocket)
}
override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket {
return configure(socketFactory.createSocket(host, port, localHost, localPort) as SSLSocket)
}
override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket {
return configure(socketFactory.createSocket(address, port, localAddress, localPort) as SSLSocket)
}
private fun configure(socket: SSLSocket): SSLSocket {
socket.enabledProtocols = socket.supportedProtocols
socket.enabledCipherSuites = socket.supportedCipherSuites
return socket
}
}