1. 程式人生 > >JAVA與C++進行sslsocket通訊,JAVA做服務端或客戶端

JAVA與C++進行sslsocket通訊,JAVA做服務端或客戶端

一、JAVA做服務端,讀取pem格式的證書和祕鑰

<span style="font-size:18px;">public class SocketServer extends Thread{
	private static final int SERVER_PORT = 10002; 

	private SSLServerSocket serverSocket;
	
	public SocketServer() {
		// Initialize SSLServer
		try {
			//Load KeyStore And TrustKeyStore
			Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
			//儲存服務端的私鑰
			KeyStore keyStore = KeyStore.getInstance("JKS");
			keyStore.load(null, null);
//			// 讀入服務端證書  
			PEMReader cacertfile = new PEMReader(new InputStreamReader(
					new FileInputStream("d:/cacert.pem")));
			X509Certificate cacert = (X509Certificate) cacertfile.readObject();
			Certificate[] certChain = new Certificate[1];  
			certChain[0] = cacert; 
			cacertfile.close();
	       // 讀入私鑰  
			PEMReader kr = new PEMReader(new InputStreamReader(new FileInputStream("d:/privkey.pem")));
			KeyPair key = (KeyPair) kr.readObject();
            kr.close();
            // 匯入服務端端私鑰和證書
            keyStore.setKeyEntry("serverkey", key.getPrivate(), new char[]{}, certChain );
            keyStore.setCertificateEntry("servercert", cacert);  
			//Initialize KeyStore Factory   建立用於管理JKS金鑰庫的X.509金鑰管理器
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");			
			keyManagerFactory.init(keyStore, "".toCharArray());			
			//Initialize SSLContext
			SSLContext context = SSLContext.getInstance("TLSv1");			
				//授權的金鑰管理器,用來授權驗證,
			context.init(keyManagerFactory.getKeyManagers(), null, null);			
			//Set up Server Socket			
				serverSocket = (SSLServerSocket) context.
					getServerSocketFactory().createServerSocket(SERVER_PORT);
				serverSocket.setWantClientAuth(false); //不需要客戶端證書
			} catch (Exception e) {
				e.printStackTrace();
			} 		
	}
		
	@Override
	public void run() {
		if(serverSocket == null){
			System.out.println("Null server socket");
			return;
		}
			try {
				Socket socket = serverSocket.accept();				
				//Receive From Client
				InputStream input = socket.getInputStream();
				System.out.println("------Receive------");
				//use byte array to initialize the output string
				System.out.println(new String(StreamToByteArray(input)));
				if(!socket.isClosed()){
					//Response To Client
					OutputStream output = socket.getOutputStream();
					output.write("服務端傳送123".getBytes());
					output.flush();
					socket.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
	}
	
	
	/**
	 * convert stream to Byte Array
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	public byte[] StreamToByteArray(InputStream inputStream) throws IOException {
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int readIndex = inputStream.read(buffer);
		bout.write(buffer, 0, readIndex);
		bout.flush();
		bout.close();
		//inputStream.close();
		return bout.toByteArray();
	}
	
	
	public static void main(String[] args){
		System.out.println("=======Start Server !======");
		new SocketServer().run();
	}
}
</span>
二、JAVA做客戶端,讀取pem格式證書和祕鑰
<span style="font-size:18px;">public class SocketClient2 {

	private Logger logger = LoggerFactory.getLogger(SocketClient2.class);
	private String tpath = Tools.getConfig("KeyPath");// 證書路徑
	private String ip = Tools.getConfig("ip");// 服務端ip
	private int port = Integer.parseInt(Tools.getConfig("port"));// 埠
	public static List<SSLSocket> socketList = new ArrayList<SSLSocket>();

	public SSLSocket getSSlSocket() {
		SSLContext context = null;
		context = this.getSSLcontext();
		SSLSocketFactory ssf = context.getSocketFactory();
		try {
			SSLSocket ss = (SSLSocket) ssf.createSocket("127.0.0.1", 10002);
			String[] protocols = { "TLSv1" }; //設定客戶端協議 
			ss.setEnabledProtocols(protocols);
			return ss;
		} catch (UnknownHostException e) {
			logger.error("a{}", e);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	private SSLContext getSSLcontext() {
		SSLContext sslContext = null;
		try {
			// 設定Security的Provider提供程式
			Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//			System.setProperty("https.protocols", "SSLv3,SSLv2Hello");
			// 建立空BKS,android只能用BKS(BouncyCastle密庫),一般java應用引數傳JKS(java自帶密庫)
			//訪問Java金鑰庫,JKS是keytool建立的Java金鑰庫,儲存金鑰。
			KeyStore ksKeys = KeyStore.getInstance("JKS");
			ksKeys.load(null, null);
			// 讀入客戶端證書  
			PEMReader cacertfile = new PEMReader(new InputStreamReader(
					new FileInputStream("d:/cacert.pem")));
			X509Certificate cacert = (X509Certificate) cacertfile.readObject();
			cacertfile.close();
			// 匯入根證書作為trustedEntry     
		    //KeyStore.TrustedCertificateEntry  儲存可信的 Certificate 的 KeyStore 項。
			KeyStore.TrustedCertificateEntry trustedEntry = new KeyStore.TrustedCertificateEntry(
					cacert);
			//用指定別名儲存 keystore Entry。
			ksKeys.setEntry("ca_root", trustedEntry, null);
			// 構建TrustManager   建立用於管理JKS金鑰庫的X.509金鑰管理器。
			TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");// 金鑰管理器
			tmf.init(ksKeys);
			// 構建SSLContext,此處傳入引數為TLS,也可以為SSL
			sslContext = SSLContext.getInstance("TLSv1");
			sslContext.init(null, tmf.getTrustManagers(), null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sslContext;
	}
	  public static void main(String[] args) {
	    	SocketClient2 client = new SocketClient2();	    	
	    	SSLSocket ss =client.getSSlSocket();	    		    	
	    	try {
	    		ss.setSoTimeout(2000);
	        	OutputStream socketOut = null;	    	
	    			if (ss != null && !ss.isClosed()) {
	    				socketOut = ss.getOutputStream();
	    				socketOut.write("客戶端傳送".getBytes());
	        			socketOut.flush(); 
	    			}    					
	    		if (ss != null && !ss.isClosed()) {
					InputStream in;		
					in = ss.getInputStream();	
					//input中的資料只能讀取一次
					System.out.println(new String(StreamToByteArray(in)));
	    	  }
	    		ss.close();
	    	} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	/**
	 * convert stream to Byte Array
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	public static byte[] StreamToByteArray(InputStream inputStream) throws IOException {
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int readIndex = inputStream.read(buffer);
		bout.write(buffer, 0, readIndex);
		bout.flush();
		bout.close();
		return bout.toByteArray();
	}  
}
</span>

三、證書

            

注:此服務端和客戶端可以進行通訊也可與C++進行通訊。