证书还是采用keytool生成的,这里都把信任库和私钥证书啥的,都放到了一个文件。
程序运行如下:
服务端:
客户端:
程序结构如下:
源码如下:
SslContextProvider.java
public interface SslContextProvider {
TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException;
KeyManager[] getKeyManagers() throws GeneralSecurityException, IOException;
String getProtocol();
}
SslUtil.java
public class SslUtil {
private static final String JKS = "JKS";
public static KeyManager[] createKeyManagers(String keyStorePath, String password) throws NoSuchAlgorithmException, KeyStoreException, IOException {
return createKeyManagers(keyStorePath, password, password);
}
public static KeyManager[] createKeyManagers(String keyStorePath, String storePassword, String keyPassword) throws NoSuchAlgorithmException, KeyStoreException, IOException {
String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmInstance = KeyManagerFactory.getInstance(defaultAlgorithm);
KeyStore ksInstance = KeyStore.getInstance(JKS);
FileInputStream fileInputStream = new FileInputStream(keyStorePath);
try {
ksInstance.load(fileInputStream, storePassword.toCharArray());
}
catch (IOException e) {
e.printStackTrace();
}
catch (CertificateException e) {
e.printStackTrace();
}
finally {
if(fileInputStream != null){
fileInputStream.close();
}
}
try {
kmInstance.init(ksInstance, keyPassword.toCharArray());
}
catch (UnrecoverableKeyException e) {
e.printStackTrace();
}
return kmInstance.getKeyManagers();
}
public static SSLContext createSSLContext(SslContextProvider provider) throws GeneralSecurityException, IOException {
SSLContext context = SSLContext.getInstance(provider.getProtocol());
context.init(provider.getKeyManagers(), provider.getTrustManagers(), new SecureRandom());
return context;
}
public static SSLServerSocket createSSLServerSocket(int port, SslContextProvider provider) throws GeneralSecurityException, IOException {
SSLContext context = createSSLContext(provider);
SSLServerSocketFactory serverSocketFactory = context.getServerSocketFactory();
SSLServerSocket sslServerSocket = (SSLServerSocket) serverSocketFactory.createServerSocket(port);
sslServerSocket.setEnabledProtocols(new String[]{provider.getProtocol()});
sslServerSocket.setNeedClientAuth(true);
return sslServerSocket;
}
public static SSLSocket createSSLSocket(String host, int port, SslContextProvider provider) throws GeneralSecurityException, IOException {
SSLContext sslContext = createSSLContext(provider);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(host, port);
sslSocket.setEnabledProtocols(new String[]{provider.getProtocol()});
return sslSocket;
}
public static TrustManager[] createTrustManagers(String keyStorePath, String password) throws NoSuchAlgorithmException, KeyStoreException, IOException {
String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmInstance = TrustManagerFactory.getInstance(defaultAlgorithm);
KeyStore ksInstance = KeyStore.getInstance(JKS);
FileInputStream fileInputStream = new FileInputStream(keyStorePath);
try{
ksInstance.load(fileInputStream, password.toCharArray());
}
catch(IOException e){
e.printStackTrace();
}
catch(CertificateException e){
e.printStackTrace();
}
finally {
if(fileInputStream != null){
fileInputStream.close();
}
}
tmInstance.init(ksInstance);
return tmInstance.getTrustManagers();
}
public static String getPeerIdentity(Socket socket){
if(!(socket instanceof SSLSocket)){
return null;
}
SSLSession session = ((SSLSocket) socket).getSession();
try {
Principal peerPrincipal = session.getPeerPrincipal();
return getCommonName(peerPrincipal);
}
catch(SSLPeerUnverifiedException e){
e.printStackTrace();
}
return "unknown client";
}
private static String getCommonName(Principal subject){
try{
LdapName ldapName = new LdapName(subject.getName());
for(Rdn rdn : ldapName.getRdns()){
if("cn".equalsIgnoreCase(rdn.getType())){
return (String)rdn.getValue();
}
}
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
}
SslServer.java
public class SslServer implements SslContextProvider {
public TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException {
return SslUtil.createTrustManagers("server.jks", "cccccc");
}
public KeyManager[] getKeyManagers() throws GeneralSecurityException, IOException {
return SslUtil.createKeyManagers("server.jks", "cccccc");
}
public String getProtocol() {
return "TLSv1.2";
}
private ServerSocket createSSLSocket(int port) throws GeneralSecurityException, IOException {
SSLServerSocket sslServerSocket = SslUtil.createSSLServerSocket(port, this);
return sslServerSocket;
}
public void run(int port) throws GeneralSecurityException, IOException {
ServerSocket serverSocket = createSSLSocket(port);
System.out.println("服务端启动成功,等待客户端连接.... .... .... ....");
try(SSLSocket client = (SSLSocket) serverSocket.accept(); OutputStream os = client.getOutputStream(); InputStream is = client.getInputStream()){
System.out.println("客户端: " + SslUtil.getPeerIdentity(client) + " 成功连接!");
int available = is.available();
byte[] b = new byte[1024];
is.read(b);
System.out.println("接收到客户端消息:" + new String(b));
System.out.println("发送消息给客户端!");
os.write("Hello!".getBytes());
os.flush();
System.out.println("发送完成!");
}
catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) throws GeneralSecurityException, IOException {
if(args.length != 1){
System.out.println("Usage: SslServer <port>");
System.exit(1);
}
Integer port = Integer.parseInt(args[0]);
new SslServer().run(port);
}
}
SslClient.java
public class SslClient implements SslContextProvider {
public static void main(String[] args) throws Exception {
if(args.length != 2){
System.out.println("Usage: SslClient <host> <port>");
System.exit(1);
}
String host = args[0];
Integer port = Integer.parseInt(args[1]);
new SslClient().run(host, port);
}
@Override
public TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException {
return SslUtil.createTrustManagers("client.jks", "cccccc");
}
@Override
public KeyManager[] getKeyManagers() throws GeneralSecurityException, IOException {
return SslUtil.createKeyManagers("client.jks", "cccccc");
}
@Override
public String getProtocol() {
return "TLSv1.2";
}
public void run(String host, Integer port) throws Exception {
try(SSLSocket sslSocket = createSSLSocket(host, port); OutputStream os = sslSocket.getOutputStream(); InputStream is = sslSocket.getInputStream()){
System.out.println("已成功连接到服务端.......");
os.write("hehe".getBytes());
os.flush();
System.out.println("已发送 hehe 到服务端");
byte[] buf = new byte[1024];
is.read(buf);
System.out.println("接收到服务端消息:" + new String(buf));
}
catch (Exception e){
e.printStackTrace();
}
}
private SSLSocket createSSLSocket(String host, Integer port) throws Exception {
return SslUtil.createSSLSocket(host, port, this);
}
}
源码打包下载地址:
https://github.com/fengfanchen/Java/tree/master/Java_Socket_Ssl_Two_Way