這篇文章主要介紹了Netty、MINA、Twisted中SSL/TLS的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
1. 相關(guān)術(shù)語(yǔ)
在學(xué)習(xí)SSL/TLS協(xié)議之前,首先要了解一些相關(guān)概念:
對(duì)稱(chēng)加密:加密和解密都采用同一個(gè)密鑰,常用的算法有DES、3DES、AES,相對(duì)于非對(duì)稱(chēng)加密算法更簡(jiǎn)單速度更快。
非對(duì)稱(chēng)加密:和對(duì)稱(chēng)加密算法不同,非對(duì)稱(chēng)加密算法會(huì)有兩個(gè)密鑰:公鑰(可以公開(kāi)的)和私鑰(私有的),例如客戶(hù)端如果使用公鑰加密,那么即時(shí)其他人有公鑰也無(wú)法解密,只能通過(guò)服務(wù)器私有的私鑰解密。RSA算法即是典型的非對(duì)稱(chēng)加密算法。
數(shù)字證書(shū):數(shù)字證書(shū)是一個(gè)包含公鑰并且通過(guò)權(quán)威機(jī)構(gòu)發(fā)行的一串?dāng)?shù)據(jù),數(shù)字證書(shū)很多需要付費(fèi)購(gòu)買(mǎi),也有免費(fèi)的,另外也可以自己生成數(shù)字證書(shū),本文中將會(huì)采用自簽名的方式生成數(shù)字證書(shū)。
2. SSL/TLS流程
使用SSL/TLS協(xié)議的服務(wù)器和客戶(hù)端開(kāi)始通信之前,會(huì)先進(jìn)行一個(gè)握手階段:
1)客戶(hù)端發(fā)出請(qǐng)求:這一步客戶(hù)端會(huì)生成一個(gè)隨機(jī)數(shù)傳給服務(wù)器。
2)服務(wù)器回應(yīng):這一步服務(wù)器會(huì)返回給客戶(hù)端一個(gè)服務(wù)器數(shù)字證書(shū)(證書(shū)中包含用于加密的公鑰),另外服務(wù)器也會(huì)生成一個(gè)隨機(jī)數(shù)給客戶(hù)端。
3)客戶(hù)端回應(yīng):這一步客戶(hù)端首先會(huì)校驗(yàn)數(shù)字證書(shū)的合法性,然后會(huì)再生成一個(gè)隨機(jī)數(shù),這個(gè)隨機(jī)數(shù)會(huì)使用第2步中的公鑰采用非對(duì)稱(chēng)加密算法(例如RSA算法)進(jìn)行加密后傳給服務(wù)器,密文只能通過(guò)服務(wù)器的私鑰來(lái)解密。
4)服務(wù)器最后回應(yīng):握手結(jié)束。
握手結(jié)束后,客戶(hù)端和服務(wù)器都有上面握手階段的三個(gè)隨機(jī)數(shù)。客戶(hù)端和服務(wù)器都通過(guò)這三個(gè)隨機(jī)生成一個(gè)密鑰,接下來(lái)所有的通信內(nèi)容都使用這個(gè)密鑰通過(guò)對(duì)稱(chēng)加密算法加密傳輸,服務(wù)器和客戶(hù)端才開(kāi)始進(jìn)行安全的通信。
3. 生成私鑰和證書(shū)
使用openssl來(lái)生成私鑰和證書(shū):
openssl req -x509 -newkey rsa:2048 -nodes -days 365 -keyout private.pem -out cert.crt
運(yùn)行以上命令后,會(huì)在當(dāng)前目錄下生成一個(gè)私鑰文件(private.pem)和一個(gè)證書(shū)文件(cert.crt)。
生成的私鑰和證書(shū)Twisted、Netty可以直接使用,然而MINA對(duì)私鑰文件的格式的要求,要將pem格式轉(zhuǎn)換成der格式,實(shí)際上就是將文本文件私鑰轉(zhuǎn)成二進(jìn)制文件私鑰。openssl將private.pem轉(zhuǎn)成private.der私鑰文件:
openssl pkcs8 -topk8 -inform PEM -in private.pem -outform DER -nocrypt -out private.der
4. SSL/TLS服務(wù)器
接下來(lái)在Netty、MINA、Twisted一起學(xué)系列02:TCP消息邊界問(wèn)題及按行分割消息 一文的基礎(chǔ)上,加上SSL/TLS層。
1)MINA
MINA 可以通過(guò) SslFilter 來(lái)實(shí)現(xiàn) SSL/TLS,初始化 SslFilter 的代碼比較繁瑣:
public class MinaServer {
public static void main(String[] args) throws Exception {
String certPath = "/Users/wucao/Desktop/ssl/cert.crt"; // 證書(shū)
String privateKeyPath = "/Users/wucao/Desktop/ssl/private.der"; // 私鑰
// 證書(shū)
// /tupian/20230522/ InputStream inStream = null;
Certificate certificate = null;
try {
inStream = new FileInputStream(certPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
certificate = cf.generateCertificate(inStream);
} finally {
if (inStream != null) {
inStream.close();
}
}
// 私鑰
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Files.readAllBytes(new File(privateKeyPath).toPath()));
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
Certificate[] certificates = {certificate};
ks.setKeyEntry("key", privateKey, "".toCharArray(), certificates);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, "".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, null);
IoAcceptor acceptor = new NioSocketAcceptor();
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
chain.addLast("ssl", new SslFilter(sslContext)); // SslFilter需要放在最前面
chain.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"), "\r\n", "\r\n")));
acceptor.setHandler(new TcpServerHandle());
acceptor.bind(new InetSocketAddress(8080));
}
}
class TcpServerHandle extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
cause.printStackTrace();
}
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String line = (String) message;
System.out.println("messageReceived:" + line);
}
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("sessionCreated");
}
@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("sessionClosed");
}
}
2)Netty
Netty 通過(guò)添加一個(gè) SslHandler 來(lái)實(shí)現(xiàn) SSL/TLS,相對(duì) MINA 來(lái)說(shuō)代碼就比較簡(jiǎn)潔:
public class NettyServer {
public static void main(String[] args) throws InterruptedException, SSLException {
File certificate = new File("/Users/wucao/Desktop/ssl/cert.crt"); // 證書(shū)
File privateKey = new File("/Users/wucao/Desktop/ssl/private.pem"); // 私鑰
final SslContext sslContext = SslContextBuilder.forServer(certificate, privateKey).build();
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// SslHandler要放在最前面
SslHandler sslHandler = sslContext.newHandler(ch.alloc());
pipeline.addLast(sslHandler);
pipeline.addLast(new LineBasedFrameDecoder(80));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new TcpServerHandler());
}
});
ChannelFuture f = b.bind(8080).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
class TcpServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
String line = (String) msg;
System.out.println("channelRead:" + line);
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("channelActive");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
System.out.println("channelInactive");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
3)Twisted
Twisted 實(shí)現(xiàn) SSL/TLS 也是非常簡(jiǎn)單的,將 reactor.listenTCP 替換為 reactor.listenSSL 即可。
# -*- coding:utf-8 –*-
from twisted.protocols.basic import LineOnlyReceiver
from twisted.internet.protocol import Factory
from twisted.internet import reactor, ssl
sslContext = ssl.DefaultOpenSSLContextFactory(
'/Users/wucao/Desktop/ssl/private.pem', # 私鑰
'/Users/wucao/Desktop/ssl/cert.crt', # 公鑰
)
class TcpServerHandle(LineOnlyReceiver):
def connectionMade(self):
print 'connectionMade'
def connectionLost(self, reason):
print 'connectionLost'
def lineReceived(self, data):
print 'lineReceived:' + data
factory = Factory()
factory.protocol = TcpServerHandle
reactor.listenSSL(8080, factory, sslContext)
reactor.run()
5. SSL/TLS客戶(hù)端
這里還是使用Java來(lái)寫(xiě)一個(gè)SSL/TLS客戶(hù)端,用來(lái)測(cè)試以上三個(gè)服務(wù)器程序。需要注意的是,在上面SSL/TLS流程的介紹中,SSL/TLS握手階段的第2步服務(wù)器會(huì)將證書(shū)傳給客戶(hù)端,第3步客戶(hù)端會(huì)校驗(yàn)證書(shū)的合法性,所以下面的代碼首先會(huì)讓客戶(hù)端信任openssl生成的證書(shū),才能正確的完成SSL/TLS握手。
public class SSLClient {
public static void main(String args[]) throws Exception {
// 客戶(hù)端信任改證書(shū),將用于校驗(yàn)服務(wù)器傳過(guò)來(lái)的證書(shū)的合法性
String certPath = "/Users/wucao/Desktop/ssl/cert.crt";
InputStream inStream = null;
Certificate certificate = null;
try {
inStream = new FileInputStream(certPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
certificate = cf.generateCertificate(inStream);
} finally {
if (inStream != null) {
inStream.close();
}
}
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry("cert", certificate);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
tmf.init(ks);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
Socket socket = null;
OutputStream out = null;
try {
socket = socketFactory.createSocket("localhost", 8080);
out = socket.getOutputStream();
// 請(qǐng)求服務(wù)器
String lines = "床前明月光\r\n疑是地上霜\r\n舉頭望明月\r\n低頭思故鄉(xiāng)\r\n";
byte[] outputBytes = lines.getBytes("UTF-8");
out.write(outputBytes);
out.flush();
} finally {
// 關(guān)閉連接
out.close();
socket.close();
}
}
}
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Netty、MINA、Twisted中SSL/TLS的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
新聞標(biāo)題:Netty、MINA、Twisted中SSL/TLS的示例分析-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)鏈接:http://www.yijiale78.com/article6/hhdog.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、App開(kāi)發(fā)、網(wǎng)站建設(shè)、動(dòng)態(tài)網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)、小程序開(kāi)發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容