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