Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
CRYPTOGRAPHY 456 ANDROID SECURE FILE TRANSFER W/ SSL Daniel Collins Advisor: Dr. Wei Zhong Contents Create Key Stores and Certificates Multi-Threaded Android applications UI Handlers Creating client and server SSL Sockets with Java Android Intents Screen Shots Creating Keystores for Android Android natively supports Bouncy Castle (BKS) key stores. However, the most recent version of Bouncy Castle is not compatible with Android. Replace the version of Bouncy Castle in the lib/ext folder with bcprov-jdk15on-146.jar We will create the keystores with the Bouncy Castle provider for use in an Android Application Commands for Creating Keystores Create a BKS keystore for the client keytool -genkey -u -keyalg RSA -keystore clientkeystore -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvid er -providerpath /path/to/bcprov-jdk15on-146.jar In this example, I will use “client” as the password Create a BKS keystore the server keytool -genkey -u -keyalg RSA -keystore serverkeystore -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvid er -providerpath /path/to/bcprov-jdk15on-146.jar In this example, I will use “server” as the password Commands for Creating Certificates Export Client Certificate from client keystore keytool -export -v -file clientcer -keystore clientkeystore -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvid er -providerpath /path/to/bcprov-jdk15on-146.jar Export Server Certificate from server keystore keytool -export -v -file servercer -keystore serverkeystore -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvid er -providerpath /path/to/bcprov-jdk15on-146.jar Commands for Trusting Certificates Import client certificate into server keystore keytool -import -v -alias filetransferclient – file clientcer -keystore serverkeystore storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvid er -providerpath /path/to/bcprov-jdk15on-146.jar Import server certificate into client keystore keytool -import -v -alias filetransferserver – file servercer -keystore clientkeystore storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvid er -providerpath /path/to/bcprov-jdk15on-146.jar Add Keystores to Android Application Copy the clientkeystore and serverkeystore files into the res/raw folder in your Android application. You may need to create this folder Code Overview MainActivityServer.java Creates FileTransferServer.java Creates client. the SSL Secured Socket and communicates with MainActivityClient.java Creates the server-side user interface. the client-side user interface. FileTransferClient.java Creates server. the SSL Secured Socket and communicates with Creating the Server Main Activity UI The MainActivityServer.java class will contain: Handler classes to allow the background thread to update the user interface. Two EditText widgets named FileNameEt and PortEt A TextView named mServerStatusTv A button named ReceiveFileBtn with an onClickListener A progress bar will be constructed and the FileTransferServer.java thread will be started when it is clicked UI Handler Classes The Android’s Handler class can be extended to allow an application to update the UI from a background thread. The class overrides the handleMessage() function of Android’s Handler class. The handleMessage() function receives a Message object which contains the data for the update. The uiHandler and pbHandler classes are selfcontained in the MainActivityServer class in this example. The uiHandler Class private class uiHandler extends Handler { @Override public void handleMessage(Message msg) { TextView mStatusMessagesTv = (TextView) findViewById(R.id.serverStatusTv); mStatusMessagesTv.append( (CharSequence) ("\n" + (String) msg.obj)); } } The Message object’s variable, obj, is an arbitrary Java Object In this case, obj contains the string to display in mServerStatusTv. pbHandler ‘s handleMessage() Function if(msg.what == 1) { progressBar.setMessage("Receiving file from " + (String) msg.obj + " ..."); progressBar.setMax(msg.arg1); } else if(msg.what == 2) { progressBar.setProgress(msg.arg1); ... // etc } To update the progress bar, the Message objects (int) what and (int) arg1 variables are used. what notifies the handler what the message is about arg1 is used to update the progress bar’s status. Creating the OnClickListener receiveFileBtn.setOnClickListener(new Button.OnClickListener() { @Override Public void onClick(View v) { // Create progress bar dialog ... // Start the FileTransferServer thread ... } v is the View object and will be used to transfer the UI’s context to the thread. Creating the Progress Bar progressBar = new ProgressDialog(v.getContext()); progressBar.setCancelable(true); progressBar.setMessage(SERVERIP + " is listening on " + mServerPort + " ..."); progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressBar.setProgress(0); progressBar.setMax(0); progressBar.show(); SERVERIP is the device’s IP Address. mServerPort is the user specified port for communication. This can be retrieved from portEt. Starting the Server Thread Thread mServerThread = new FileTransferServer(SERVERIP, mServerPort, new uiHandler(), new pbHandler(), v.getContext(), mServerFilePath); mServerThread.start(); v.getContext() will be used to retrieve the keystore from Android’s res/raw folder. mServerFilePath is the user specified fileName from fileNameEt The FileTransferServer.java Class public class FileTransferServer extends Thread { public FileTransferServer(String LocalIP, int Port, Handler uiHandler, Handler ProgressBarHandler, Context context, String fileToReceive) { ... } public void run() { ... } } The constructor simply assigns it’s parameters to class variables The run() function does the following: Creates the SSL Socket Receives a file from the client on this socket. Creating the SSL Socket (Server) Get instance of a KeyManagerFactory object KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory. getDefaultAlgorithm()); Get a Bouncy Castle instance of a KeyStore object KeyStore keyStore = KeyStore.getInstance("BKS"); Creating the SSL Socket (Server) cont’d… Load the keystore file into the keystore object keyStore.load(UiContext.getResourc es().openRawResource(R.raw.filetra nsferserverkeystore), "server".toCharArray()); The first parameter loads the serverkeystore file from the Android res/raw folder using the UI class’s context. The second parameter is the keystore password. Creating the SSL Socket (Server) cont’d… Initialize the KeyManagerFactory with the KeyStore Get Instance of TrustManagerFactory kmf.init(keyStore, "server".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustMan agerFactory.getDefaultAlgorithm()); Initialize TrustManagerFactory tmf.init(keyStore); Creating the SSL Socket (Server) cont’d… Create SSLContext object SSLContext SSLctx = SSLContext.getInstance("TLS"); Initialize the SSLContext SSLctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); Initiate ServerSocketFactory SSLServerSocketFactory ssf = SSLctx.getServerSocketFactory(); Creating the SSL Socket (Server) cont’d… Create Server Socket SSLServerSocket ss = (SSLServerSocket) ssf.createServerSocket(myPort); Authenticate Client ss.setNeedClientAuth(true); Receiving the File (Server) A secure socket is now available to receive a file from the client. This file will be received in two parts First, the file size will be sent Then the client will begin the actual file transfer, which will be sent in packets of 1024 bytes. As the file is being received, the progress bar is updated. Updating the UI from Server Thread public void updateUI(String message) { Message msg = Message.obtain(mHandler); msg.obj = message; mHandler.sendMessage(msg); } The updateUI function is part of the FileTransferServer class. mHandler references the uiHandler class we created in MainActivityServer.java After assigning data to the Message object, msg, we send it to the Handler which will update the UI. Updating the ProgressBar public void updatePBMax(long fileSize, String clientIP) { Message msg = Message.obtain(pbHandler); msg.arg1 = (int) fileSize; msg.obj = clientIP; msg.what = 1; pbHandler.sendMessage(msg); } pbHandler references the pbHandler class we created in MainActivityServer.java After assigning data to the Message object, msg, we send it to the Handler which will update the UI. Updating the ProgressBar cont’d... public void updatePBProgress(int progress) { Message msg = Message.obtain(pbHandler); msg.arg1 = progress; msg.what = 2; pbHandler.sendMessage(msg); } public void closePB() { Message msg = Message.obtain(pbHandler); msg.what = 3; pbHandler.sendMessage(msg); } These two functions send unique msg.what variables which allow the pbHandler to determine the purpose of the message. Creating the Client Main Activity UI The MainActivityClient.java class will contain: A Handler class for the ProgressBar and TextViews Two EditText widgets named serverIpEt and portEt Two TextView widgets named main_local_ip_address_tv and main_chat_box_tv Two buttons named selectFileBtn and main_send_file_btn with OnClickListeners selectFileBtn will launch an Android Intent to allow the user to choose a file main_send_file_btn will create a progress bar and start the FileTransferClient thread Android Intents Android Intents can be used to allow separate applications to transfer data with each other When the Intent is broadcast, the Android system displays a list of applications that can handle the request. This example looks for a file explorer application Not all Android devices have a pre-installed file browser. You can download a third-party file browser, such as ES File Explorer, to handle the Intent To install ES File Explorer on an emulator: Download the apk file and store it on the device sdcard Open an internet browser type "file:///sdcard/es_file_explorer_file_name.apk" then press Go The function, onActivityResult() will be called when the user selects a file. Launching the Intent selectFileBtn.setOnClickListener(new Button.OnClickListener(){ @Override public void onClick(View v) { // Create a new intent Intent intent = new Intent(Intent.ACTION_GET_CONTENT); // Look for any file type intent.setType("file/*"); // Start the Activity startActivityForResult(intent,PICKFILE_RESULT_CODE); } }); Getting Results from the Intent @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch(requestCode){ case PICKFILE_RESULT_CODE: if(resultCode==RESULT_OK){ // Gets data from Intent Uri dataURI = data.getData(); // ... } break; } } Verify file existance and get details Starting the Client Thread mClientThread = new FileTransferClient(SERVERIP, mClientFilePort, new uiHandler(), new pbHandler(), mClientFilePath, mClientFileSize, v.getContext()); mClientThread.start(); The thread will be started from the main_send_file_btn OnClickListener mClientFilePath and mClientFileSize are available in the URI data from the Intent. The FileTransferClient.java Class public class FileTransferClient extends Thread { public FileTransferClient(String remoteIP, int remotePort, Handler UIHandler, Handler PBHandler, String fileToSend, long fileSendSize, Context uicontext) { ... } public void run() { ... } } The constructor simply assigns it’s parameters to class variables The run() function does the following: Creates the SSL Socket Sends a file to the server on this socket. Creating the SSL Socket (Client) Setting up the KeyManagerFactory, TrustManagerFactory, and SSL context is the same for the client as it is the server. KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDe faultAlgorithm()); KeyStore keyStore = KeyStore.getInstance("BKS"); keyStore.load(UiContext.getResources().openRawResourc e(R.raw.filetransferclientkeystore), "client".toCharArray()); kmf.init(keyStore, "client".toCharArray()); SSLContext SSLctx = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.g etDefaultAlgorithm()); tmf.init(keyStore); SSLctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); Creating the SSL Socket (Client) cont’d… Initiate Client SSLSocketFactory Create the SSL secured socket SSLSocketFactory sf = SSLctx.getSocketFactory(); SSLSocket socket = (SSLSocket) sf.createSocket(serverAddr, serverPort); Start handshake with server socket.startHandshake(); Client and Server decide which protocol and cipher’s to use. Client and Server authenticate each other’s digital certificates. Sending the File (Client) A secure socket is now available to send a file to the server. This file will be sent in two parts First, the file size will be sent Then the client send the file in packets of 1024 bytes. As the file is being sent, the progress bar is updated. Screen Shots (Server) Server GUI Server waiting for file Screen Shots (Client) Client GUI Client sending file Screen Shots (Intent) Intent Broadcast Selecting a file w/ ES File Explorer