预备知识
Java Socket, SSL单向认证
基本思路
服务端:使用keytool生成私钥和对应的证书。
客户端:代码生成私钥并自动添加服务端证书。
服务端
使用keytool生成keystore
keytool -genkey -v -alias <别名> -keyalg RSA -keystore <生成路径>
例:keytool -genkey -v -alias server_ssl -keyalg RSA -keystore C:\Users\ASUS\desktop\key
导出服务端证书
keytool -export -ailas <别名> -keystore <keystore路径> -file <证书导出路径>
例:keytool -export -ailas server_ssl -keystore C:\Users\ASUS\desktop\key -file C:\Users\ASUS\desktop\server_key.cer
keystore文件由服务端保存。证书文件由客户端保存。
服务端代码:
System.setProperty("javax.net.ssl.trustStore", "resources/key");
SSLContext context = SSLContext.getInstance("TLS");
KeyStore ks = KeyStore.getInstance("jceks");
ks.load(new FileInputStream("resources/key"), null); //keystore文件路径
KeyManagerFactory kf = KeyManagerFactory.getInstance("SunX509");
kf.init(ks, "123123".toCharArray()); //keystore密码 (生成keystore时设置的密码)
context.init(kf.getKeyManagers(), null, null);
SSLServerSocket ss = (SSLServerSocket) context.getServerSocketFactory().createServerSocket(65510);
ss.setNeedClientAuth(false);
此时得到的SSLServerSocket即是建立在TSL上的ServerSocket,用法与普通的ServerSocket基本一致。
客户端
生成keystore并将服务端证书添加进keystore
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
CertAndKeyGen keypair = new CertAndKeyGen("RSA", "SHA1WithRSA", null);
X500Name x500Name = new X500Name("test", "test", "test", "test", "test", "cn");
keypair.generate(1024);
PrivateKey privKey = keypair.getPrivateKey();
X509Certificate[] chain = new X509Certificate[1];
chain[0] = keypair.getSelfCertificate(x500Name, new Date(), (long) validity * 24 * 60 * 60);
keyStore.setKeyEntry("alias", privKey, "password", chain);
keyStore.setCertificateEntry("bluedash-ssl-demo-server", CertificateFactory.getInstance("X.509").
generateCertificate(new FileInputStream("resources/certificate/server_key.cer"))); //服务端证书路径
keyStore.store(new FileOutputStream(file), "password"); // file为导出的keystore文件的File对象
连接服务器
System.setProperty("javax.net.ssl.trustStore", "resources/users/loginregister/key"); // 生成的keystore文件的路径
SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
socket.connect(new InetSocketAddress(ip, port), 3000);
// socket.setNeedClientAuth(false);
此时得到的SSLSocket对象就是建立在TSL上的Socket,其用法与普通的Socket基本一致。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。