ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【加密与解密】【07】SSL安全套件全剖析 [打印本页]

作者: 莫张周刘王    时间: 2024-7-31 02:05
标题: 【加密与解密】【07】SSL安全套件全剖析
SSL/TLS协议

SSL,Secure Socket Layer,安全套接层
TLS,Transport Layer Security,传输层安全协议
TLS是SSL的最终完善版本,一样平常也可称为SSL协议
SSL是负责传输层安全,确定传输层数据怎样封装的一套协议
SSL协议阶段


SSL协议核心内容


SSL协议应用


SSL核心类


通过KeyTool生成KeyStore

学习SSL起首得有用于测试的SSL证书库,所以我们先来看看怎样生成KeyStore
private.keystore和public.truststore本质上都是JKS文件,只是为了区分作用而换了后缀
  1. # 生成私钥证书,首个名称请输入域名或ip
  2. keytool -genkeypair -alias alias -keyalg RSA -validity 365 -keystore private.keystore
  3. # 生成公钥证书
  4. keytool -export -alias alias -keystore private.keystore -rfc -file public.cer
  5. # 公钥证书转为JKS格式
  6. keytool -import -alias alias -file public.cer -keystore public.truststore
复制代码
KeyStore格式转换

JKS是Java专用的秘钥仓库格式
差别平台和语言的对KeyStore的支持性和使用习惯并不一样
比如安卓就不支持JKS格式,安卓上的证书一样平常使用P12格式
我们可以通过KeyStore Explorer软件来转换
  1. https://keystore-explorer.org/downloads.html
复制代码
使用带SSL的TcpSocket

  1. import java.io.*
  2. import java.security.KeyStore
  3. import javax.net.ssl.KeyManagerFactory
  4. import javax.net.ssl.SSLContext
  5. import javax.net.ssl.SSLServerSocket
  6. import javax.net.ssl.SSLSocket
  7. import javax.net.ssl.TrustManagerFactory
  8. const val serverKeyStore = "resources/private.keystore"
  9. const val clientKeyStore = "resources/public.truststore"
  10. const val passphrase = "123456"
  11. const val serverPort = 18001
  12. fun main() {
  13.     Thread(::launchServerSocket).start()
  14.     Thread.sleep(500)
  15.     Thread(::launchClientSocket).start()
  16. }
  17. fun launchServerSocket() {
  18.     // load key manager from key store
  19.     val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")
  20.     val keyStore = KeyStore.getInstance("JKS")
  21.     keyStore.load(FileInputStream(serverKeyStore), passphrase.toCharArray())
  22.     keyManagerFactory.init(keyStore, passphrase.toCharArray())
  23.     val keyManagers = keyManagerFactory.keyManagers
  24.     // init ssl context
  25.     val context = SSLContext.getInstance("TLS")
  26.     context.init(keyManagers, null, null)
  27.     // create server socket
  28.     val serverSocketFactory = context.serverSocketFactory
  29.     val serverSocket = serverSocketFactory.createServerSocket(serverPort) as SSLServerSocket
  30.     serverSocket.needClientAuth = false
  31.     // accept client session
  32.     val socket = serverSocket.accept() as SSLSocket
  33.     // communication with client
  34.     while (true) {
  35.         Thread.sleep(500)
  36.         socket.getOutputStream().write("Hello World".encodeToByteArray())
  37.         socket.getOutputStream().flush()
  38.     }
  39. }
  40. fun launchClientSocket() {
  41.     // load trust manager from trust store
  42.     val trustManagerFactory = TrustManagerFactory.getInstance("SunX509")
  43.     val trustStore = KeyStore.getInstance("JKS")
  44.     trustStore.load(FileInputStream(clientKeyStore), passphrase.toCharArray())
  45.     trustManagerFactory.init(trustStore)
  46.     val trustManagers = trustManagerFactory.trustManagers
  47.     // init ssl context
  48.     val context = SSLContext.getInstance("TLS")
  49.     context.init(null, trustManagers, null)
  50.     // create client socket and auto connect
  51.     val sslSocketFactory = context.socketFactory
  52.     val socket = sslSocketFactory.createSocket("localhost", serverPort) as SSLSocket
  53.     // communication with server
  54.     val buffer = ByteArray(1024)
  55.     while (true) {
  56.         val len = socket.getInputStream().read(buffer)
  57.         if (len > 0) {
  58.             val message = String(buffer, 0, len)
  59.             println("Client Received: $message")
  60.         }
  61.     }
  62. }
复制代码
使用带SSL的HttpServer

大多网络编程框架,都是默认支持Https协议的,但仅限于由CA机构颁发的可信任证书
对于人工签发,未经CA机构授权的自署名证书,必须由开辟者自己去实现验证逻辑
  1. import com.sun.net.httpserver.HttpsConfigurator
  2. import com.sun.net.httpserver.HttpsServer
  3. import java.io.*
  4. import java.net.InetSocketAddress
  5. import java.net.URI
  6. import java.net.http.HttpClient
  7. import java.net.http.HttpRequest
  8. import java.net.http.HttpResponse
  9. import java.security.KeyStore
  10. import java.util.*
  11. import javax.net.ssl.KeyManagerFactory
  12. import javax.net.ssl.SSLContext
  13. import javax.net.ssl.TrustManagerFactory
  14. const val serverKeyStore = "resources/private.keystore"
  15. const val clientKeyStore = "resources/public.truststore"
  16. const val passphrase = "123456"
  17. const val serverPort = 18001
  18. fun main() {
  19.     Thread(::launchHttpServer).start()
  20.     Thread.sleep(1500)
  21.     Thread(::launchHttpClient).start()
  22. }
  23. fun launchHttpServer() {
  24.     // load key manager from key store
  25.     val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")
  26.     val keyStore = KeyStore.getInstance("JKS")
  27.     keyStore.load(FileInputStream(serverKeyStore), passphrase.toCharArray())
  28.     keyManagerFactory.init(keyStore, passphrase.toCharArray())
  29.     val keyManagers = keyManagerFactory.keyManagers
  30.     // configure ssl context
  31.     val context = SSLContext.getInstance("TLS")
  32.     context.init(keyManagers, null, null)
  33.     // create https server
  34.     val server = HttpsServer.create(InetSocketAddress(serverPort), 10)
  35.     // configure https
  36.     val configurator = HttpsConfigurator(context)
  37.     server.httpsConfigurator = configurator
  38.     // create service
  39.     server.createContext("/home") { exchange ->
  40.         val response = Date().toString().encodeToByteArray()
  41.         exchange.sendResponseHeaders(200, response.size.toLong())
  42.         exchange.responseBody.write(response)
  43.         exchange.responseBody.close()
  44.     }
  45.     // start https server
  46.     server.start()
  47. }
  48. fun launchHttpClient() {
  49.     // load trust manager from trust store
  50.     val trustManagerFactory = TrustManagerFactory.getInstance("SunX509")
  51.     val trustStore = KeyStore.getInstance("JKS")
  52.     trustStore.load(FileInputStream(clientKeyStore), passphrase.toCharArray())
  53.     trustManagerFactory.init(trustStore)
  54.     val trustManagers = trustManagerFactory.trustManagers
  55.     // init ssl context
  56.     val context = SSLContext.getInstance("TLS")
  57.     context.init(null, trustManagers, null)
  58.     // create http client
  59.     val uri = URI.create("https://localhost:18001/home")
  60.     val client = HttpClient.newBuilder()
  61.         .version(HttpClient.Version.HTTP_1_1)
  62.         .sslContext(context)
  63.         .build()
  64.     // send request
  65.     val request = HttpRequest.newBuilder()
  66.         .GET()
  67.         .uri(uri)
  68.         .build()
  69.     // get response
  70.     val response = client.send(request, HttpResponse.BodyHandlers.ofString())
  71.     println(response.body())
  72. }
复制代码
使用带SSL的WebSocket

这里我们使用比力出名的Java-WebSocket库来实现WebSocket服务端和客户端功能
  1. api("org.java-websocket:Java-WebSocket:1.5.1")
复制代码
为WebSocketServer设置SSL
  1. fun setServerSSL(server: WebSocketServer) {
  2.     // load key manager from key store
  3.     val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")
  4.     val keyStore = KeyStore.getInstance("JKS")
  5.     keyStore.load(FileInputStream(serverKeyStore), passphrase.toCharArray())
  6.     keyManagerFactory.init(keyStore, passphrase.toCharArray())
  7.     val keyManagers = keyManagerFactory.keyManagers
  8.     // configure ssl context
  9.     val context = SSLContext.getInstance("TLS")
  10.     context.init(keyManagers, null, null)
  11.     // configure server ssl
  12.     val websocketServerFactory = DefaultSSLWebSocketServerFactory(context)
  13.     server.setWebSocketFactory(websocketServerFactory)
  14. }
复制代码
为WebSocketClient设置SSL
  1. fun setClientSSL(client: WebSocketClient) {
  2.     // load trust manager from trust store
  3.     val trustManagerFactory = TrustManagerFactory.getInstance("SunX509")
  4.     val trustStore = KeyStore.getInstance("JKS")
  5.     trustStore.load(FileInputStream(clientKeyStore), passphrase.toCharArray())
  6.     trustManagerFactory.init(trustStore)
  7.     val trustManagers = trustManagerFactory.trustManagers
  8.     // configure ssl context
  9.     val context = SSLContext.getInstance("TLS")
  10.     context.init(null, trustManagers, null)
  11.     // configure client ssl
  12.     val sslSocketFactory = context.socketFactory
  13.     client.setSocketFactory(sslSocketFactory)
  14. }
复制代码
在OkHttp中自界说KeyManager和TrustManager

以上案例,都是通过KeyStore来实现KeyManager和TrustManager的管理功能
现在我们不用KeyStore,通过自界说规则,来实现秘钥管理和证书验证功能
我们以OkHttp框架为例
  1. import okhttp3.OkHttpClient
  2. import java.security.cert.X509Certificate
  3. import javax.net.ssl.HostnameVerifier
  4. import javax.net.ssl.SSLContext
  5. import javax.net.ssl.SSLSession
  6. import javax.net.ssl.X509TrustManager
  7. fun setOkHttpSSL(builder: OkHttpClient.Builder) {
  8.     val trustManager = object : X509TrustManager {
  9.         override fun checkClientTrusted(chain: Array<out X509Certificate>, authType: String) {}
  10.         override fun checkServerTrusted(chain: Array<out X509Certificate>, authType: String) {}
  11.         override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
  12.     }
  13.     val trustManagers = arrayOf(trustManager)
  14.     val hostnameVerifier = HostnameVerifier { hostname: String, session: SSLSession -> true }
  15.     val sslContext = SSLContext.getInstance("SSL")
  16.     sslContext.init(null, trustManagers, null)
  17.     val socketFactory = sslContext.socketFactory
  18.     builder.sslSocketFactory(socketFactory, trustManager)
  19.     builder.hostnameVerifier(hostnameVerifier)
  20. }
复制代码
现在我们用OkHttp来更换上面的HttpClient来访问服务器
  1. fun launchHttpClient() {
  2.     val url = "https://localhost:18001/home"
  3.     // create okhttp client
  4.     val builder = OkHttpClient.Builder()
  5.     setOkHttpSSL(builder)
  6.     val client = builder.build()
  7.     // create request
  8.     val request = Request.Builder()
  9.         .url(url)
  10.         .get()
  11.         .build()
  12.     // execute call
  13.     val call = client.newCall(request)
  14.     val response = call.execute()
  15.     // print response
  16.     val responseBody = response.body.string()
  17.     println(responseBody)
  18. }
复制代码
这里我们为了演示,不让问题复杂化,只是简单地信任了全部的证书,并不能起到现实的安全作用
关于KeyManager,TrustManager,HostnameVerifier的正式用法,可以参考以下类的源码
SunX509KeyManagerImpl X509TrustManagerImpl OkHostnameVerifier
SSL证书格式


SSL证书转换工具


OpenSSL指令


OpenSSL制作证书

  1. # 创建根证书
  2. openssl req -new -x509 -days 365 -extensions v3_ca -keyout crt/ca.key -out crt/ca.crt
  3. # 颁发服务端证书
  4. openssl genrsa -out crt/server.key 2048
  5. openssl req -out crt/server.csr -key crt/server.key -new
  6. openssl x509 -req -in crt/server.csr -CA crt/ca.crt -CAkey crt/ca.key -CAcreateserial -out crt/server.crt -days 365
  7. # 颁发客户端证书
  8. openssl genrsa -out crt/client.key 2048
  9. openssl req -out crt/client.csr -key crt/client.key -new
  10. openssl x509 -req -in crt/client.csr -CA crt/ca.crt -CAkey crt/ca.key -CAcreateserial -out crt/client.crt -days 365
  11. # 查看服务端证书
  12. openssl x509 -in crt/server.crt -text -noout
复制代码
End

到此为止,基本涵盖了Java SSL的全部核心内容,已经足以满足各人日常开辟需要
更高阶的用法,大概在专业的范畴才气用得到,希望各人遇到时,能勇于自己去研究!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4