Upload
sheffield
View
3
Download
0
Embed Size (px)
Citation preview
Department of Electronic & Electrical Engineering
MSc Avionic Systems Engineering
Dissertation 2015
SafeTime Application
Student: Viteri Buendía, Ricardo Mauricio Registration: 140209688 Date: August 28, 2015 Supervisor: Dr. Jonathan M Rigelsford Second Marker: Dr. Gregory Cook
This dissertation is a part requirement for the degree of MSc in Avionic
Systems Engineering.
Abstract
Communication is a basic part of our lives in a daily basis, messages come and go
from various places worldwide as long as the user have access to the web. All those
messages transform in sets of bytes that will be “surfing” through the net to get to
their destination, but not necessarily in a secure way. Lately, many issues
concerning security have been announced in the news, some of them are personal
cases such as photos and messages hacked from celebrities phones, others
concerning big companies such as NBC.
The world is becoming more accessible day-‐by-‐day and personal security is also
becoming more important. This project’s aim is to develop an instant messaging
application in Android platform that will, by all means necessary, protect the user’s
data, not by preventing it to be stolen, but preventing it to be read by any peer not
involved in the communication nor the server managing the communication.
Acknowledgements
To my supervisor, Dr. Jonathan Rigelsford for his support and help during
the developing of this project and helping me focus my ideas and objectives
in order to successfully complete not only what was intended, but more. To
my family and friends that were always there to support me not only
during my studies, but throughout my life. To Pamela Garcia for being my
biggest support in the most stressful moments and being as crazy as me in
my craziest moments.
Juan Marito, this is what your uncle was doing while you were so busy
being born.
Table of Contents 1. Introduction .......................................................................................................................... 1 2. Background ........................................................................................................................... 2 2.1 Instant messaging ...................................................................................................................... 2 2.2 Android programming ............................................................................................................. 3 2.3 Client/Server communication ............................................................................................... 4 2.4 TCP/IP sockets ............................................................................................................................ 6 2.5 Encryption algorithms ............................................................................................................. 7 2.5.1 AES algorithm ........................................................................................................................................ 8 2.5.2 RSA algorithm ........................................................................................................................................ 9
3. What is SafeTime? ............................................................................................................ 10 3.1 How it works? ........................................................................................................................... 11 3.2 Application flow diagram ..................................................................................................... 12 3.3 SafeTime screen by screen ................................................................................................... 13 3.3.1 Login screen ......................................................................................................................................... 13 3.3.2 Register screen .................................................................................................................................... 14 3.3.3 User list tab ........................................................................................................................................... 14 3.3.4 Conversation tab ................................................................................................................................ 15 3.3.5 Add contacts tab ................................................................................................................................. 16
3.4 Android application tasks .................................................................................................... 16 3.5 Server tasks ............................................................................................................................... 17
4. Research methods ............................................................................................................ 18 4.1 Development tools .................................................................................................................. 18 4.1.1 Android studio .................................................................................................................................... 18 4.1.2 Linux server .......................................................................................................................................... 19 4.1.3 Eclipse Mars ......................................................................................................................................... 19 4.1.4 MongoDB ............................................................................................................................................... 19 4.1.5 TeamViewer ......................................................................................................................................... 20
4.2 Encryption algorithm implemented ................................................................................. 21 5. SafeTime main processes .............................................................................................. 23 5.1 Registration process ............................................................................................................... 23 5.2 Login process ............................................................................................................................ 27 5.3 Add contact process ................................................................................................................ 31 5.4 Encryption process ................................................................................................................. 35 5.5 Decryption process ................................................................................................................. 38 5.6 Message send/receive process ........................................................................................... 41
6. SafeTime tests ................................................................................................................... 45 6.1 Test 1: Key generation, Encryption and Decryption .................................................... 45 6.2 Test 2: TCP socket communication .................................................................................... 48 6.3 Test 3: Encryption and decryption of plain text with one set of keys .................... 49 6.4 Test 4: Encryption and decryption of plain text with two different set of keys . 51 6.5 Test 5: Encryption and decryption of images with one set of keys ......................... 52 6.6 Test 6: Encryption and decryption of images with two different set of keys ...... 54
7. Discussion ........................................................................................................................... 55 7.1 Achievements of SafeTime ................................................................................................... 55 7.2 Limitations and upgrades ..................................................................................................... 56 7.3 SafeTime’s use for industry .................................................................................................. 57
8. Conclusions ........................................................................................................................ 57
9. Bibliography ...................................................................................................................... 59 Appendix A: Application codes ............................................................................................ i Appendix B: Server codes .............................................................................................. xxvii Appendix C: Test RSA keys ................................................................................................... xl Appendix D: Encryption algorithm C code tests ........................................................ xlii
1
1. Introduction
Cyber security is a term that has been sounding very loudly lately. All of us,
smartphone users, have heard of this term at least once, but are we sure of what
that means?
As taken from the Oxford English dictionary: “Cyber security is the state of being
protected against criminal or unauthorized use of electronic data or the
measures to achieve this”. It considers defending against attacks to all kinds of
computer systems [1]. So we now understand the importance of this. Every day
we as individuals keep in touch with our loved ones, colleagues, bosses and
other people through instant messaging applications sharing personal
information, pictures and other files taking the risk of being hacked. It will not
seem that much of a big deal if we just take into consideration simple messages
and conversations, but what if we reveal our passwords for some reason, or
credit card information, or bank information, and that’s only speaking about
personal use, for big companies that kind of information can involve thousands
of pounds. With this project, I’m developing a way to communicate in a secure
way, using as my interface an Android application. But the principles taken from
this research can be applicable for other kind of communications in more
delicate fields such as the government or the military. This way, some of the
latest concerns in cyber security can be covered in both civil and military
applications.
In this dissertation, first of all, the theory behind the application will be
explained, instant messaging, Android and Client/Server communication, so that
the later explanation of the project can make more sense and finally, the process
in which it has been developed along with their achievements, limitations and
conclusions.
2
2. Background 2.1. Instant messaging Messaging applications like Whatsapp, Facebook messenger and Skype are
amongst the most downloaded and used applications in the Google market [2].
The main objective of these applications is to provide the user with a
communication service between themselves and other users with an account in
it. In general, the way in which the IM communications work is that, users, which
are the clients and have an account authenticated by the server, send a packet
with a set of information such as: its own client ID, the client ID of whom the
message is sent to and the message itself. That packet is sent through internet to
a main server, which is going to be the one that will manage the connection
between the two clients, like the post service, the server will look for the ID of
the second client, confirm it is actually a client and not corrupt data, and then
send the packet to its destination. The following diagram represents this basic
communication:
Figure 1: Basic point to point communication
In this model, which is the one that will be used for this project, represent how
the clients uniquely communicate with the server, therefore, it works as a
mediator between the clients [3]. In order to make this model possible,
client/server communication is needed. This communication structure will be
explained in detail later on.
3
2.2. Android programming Android is a mobile operating system created in 2003 by Android Inc. In 2005
Google acquired Android Inc. and started to work on their new mobile
development branch. In 2010, Google finally released their phone Nexus with the
new Linux kernel based operating system Android 2.2 (Froyo). From the on,
Android OS has positioned itself as one of the most important mobile system in
the last few years. Because of its Linux roots and Google’s open source mentality,
it’s one, if not the most, accessible and affordable OS for developers worldwide,
for this reason Android OS has been chosen as the platform in which this project
will be worked.
Android development is based in the object oriented programming language
Java, designed by Oracle Corporation, and its structure is based in 4 main blocks
and 5 main features at the developers disposal [4].
Main blocks:
• Activities: Is the building block of the user interface, the main window in
which the developer will be programming what the app is going to do.
• Content providers: provides a level of abstraction for the data stored by
an application. By having this, data can be accessed by other applications
while maintaining complete control of such data.
• Intents: These are system messages in the device. This messages can
notify an app of various events which could be: hardware events,
incoming data of application events.
• Services: Are features in an app that can keep running even though the
application is no longer operating. Different than the Activities, Content
providers and Intents, which are short-‐lived, Services can stay “alive”
waiting for events an app may be waiting, for example waiting for a
message from the server.
4
Main features:
• Storage: an application’s data files can be stored either in the phone’s
internal memory or an external memory provided by the user (SD card).
• Network: generally, Android apps are Internet ready, and is able to
access it in order to load or send data, for example, Java sockets which
will be widely used in this project.
• Multimedia: Depending on the device, an app can access video and audio
recorders and players and also camera and picture galleries.
• GPS: With this, an application can access the user’s location in the earth.
• Phone services: applications can dial calls or send and receive SMS
messages.
For an application to be able to use these services, the user must grant
permission. These permissions will be typically asked for while installing an
application.
Various software can be used to develop Android applications. The two that are
mainly used are Eclipse and Android Studio. For this project, I’ve decided to use
Android Studio because it simplicity and quick installation process, also taking
into account that, since the release of their first stable version in December
2014, it has become officially the principal development environment for
Android.
2.3. Client/Server communication Client/Server is an information sharing mode widely used in information
systems [5]. Is the communication between three main components, the client,
the server and the network system.
• Client: the workstation, in this project’s case, the application that
provides the user with a friendly interface to be used.
• Server: the one that holds the information. A database server provides
the clients with a main information center were they have access and can
also share new information.
5
• Network system: is the link between client and server. This link can be
done through LAN, WAN or Internet.
The way in which this model works is quite simple. The client will send a request
to the server, once the server processes de request it will send a response back
to the client. An example for this is illustrated as follows:
Figure 2: Client/Server model
For this example, I’m considering a basic instant messaging system in which the
server may act as an intermediary between two clients. Client 1 is sending a
message to another client; the process will follow these steps:
1. Client 1 assembles a data packet and sends the request to the server
through the network.
2. The server receives the packet and processes the request. It identifies the
client to whom the packet must be sent.
3. The server sends the packet to the receiver client through the network.
4. The server sends an acknowledgment packet to Client 1 confirming that
the packet has been sent to the destination client.
Once understood client/server communication, it’s important to understand
how a connection between client and server must be established. In this
project’s case, the most suitable are the TCP/IP Sockets.
6
2.4. TCP/IP sockets TCP/IP:
In order to initiate a point-‐to-‐point client/server connection a communication
protocol must be used. The Transmission Control Protocol is one of the most
widely used because of its reliability. TCP guarantees the delivery of data it
transmits in form of packets to its final destination. If a packet is damaged, TCP
will resend the data until the packets are successfully transmitted.
Socket:
A socket is an endpoint of the two-‐way communication link used to send packets
between server and client. A socket is established by a combination of both IP
address and port number, because of this, multiple connections can be initiated
between client and server making every connection unique.
To establish a connection, both client and server must bind a socket to their end
of connection. Once that is done, both can read from and write to the socket
when communicating.
Establishing a connection:
The process to create sockets varies depending if it’s a client or a server. A
socket created in the server is called a “passive socket” since it waits for and
responds to clients. A socket created for clients in the other hand are called
“active sockets” and will be initiated with the main goal of sending a message to
the server, for that, the client must know the IP address and port number of the
server’s socket [6]. So the lifecycle of a socket can be represented in this way:
7
Figure 3: Client and Server Sockets
2.5. Encryption algorithms This projects main goal is to achieve secure communication between two clients.
The way in which such communication will be possible is by encrypting
messages so that no one can understand the contents of a packet without having
the key to decipher it. Many encryption algorithms may be useful, the ones that I
consider more relevant and for this project are:
• Data Encryption Standard (DES)
• Advanced Encryption Standard (AES)
• RSA
Because of the small key size of DES algorithm (56 bits) and considering that the
National Institute of Standards and Technology withdrew it as a standard, I have
neglected DES from my project.
8
2.5.1. Advanced Encryption Standard (AES) algorithm Is a symmetric block cipher based on Rijndael Cypher, and designed by
Vincent Rijmen and Joan Daemen in 1998. A symmetric block cipher means
that its key is also symmetric, meaning that the same key can be used for
both encrypting and decrypting data.
This cipher can process data blocks of 128 bits using different sizes of
cryptographic keys of 128, 192 and 256 bits [7]. In 2002 AES became a
federal government standard in the United States of America.
This algorithm works in a 4x4 matrix of bytes named “state”. The key size
defines the amount of transformations from the input are done to convert it
on the output:
Table 1: Repetitions for key sizes
A cycle consists of four main steps:
1. AddRoundKey: using bitwise xor, each bite is combined with a block
of the round key.
2. SubBytes: each byte is replaced with another using a lookup table.
(non-‐linear).
3. ShiftRows: The last three rows of the state are shifted a number of
steps (transposition).
4. MixColumns: it combines all the bytes within each column (mixing).
How the cycles work is demonstrated by the following diagram:
9
Figure 4: AES cycle structure
2.5.2. RSA algorithm First published in 1977 by Ron Rivest, Adi Shamir and Leonard Adleman, RSA
is an asymmetric public-‐key cryptosystem. It works with two keys: a public
encryption key and a secret decryption key [8].
This algorithm work by 3 main steps: key generation, encryption and
decryption.
• Key generation: Two different prime numbers (p and q) must be
selected, and multiplied amongst each other to generate:
n = p*q
Now, Euler’s totient function has to be used to get:
φ(n) = n – (p + q -‐ 1)
Choose an integer e such as 1 < e < φ, this number must be coprime
with φ(n). Using e, d can be calculated:
d ≡ e – 1 (mod φ(n))
10
Finally, values of p and q must be erased and the keys are ready:
o Public key = (n, e)
o Private key = (n, d)
• Encryption: Client_1, which already generated its keys, sends the
public key to Client_2 and keeps the private key. With the acquired
key, Client_2 encrypts a message M using the following steps:
o Turn M into an integer m such that 0 ≤ m ≤ n using a padding
scheme.
o Now compute cypher text c:
c ≡ me (mod n)
o Client_2 transmits c to Client_1.
• Decryption: Client_1 receives the ciphertext c from Client_2 and in
order to recover m the following steps must be done:
o Calculate m using:
m ≡ cd (mod n)
o Reversing the padding scheme, message M can be recovered.
3. What is SafeTime? SafeTime is an instant messaging application programmed in Android platform. Its
main objective is to guarantee a secure communication between two users, not by
preventing data sent by users to be intercepted or hacked, but by preventing that
data to be read. The way to do this is by encrypting the messages sent by the users
using an encryption algorithm RSA so that people trying to intercept those messages
either via an sniffer reading packets or hacking into the main server. For this
version of the application, encryption of plain text messages and images has been
developed.
11
3.1. How it works? The way in which this application will work is represented in the following
diagram:
Figure 5: SafeTime communication flow
Based on the figure shown, the way in which the app will work is explained:
1. User_1 writes a message in plain text, once finished, the message is then
sent to the encryption process.
2. Here the message will be encrypted using the RSA public key, the packet
with the user IDs and the cyphered message is then sent to the server.
3. Using sockets, configuring the correct port and IP address, the packet will
go to the server.
4. The server will check to which user the packet must be sent and will
configure the socket that will be used for communicate with that user.
5. The encrypted packet will be sent through the socket to the receiving user.
6. The application will open the packet and with its RSA private key will
begin the process of decrypting the message.
12
7. Once the message is decrypted to plain text or image again, it will be
displayed in the user interface of both end users.
3.2. Application flow diagram For the application, the following flow chart represents the sequence of windows
it will have:
Figure 6: SafeTime design flow chart
Five different screens are planned for the basic application:
• Login screen: is the first screen to be shown by the app. If the user
already has an account, it will be able to insert the email and password in
13
order to start sending messages to its contacts. If not registered, a button
to go to the register screen is provided.
• Register screen: If a user is not registered to the app, in this screen with
a simple form, which will be sent to authenticate.
• Multi-‐fragment Tabhost: This view consists on 3 different tabs which
will fulfill three main purposes:
o User list tab: Once logged into the app, the user will be able to see
the list of its contacts, which can be selected in order to open a
new conversation.
o Conversation tab: The screen in which the user will be able to see
the messages received from other user and in which it will be able
to write and send new messages.
o Add contacts tab: In this last screen, the user will be able to add a
new user to his contacts by writing its email and requesting it to
the server.
3.3. SafeTime screen by screen
3.3.1. Login screen Login screen is the one that will enable a user to log
into their already registered account of SafeTime
app. This screen has 5 main components:
A. App title: This is a field dedicated to show the
name of the app, developer and supervisor of
the app.
B. Text fields: In this fields the user will be able
to write its email and password in order to log
into the application.
C. Login button: Will execute the login action. D. Register button: Will open the “Register screen”.
Figure 7: Login screen
14
3.3.2. Register screen In this screen the user will be able to register a new
account in SafeTime. Its main components are:
A. Text fields: In this fields, the basic
information of the user can be filled.
B. Generate keys and register button: By
pressing this button, the registration process
will start.
3.3.3. User list tab This screen is part of the Multi-‐fragment Tabhost
along with the “conversation” and “add contacts”
tabs. Here, a list with the contacts added by the user
is shown. The main components in this screen are:
A. Tabhost manager: Used by the user in order
to switch tabs.
B. User list: Here the list of the users added by
the user is displayed. If the user taps in one of
the items in the list, the conversation window
for that user will be opened.
Figure 8: Registration screen
Figure 9: User list tab
15
3.3.4. Conversation tab It’s the window in which the user will write
messages to another user previously added to the
user list. Plain text and images can be sent to the
other user. Its main components are:
A. Tabhost manager: Used by the user in order
to switch tabs.
B. User’s name: This is the name of the user to
whom the message will be sent.
C. Conversation field: In this space, the
conversation between the two users will be
displayed. Messages focused on the right side
are messages sent by the user and the ones focused on the left are the
ones received.
D. Text field: In this field, the user can write a text message to be sent. E. Send button: By pressing this button, the message written in the
“Text field” will be sent.
F. Image button: When this button is pressed, the
phone’s gallery will be opened so that the user
can select an image to be sent. Once selected, a
pop-‐up will appear with the following
components:
a. Image: This is a sample of the image to
be sent.
b. Send picture button: Once this button is
pressed, the image message will be sent.
Figure 10: Conversation tab
Figure 11: Image selection window
16
3.3.5. Add contacts tab In this tab, the user can add a new contact to its list.
This can be done by writing the other user’s email
and sending the request. Its main components are:
A. Tabhost manager: Used by the user in order
to switch tabs.
B. Text field: In this field, the user will write
the email of the user that will be added.
C. Add contact button: Once this button is
pressed, the request will be sent.
3.4. Android application tasks The Android application is the interface in which a user can interact with other
users and manage its own account in SafeTime. The application is designed so it
has two simultaneous running threads:
o Main thread: This thread is the one that can be visualized by the user
and hence can interact with it. Here is were the user can use the screens
shown in the last chapter which consists on the main functionalities of
the app. A number of Android simultaneous tasks, called Asynctasks[9]
are executed for various purposes like sending text and image messages,
sending contact requests, encrypting/ decrypting processes, login task
and registration task which will be running in the background until the
task at hand is done.
o Listening thread: This thread is always running in the background. Its
main purpose is to scan for a socket connection with the server,
whenever a connection is established between the application and the
server, this thread gets in charge of managing upcoming tasks from the
server and if needed, send tasks to the server (messages or requests).
Figure 12: Add contacts tab
17
3.5. Server tasks The server can be considered the “manager” of the information flowing between
users of SafeTime. It will receive every request or message from the different
users and either process it or resend it depending on the situation. In order to
manage all this different tasks, 7 different threads were developed and can be
seen in the Appendix A. These threads are the following:
o socketServer: This is the main thread, it will manage messages between
users and contact requests. This task will loop infinitely creating a socket
connection with the ports assigned to the users, this way, it can listen and
send information to the user with which is connected at its turn. When a
message or contact request is received, the task will store the information
received into a “pending task stack” which will be read every time it
opens a new connection with a user, at that moment it will check if it has
something to send to that particular user and will also listen to that user
in order to receive new information.
o TimerThread: The port scanning done by the “socketServer” thread is
managed by time in case that it finds no connection with a user. In order
to do so, this thread is executed every time a new connection is
established in “socketServer”, this will initialize a timer that will serve as
a process timer, when the timer is over, a signal is sent to the main thread
so it can terminate the actual connection and proceed to scan the next
port.
o NewUserThread: This thread keeps a socket connection open at port
9003 so that any application that sends a registration request can
communicate with the server. This task will receive that registration
request and send a response back to the user and then go back to wait for
a new request.
o LoginUserThread: The way this thread works is about the same as the
“NewUserThread”, that means, it will wait for a request, when it is
received, it is solved, send a response back to the app and return to wait
18
for a new request. This thread will manage all the login requests on port
9001.
o UpdateKeyThread: When a user logs into the application on a new
device, a new set of encryption keys need to be generated. This thread is
the one in charge of receiving and updating in the database the new key
for a given user.
o TestThread: This thread is the one in charge of receiving the message
data sent from users. For this process, the “socketServer” thread receives
the command from the application to receive a new message and then,
this thread will be ready for listening and store the message into the
“pending task stack”.
o SendMessageTask: This thread will send a message stored in the
“pending task stack” and send it to its destination. For this process, the
“socketServer” will send a command to the application so it can be ready
to listen to this thread sending a given message.
4. Research methods 4.1. Development tools
4.1.1. Android studio 1.1.0 The latest version of Google’s software for Android developers. Once
installed, developers are already provided with the Android SDK and
therefore ready to develop new applications. Java is the programming
language used to program most of the application, since the graphic user
interface is programmed in xml.
Testing device
To test the application, two different devices are used: an Android virtual
device provided by the Android Studio IDE and a Samsung Galaxy S3 phone.
The specifications for both devices are:
• Android virtual device (AVD):
19
o Running Android 4.4
o API level 19
o Adjustable screen
• Samsung Galaxy S3:
o Running Android 4.3.1
o API level 15
o 4.8 inches screen
4.1.2. Linux server A CPU Linux box with is used as the server for SafeTime. This computer has
the following specifications:
o Operating system: Ubuntu 14.04 LTS – 32-‐bit
o Memory: 3.9 GiB
o Processor: Intel Core 2 Quad CPU !8400 @ 2.66GHz x 4
o Disk: 134.9 GiB
4.1.3. Eclipse Mars Eclipse Mars is the latest version of the Eclipse integrated development
environment (IDE). This is a computer application that provide programmers
with a friendly environment to develop software in various programming
languages [10]. This IDE is widely used by programmers due to its
practicality and the number of tools and libraries that can be used in order to
develop complex projects. For SafeTime project, this IDE will be used to
develop the server application. For this, Eclise Mars linux version was
downloaded and installed using the Ubuntu software centre.
4.1.4. MongoDB MongoDB is an open source document database. It’s a high performance and
salable database that lets a developer create, manage and develop databases
for any type of applications. One of the main reasons this database was
20
chosen to be used for this application is because of its practical libraries in
Java. With a few simple java code lines, a wide range of commands can be
done such as:
o Initialize MongoDB client:
MongoClient mongo = null;
mongo = new MongoClient("localhost", 27017);
o Get or create a new database:
// if database doesn't exists, MongoDB will create it for you
DB db = mongo.getDB("safetimedb");
/**** Get collection / table from 'testdb' ****/
// if collection doesn't exists, MongoDB will create it for you
DBCollection table = db.getCollection("users");
o Create search queries and cursors to search for objects in
database:
BasicDBObject searchQuery = new BasicDBObject();
searchQuery.put("email", toUser);
DBCursor cursor = table.find(searchQuery);
4.1.5. TeamViewer This is a software with which a user can be able to access and control another
computer or device remotely. In order to do so, a user can create a free
account and register their different devices on it so it can be easily connected
at any given time by selecting the device from the “My Computers” list:
21
Figure 13: TeamViewer main window
Once a device is selected, a window will open displaying its desktop:
Figure 14: TeamViewer shared screen window
By enabling the “Remote control” feature, the user is able to interact with
that computer and all its components.
4.2. Encryption algorithm implemented Two different encryption algorithms were considered and explained for this
project, AES and RSA algorithms. In order to understand them an get to test their
functionality, both were developed first in a basic way in C code (Appendix D).
22
Once considering the programming complexity and functionality in terms of the
project’s objectives, it was concluded that the RSA algorithm is the best option
for encrypting messages in this proyect. The factors taken into account in this
consideration were the following:
o Programming complexity: Both algorithms were developed and it could
be concluded that AES is, by not too far, more complex to develop. AES has
in fact more stages to follow in order to generate the key, but those
individual stages are not so difficult to program and can be executed in a
loop. RSA is simpler, but its mathematical calculations are more complex
and a library called “BigIntegers” needed to be imported in order to be
able to handle such big numbers. This was not a crucial factor in the final
consideration.
o Key management: AES algorithm will generate a key of 128 bits (or 192
or 256 depending on the complexity) for every data block of 128 bits [11],
while RSA will generate two bigger keys based on two prime numbers
with a length of 1024 that can cypher a block of up to 256 bytes. Since
SafeTime is an instant messaging application, generating a key for every
block of 128 bits (16 bytes) that has to be sent along with the cyphered
message in order to be decrypted represents a problem in terms of data to
be sent, since practically the double of the data size would be needed to be
sent (data+key), which means data consumption for the user and
encryption/decryption processing times, since for every message every 16
byte block needed to be encrypted generating the key, which would take
considerable amount of processing time, as well as in the decryption
processes. On the other side, RSA would generate at the moment a new
user registers or logs in a new set of keys which will stay the same until
the user logs into another device, meaning that the generation process,
which does takes time (about 1 second), will be done once, from then on
just the encryption and decryption processes will be done every time a
message is sent or received, making this algorithm more practical for this
application. This was a crucial factor in the final consideration.
23
o Data block size: As it was mentioned before, AES cyphers blocks of 16
bytes. In terms of plain text that means 16 letters, so a plain text message
bigger than that will require to cypher multiple blocks generating multiple
keys. The RSA algorithm considered for this app permits to cypher a data
block of 256 bytes not needing to generate new keys. This was a relevant
factor in the final consideration.
o Algorithm security: AES is the actual official encryption algorithm used
by various government and military branches around the world including
the US government [12], so it has been proven as the most robust
encryption algorithm nowadays. Still, RSA is almost as secure as AES or at
least, in terms of this project, more than enough considering that an
attempt on factoring a public key of 500 characters in order to figure out
the private key could take 4.2 x 1025 years [8], and for this application, a
key can have approximately 617 characters depending on the prime
numbers.
5. SafeTime main processes 5.1. Registration process Registration is the process in which a user will be able to activate an account on
SafeTime. In order to do so, a form will have to be filled by the user; pressing the
“Register” button in the application’s main screen can do this.
24
Figure 15: Login to Registration flow
This form has to be filled with basic information about the user in the
application:
• Name: it will be used to display the name of the registered user in the
contact list of other users that has been added.
• Phone: not used in this version of the application, it is asked in order to
be able to be used in future versions (scalability of the application).
• E-‐mail: is the main id of the user used for internal processing. There can
only be one user per email address.
• Password: is the password designated by the user in order to be able to
log back into the app in any other device.
• Repeat password: it is used to confirm that the password typed in the
“Password” section and this section is the same and hence, the password
the user intended to type.
Validations:
For this screen, two validations were developed in order to be able to start the
registration process with the server. The first validation is to make sure that all
the fields on the form are filled, if this condition is not met, a toast with the
message “Fields are not complete” will be shown. The second validation is for
25
the passwords, if both password fields do not match, a toast with the message
“Passwords does not match” will be shown.
Process:
The registration process will require a communication between the application
and the server. With the information provided by the application, the server will
register the new user in the database and assign a port number for it and will
send it back to the user. The detailed process on how it goes is the following:
1) Server: The “NewUserThread”, which is the registration thread, is already
running in the server with a socket set on port number #9000.
2) Application: The user fills the registration form with all its details and taps
the “Generate keys and register” button.
3) Application: The form is checked by the app to see if the form is filled
correctly, if not, a toast is shown to the user saying what is the problem so he
can correct it.
4) Application: Once the information is correctly filled, the RSA keys are
generated.
5) Application: A connection is established with the server by initializing a
socket in the port #9000.
6) Application: A string array “UserInfo” with the user’s information and the
public RSA key is initialized and sent through a socket so it can be read by the
server. “UserInfo” will be filled with the following information:
Table 2: Registration variables
Variable Description
usrName The name of the user.
usrPhone The phone number of the user.
usrEmail The email of the user.
usrPass The password set by the user.
usrPKey The RSA public key generated for the user.
26
7) Server: The server successfully receives the “UserInfo” string array through
the socket.
8) Server: The server searches in it’s database for the “usrEmail” to check if it
already exists and will assign a CODE to be sent to the application:
Table 3: Registration server CODEs
CODE Description
1 usrEmail is not registered
2 usrEmail is registered
9) Server: If the usrEmail is not registered, a port number is designated to that
user, this port is assigned sequentially considering what was the last port
assigned before (i.e. the last user registered port was #9005, so the port
assigned to this user will be #9006). The port number and the UserInfo is
then inserted to the “User Info Table” in the server’s database. Finally the
port number and the CODE are sent to the application through the socket. If
the usrEmail is already registered, only the CODE will be sent to the
application. After this, the server returns to a listening state waiting for other
registration request.
10) Application: The CODE sent by the server is received. If CODE is equal to “1”
the port number is read from the socket and added to the “User Info Table” in
the device’s database and an Intent to the main application window is done.
If CODE is equal to “2”, then a toast with the text: “Email already registered”
is displayed in the screen and no further action is taken.
Once this process has been done successfully, the new registered user is now
able to use SafeTime application’s functions and also log into other devices.
27
Figure 16: Registration flow chart
5.2. Login process Once a user has been registered in the server and hence its basic information
stored in the server, that user will be able to log into his account by using the
email address provided in the registration process and the password also set.
28
The server will be in charge of authenticate the user comparing that information
with the one stored in its database.
Process:
The login process will require communication between the application and the
server. For this task, the server has an individual thread waiting for a login
request at all times in a socket set on port #9001. The process in which a user in
logging into its account is the following:
1) Server: The “LoginThread” which is the thread in charge of the login requests,
is already running in the server with a socket set at the port #9001.
2) Application: The user fills the fields shown in the main screen of the SafeTime
application:
a. Username: The user’s email address provided during the registration
process.
b. Password: The user’s password provided during the registration
process.
Once the information is written, the user taps the “Login” button.
3) Application: The fields are checked by the app to make sure they are filled
correctly, if not, a toast with the message “Fields are not complete” is shown.
4) Application: Once the form is correctly filled, a connection is established with
the server by initializing a socket in port #9001.
5) Application: A string array “LoginInfo” is initialized with the basic
information needed to perform the login task:
Table 4: Login variables
Variable Description
usrName The email of the user intending to log in.
usrPass The password corresponding to that user.
29
6) Server: The server successfully receives “LoginInfo” string array through the
socket.
7) Server: The server checks on its database for the user with the email
provided, if not found, the user will be notified that such user doesn’t exist. If
found, its password is retrieved and compared with the one received in the
socket. If the passwords match, the main information of the user is retrieved
from the database and is prepared to be sent to the application. Depending
on the scenario, a CODE is sent to the application:
Table 5: Login server CODEs
CODE Description
1 usrName is not registered.
2 Correct usrPass for usrName.
3 Incorrect usrPass for usrName.
8) Server: The CODE is sent to the application through the socket. If the usrPass
matched for the usrName, the information already retrieved from the
database is also sent through the socket.
9) Application: The CODE sent by the server is received through the socket. If
the CODE is “1”, a toast displaying the message “User not registered” is
shown. If the CODE signal is “3”, a toast with the message “Incorrect
password” is displayed. If CODE is “2”, then the user information also sent by
the server is received.
10) Application: A new set of RSA keys is generated by the application. This is
done because, since the previous private key generated at the registration (or
past login) is already erased from the device’s database. Since the user is able
to login at any device with SafeTime app installed, this is the way in which
the user can be sure that encrypted communication will work only in one
device, since the private key is never shared with the server and hence
cannot be saved.
30
11) Application: Once the new keys are generated, the user info received from
the server and the keys are saved into the “User Info Table” in the device’s
database.
12) Application: The public key generated is sent to the server using the active
socket and an Intent to the main application window is done.
13) Server: The public key received through the socket is used to update the key
field in the server’s database for the user with usrName. After this, the server
returns to a listening state waiting for other login request.
Once this process is done successfully, the user will be logged on its account in
the SafeTime app.
31
Figure 17: Login flow chart
5.3. Add contact process This process is the one that actually lets a user add another user to his contact
list, hence allowing communication between both users. For this version of
SafeTime app, only the email of a user is needed in order to add it to the contacts
32
list. The process to do so is the following, given the case in which a User_1 is
adding User_2 to his contact list:
Process:
1) App User_1: User_1 writes User_2’s email in the available field in the “+Add
Contact” tab and taps the “Add Contact” button.
2) App User_1: The add contact task is added to the “task stack” waiting for a
“receiving” signal from the server.
3) Server: The server’s main thread is scanning the user ports and arrives to the
User_1 port turn.
4) Server: Given the case that in its own task stack it has nothing to send User_1,
the server sends a “receiving” signal through the socket initialized on
User_1’s port and waits for a response.
5) App User_1: “receiving” signal is detected from the socket. And sends a
TaskID of “10” back to the server.
6) App User_1: The task with the message that includes the following
information is sent to the server through an active socket on port #9003:
Table 6: Add contact variables
Variable Description
usrToAdd The email of the user that wants to be added (User_2).
7) Server: TaskID of “10” is received, so the server knows that a message is
about to arrive. The TaskID’s will let know the server what kind of task is
about to receive: Table 7: Add contact TaskIDs
TaskID Description
10 Add contact task.
11 Message task.
33
8) Server: Listens to the “AddContactTask” that has a socket initialized in port
#9003 and receives the “usrToAdd” sent by User_1.
9) Server: It searches for “usrToAdd” email in the “Users” table in the server’s
database. If the user is not found, a CODE will be sent to the user notifying
that the user does not exist. If it is actually found, then a different CODE
confirming the existence of the user is sent:
Table 8: Add contact server CODEs
CODE Description
1 User exists
2 User not found
10) Server: CODE signal is sent to User_1. If the user was found, the information
about that user (in this case User_2) is retrieved from the server’s database
and is sent to User_1 through the port #9003 socket.
11) Server: Using the number of the active port in the main thread (User_1’s port
in this case), the server retrieves the information of the User_1 and creates a
new task to send the User_1’s information to User_2. The information to be
sent is the following: Table 9: Add contact server variables
Variable Description
11 TaskID for “Add contacts”.
usrName Name of the user to be added to contact list.
usrEmail Email of the user to be added to contact list.
usrKey Public key of the user to be added to contact list.
12) App User_1: User_1 receives the CODE signal. If its value is a “2”, a toast with
the message “User not found” is displayed in the screen and no further action
is taken. If the CODE was “1”, then the User_2’s info is read from the socket.
34
13) App User_1: The information received by the server is now stored in the
“contacts” table in the device’s database.
14) App User_1: The contact list window is refreshed.
15) Server: The server scans through ports until it reaches User_2’s port. Since it
has a task to send to User_2, it sends a “listen” signal through the socket
initialized with User_2’s port number.
16) App User_2: “ServerThread” is looping until it receives a signal from the
server. In this case, it receives a “listen” signal.
17) App User_2: Sends “acknowledge” signal to the server.
18) Server: Once received the “acknowledge” signal, the server sends the
User_1’s info task to User_2.
19) App User_2: User_1’s info is received from the server and is stored in the
“contacts” table in the device’s database.
20) App User_2: The contact list window is refreshed.
Is important to point out that in this version of SafeTime, when User_1 requests
to add User_2 to its contact list, the server will provide User_1 with User_2’s
information and at the same time will provide User_2 with User_1’s information
in order to achieve communitation between both users.
35
Figure 18: Add contact flow diagram
5.4. Encryption process Encryption is the core and most important part of SafeTime application (with
Decryption). This process is the responsible of using the RSA public key assigned
to the user to whom the message is going to be sent to cypher it and therefore
protect it from potential intruders or sniffers trying to read them. There are two
possible types of messages developed for SafeTime, plain text or images. For
36
both cases the main process of encryption is the same, but the way in which the
size of the data is treated is different. Given that the amount of data that can be
encrypted with the RSA algorithm is 256 bytes, images have to be divided into
sets of bytes in order to be able to encrypt them but text messages (with 256
characters or less) can be encrypted in the same block. Assuming a User_1 is
sending a message to User_2, the process to do so is the following:
Plain text:
1. User_1 writes a message for User_2 in the text field and taps “SEND”.
2. The string is read from the text field and is converted to a byte array by
using the “getBytes()” function in java.
3. The byte array obtained is used to initialize a new BigInteger “M”.
4. By using “M” and the public key of User_2, the message is encrypted
giving as a result the cypher-‐text “C”.
5. C is the converted to a byte array using the function “toByteArray()” in
the BigInteger library.
6. This byte array is now ready to be sent to the SafeTime server and hence,
to User_2.
Image:
1. User_1 selects an image from the gallery and taps “SEND PICTURE” in the
confirmation window.
2. The image is taken as a drawable, which will be converted to a Bitmap
“B”.
3. B is then compressed in a JPEG format into a ByteArrayOutputStream
“stream”.
4. “stream” is now converted to byte array “I” by using the “toByteArray()”
function.
5. Since “I” is bigger than 256, the whole byte array is divided into blocks of
255 bytes (as a safe size) and that are introduced in order into an
ArrayList “L”.
37
6. Each byte array goes through the encryption process individually:
6.1. Byte array is used to initialize a new BigInteger “M”.
6.2. If “M” is negative, it is multiplied by -‐1 in order to make it positive
and a sign variable “s” is set to “1”. If “M” is positive, it is left as it is
and the sign variable “s” is set to “2”. This is done because the RSA
algorithms permits encryption on numeric values greater than zero
and less than the “N” value of the key. The sign variable “s” will let
User_2 know if the BigInteger value obtained after the decryption
process is supposed to be positive or negative, so it can do the
calculations necessary to make the value be the same as it was before
encryption.
6.3. By using “M” and the public key of User_2, M is encrypted giving as a
result a cypher-‐section “C”.
6.4. “C” is then converted to a byte array using the function
“toByteArray()” in the BigInteger library.
6.5. A byte with the value “s” is added at the end of the byte array.
6.6. This byte array is then replaced in the ArrayList.
7. Once every byte array in the ArrayList is encrypted, the cyphered image
is ready to be sent to the server and hence, to User_2.
The encrypted message is now ready to be sent to the server, so the following
task ArrayList is added to the tasks queue in the SafeTime main thread:
Table 10: Encryption task ArrayList
Field Description
“11” Id given to the message task.
User_2 email Email of the user, which will receive the
message.
message The data to be sent to the receiving user:
• If plain text -‐> byte array.
• If Image -‐> ArrayList
38
Figure 19: Encryption process flow diagram
5.5. Decryption process Decryption is the process by which a user decrypts the cypher-‐text or cyphered
image received from another user. This message, as explained in the encryption
39
process, can be either plain text or an image. The type can be identified
depending on the type of data received, a byte array in case of plain text or an
ArrayList of byte arrays in case of an image and both types are treated differenty
due to the amount of information they carry. Continuing with the scenario
previously explained for the encryption process, a User_2 is receiving a message
from User_1:
Plain text:
1. User_2 receives a cyphered message “M” (byte array) from the server.
2. A BigInteger “m” is initialized with the byte array “M”.
3. By using “m” and User_2’s private key, the message is decrypted into the
BigInteger number “d”.
4. “d” is now converted into a deciphered byte array “D” by using the
“toByteArray()” function in the BigInteger library.
5. “D” will finally be used to initialize a new String that will be the
deciphered message as the User_1 wrote it.
6. The conversation window with User_1 is now refreshed.
Image:
1. User_2 receives a cyphered message “M” (ArrayList) from the server.
2. Each byte array in the ArrayList goes through the decryption process
individually:
2.1. The last byte of the byte array is removed and set into the variable
“t”. This byte will determine whether the BigInteger obtained after
decryption must be negative or not.
2.2. A BigInteger “m” is initialized using the rest of the byte array.
2.3. By using “m” and User_2’s private key, the section “m” is decrypted
into the BigInteger number “D”.
2.4. Depending on the value of “t”, “D” will change. If “t” is “1”, then “D” is
multiplied by -‐1. If “t” is “2”, then “D” is left as it is.
40
2.5. “D” is now converted into a byte array by using the “toByteArray()”
function in the BigInteger library. At this point, in some cases, the
byte array results to be 1 byte shorter than what it should be (254
bytes instead of 255). This happens because at the encryption
process made by User_1, the byte array that was converted into the
BigInteger that was encrypted started with a 0 as it first byte, which
resulted in a BigInteger number with a leading zero, which is
neglected by the initialization. So in order to compensate for it, every
time a byte array falls short by a byte, a ‘0’ byte is added as the first
value of the byte array.
2.6. This byte array is the replaced in the ArrayList.
3. Once all the sections has been decrypted, all byte arrays are padded one
next to the other in one big byte array. This is the byte array
corresponding to the image sent by User_1.
4. This big byte array is used to initialize a drawable.
5. The conversation window with User_1 is now refreshed.
41
Figure 20: Decryption flow diagram
5.6. Message send/receive process Messaging is the whole point of SafeTime app. It provides a communication
between two users of the application in a secure manner by using each other’s
public key to encrypt and their own private key to decrypt the received message.
In this process, the server works as a conduit for the two users, it doesn’t read or
42
stores the message received, but just resends it to the intended user. For this
process, because of the density of information that can be sent (in the case of
images) two different ports were assigned in order to let the server receive (port
#8999) and send (port #8998) messages. The only task of these threads is to
receive or send messages from and to the applications, this way, a potential
problem regarding saturation of ports is prevented.
Process:
This process describes the communication between two users, User_1 is sending
a message to User_2 like the example below:
Figure 21: Message send flow
1) App User_1: A message (text or image) is introduced and in the User_2
conversation window and the “Send” button is tapped.
2) App User_1: The message goes through the encryption process using User_2’s
public key and a message task is added to the “task stack” in the app and
waits for a “receiving” signal from the server. Also the sent message is
displayed on the conversation window with User_2.
3) Server: The server’s main thread is scanning the user ports and arrives to the
User_1 port turn.
43
4) Server: Given the case that in its own task stack it has nothing to send User_1,
the server sends a “receiving” signal through the socket initialized on
User_1’s port and waits for a response.
5) App User_1: “receiving” signal is detected from the socket. And sends a
TaskID of “11” back to the server.
6) App User_1: The task with the message that includes the following
information is sent to the server through an active socket on port #8999: Table 11: Message sending task variables
Variable Description
“M” or “I” The type of message that will be sent:
M: text message.
I: image.
encMessage The encrypted message to be sent.
toUser The email of the user to whom the message is destined (User_2).
fromUser The email of the user that sends the message (User_1)
7) Server: TaskID of “11” is received, so the server knows that a message is
about to arrive. The TaskID’s will let know the server what kind of task is
about to receive: Table 12: Messaging server TaskID
TaskID Description
10 Add contact task.
11 Message task.
8) Server: The message task is received through the “receiveMessageTask”
initialized in port #8999 and a new server message task is initialized with
the port number of the User_2. That information is retrieved from the
server’s database. Then the server returns to the “scanning ports” loop.
44
9) Server: The server arrives the port number of User_2. It finds that there is
one pending task for User_2 and sends through the socket initialized with
User-‐2’s port number a “listening” signal.
10) App User_2: User_2 is constantly scanning its port for an active connection
with the server. If a connection is not found, it keeps looping. If a connection
is found, it reads the signal sent by the server: Table 13: Message receiving task variables
Signal Description
“1” “listening” signal, the server will send data to the application and it
must be ready to receive it.
“2” “receiving” signal, the server has nothing to send and will wait for
the application to send a task if there is one.
No signal Nothing happens, the server will continue scanning ports.
11) App User_2: “listening” signal is received from the server. Initialized
connection with socket in port #8998 and sends an “acknowledgement”
signal to the server through the socket initialized with User_2’s port.
12) Server: “acknowledgement” signal is received from User_2. Now the server
will start transmitting the message through the “sendMessageThread”
initialized in port #8998.
13) App User_2: Message is received from the server through the socket
previously initialized in port #8998 with the information of from whom the
message was sent (User_1) and the type (image or plain text).
14) App User_2: The message goes through the decryption process using User_2’s
private key.
15) App User_2: The decrypted message is displayed in the conversation window
with User_1.
45
Figure 22: Message send/receive flow diagram
6. SafeTime tests A number of tests were made in order to ensure the functionality of the application.
Some of them to test the RSA algorithm for encryption and decryption, some for the
fragmentation and rebuild of images and others for communication.
6.1. Test 1: Key generation, Encryption and Decryption
46
For this application, RSA keys must be generated in order to ensure secure
communication as well as the encryption and decryption processes. One of the
most notorious concerns is the time it takes to generate such keys, encrypting
and decrypting messages, so in order to figure that out, the following code was
used to generate both public and private keys: //Generate a random number and look for two prime numbers of "bitlength" size r = new Random(); firstPrime = BigInteger.probablePrime(bitlength, r); secondPrime = BigInteger.probablePrime(bitlength, r); //First we need to obtain the number N = firstPrime*secondPrime N = firstPrime.multiply(secondPrime); //use Euler totient function to obtain phi (phi(N)) BigInteger phi = N.subtract(firstPrime.add(secondPrime).subtract(BigInteger.ONE)); //Obtain a prime number between 0 and N (should be coprime with phi) e = BigInteger.probablePrime(bitlength/2, r); //Making sure that e is coprime with N while (phi.gcd(e).compareTo(BigInteger.ONE) > 0 && e.compareTo(phi) < 0 ) { e.add(BigInteger.ONE); } //Obtain the private key by calculating e inverse module of phi d = e.modInverse(phi); System.out.println("Finish key generation"); keys[0] = N; keys[1] = e; keys[2] = d;
This keys were obtained by generating two prime numbers with a bitlength of
1024.
Encryption of a standard message of a size of 256 or less bytes is done with the
following code: public byte[] messageEncryption(byte[] M){ BigInteger N = new BigInteger(key.split("-‐")[0]); BigInteger e = new BigInteger(key.split("-‐")[1]); BigInteger encryptedMsg = new BigInteger(M); if (encryptedMsg.signum() != 1){ encryptedMsg = encryptedMsg.multiply(BigInteger.valueOf(-‐1)); encryptedMsg = encryptedMsg.modPow(e, N); byte[] encMsgBytestemp = encryptedMsg.toByteArray(); byte[] encMsgBytes = new byte[encMsgBytestemp.length+1]; for (int i = 0; i<encMsgBytes.length; i++){ if (i == encMsgBytes.length-‐1){ encMsgBytes[i] = (byte)1; }else{
47
encMsgBytes[i] = encMsgBytestemp[i]; } } return encMsgBytes; }else{ encryptedMsg = encryptedMsg.modPow(e, N); byte[] encMsgBytestemp = encryptedMsg.toByteArray(); byte[] encMsgBytes = new byte[encMsgBytestemp.length+1]; for (int i = 0; i<encMsgBytes.length; i++){ if (i == encMsgBytes.length-‐1){ encMsgBytes[i] = (byte)2; }else{ encMsgBytes[i] = encMsgBytestemp[i]; } } return encMsgBytes; }
Decryption of a standard message of 256 bytes or less is done with the following
code: public byte[] messageDecryption(byte[] D){ byte[] msgToDecrypt = new byte[D.length-‐1]; for (int i = 0; i<D.length-‐1; i++){ msgToDecrypt[i] = D[i]; } System.out.println(""+D[D.length-‐1]); BigInteger encryptedMsg = new BigInteger(msgToDecrypt); encryptedMsg = encryptedMsg.modPow(d, N); if (D[D.length-‐1] == (byte)1){ encryptedMsg = encryptedMsg.multiply(BigInteger.valueOf(-‐1)); } return encryptedMsg.toByteArray(); //return (new BigInteger(D)).modPow(d, N).toByteArray(); }
Result: The following table of processing times was obtained by running this
codes on the Android Studio simulator:
Table 14: RSA processing times
Process Processing time (seconds)
Key generation 0.252
Encryption process 0.008
Decryption process 0.018
48
Given the results on this table, it can be concluded that the processes are done in
a more than acceptable time.
6.2. Test 2: TCP socket communication In order to establish communication between the android application and the
server, TCP sockets were developer. So communication between two points was
tested, this was done by programming a Server socket and a Client socket as
follows:
• Server socket: import java.io.*; import java.net.*; public class SOK_SERVER { public static void main(String[] args) throws Exception{ SOK_SERVER SERVER = new SOK_SERVER(); SERVER.run(); } public void run() throws Exception{ //create a ServerSocket for port 1500 ServerSocket srvrSocket = new ServerSocket(1500); //open socket connection Socket sock = srvrSocket.accept(); InputStreamReader IR = new InputStreamReader(sock.getInputStream()); BufferedReader BR = new BufferedReader(IR); //check for messages received from the socket String MESSAGE = BR.readLine(); System.out.println(MESSAGE); if(MESSAGE != null){ //if a message is received, print in console PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("MESSAGE recieved"); } } }
• Client socket: import java.io.*; import java.net.*; public class SOK_CLIENT { public static void main(String[] args) throws Exception{ SOK_CLIENT CLIENT = new SOK_CLIENT(); CLIENT.run(); } public void run() throws Exception{ //create a socket for port 1500 at the Localhost Socket sock = new Socket("localhost", 1500); //print a message to be sent to the server PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("Hello! I am Client_1"); //initialize reading InputStreamReader IR = new InputStreamReader(sock.getInputStream()); BufferedReader BR = new BufferedReader(IR);
49
//look for messages that might be received by the server String MESSAGE = BR.readLine(); System.out.println(MESSAGE); } }
Result: communication was successful as shown in the logs presented on
console.
• ServerSocket console:
Figure 23: ServerSocket console screen
The message sent by the Client socket was received by the server, and the
server sent an acknowledgment message.
• ClientSocket console:
Figure 24: ClientSocket console screen
Client sent the message “Hello! I am Client_1”, the server received the
message and sent a message “MESSAGE received” in response. 6.3. Test 3: Encryption and decryption of text with one set of
keys This test consists on generating a set of keys using the RSA algorithm in order to
test its actual functionality. First the RSA keys “A” in the Appendix C were
generated.
Now, using the public key A, the message “hello bruce” written by a user will be
encrypted and sent to the server:
50
Figure 25: Sender text message
The cyphered message received by the server represents a lot of characters that
makes no sense as shown in this print from the server’s console:
Figure 26: Server log when a text message is received
Here, the information about the sender and recipient can be seen as well as the
cyphered message, at the end of this print, it can be seen that the message is
being sent to the recipient, who will receive the message and will decrypt it
using the private key A.
51
Figure 27: Received decrypted text message
Result: The message encrypted is received by the other user and is successfully
decrypted so it can be readable again, this works well because the pair of keys
generated are the ones that are used, that means, that the public key generated
will have only one way to decrypt which is the private key.
6.4. Test 4: Encryption and decryption of text with two
different set of keys This test is done in just about the same way the last one is done, but its main
objective is to show what will happen if a message encrypted with one public
key is tried to be decrypted with a private key not corresponding to it. For this,
two different set of keys in the Appendix C are used.
We now get the message “hello bruce” just like it was done in Test 1. The
message is then encrypted using the Public key A and is sent to the server and
later on is received by the other user. At this point, instead of using the Private
key A, which is the one corresponding to the public key used, Private key B will
be used for decryption and the result is the following:
52
Figure 28: Received decrypted message with wrong key
Result: As it can be seen, the message was not successfully decrypted. This
happens because the both public and private keys must be generated in the same
process using the same prime numbers, if this is not done this way the
calculation done at the decryption process will return a wrong number and
hence a wrong set of bytes that will end up in a group of characters that make no
sense as it can be seen in Figure 28.
6.5. Test 5: Encryption and decryption of images with one
set of keys The objective of this test is to show the functionality of the image encryption
process. For this, the same set of keys in Test 1 is going to be used. Using the
public key, the image chosen to be sent is encrypted and sent to the server:
53
Figure 29: Sender image message
Since is an image, a number of different encrypted blocks of 255 bytes are going
to be sent to the server in order to be sent to the receiving user.
Figure 30: Server log, receiving image
Once the end user receives those packets, they go through the decryption
process using the private key and reassemble of the image to finally display it on
the conversation window:
54
Figure 31: Received image message
Result: The image sent by the sending user was received successfully by the end
user, which means that both processes of encryption and decryption worked
perfectly. Also the process of segmentation and reassemble of the image was
successful.
6.6. Test 6: Encryption and decryption of images with two
different set of keys Using the two set of keys in Test 2, the same process as in Test 3 is repeated, but
this time the encryption process is done with the public key A by the sending
user and is later decrypted by the end user using the private key B:
55
Figure 32: Received corrupted image
Result: The blank space at the bottom of the list in Figure 31 shows that the
image was not successfully displayed. This happened because at the moment of
decryption a private key not corresponding to the public key used for encryption
was used. Because of that, the correct pattern of bytes for the image at the
process of reassemble was not obtained; hence the drawable could not be
assembled and resulted in a corrupted file.
7. Discussion 7.1. Achievements of SafeTime At the beginning of this project, encryption of just plain text messages was
considered. Since that task could be completed promptly, the idea of encrypting
files like images was considered. Since an image was a type of file that could be
considered a little more complex than text files, this became the goal from then
on. After some time working on the processes to encrypt/decrypt images
explained previously, this could be achieved proving that encryption of images
using RSA algorithm based on the fragmentation of an image was possible. This
proves that also files can be encrypted and sent in a secure way to other peers
guaranteeing confidentiality of files while they are transmitted.
56
Also, with the success of this application, it could be demonstrated that
encrypted communication can be fast and not much heavier in terms of data size
than conventional communication which will be appealing for the actual cyber
security concerns [13].
7.2. Limitations and upgrades In this version of SafeTime, some limitations have been detected in terms of
communication, development and design:
o Amount of users supported: Because of its port based socket
communication, SafeTime’s server has a limited number of ports for its ip
address. For TCP communication, the ports in a range from 32768 to
65535 are the ones considered as “Ephemeral ports” which are the ports
typically used for client communication. This port connections are short
lived and will exist as long as the client needs its service [14]. This will
leave SafeTime with a maximum capacity 32,767 users.
This can be upgraded by changing the socket communication model for a
more scalable model that can permit an exponentially bigger amount of
users to register and send requests and messages to the server without
depending on a single port connection.
o Data size: Socket communication can get saturated due to the amount of
information that is being sent. In case of images, which are substantially
bigger than plain text, saturation of ports in the middle of the
transmission is possible, truncating communication and making possible
the lost of data.
This can be fixed with the same solution as the last point, by using
another communication model.
o Limitation of file types: At the moment, the app can send plain text and
image messages, but with the code already developed, inclusion of other
file types such as .txt, .doc or even .pdf can be possible in a way similar as
the images. With this same principle, but with more complex features
57
developed in Android, encrypted half duplex communication [15] might
be possible. Full duplex would be less likely due to the processing times
for encrypting data which will not permit a real simultaneous
communication.
o Application design: A more user friendly design of the app with more
appealing user interface can be done with more time of development.
7.3. SafeTime’s use for industry Companies managing and working on projects that are competing with others
and need to maintain a secure communication between its developers, managers
and executives in order to prevent a potential intruder trying to read their
messages while they are being transmitted by using a sniffer. With a system
using the same type of communication as SafeTime the packages read by this
hypothetical intruder will be of no use because of the way its encrypted. This can
ensure full disclosure of the project in terms of internal communication.
Many industries today are getting more concerned on their communication
security. For example, due to the increasing digitalization of aviation systems
because of the “More electric aircraft [16]” tendency and the centralization of
information and control with the FMS (Flight management system), very
sensitive information about flights is transmitted from the airplane to other
peers such as the engine providers, airplane assemblers or airline companies.
This communications can be vulnerable without the proper security in their
transmissions, this can be managed with a model like the one used for SafeTime
which can be fast enough.
8. Conclusions Developing SafeTime application turned out to be as complex as was expected.
Instant messaging represents a difficulty while developing because of the speed
at which messages are expected to arrive, and that expectation has been
58
guarantied within its limitations. Cyber security has been one of the most
important topics lately regarding digitalization of information, many scandals
regarding this can be seen more and more in the media this past few years.
Whether it is in how the information is stored, or how is transmitted and even
on how easy can be for a skilled hacker to access remotely to systems and be
able to obtain confidential information, work in this field concerning security has
been increasing. The main purpose of developing this application is to
demonstrate how encryption algorithms (in this case RSA) can be used in
something as delicate as the transmission of data. It could be demonstrated that
various types of files can be encrypted in a relatively fast way and be transmitted
without the fear of getting that information stolen since, while been transmitted,
it is actually nonsense without a private key to decrypt it. I believe this same
model can be used in other security sensitive systems based on the model
described in this paper. For this purpose I’ve taken as one of my examples the
digital security in actual civil aviation, which is known for its flight management
systems that function as a central computer controlling the airplane, managing
transmissions and sending signals to actuators. In April 2015, a professional
security researcher managed to hack an airplane inflight in the United States and
was able to modify its flight path slightly of course [17]. The fact that this could
be done indicates how vulnerable these systems actually are. I believe that by
using encrypted commands transmitted to the systems, this kind of issues can be
prevented and hence guarantee more inflight security considering the estimated
times for breaking RSA keys is substantially less than the time an airplane stays
in the air.
This is just an example of how a model like the one used on SafeTime can help
enhance security not only in the aviation industry, but also in any other that
depends on digital technologies management systems.
59
9. Bibliography
[1] J. Pindar and J. Rigelsford, “Cybersecurity and Information Assurance,” 2011.
[2] “Top Apps – Android Apps on Google Play.” [Online]. Available: https://play.google.com/store/apps/collection/topselling_free?hl=en_GB. [Accessed: 30-‐Apr-‐2015].
[3] M. Mannan and P. C. Van Oorschot, “Secure Public Instant Messaging : A Survey,” Proc. 2nd Annu. Conf. Privacy, Secur. Trust., pp. 69–77, 2004.
[4] M. L. Murphy, Beginning Android. New York, 2009.
[5] M. Xue and C. Zhu, “The socket programming and software design for communication based on client/server,” Proc. 2009 Pacific-‐Asia Conf. Circuits, Commun. Syst. PACCS 2009, pp. 775–777, 2009.
[6] K. L. Calvert, “TCP / IP Sockets in C : Practical Guide for Programmers.”
[7] M. Y. Rhee, Advanced Encryption Standard and Elliptic Curve Cryptosystems. 2009.
[8] E. Milanov, “The RSA Algorithm,” no. June, pp. 1–11, 2009.
[9] A. Porter, “Programming the Android Platform -‐ Threads, Asynctasks & Handlers.” [Online]. Available: http://www.cs.umd.edu/class/fall2011/cmsc436/CMSC436/Lectures_Labs_files/ThreadsAndMessaging.pdf. [Accessed: 21-‐Aug-‐2015].
[10] “Eclipse Platform Technical Overview,” 2006.
[11] “Advanced Encryption Standard,” National Institute of Standards and Technology. [Online]. Available: http://csrc.nist.gov/publications/fips/fips197/fips-‐197.pdf. [Accessed: 22-‐Aug-‐2015].
[12] “National Policy on the Use of the Advanced Encryption Standard (AES) to Protect National Security Systems and National Security Information,” National Institute of Standards and Technology. [Online]. Available: http://csrc.nist.gov/groups/ST/toolkit/documents/aes/CNSS15FS.pdf. [Accessed: 22-‐Aug-‐2015].
[13] “Special Eurobarometer 423 ‘Cyber security,’” European Commission. [Online]. Available: http://ec.europa.eu/public_opinion/archives/ebs/ebs_423_en.pdf. [Accessed: 22-‐Aug-‐2015].
60
[14] P. Schneider, “TCP/IP Traffic Classification Based on Port Numbers,” Schneidergrinch, pp. 2–7, 1992.
[15] “Simplex, Half Duplex, Full Duplex Communication Channel.” [Online]. Available: http://www.idc-‐online.com/technical_references/pdfs/electronic_engineering/Simplex.pdf. [Accessed: 22-‐Aug-‐2015].
[16] a a Abdelhafez and a J. Forsyth, “A Review of More-‐Electric Aircraft,” Aerosp. Sci. Aviat. Technol., pp. 1–13, 2009.
[17] M. Hurley, “Warrant for Chris Robberts,” pp. 1–22, 2015.
ii
Appendix A: Application codes
Ø SplashScreenActivity.javapackage com.example.ricardoviteri.safetimeapp; import android.content.Intent; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import java.util.ArrayList; public class SplashScreenActivity extends ActionBarActivity { private DBHelper myDataBase; public ArrayList<String> myUser; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash_screen); myDataBase = new DBHelper(this); if (myDataBase.numberOfRowsUser() != 0){ /** LOAD THE USER'S INFO AND CONTACTS **/ Intent intent = new Intent(this, ContactsTabActivity.class); startActivity(intent); this.finish();
}else{ /** RUN SAFETIME'S MAIN LOGIN WINDOW **/ Intent intent = new Intent(this, LoginActivity.class); startActivity(intent); this.finish(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_splash_screen, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
Ø DBHelper.java
package com.example.ricardoviteri.safetimeapp; /** * Created by ricardoviteri on 6/18/15. */ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteDatabase; public class DBHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "MyDBName.db"; /******* CONTACTS TABLE ***********/ public static final String CONTACTS_TABLE_NAME = "contacts"; public static final String CONTACTS_COLUMN_ID = "id"; public static final String CONTACTS_COLUMN_NAME = "name"; public static final String CONTACTS_COLUMN_EMAIL = "email"; public static final String CONTACTS_COLUMN_KEY = "key"; /*********************************************/ /******* USER INFO TABLE ***********/ public static final String USER_TABLE_NAME = "user"; public static final String USER_COLUMN_ID = "id"; public static final String USER_COLUMN_NAME = "name";
iii
public static final String USER_COLUMN_PHONE = "phone"; public static final String USER_COLUMN_EMAIL = "email"; public static final String USER_COLUMN_PRIVATE = "privateKey"; public static final String USER_COLUMN_PUBLIC = "publicKey"; public static final String USER_COLUMN_PORT = "port"; /********************************************/ private HashMap hp; public DBHelper(Context context) { super(context, DATABASE_NAME , null, 1); } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-‐generated method stub db.execSQL( "create table contacts " + "(id integer primary key, name text,email text, key text)" ); db.execSQL( "create table user " + "(id integer primary key, name text, phone text, email text, privateKey text, publicKey text, port text)" ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-‐generated method stub db.execSQL("DROP TABLE IF EXISTS contacts"); db.execSQL("DROP TABLE IF EXISTS user"); onCreate(db); } /********* CONTACTS TABLE **********/ public boolean insertContact (String name, String email, String key) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues contentValues = new ContentValues(); contentValues.put("name", name); contentValues.put("email", email); contentValues.put("key", key); db.insert("contacts", null, contentValues); return true; } public Cursor getDataContact(String name){ SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery( "select * from contacts where name="+name+"", null ); System.out.println(res); return res; } public int numberOfRowsContacts(){ SQLiteDatabase db = this.getReadableDatabase(); int numRows = (int) DatabaseUtils.queryNumEntries(db, CONTACTS_TABLE_NAME); return numRows; } public boolean updateContact (Integer id, String name, String email, String key) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues contentValues = new ContentValues(); contentValues.put("name", name); contentValues.put("email", email); contentValues.put("key", key); db.update("contacts", contentValues, "id = ? ", new String[] { Integer.toString(id) } ); return true; } public Integer deleteContact (Integer id) { SQLiteDatabase db = this.getWritableDatabase(); return db.delete("contacts", "id = ? ", new String[] { Integer.toString(id) }); } public ArrayList<String> getAllCotacts() { ArrayList<String> array_list = new ArrayList<String>(); //hp = new HashMap(); SQLiteDatabase db = this.getReadableDatabase(); Cursor res = db.rawQuery( "select * from contacts", null ); res.moveToFirst(); while(res.isAfterLast() == false){ array_list.add(res.getString(res.getColumnIndex(CONTACTS_COLUMN_EMAIL))); res.moveToNext(); } return array_list; } public ArrayList<String[]> getAllCotactsWithInfo() { ArrayList<String[]> array_list = new ArrayList<String[]>(); //hp = new HashMap();
iv
SQLiteDatabase db = this.getReadableDatabase(); Cursor res = db.rawQuery( "select * from contacts", null ); res.moveToFirst(); while(res.isAfterLast() == false){ String[] contact = new String[4]; contact[0] = res.getString(res.getColumnIndex(CONTACTS_COLUMN_ID)); contact[1] = res.getString(res.getColumnIndex(CONTACTS_COLUMN_NAME)); contact[2] = res.getString(res.getColumnIndex(CONTACTS_COLUMN_EMAIL)); contact[3] = res.getString(res.getColumnIndex(CONTACTS_COLUMN_KEY)); ArrayList<String> cosa = new ArrayList<String>(Arrays.asList(contact)); array_list.add(contact); res.moveToNext(); } return array_list; } public ArrayList<ArrayList<Object>> getAllCotactsWithInfoAsList() { ArrayList<ArrayList<Object>> array_list = new ArrayList<ArrayList<Object>>(); //hp = new HashMap(); SQLiteDatabase db = this.getReadableDatabase(); Cursor res = db.rawQuery( "select * from contacts", null ); res.moveToFirst(); while(res.isAfterLast() == false){ String[] contact = new String[4]; contact[0] = res.getString(res.getColumnIndex(CONTACTS_COLUMN_ID)); contact[1] = res.getString(res.getColumnIndex(CONTACTS_COLUMN_NAME)); contact[2] = res.getString(res.getColumnIndex(CONTACTS_COLUMN_EMAIL)); contact[3] = res.getString(res.getColumnIndex(CONTACTS_COLUMN_KEY)); ArrayList<Object> contactList = new ArrayList<Object>(Arrays.asList(contact)); array_list.add(contactList); res.moveToNext(); } return array_list; } /*********************************************/
/************ USER INFO TABLE ***********/ public boolean insertUser (String name, String phone, String email, String privateKey, String publicKey, String port) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues contentValues = new ContentValues(); contentValues.put("name", name); contentValues.put("phone", phone); contentValues.put("email", email); contentValues.put("privateKey", privateKey); contentValues.put("publicKey", publicKey); contentValues.put("port", port); db.insert("user", null, contentValues); return true; } public Cursor getDataUser(int id){ SQLiteDatabase db = this.getReadableDatabase(); Cursor res = db.rawQuery( "select * from user where id="+id+"", null ); return res; } public int numberOfRowsUser(){ SQLiteDatabase db = this.getReadableDatabase(); int numRows = (int) DatabaseUtils.queryNumEntries(db, USER_TABLE_NAME); return numRows; } public boolean updateUser (Integer id, String name, String phone, String email, String privateKey, String publicKey, String port) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues contentValues = new ContentValues(); contentValues.put("name", name); contentValues.put("phone", phone); contentValues.put("email", email); contentValues.put("street", privateKey); contentValues.put("place", publicKey); db.update("user", contentValues, "id = ? ", new String[] { Integer.toString(id) } ); return true; } public Integer deleteUser (Integer id) { SQLiteDatabase db = this.getWritableDatabase(); return db.delete("user", "id = ? ", new String[] { Integer.toString(id) }); }
v
public ArrayList<String> getUser() { ArrayList<String> array_list = new ArrayList<String>(); //hp = new HashMap(); SQLiteDatabase db = this.getReadableDatabase(); Cursor res = db.rawQuery( "select * from user", null ); res.moveToFirst(); array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_ID))); array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_NAME))); array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_PHONE)));
array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_EMAIL))); array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_PRIVATE))); array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_PUBLIC))); array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_PORT))); return array_list; } /********************************************/ }
Ø ContactsTabActivity.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTabHost; import android.util.AttributeSet; import android.view.View; import android.widget.Toast; import java.lang.reflect.Array; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; /** * Created by ricardoviteri on 7/2/15. */ public class ContactsTabActivity extends FragmentActivity{ public FragmentTabHost mTabHost; ArrayList<String[]> contacts; ArrayList<ArrayList<Object>> contacts2; ArrayList<ArrayList<Object>> tasksToDo; String thisUser; int Port; BigInteger N, d; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.contacts_layout); DBHelper db = new DBHelper(this);
contacts = db.getAllCotactsWithInfo(); contacts2 = db.getAllCotactsWithInfoAsList(); tasksToDo = new ArrayList<ArrayList<Object>>(); Port = Integer.parseInt(db.getUser().get(6)); thisUser = db.getUser().get(3); N = new BigInteger(db.getUser().get(4).split("-‐")[0]); d = new BigInteger(db.getUser().get(4).split("-‐")[1]); mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost); mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent); mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Contacts"), ContactListTab.class, null); mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Conv."), ConversationListTab.class, null); mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator("+Add contact"), AddContactTab.class, null); mTabHost.setCurrentTab(1); } @Override protected void onStart() { super.onStart(); ServerThread listeningThread = new ServerThread(this, thisUser);
vi
listeningThread.start(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); System.out.println("In Activity"); ConversationListTab activeConv = (ConversationListTab)this.getSupportFragmentManager().findFragmentByTag("tab2"); Uri selectedImageUri = data.getData(); String selectedImagePath = activeConv.getPath(selectedImageUri); activeConv.image.setImageURI(selectedImageUri); activeConv.layoutImage.setVisibility(View.VISIBLE); } public void switchTabTo(int index){ mTabHost.setCurrentTab(index); } public void openConversation(int contact){ ConversationListTab activeConv = (ConversationListTab)this.getSupportFragmentManager().findFragmentByTag("tab2"); activeConv.activeContact = contact; activeConv.key = (String) contacts2.get(contact).get(3); mTabHost.setCurrentTab(1); } public void addContact(String[] newContact){ System.out.println(newContact[0]); System.out.println(newContact[1]); System.out.println(newContact[2]); DBHelper db = new DBHelper(this); db.insertContact(newContact[0], newContact[1], newContact[2]); refreshContacts(); } public void contactNotFound(String contact){ Toast toast = Toast.makeText(this, "User "+contact+" not found", Toast.LENGTH_SHORT); toast.show(); } public void refreshContacts(){ DBHelper db = new DBHelper(this); contacts = db.getAllCotactsWithInfo(); contacts2 = db.getAllCotactsWithInfoAsList(); } public void addToConversation(String fromUser, Object message){ int contactsId = 0; for (int i = 0; i < contacts.size(); i++){
if (contacts.get(i)[2].equals(fromUser)){ contactsId = i; } } ArrayList<Object> userInfo = contacts2.get(contactsId); Object info = null; if (message instanceof byte[]){ System.out.println("Actual message: "+new String((byte[])message)); System.out.println("Actual fromUser: "+fromUser); info = new String[]{"1", new String(messageDecryption((byte[]) message))}; }else{ info = new ArrayList<Object>(); ((ArrayList)info).add("1"); ((ArrayList)info).add(message); } ArrayList<Object> savedConversation; if (userInfo.size() == 4){ savedConversation = new ArrayList<Object>(); savedConversation.add(info); contacts2.get(contactsId).add(savedConversation); }else{ ((ArrayList<Object>)contacts2.get(contactsId).get(4)).add(info); } ConversationListTab activeConv = (ConversationListTab)this.getSupportFragmentManager().findFragmentByTag("tab2"); if (contactsId == activeConv.activeContact){ activeConv.postNewMessage(); } } public byte[] messageDecryption(byte[] D){ byte[] msgToDecrypt = new byte[D.length-‐1]; for (int i = 0; i<D.length-‐1; i++){ msgToDecrypt[i] = D[i]; } System.out.println(""+D[D.length-‐1]); BigInteger encryptedMsg = new BigInteger(msgToDecrypt); encryptedMsg = encryptedMsg.modPow(d, N); if (D[D.length-‐1] == (byte)1){ encryptedMsg = encryptedMsg.multiply(BigInteger.valueOf(-‐1)); }
vii
ConversationListTab activeConv = (ConversationListTab)this.getSupportFragmentManager().findFragmentByTag("tab2"); return encryptedMsg.toByteArray();
//return (new BigInteger(D)).modPow(d, N).toByteArray(); } }
Ø ContactListTab.java
package com.example.ricardoviteri.safetimeapp; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListView; import java.util.ArrayList; /** * Created by ricardoviteri on 7/2/15. */ public class ContactListTab extends Fragment implements AdapterView.OnItemClickListener{ ListView contactList; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment View V = inflater.inflate(R.layout.contact_list_tab, container, false); contactList = (ListView)V.findViewById(R.id.listView); ContactListAdapter adapter = new ContactListAdapter(this.getActivity(), 1, ((ContactsTabActivity)this.getActivity()).contacts2.toArray()); contactList.setAdapter(adapter); contactList.setOnItemClickListener(this); return V; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { System.out.println(""+position); ((ContactsTabActivity)this.getActivity()).openConversation(position); } }
Ø ContactListAdapter.java
package com.example.ricardoviteri.safetimeapp; import android.app.Fragment; import android.content.Context; import android.support.v4.app.FragmentActivity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; import java.util.ArrayList; import java.util.Objects; /** * Created by ricardoviteri on 7/19/15. */ public class ContactListAdapter extends ArrayAdapter { Object[] contacts; Context context; public ContactListAdapter(Context ctx, int resource, Object[] objects) { super(ctx, resource, objects); contacts = objects;
context = ctx; } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView==null){ // inflate the layout LayoutInflater inflater = ((FragmentActivity)context).getLayoutInflater(); convertView = inflater.inflate(R.layout.contact_cell, parent, false); } TextView name = (TextView)convertView.findViewById(R.id.textView15); ArrayList contact = (ArrayList) contacts[position]; name.setText(contact.get(1).toString()); return convertView; } }
8
Ø ConversationListTab.java package com.example.ricardoviteri.safetimeapp; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.provider.MediaStore; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.util.ArrayList; /** * Created by ricardoviteri on 7/7/15. */ public class ConversationListTab extends Fragment implements View.OnClickListener { int activeContact = 0; TextView txtUser; EditText message; ListView conversation; Button sendMessage, loadImg, sendImage; ImageView image; RelativeLayout layoutImage; ArrayList<Object> userInfo; ArrayList<Object> savedConversation; String key; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); System.out.println("Conversation tab "+activeContact); if (((ContactsTabActivity)this.getActivity()).mTabHost != null){ ((ContactsTabActivity)this.getActivity()).switchTabTo(0); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment
View V = inflater.inflate(R.layout.conversation_tab, container, false); txtUser = (TextView)V.findViewById(R.id.textView16); message = (EditText)V.findViewById(R.id.editText10); conversation = (ListView)V.findViewById(R.id.listView2); sendMessage = (Button)V.findViewById(R.id.button7); loadImg = (Button)V.findViewById(R.id.button8); sendImage = (Button)V.findViewById(R.id.button9); image = (ImageView)V.findViewById(R.id.imageView3); layoutImage = (RelativeLayout)V.findViewById(R.id.imageLayout); if((((ContactsTabActivity)this.getActivity()).contacts2).size() != 0){ userInfo = ((ContactsTabActivity)this.getActivity()).contacts2.get(activeContact); key = (String) userInfo.get(3); if (userInfo.size() == 4){ savedConversation = new ArrayList<Object>(); userInfo.add(savedConversation); }else{ savedConversation = (ArrayList<Object>) userInfo.get(4); } txtUser.setText(userInfo.get(1).toString()); sendMessage.setOnClickListener(this); loadImg.setOnClickListener(this); sendImage.setOnClickListener(this); ConversationAdapter adapter = new ConversationAdapter(this.getActivity(), 1, savedConversation.toArray()); conversation.setAdapter(adapter); conversation.setSelection(savedConversation.size()-‐1); }else{ txtUser.setText("No contacts"); } return V; } @Override public void onClick(View v) { switch (v.getId()){ case R.id.button7:
ix
if (message.getText().toString().length()>0){ String[] info = {"0", message.getText().toString()}; ArrayList<Object> task = new ArrayList<Object>(); task.add("11"); task.add(userInfo.get(2)); task.add(messageEncryption((message.getText().toString()).getBytes())); ((ContactsTabActivity)this.getActivity()).tasksToDo.add(task); /*SOK_CLIENT_BASIC cosa = new SOK_CLIENT_BASIC((message.getText().toString()).getBytes()); try { cosa.run(); } catch (Exception e) { e.printStackTrace(); }*/ savedConversation.add(info); ConversationAdapter adapter = new ConversationAdapter(this.getActivity(), 1, savedConversation.toArray()); conversation.setAdapter(adapter); message.setText(""); conversation.setSelection(savedConversation.size()-‐1); } break; case R.id.button8: Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); this.getActivity().startActivityForResult(Intent.createChooser(intent,"Select Picture"), 101); break; case R.id.button9: ArrayList<Object> info = new ArrayList<Object>(); info.add("0"); info.add(image.getDrawable()); savedConversation.add(info); ConversationAdapter adapter = new ConversationAdapter(this.getActivity(), 1, savedConversation.toArray()); conversation.setAdapter(adapter); message.setText(""); conversation.setSelection(savedConversation.size()-‐1); layoutImage.setVisibility(View.INVISIBLE); Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap(); ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); byte[] bitmapdata = stream.toByteArray(); new EncryptPictureTask(this.getActivity(), new BigInteger(key.split("-‐")[0]), new BigInteger(key.split("-‐")[1]), (String)userInfo.get(2)).execute(bitmapdata); break; } } public void addPictureTask(ArrayList<Object> task){ ((ContactsTabActivity)this.getActivity()).tasksToDo.add(task); } public String getPath(Uri uri) { // just some safety built in if( uri == null ) { // perform some logging or show user feedback Toast.makeText(this.getActivity(), "Loading picture failed", Toast.LENGTH_LONG).show(); return null; } // try to retrieve the image from the media store first // this will only work for images selected from gallery String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = this.getActivity().managedQuery(uri, projection, null, null, null); if( cursor != null ){ int column_index = cursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } // this is our fallback here, thanks to the answer from @mad indicating this is needed for // working code based on images selected using other file managers return uri.getPath(); } public void postNewMessage(){ ConversationAdapter adapter = new ConversationAdapter(this.getActivity(), 1, savedConversation.toArray()); conversation.setAdapter(adapter); message.setText(""); conversation.setSelection(savedConversation.size()-‐1);
x
} public byte[] messageEncryption(byte[] M){ BigInteger N = new BigInteger(key.split("-‐")[0]); BigInteger e = new BigInteger(key.split("-‐")[1]); BigInteger encryptedMsg = new BigInteger(M); if (encryptedMsg.signum() != 1){ encryptedMsg = encryptedMsg.multiply(BigInteger.valueOf(-‐1)); encryptedMsg = encryptedMsg.modPow(e, N); byte[] encMsgBytestemp = encryptedMsg.toByteArray(); byte[] encMsgBytes = new byte[encMsgBytestemp.length+1]; for (int i = 0; i<encMsgBytes.length; i++){ if (i == encMsgBytes.length-‐1){ encMsgBytes[i] = (byte)1; }else{ encMsgBytes[i] = encMsgBytestemp[i];
} } return encMsgBytes; }else{ encryptedMsg = encryptedMsg.modPow(e, N); byte[] encMsgBytestemp = encryptedMsg.toByteArray(); byte[] encMsgBytes = new byte[encMsgBytestemp.length+1]; for (int i = 0; i<encMsgBytes.length; i++){ if (i == encMsgBytes.length-‐1){ encMsgBytes[i] = (byte)2; }else{ encMsgBytes[i] = encMsgBytestemp[i]; } } return encMsgBytes; } //return encryptedMsg.toByteArray(); //return (new BigInteger(M)).modPow(e, N).toByteArray(); } }
Ø ConversationAdapter.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.graphics.drawable.Drawable; import android.support.v4.app.FragmentActivity; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; /** * Created by ricardoviteri on 7/20/15. */ public class ConversationAdapter extends ArrayAdapter { Object[] conversation; Context context; public ConversationAdapter(Context ctx, int resource, Object[] objects) { super(ctx, resource, objects); conversation = objects; context = ctx; } @Override public View getView(int position, View convertView, ViewGroup parent) { // inflate the layout
LayoutInflater inflater = ((FragmentActivity)context).getLayoutInflater(); if (conversation[position] instanceof String[]){ convertView = inflater.inflate(R.layout.conversation_cell, parent, false); TextView name; if (Integer.parseInt(((String[])conversation[position])[0]) == 0){ name = (TextView)convertView.findViewById(R.id.textView18); }else{ name = (TextView)convertView.findViewById(R.id.textView17); } name.setText(((String[])conversation[position])[1]); }else{ convertView = inflater.inflate(R.layout.conversation_image_cell, parent, false); ImageView image; if (Integer.parseInt((String) ((ArrayList<Object>)conversation[position]).get(0)) == 0){ image = (ImageView)convertView.findViewById(R.id.imageView5); }else{
xi
image = (ImageView)convertView.findViewById(R.id.imageView4); } image.setImageDrawable((Drawable) ((ArrayList<Object>)conversation[position]).get(1));
} return convertView; } }
Ø AddContactTab.java
package com.example.ricardoviteri.safetimeapp; import android.content.DialogInterface; import android.database.Cursor; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.RelativeLayout; import android.widget.Toast; import java.util.ArrayList; /** * Created by ricardoviteri on 7/7/15. */ public class AddContactTab extends Fragment implements View.OnClickListener { public EditText userEdt; public Button btnAdd; public RelativeLayout loadingLayout; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View V = inflater.inflate(R.layout.add_contact_tab, container, false); userEdt = (EditText) V.findViewById(R.id.editText9); btnAdd = (Button) V.findViewById(R.id.button6); loadingLayout = (RelativeLayout) V.findViewById(R.id.loadingLayout); btnAdd.setOnClickListener(this); return V; } @Override public void onClick(View v) { if (userEdt.getText().toString().length() > 0){ DBHelper db = new DBHelper(this.getActivity()); ArrayList<String> contacts = db.getAllCotacts(); boolean userExists = false; if (contacts.size() > 0){
String mail = userEdt.getText().toString(); for (int i = 0; i < contacts.size(); i++){ if (contacts.get(i).equals(mail)){ userExists = true; break; } } if (userExists){ Toast toast = Toast.makeText(this.getActivity(), "Contact already added", Toast.LENGTH_SHORT); toast.show(); }else{ //new AddContactTask(this, userEdt.getText().toString()).execute(); ArrayList<Object> addUser = new ArrayList<Object>(); addUser.add("10"); addUser.add(userEdt.getText().toString()); ((ContactsTabActivity) this.getActivity()).tasksToDo.add(addUser); } }else{ //new AddContactTask(this, userEdt.getText().toString()).execute(); ArrayList<Object> addUser = new ArrayList<Object>(); addUser.add("10"); addUser.add(userEdt.getText().toString()); ((ContactsTabActivity) this.getActivity()).tasksToDo.add(addUser); } } } public void addContact(String[] newContact){ System.out.println(newContact[0]); System.out.println(newContact[1]); System.out.println(newContact[2]); DBHelper db = new DBHelper(this.getActivity()); db.insertContact(newContact[0], newContact[1], newContact[2]); ((ContactsTabActivity)this.getActivity()).refreshContacts(); } public void contactNotFound(){ Toast toast = Toast.makeText(this.getActivity(), "User not found", Toast.LENGTH_SHORT);
xii
toast.show(); }
}
Ø LoginActivity.java
package com.example.ricardoviteri.safetimeapp; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.RelativeLayout; import android.widget.Switch; import android.widget.Toast; import java.math.BigInteger; import java.util.ArrayList; /** * Created by ricardoviteri on 6/28/15. */ public class LoginActivity extends Activity implements View.OnClickListener{ EditText txtUsername, txtPassword; Button btnRegister, btnLogin; BigInteger N, e, d; String[] userInfo = new String[3]; RelativeLayout loadingView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); txtUsername = (EditText) findViewById(R.id.editText5); txtPassword = (EditText) findViewById(R.id.editText6); loadingView = (RelativeLayout) findViewById(R.id.loadingLayout); btnLogin = (Button) findViewById(R.id.button2); btnRegister = (Button) findViewById(R.id.button3); btnLogin.setOnClickListener(this); btnRegister.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.button2: boolean isComplete = true; if (txtUsername.getText().toString().length() == 0 || txtPassword.getText().toString().length() == 0){ isComplete = false; }
if (isComplete){ loadingView.setVisibility(View.VISIBLE); new LoginTask(this, txtUsername.getText().toString(), txtPassword.getText().toString()).execute(); }else{ Toast toast = Toast.makeText(this, "Fields are not complete", Toast.LENGTH_SHORT); toast.show(); } break; case R.id.button3: Intent intent = new Intent(this, RegisterActivity.class); startActivity(intent); //this.finish(); break; } } public void loginAction(int code, String[] user){ /** * 1: User not found * 2: Correct password * 3: Incorrect password * 4: Info not received **/ switch (code){ case 1: executeToast("User not registered"); break; case 2: System.out.println(user[0]); System.out.println(user[1]); System.out.println(user[2]); System.out.println(user[3]); userInfo = user; new KeyGenerationTask(this).execute(); break; case 3: executeToast("Incorrect password"); break; default: executeToast("Connection error"); } } public void keysGenerated(BigInteger[] keys){ N = keys[0]; e = keys[1]; d = keys[2]; new UpdateKeyTask(this, ""+N+"-‐"+e, userInfo[2]).execute(); }
xiii
public void keysUpdated(String str){ DBHelper db = new DBHelper(this); db.insertUser(userInfo[0], userInfo[1], userInfo[2], ""+N+"-‐"+d, ""+N+"-‐"+e, userInfo[3]); System.out.println("User saved in DB"); ArrayList<String> userSaved = db.getUser(); System.out.println(""+userSaved.get(0)+"\n"+userSaved.get(1)+"\n"+userSaved.get(2)+"\n"+userSaved.get(3)+"\n"+userSaved.get(4)+"\n"+userSaved.get(5)+"\n"+userSaved.get(6)+"\n");
executeToast(str); Intent intent = new Intent(this, ContactsTabActivity.class); startActivity(intent); this.finish(); } public void executeToast(String msg){ Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT); toast.show(); } }
Ø RegisterActivity.java
package com.example.ricardoviteri.safetimeapp; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.lang.reflect.Array; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Random; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import java.util.Arrays; /** * Created by ricardoviteri on 6/18/15. */ public class RegisterActivity extends Activity implements View.OnClickListener{ EditText txtName, txtEmail, txtPass, txtRepPass, txtPhone; ImageView imgTest; TextView txtProgress; ProgressBar progBar; RelativeLayout loadingView; Button btnRegister; BigInteger firstPrime, secondPrime, N, e, d; String name, email, password, phone; byte[] encrypted, decrypted; int bitlength = 1024; Random r; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register); txtName = (EditText) findViewById(R.id.editText); txtPhone = (EditText) findViewById(R.id.editText7); txtEmail = (EditText) findViewById(R.id.editText2); txtPass = (EditText) findViewById(R.id.editText3); txtRepPass = (EditText) findViewById(R.id.editText4); btnRegister = (Button) findViewById(R.id.button); imgTest = (ImageView) findViewById(R.id.imageView); txtProgress = (TextView) findViewById(R.id.textView13); progBar = (ProgressBar) findViewById(R.id.progressBar2); loadingView = (RelativeLayout) findViewById(R.id.loadingLayout); btnRegister.setOnClickListener(this); } @Override public void onClick(View v) { loadingView.setVisibility(View.VISIBLE); boolean isComplete = true, passMatch = true; System.out.println("Button pushed!"); if (txtName.getText().toString().length() > 0){ name = txtName.getText().toString(); }else{ isComplete = false; } if (txtPhone.getText().toString().length() > 0){ phone = txtPhone.getText().toString(); }else{ isComplete = false; } if (txtEmail.getText().toString().length() > 0){ email = txtEmail.getText().toString(); }else{
xiv
isComplete = false; } if (txtPass.getText().toString().length() > 0){ password = txtPass.getText().toString(); }else{ isComplete = false; } if (txtRepPass.getText().toString().length() > 0){ if (!txtRepPass.getText().toString().equals(password)){ passMatch = false; } }else{ isComplete = false; } if (isComplete){ if (passMatch){ System.out.println("Register Successful"); //keyGeneration(); new KeyGenerationTask(this).execute(); }else{ Toast toast = Toast.makeText(this, "Passwords does not match", Toast.LENGTH_SHORT); toast.show(); } }else{ Toast toast = Toast.makeText(this, "Fields are not complete", Toast.LENGTH_SHORT); toast.show(); } //keyGeneration(); } public void keyGeneration(){ //Generate a random number and look for two prime numbers of "bitlength" size r = new Random(); firstPrime = BigInteger.probablePrime(bitlength, r); secondPrime = BigInteger.probablePrime(bitlength, r); //First we need to obtain the number N = firstPrime*secondPrime N = firstPrime.multiply(secondPrime); //use Euler totient function to obtain phi (phi(N)) BigInteger phi = N.subtract(firstPrime.add(secondPrime).subtract(BigInteger.ONE)); //Obtain a prime number between 0 and N (should be coprime with phi) e = BigInteger.probablePrime(bitlength/2, r);
//Making sure that e is coprime with N while (phi.gcd(e).compareTo(BigInteger.ONE) > 0 && e.compareTo(phi) < 0 ) { e.add(BigInteger.ONE); } //Obtain the private key by calculating e inverse module of phi d = e.modInverse(phi); System.out.println("Finish key generation"); /* Drawable d = getResources().getDrawable(R.drawable.shefuni); Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); byte[] bitmapdata = stream.toByteArray(); Drawable d2 = getResources().getDrawable(R.drawable.banana); Bitmap bitmap2 = ((BitmapDrawable)d2).getBitmap(); ByteArrayOutputStream stream2 = new ByteArrayOutputStream(); bitmap2.compress(Bitmap.CompressFormat.JPEG, 100, stream2); byte[] bitmapdata2 = stream2.toByteArray(); int counter = 0; for (int i = 0; i < (bitmapdata.length < bitmapdata2.length ? bitmapdata.length : bitmapdata2.length); i++){ if ((int)bitmapdata[i] == (int)bitmapdata2[i]){ counter++; }else{ break; } } //163 header System.out.println("Size of picture 1 is: "+bitmapdata.length+" bytes"); System.out.println("Size of picture 2 is: "+bitmapdata2.length+" bytes"); System.out.println("Header size of pictures is: "+counter+" bytes"); new EncryptPictureTask(this).execute(bitmapdata); txtProgress.setText("Encrypting..."); txtProgress.setVisibility(View.VISIBLE);
xv
progBar.setVisibility(View.VISIBLE); */ } public void keysGenerated(BigInteger[] keys){ N = keys[0]; e = keys[1]; d = keys[2]; new RegisterUserTask(this, name, phone, email, password, ""+N+"-‐"+e).execute(); } public void startApp(int result, String port){ loadingView.setVisibility(View.INVISIBLE); /** * 1: Successfully added * 2: Email already registered * 3: User not received **/ switch(result){ case 1: DBHelper db = new DBHelper(this); db.insertUser(name, phone, email, ""+N+"-‐"+d, ""+N+"-‐"+e, port); System.out.println("User saved in DB"); ArrayList<String> userSaved = db.getUser(); System.out.println(""+userSaved.get(0)+"\n"+userSaved.get(1)+"\n"+userSaved.get(2)+"\n"+userSaved.get(3)+"\n"+userSaved.get(4)+"\n"+userSaved.get(5)+"\n"+userSaved.get(6)+"\n"); Intent intent = new Intent(this, ContactsTabActivity.class); startActivity(intent); this.finish(); break; case 2: executeToast("Email already registered"); break; default: executeToast("Connection error"); } } public void executeToast(String msg){ Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT); toast.show(); } /* public byte[] messageEncryption(byte[] M){ BigInteger encryptedMsg = new BigInteger(M); if (encryptedMsg.signum() != 1){ encryptedMsg = encryptedMsg.multiply(BigInteger.valueOf(-‐1));
encryptedMsg = encryptedMsg.modPow(e, N); byte[] encMsgBytestemp = encryptedMsg.toByteArray(); byte[] encMsgBytes = new byte[encMsgBytestemp.length+1]; for (int i = 0; i<encMsgBytes.length; i++){ if (i == encMsgBytes.length-‐1){ encMsgBytes[i] = (byte)1; }else{ encMsgBytes[i] = encMsgBytestemp[i]; } } return encMsgBytes; }else{ encryptedMsg = encryptedMsg.modPow(e, N); byte[] encMsgBytestemp = encryptedMsg.toByteArray(); byte[] encMsgBytes = new byte[encMsgBytestemp.length+1]; for (int i = 0; i<encMsgBytes.length; i++){ if (i == encMsgBytes.length-‐1){ encMsgBytes[i] = (byte)2; }else{ encMsgBytes[i] = encMsgBytestemp[i]; } } return encMsgBytes; } //return encryptedMsg.toByteArray(); //return (new BigInteger(M)).modPow(e, N).toByteArray(); } public byte[] messageDecryption(byte[] D){ byte[] msgToDecrypt = new byte[D.length-‐1]; for (int i = 0; i<D.length-‐1; i++){ msgToDecrypt[i] = D[i]; } System.out.println(""+D[D.length-‐1]); BigInteger encryptedMsg = new BigInteger(msgToDecrypt); encryptedMsg = encryptedMsg.modPow(d, N); if (D[D.length-‐1] == (byte)1){ encryptedMsg = encryptedMsg.multiply(BigInteger.valueOf(-‐1)); } return encryptedMsg.toByteArray(); //return (new BigInteger(D)).modPow(d, N).toByteArray(); } private static String bytesToString(byte[] encrypted) { String test = ""; for (byte b : encrypted) { test += Byte.toString(b); } return test; }
xvi
public static boolean isPrime(long n) { if (n <= 3) { return n > 1; } else if (n % 2 == 0 || n % 3 == 0) { return false; } else { for (int i = 5; i * i <= n; i += 6) { if (n % i == 0 || n % (i + 2) == 0) { return false; } } return true; } } */
public void imageWasEncrypted(ArrayList<byte[]> encImg){ new DecryptPictureTask(this, "").execute(encImg); txtProgress.setText("Decrypting..."); } public void displayDecriptedImg(Drawable img){ imgTest.setImageDrawable(img); txtProgress.setText("Done!!"); progBar.setVisibility(View.INVISIBLE); } }
Ø ServerThread.java
package com.example.ricardoviteri.safetimeapp; import android.widget.Toast; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; /** * Created by ricardoviteri on 7/20/15. */ public class ServerThread extends Thread { ContactsTabActivity parent; String thisUser; public ServerThread(ContactsTabActivity context, String user) { parent = context; thisUser = user; } public void run(){ while(true){ Socket sock = null; try { sock = new Socket("192.168.1.103", parent.Port); } catch (IOException e) { //System.out.println("No connection"); } if (sock != null){ PrintStream PS = null; try { PS = new PrintStream(sock.getOutputStream());
} catch (IOException e) { e.printStackTrace(); } //TODO: sent this depending on if there is something to send or not if (parent.tasksToDo.size() > 0){ PS.println("1"); }else{ PS.println("0"); } //initialize reading InputStreamReader IR = null; try { IR = new InputStreamReader(sock.getInputStream()); } catch (IOException e) { e.printStackTrace(); } BufferedReader BR = new BufferedReader(IR); //look for messages that might be received by the server String MESSAGE = null; try { MESSAGE = BR.readLine(); if (MESSAGE == null){ MESSAGE = "20"; } //System.out.println(MESSAGE); } catch (Exception e) { e.printStackTrace(); MESSAGE = "20"; } /** * 1: Listen * 2: Send data **/ if (Integer.parseInt(MESSAGE) == 1){ System.out.println("Recieving something from server"); try { MESSAGE = BR.readLine(); //System.out.println(MESSAGE); } catch (Exception e) { e.printStackTrace();
xvii
MESSAGE = "20"; } int idTask = Integer.parseInt(MESSAGE); if (idTask == 10){ try { String[] userInfo = new String[3]; userInfo[0] = BR.readLine(); userInfo[1] = BR.readLine(); userInfo[2] = BR.readLine(); parent.addContact(userInfo); //System.out.println(MESSAGE); } catch (Exception e) { e.printStackTrace(); MESSAGE = "20"; } } if (idTask == 11){ System.out.println("READING MESSAGE"); new RecieveMessageTask(parent).execute(); /*byte[] encMessage = new byte[257]; try { BR.read(encMessage); //System.out.println(MESSAGE); } catch (Exception e) { e.printStackTrace(); MESSAGE = "20"; }*/ } } if (Integer.parseInt(MESSAGE) == 2){ final ArrayList<Object> task = parent.tasksToDo.get(0); int idTask = Integer.parseInt(task.get(0).toString()); /** * *********** idTask **************** * 10: Add Contact * 11: Send Message */ if (idTask == 10){ PS = null; try { PS = new PrintStream(sock.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } PS.println("1"); PS.println(task.get(1).toString()); System.out.println("Request sent"); //initialize reading IR = null;
try { IR = new InputStreamReader(sock.getInputStream()); } catch (IOException e) { e.printStackTrace(); } BR = new BufferedReader(IR); //look for messages that might be received by the server MESSAGE = null; try { MESSAGE = BR.readLine(); System.out.println("command received "+MESSAGE); } catch (IOException e) { e.printStackTrace(); } /** * 1: User found * 2: User not found **/ if (Integer.parseInt(MESSAGE) == 1){ System.out.println("Found user"); String[] userInfo = new String[3]; try { userInfo[0] = BR.readLine(); userInfo[1] = BR.readLine(); userInfo[2] = BR.readLine(); parent.addContact(userInfo); } catch (IOException e) { e.printStackTrace(); } if (parent.tasksToDo.size() > 0){ parent.tasksToDo.remove(0); } }else{ System.out.println("Not found"); parent.runOnUiThread(new Runnable() { public void run() { //Toast.makeText(parent, "Hello", Toast.LENGTH_SHORT).show(); parent.contactNotFound(task.get(1).toString()); } }); parent.tasksToDo.remove(0); } } if (idTask == 11){ PS = null; try { PS = new PrintStream(sock.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } PS.println("2"); //PS.println(task.get(1).toString());
xviii
SOK_CLIENT_BASIC cosa = new SOK_CLIENT_BASIC(task.get(2), task.get(1).toString(), thisUser); try { cosa.run(); } catch (Exception e) { e.printStackTrace(); } /* //Send de message byte[] byte[] encMessage = (byte[]) task.get(2); System.out.println(new String(encMessage)); OutputStream out = null; try { out = sock.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } DataOutputStream dos = new DataOutputStream(out); try { dos.writeInt(encMessage.length); } catch (IOException e) { e.printStackTrace(); } if (encMessage.length > 0) { try { dos.write(encMessage, 0, encMessage.length); System.out.println("Sending..."); } catch (IOException e) {
e.printStackTrace(); } } //initialize reading IR = null; try { IR = new InputStreamReader(sock.getInputStream()); } catch (IOException e) { e.printStackTrace(); } BR = new BufferedReader(IR); //look for messages that might be received by the server MESSAGE = null; try { MESSAGE = BR.readLine(); } catch (IOException e) { e.printStackTrace(); } System.out.println(MESSAGE); */ parent.tasksToDo.remove(0); System.out.println("Erased"); } } } } } }
Ø AddContactTask.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.os.AsyncTask; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.ArrayList; /** * Created by ricardoviteri on 7/19/15. */ public class AddContactTask extends AsyncTask<String, Integer, String[]> { AddContactTab context; String usrToAdd; String[] userInfo = new String[3]; public AddContactTask(AddContactTab ctx, String user) { context = ctx; usrToAdd = user;
} @Override protected String[] doInBackground(String... params) { Socket sock = null; try { DBHelper db = new DBHelper(context.getActivity()); ArrayList<String> userSaved = db.getUser(); sock = new Socket("192.168.1.103", 9003);//Integer.parseInt(userSaved.get(6)));//userSaved.get(6))); } catch (IOException e) { e.printStackTrace(); } PrintStream PS = null; try { PS = new PrintStream(sock.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } PS.println("1");
xix
PS.println(usrToAdd); //initialize reading InputStreamReader IR = null; try { IR = new InputStreamReader(sock.getInputStream()); } catch (IOException e) { e.printStackTrace(); } BufferedReader BR = new BufferedReader(IR); //look for messages that might be received by the server String MESSAGE = null; try { MESSAGE = BR.readLine(); System.out.println(MESSAGE); } catch (IOException e) { e.printStackTrace(); } /** * 1: User found * 2: User not found **/ if (Integer.parseInt(MESSAGE) == 1){ try { userInfo[0] = BR.readLine(); userInfo[1] = BR.readLine();
userInfo[2] = BR.readLine(); } catch (IOException e) { e.printStackTrace(); } }else{ this.cancel(true); } return userInfo; } @Override protected void onPostExecute(String[] strings) { super.onPostExecute(strings); context.addContact(strings); } @Override protected void onCancelled() { super.onCancelled(); context.contactNotFound(); } @Override protected void onPreExecute() { super.onPreExecute(); } }
Ø LoginTask.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.os.AsyncTask; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintStream; import java.net.Socket; /** * Created by ricardoviteri on 7/16/15. */ public class LoginTask extends AsyncTask<String, Integer, Integer> { Context context; String usr, pass; String[] userInfo = new String[4]; public LoginTask(Context ctx, String user, String password) { context = ctx; usr = user; pass = password; } @Override
protected Integer doInBackground(String... params) { String[] user = new String[2]; user[0] = usr; user[1] = pass; Socket sock = null; try { sock = new Socket("192.168.1.103", 9001); } catch (IOException e) { e.printStackTrace(); } ObjectOutputStream out = null; try { out = new ObjectOutputStream(sock.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } try { out.writeObject(user); } catch (IOException e) { e.printStackTrace(); } //initialize reading InputStreamReader IR = null; try { IR = new InputStreamReader(sock.getInputStream());
xx
} catch (IOException e) { e.printStackTrace(); } BufferedReader BR = new BufferedReader(IR); //look for messages that might be received by the server String MESSAGE = null; try { MESSAGE = BR.readLine(); System.out.println(MESSAGE); } catch (IOException e) { e.printStackTrace(); } if (Integer.parseInt(MESSAGE) == 2){ try { userInfo[0] = BR.readLine(); userInfo[1] = BR.readLine(); userInfo[2] = BR.readLine(); userInfo[3] = BR.readLine(); } catch (IOException e) { e.printStackTrace(); } PrintStream PS = null; try { PS = new PrintStream(sock.getOutputStream()); PS.println("UserInfo received"); } catch (IOException e) { e.printStackTrace();
} } return Integer.parseInt(MESSAGE); } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); ((LoginActivity)context).loginAction(integer, userInfo); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onCancelled(Integer integer) { super.onCancelled(integer); } }
Ø RegisterUserTask.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.os.AsyncTask; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; /** * Created by ricardoviteri on 7/14/15. */ public class RegisterUserTask extends AsyncTask<String, Integer, Integer>{ String usrName, usrPhone, usrEmail, usrPass, usrPKey, port; Context context; public RegisterUserTask(Context ctx, String name, String phone, String email, String pass, String pKey) { usrName = name; usrPhone = phone; usrEmail = email; usrPass = pass; usrPKey = pKey;
context = ctx; } @Override protected Integer doInBackground(String... params) { String[] user = new String[5]; user[0] = usrName; user[1] = usrPhone; user[2] = usrEmail; user[3] = usrPass; user[4] = usrPKey; Socket sock = null; try { sock = new Socket("192.168.1.103", 9000); } catch (IOException e) { e.printStackTrace(); } ObjectOutputStream out = null; try { out = new ObjectOutputStream(sock.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } try { out.writeObject(user);
xxi
} catch (IOException e) { e.printStackTrace(); } //initialize reading InputStreamReader IR = null; try { IR = new InputStreamReader(sock.getInputStream()); } catch (IOException e) { e.printStackTrace(); } BufferedReader BR = new BufferedReader(IR); //look for messages that might be received by the server String MESSAGE = null; try { MESSAGE = BR.readLine(); System.out.println(MESSAGE); if (Integer.parseInt(MESSAGE) == 1){ port = BR.readLine(); } } catch (IOException e) { e.printStackTrace(); }
return Integer.parseInt(MESSAGE); } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onPostExecute(Integer code) { super.onPostExecute(code); ((RegisterActivity)context).startApp(code, port); } @Override protected void onCancelled() { super.onCancelled(); } }
Ø KeyGenerationTask.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.os.AsyncTask; import java.math.BigInteger; import java.util.Random; /** * Created by ricardoviteri on 7/16/15. */ public class KeyGenerationTask extends AsyncTask<String, Integer, BigInteger[]> { BigInteger firstPrime, secondPrime, N, e, d; Random r; int bitlength = 1024; BigInteger[] keys = new BigInteger[3]; Context context; public KeyGenerationTask(Context ctx) { context = ctx; } @Override protected BigInteger[] doInBackground(String... params) { //Generate a random number and look for two prime numbers of "bitlength" size r = new Random(); firstPrime = BigInteger.probablePrime(bitlength, r); secondPrime = BigInteger.probablePrime(bitlength, r);
//First we need to obtain the number N = firstPrime*secondPrime N = firstPrime.multiply(secondPrime); //use Euler totient function to obtain phi (phi(N)) BigInteger phi = N.subtract(firstPrime.add(secondPrime).subtract(BigInteger.ONE)); //Obtain a prime number between 0 and N (should be coprime with phi) e = BigInteger.probablePrime(bitlength/2, r); //Making sure that e is coprime with N while (phi.gcd(e).compareTo(BigInteger.ONE) > 0 && e.compareTo(phi) < 0 ) { e.add(BigInteger.ONE); } //Obtain the private key by calculating e inverse module of phi d = e.modInverse(phi); System.out.println("Finish key generation"); keys[0] = N; keys[1] = e; keys[2] = d; return keys; } @Override
xxii
protected void onPostExecute(BigInteger[] bigIntegers) { super.onPostExecute(bigIntegers); if (context instanceof RegisterActivity) { ((RegisterActivity) context).keysGenerated(bigIntegers);
}else{ ((LoginActivity) context).keysGenerated(bigIntegers); } } }
Ø EncryptionPictureTask.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.os.AsyncTask; import java.math.BigInteger; import java.util.ArrayList; /** * Created by ricardoviteri on 7/2/15. */ public class EncryptPictureTask extends AsyncTask<byte[], Integer, ArrayList<byte[]>> { BigInteger N, e; Context context; String whoToSend; public EncryptPictureTask(Context ctx, BigInteger iN, BigInteger ie, String user) { context = ctx; N = iN; e = ie; whoToSend = user; } @Override protected ArrayList<byte[]> doInBackground(byte[]... params) { //DBHelper db = new DBHelper(context); //ArrayList<String> user = db.getUser(); byte[] bitmapdata = params[0]; /* N = BigInteger.valueOf(0); e = BigInteger.valueOf(0); N = N.add(new BigInteger((user.get(5).split("-‐"))[0])); e = e.add(new BigInteger((user.get(5).split("-‐"))[1])); */ int rounds = (int) Math.ceil((float)bitmapdata.length / 255.0); ArrayList<byte[]> cosa = new ArrayList<byte[]>(); for (int i = 0; i<rounds; i++){ byte[] contents = new byte[(bitmapdata.length-‐(255*i)<255 ? bitmapdata.length-‐(255*i) : 255)]; for (int j = 0; j<(bitmapdata.length-‐(255*i)<255 ? bitmapdata.length-‐(255*i) : 255); j++){ contents[j] = bitmapdata[i*255+j]; }
cosa.add(contents); } System.out.println("Finish Padding "+cosa.get(cosa.size()-‐1).length); int listSize = cosa.size(); for (int i = 0; i<listSize; i++){ byte[] temp = cosa.get(i); byte[] temp2 = messageEncryption(temp); cosa.remove(i); cosa.add(i, temp2); //System.out.println("Encrypted "+i); } return cosa; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onPostExecute(ArrayList<byte[]> bytes) { super.onPostExecute(bytes); System.out.println("Encryption done!!"); ArrayList<Object> task = new ArrayList<Object>(); task.add("11"); task.add(whoToSend); task.add(bytes); ((ContactsTabActivity)context).tasksToDo.add(task); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onCancelled() { super.onCancelled(); } public byte[] messageEncryption(byte[] M){ BigInteger encryptedMsg = new BigInteger(M); if (encryptedMsg.signum() != 1){ encryptedMsg = encryptedMsg.multiply(BigInteger.valueOf(-‐1)); encryptedMsg = encryptedMsg.modPow(e, N);
xxiii
byte[] encMsgBytestemp = encryptedMsg.toByteArray(); byte[] encMsgBytes = new byte[encMsgBytestemp.length+1]; for (int i = 0; i<encMsgBytes.length; i++){ if (i == encMsgBytes.length-‐1){ encMsgBytes[i] = (byte)1; }else{ encMsgBytes[i] = encMsgBytestemp[i]; } } return encMsgBytes; }else{ encryptedMsg = encryptedMsg.modPow(e, N); byte[] encMsgBytestemp = encryptedMsg.toByteArray();
byte[] encMsgBytes = new byte[encMsgBytestemp.length+1]; for (int i = 0; i<encMsgBytes.length; i++){ if (i == encMsgBytes.length-‐1){ encMsgBytes[i] = (byte)2; }else{ encMsgBytes[i] = encMsgBytestemp[i]; } } return encMsgBytes; } //return encryptedMsg.toByteArray(); //return (new BigInteger(M)).modPow(e, N).toByteArray(); } }
Ø DecryptPictureTask.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import java.io.ByteArrayInputStream; import java.math.BigInteger; import java.util.ArrayList; /** * Created by ricardoviteri on 7/2/15. */ public class DecryptPictureTask extends AsyncTask<ArrayList<byte[]>, Integer, Drawable> { Context context; BigInteger N, d; String fromUser; public DecryptPictureTask(Context context, String user) { this.context = context; fromUser = user; } @Override protected Drawable doInBackground(ArrayList<byte[]>... params) { DBHelper db = new DBHelper(context); ArrayList<String> user = db.getUser(); N = BigInteger.valueOf(0); d = BigInteger.valueOf(0); N = N.add(new BigInteger((user.get(5).split("-‐"))[0])); d = d.add(new BigInteger((user.get(4).split("-‐"))[1])); ArrayList<byte[]> imgBytesEnc = params[0]; int listSize = imgBytesEnc.size();
for (int i = 0; i<listSize; i++){ byte[] temp = messageDecryption(imgBytesEnc.get(i)); imgBytesEnc.remove(i); imgBytesEnc.add(i, temp); //System.out.println("Decrypted "+i); } System.out.println("Decrypted "); int counter = 0; for(int i = 0; i < imgBytesEnc.size(); i++){ counter += imgBytesEnc.get(i).length; if (imgBytesEnc.get(i).length < 255 && i != imgBytesEnc.size()-‐1){ counter++; } } byte[] newBitmapData = new byte[counter]; int newCounter = 0; for (int i = 0; i < imgBytesEnc.size(); i++){ for (int j = 0; j < imgBytesEnc.get(i).length; j++){ if (imgBytesEnc.get(i).length < 255 && j==0 && i != imgBytesEnc.size()-‐1){ newBitmapData[newCounter] = (i == 0 ? (byte)-‐1 : (byte)0); newCounter++; } newBitmapData[newCounter] = imgBytesEnc.get(i)[j]; newCounter++; } } System.out.println("Reassembled "); ByteArrayInputStream is = new ByteArrayInputStream(newBitmapData); Drawable drw = Drawable.createFromStream(is, "articleImage");
xxiv
return drw; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onPostExecute(Drawable drawable) { super.onPostExecute(drawable); ((ContactsTabActivity)context).addToConversation(fromUser, drawable); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onCancelled(Drawable drawable) {
super.onCancelled(drawable); } public byte[] messageDecryption(byte[] D){ byte[] msgToDecrypt = new byte[D.length-‐1]; for (int i = 0; i<D.length-‐1; i++){ msgToDecrypt[i] = D[i]; } System.out.println(""+D[D.length-‐1]); BigInteger encryptedMsg = new BigInteger(msgToDecrypt); encryptedMsg = encryptedMsg.modPow(d, N); if (D[D.length-‐1] == (byte)1){ encryptedMsg = encryptedMsg.multiply(BigInteger.valueOf(-‐1)); } return encryptedMsg.toByteArray(); //return (new BigInteger(D)).modPow(d, N).toByteArray(); } }
Ø ReceiveMessageTask.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.os.AsyncTask; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; import java.util.ArrayList; /** * Created by ricardoviteri on 7/22/15. */ public class RecieveMessageTask extends AsyncTask<ArrayList<Object>, Integer, Integer> { Context context; String fromUser; Object message; public RecieveMessageTask(Context ctx){ context = ctx; } @Override protected Integer doInBackground(ArrayList<Object>... params) { Socket sock = null; try {
sock = new Socket("192.168.1.103", 8998); } catch (IOException e) { e.printStackTrace(); } OutputStream out = null; try { out = sock.getOutputStream(); DataOutputStream dos = new DataOutputStream(out); dos.writeChar('E'); } catch (IOException e) { e.printStackTrace(); } InputStream in = null; try { in = sock.getInputStream(); DataInputStream dis = new DataInputStream(in); //dis.wait(1000); char type = dis.readChar(); if (type == 'M'){ int len = dis.readInt(); System.out.println("size: "+len); byte[] data = new byte[len]; if (len > 0){ dis.readFully(data); } System.out.println("message: "+new String(data)); message = data; }else{ int imgLen = dis.readInt(); System.out.println("size: "+imgLen);
xxv
ArrayList<byte[]> image = new ArrayList<byte[]>(); for (int i = 0; i < imgLen; i++){ System.out.println("Receiving"); int len = dis.readInt(); byte[] data = new byte[len]; if (len > 0){ dis.readFully(data); } image.add(data); System.out.println("Received #"+i); } System.out.println("Info received: "+image.size()); message = image; } } catch (IOException e) { e.printStackTrace(); } //initialize reading InputStreamReader IR = null; try { IR = new InputStreamReader(sock.getInputStream()); } catch (IOException e) { e.printStackTrace(); } BufferedReader BR = new BufferedReader(IR);
//look for messages that might be received by the server try { fromUser = BR.readLine(); System.out.println("from: "+fromUser); //System.out.println(MESSAGE); } catch (Exception e) { e.printStackTrace(); } try { sock.close(); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); if (message instanceof byte[]){ ((ContactsTabActivity)context).addToConversation(fromUser, message); }else{ new DecryptPictureTask(context, fromUser).execute((ArrayList<byte[]>)message); } } }
Ø UpdateKeyTask.java
package com.example.ricardoviteri.safetimeapp; import android.content.Context; import android.os.AsyncTask; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.PrintStream; import java.net.Socket; /** * Created by ricardoviteri on 7/16/15. */ public class UpdateKeyTask extends AsyncTask<String, Integer, String> { Context context; String key, email; String[] userInfo = new String[3]; public UpdateKeyTask(Context ctx, String publicKey, String mail) { context = ctx; key = publicKey; email = mail; }
@Override protected String doInBackground(String... params) { String[] user = new String[2]; user[0] = email; user[1] = key; Socket sock = null; try { sock = new Socket("192.168.1.103", 9002); } catch (IOException e) { e.printStackTrace(); } ObjectOutputStream out = null; try { out = new ObjectOutputStream(sock.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } try { out.writeObject(user); } catch (IOException e) { e.printStackTrace(); }
xxvi
//initialize reading InputStreamReader IR = null; try { IR = new InputStreamReader(sock.getInputStream()); } catch (IOException e) { e.printStackTrace(); } BufferedReader BR = new BufferedReader(IR); //look for messages that might be received by the server String MESSAGE = null; try { MESSAGE = BR.readLine(); System.out.println(MESSAGE); } catch (IOException e) { e.printStackTrace(); } return MESSAGE; }
@Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onPostExecute(String string) { super.onPostExecute(string); ((LoginActivity)context).keysUpdated(string); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } }
Ø SOK_CLIENT.java
package com.example.ricardoviteri.safetimeapp; import android.os.AsyncTask; import java.io.*; import java.net.*; /** * Created by ricardoviteri on 7/7/15. */ public class SOK_CLIENT { byte[] encMessage; String key; public SOK_CLIENT(byte[] msg, String key) { encMessage = msg; this.key = key; } public void run() throws Exception{ new MyAsyncTask().execute(); } private class MyAsyncTask extends AsyncTask<Void, Void, Void> { @Override protected void onPostExecute(Void result) { //Task you want to do on UIThread after completing Network operation //onPostExecute is called after doInBackground finishes its task. } @Override protected Void doInBackground(Void... params) { //Do your network operation here //create a socket for port 1500 at the Localhost Socket sock = null; try {
sock = new Socket("192.168.1.103", 9000); } catch (IOException e) { e.printStackTrace(); } //print a message to be sent to the server PrintStream PS = null; try { PS = new PrintStream(sock.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } PS.println(key); OutputStream out = null; try { out = sock.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } DataOutputStream dos = new DataOutputStream(out); try { dos.writeInt(encMessage.length); } catch (IOException e) { e.printStackTrace(); } if (encMessage.length > 0) { try { dos.write(encMessage, 0, encMessage.length); } catch (IOException e) { e.printStackTrace(); } } //initialize reading InputStreamReader IR = null;
xxvii
try { IR = new InputStreamReader(sock.getInputStream()); } catch (IOException e) { e.printStackTrace(); } BufferedReader BR = new BufferedReader(IR); //look for messages that might be received by the server String MESSAGE = null; try { MESSAGE = BR.readLine(); } catch (IOException e) { e.printStackTrace(); } System.out.println(MESSAGE); return null; } } }
xxviii
Appendix B: Server codes Ø socketServer.java
package saveTimeServer; import java.io.*; import java.net.*; import java.util.ArrayList; import java.util.Date; import java.util.List; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MongoClient; import socketThreads.LoginUserThread; import socketThreads.NewUserThread; import socketThreads.SendMessageThread; import socketThreads.TestThread; import socketThreads.TimerThread; import socketThreads.UpdateKeyThread; import java.math.BigInteger; public class socketServer { static BigInteger d; static BigInteger N; static boolean keepLoop = true; static boolean receivingMsg = true; static int actualPort; static ArrayList<ArrayList<Object>> tasksToDo = new ArrayList<ArrayList<Object>>(); static ArrayList<ArrayList<Object>> tasksForCycle = new ArrayList<ArrayList<Object>>(); public static void main(String[] args) throws Exception{ socketServer SERVER = new socketServer(); N = BigInteger.valueOf(0); d = BigInteger.valueOf(0); NewUserThread newUserThread = new NewUserThread(); newUserThread.start(); UpdateKeyThread updateKeyThread = new UpdateKeyThread(); updateKeyThread.start(); LoginUserThread loginUserThread = new LoginUserThread(); loginUserThread.start(); TestThread test = new TestThread(SERVER); test.start(); //SERVER.runKeyDecryption(); MongoClient mongo = new MongoClient("localhost", 27017); /**** Get database ****/ // if database doesn't
exists, MongoDB will create it for you DB db = mongo.getDB("safetimedb"); actualPort = 9003; while(true){ //System.out.println("TaskPending: "+tasksToDo.size()); //System.out.println("TaskForCycle: "+tasksForCycle.size()); while(tasksForCycle.size() > 0){ tasksToDo.add(tasksForCycle.get(0)); tasksForCycle.remove(0); } for(int i = 0; i < tasksToDo.size(); i++){ if(Integer.parseInt((String) tasksToDo.get(i).get(0)) == actualPort){ tasksForCycle.add(tasksToDo.get(i)); tasksToDo.remove(i); i-‐-‐; } } //System.out.println("TaskPending: "+tasksToDo.size()); //System.out.println("TaskForCycle: "+tasksForCycle.size()); keepLoop = true; TimerThread timer = new TimerThread(SERVER); timer.start(); ServerSocket srvrSocket = new ServerSocket();; try{ SERVER.mainUsersCycle(actualPort, srvrSocket, timer); }catch(Exception e){ //e.printStackTrace(); timer.stop(); srvrSocket.close(); } //srvrSocket.close(); DBCollection table = db.getCollection("users"); int numUsers = (int) table.count(); actualPort = (actualPort == 9003+numUsers-‐1 ? 9003 : actualPort+1); //System.out.println("yo ya estoy! -‐-‐-‐> "+actualPort); timer = null; } }
xxix
public void mainUsersCycle(int Port, ServerSocket srvrSocket, TimerThread timer) throws Exception{ //System.out.println("MainUsersCycle: "+"Main socket open"); //create a ServerSocket for Port srvrSocket.setReuseAddress(true); srvrSocket.bind(new InetSocketAddress(Port)); srvrSocket.setSoTimeout(21000); Socket sock; while(keepLoop){ //open socket connection sock = srvrSocket.accept(); sock.setSoTimeout(21000); //sock.setKeepAlive(true); InputStreamReader ir = new InputStreamReader(sock.getInputStream()); BufferedReader br = new BufferedReader(ir); String MESSAGE = br.readLine(); PrintStream Ps = new PrintStream(sock.getOutputStream()); /** * 0: Nothing to do * 1: Make app listen * 2: Make app send data **/ if(Integer.parseInt(MESSAGE) == 0 && tasksForCycle.size() == 0){ //System.out.println("Nothing to do with "+Port); keepLoop = false; timer.stop(); srvrSocket.close(); Ps.println("0"); }else
if(tasksForCycle.size() != 0){ Ps.println("1"); System.out.println("Send stuff to app"); /** * 10: SOMEONE ADDED AS CONTACT * 11: SOMEONE SENT A MESSAGE */ ArrayList<Object> task = tasksForCycle.get(0); if(Integer.parseInt((String) task.get(1)) == 10){ /** * *********** Add contact task list ************** * 0: Port * 1: taskId * 2: name * 3: email * 4: key */ Ps.println("10"); System.out.println("Sending contact!!!"); Ps.println(task.get(2)); Ps.println(task.get(3)); Ps.println(task.get(4)); } if(Integer.parseInt((String) task.get(1)) == 11){ /** * *********** Send message task list ************** * 0: Port * 1: taskId * 2: from who
xxx
* 3: message */ SendMessageThread loginUserThread = new SendMessageThread(this, task.get(3), (String) task.get(2)); loginUserThread.start(); Ps.println("11"); System.out.println("Sending message!!!"); /*byte[] encMessage = (byte[]) task.get(3); //Ps.println(""+encMessage.length); Ps.println(encMessage); OutputStream out = sock.getOutputStream(); DataOutputStream dos = new DataOutputStream(out); dos.write(encMessage); if(encMessage.length > 0){ dos.write(encMessage, 0, encMessage.length); } */ } tasksForCycle.remove(0); //TODO: Send stuff to app! }else{ Ps.println("2"); MESSAGE = br.readLine(); /** * 1:
ADD CONTACT * 2: MESSAGE **/ //ADD CONTACT PROCESS if(Integer.parseInt(MESSAGE) == 1){ String user = br.readLine(); MongoClient mongo = new MongoClient("localhost", 27017); /**** Get database ****/ // if database doesn't exists, MongoDB will create it for you DB db = mongo.getDB("safetimedb"); /**** Get collection / table from 'testdb' ****/ // if collection doesn't exists, MongoDB will create it for you DBCollection table = db.getCollection("users"); /**** Find and display ****/ BasicDBObject searchQuery = new BasicDBObject(); searchQuery.put("email", user); DBCursor cursor = table.find(searchQuery); /** * 1: User found * 2: User not found **/ List<DBObject> csrList = cursor.toArray(); PrintStream PS = new PrintStream(sock.getOutputStream()); if (csrList.size() > 0) { System.out.println("MainUsersCycle
xxxi
/AddContact: User found"); PS.println("1"); PS.println(csrList.get(0).get("name").toString()); PS.println(csrList.get(0).get("email").toString()); PS.println(csrList.get(0).get("key").toString()); /** * *********** Add contact task list ************** * 0: Port * 1: taskId * 2: name * 3: email * 4: key */ BasicDBObject searchQuery2 = new BasicDBObject(); searchQuery.put("port", Port); DBCursor cursor2 = table.find(searchQuery2); List<DBObject> csrList2 = cursor2.toArray(); ArrayList<Object> task = new ArrayList<Object>(); task.add(csrList.get(0).get("port").toString()); task.add("10"); task.add(csrList2.get(0).get("name").toString());
task.add(csrList2.get(0).get("email").toString()); task.add(csrList2.get(0).get("key").toString()); tasksToDo.add(task); }else{ System.out.println("MainUsersCycle/AddContact: User not found"); PS.println("2"); } } if(Integer.parseInt(MESSAGE) == 2){ while(receivingMsg){ //System.out.println("waiting"); } System.out.println("finished waiting"); receivingMsg = true; } } sock.close(); } srvrSocket.close(); } public void changeStopLoop(){ keepLoop = false; } public void stopReceiving(){ receivingMsg = false; } public void stopReceivingMsg(Object msg, String toUser,
xxxii
String fromUser){ //int thisPort = actualPort; receivingMsg = false; if(msg instanceof byte[]){ System.out.println(new String((byte[])msg)); }else{ System.out.println("Is an image"); } System.out.println(toUser); ArrayList<Object> task = new ArrayList<Object>(); /** * *********** Send message task list ************** * 0: Port * 1: taskId * 2: from who * 3: message */ MongoClient mongo = null; try { mongo = new MongoClient("localhost", 27017); } catch (UnknownHostException e) { // TODO Auto-‐generated catch block e.printStackTrace(); } /**** Get database ****/ // if database doesn't exists, MongoDB will create it for you DB db = mongo.getDB("safetimedb"); /**** Get collection / table from 'testdb' ****/ // if collection doesn't exists, MongoDB will create it for you DBCollection table = db.getCollection("users"); /**** Find and display ****/ BasicDBObject searchQuery = new BasicDBObject(); searchQuery.put("email", toUser); DBCursor cursor = table.find(searchQuery); List<DBObject> csrList = cursor.toArray(); String endUserPort = csrList.get(0).get("port").toString();
System.out.println("Send message task list port: "+endUserPort); /*BasicDBObject searchQuery2 = new BasicDBObject(); System.out.println("thisPort"+thisPort); searchQuery2.put("port", thisPort); DBCursor cursor2 = table.find(searchQuery); List<DBObject> csrList2 = cursor2.toArray(); String thisUser = csrList2.get(0).get("email").toString(); */ System.out.println("Send message task list user: "+fromUser); task.add(endUserPort); task.add("11"); task.add(fromUser); task.add(msg); tasksToDo.add(task); } public void runKeyDecryption() throws Exception{ //create a ServerSocket for port 8080 ServerSocket srvrSocket = new ServerSocket(9003); srvrSocket.setReuseAddress(true); Socket sock; while(true){ //open socket connection sock = srvrSocket.accept(); //sock.setKeepAlive(true); System.out.println("Checkpoint 1"); InputStreamReader IR = new InputStreamReader(sock.getInputStream()); BufferedReader BR = new BufferedReader(IR); //check for messages received from the socket String MESSAGE = BR.readLine(); N = N.add(new BigInteger((MESSAGE.split("-‐"))[0])); d = d.add(new BigInteger((MESSAGE.split("-‐"))[1])); System.out.println(""+N);
xxxiii
System.out.println(""+d); System.out.println("Checkpoint 2"); MESSAGE = "now the message..."; InputStream in = sock.getInputStream(); DataInputStream dis = new DataInputStream(in); int len = dis.readInt(); System.out.println("size: "+len); System.out.println("Checkpoint 3"); byte[] data = new byte[len]; if (len > 0) { dis.readFully(data); } System.out.println("Checkpoint 4"); System.out.println(new String(data)); if(data.length != 0){ //if a message is received, print in console
PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("MESSAGE recieved"); } System.out.println("Checkpoint 5"); /*byte[] decMessage = messageDecryption(data); System.out.println(new String(decMessage)); N = BigInteger.valueOf(0); d = BigInteger.valueOf(0); */ data = null; sock.close(); } } public byte[] messageDecryption(byte[] D){ BigInteger encryptedMsg = new BigInteger(D); encryptedMsg = encryptedMsg.modPow(d, N); return encryptedMsg.toByteArray(); //return (new BigInteger(D)).modPow(d, N).toByteArray(); } }
Ø LoginUserThread.java
package socketThreads; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.List; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MongoClient; public class LoginUserThread extends Thread { public void run(){ try { loginUserTask();
} catch (Exception e) { // TODO Auto-‐generated catch block e.printStackTrace(); } } public void loginUserTask() throws Exception{ //create a ServerSocket for port 8080 ServerSocket srvrSocket = new ServerSocket(9001); srvrSocket.setReuseAddress(true); Socket sock; System.out.println("LoginUserThread: "+"Login socket open"); while(true){ //open socket
xxxiv
connection sock = srvrSocket.accept(); InputStream in = sock.getInputStream(); ObjectInputStream dis = new ObjectInputStream(in); String[] user = new String[2]; user = (String[]) dis.readObject(); if(user.length != 0){ //if a message is received, print in console System.out.println("LoginUserThread: "+""+user[0]); System.out.println("LoginUserThread: "+""+user[1]); //TODO: Add user to DataBase! send a unique port number to user. MongoClient mongo = new MongoClient("localhost", 27017); /**** Get database ****/ // if database doesn't exists, MongoDB will create it for you DB db = mongo.getDB("safetimedb"); /**** Get collection / table from 'testdb' ****/ // if collection doesn't exists, MongoDB will create it for you DBCollection table = db.getCollection("users"); /**** Find and display ****/ BasicDBObject searchQuery = new BasicDBObject(); searchQuery.put("email", user[0]); DBCursor cursor = table.find(searchQuery); /** * 1: User not found * 2: Correct password
* 3: Incorrect password * 4: Info not received **/ List<DBObject> csrList = cursor.toArray(); if (csrList.size() > 0) { String pass = csrList.get(0).get("password").toString(); System.out.println(pass); if(pass.equals(user[1])){ PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("2"); PS.println(csrList.get(0).get("name").toString()); PS.println(csrList.get(0).get("phone").toString()); PS.println(csrList.get(0).get("email").toString()); PS.println(csrList.get(0).get("port").toString()); InputStreamReader IR = new InputStreamReader(sock.getInputStream()); BufferedReader BR = new BufferedReader(IR); //check for messages received from the socket String MESSAGE = BR.readLine(); System.out.println(MESSAGE); }else{ PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("3");
xxxv
} }else{ PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("1"); } }else{
PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("4"); } sock.close(); } } }
Ø NewUserThread.java package socketThreads; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.MongoClient; public class NewUserThread extends Thread { public void run(){ try { runNewUserTask(); } catch (Exception e) { // TODO Auto-‐generated catch block e.printStackTrace(); } } public void runNewUserTask() throws Exception{ //create a ServerSocket for port 8080 ServerSocket srvrSocket = new ServerSocket(9000); srvrSocket.setReuseAddress(true); Socket sock; System.out.println("NewUserThread: "+"Registration socket open"); while(true){ //open socket connection sock = srvrSocket.accept(); InputStream in = sock.getInputStream();
ObjectInputStream dis = new ObjectInputStream(in); String[] user = new String[5]; user = (String[]) dis.readObject(); if(user.length != 0){ //if a message is received, print in console System.out.println("NewUserThread: "+""+user[0]); System.out.println("NewUserThread: "+""+user[1]); System.out.println("NewUserThread: "+""+user[2]); System.out.println("NewUserThread: "+""+user[3]); System.out.println("NewUserThread: "+""+user[4]); //TODO: Add user to DataBase! send a unique port number to user. MongoClient mongo = new MongoClient("localhost", 27017); /**** Get database ****/ // if database doesn't exists, MongoDB will create it for you DB db = mongo.getDB("safetimedb"); /**** Get collection / table from 'testdb' ****/ // if collection doesn't exists, MongoDB will create it for you
xxxvi
DBCollection table = db.getCollection("users"); /**** Find and display ****/ BasicDBObject searchQuery = new BasicDBObject(); searchQuery.put("email", user[2]); DBCursor cursor = table.find(searchQuery); /** * 1: Sucessfully added * 2: Email already registered * 3: User not received **/ if (cursor.length() > 0) { PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("2"); }else{ long port = 9003 + table.count(); /**** Insert ****/ // create a document to store key and value BasicDBObject document = new
BasicDBObject(); document.put("name", user[0]); document.put("phone", user[1]); document.put("email", user[2]); document.put("password", user[3]); document.put("key", user[4]); document.put("port", ""+port); table.insert(document); PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("1"); PS.println(""+port); } }else{ PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("3"); } sock.close(); } } }
Ø SendMessageThread.java package socketThreads; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import saveTimeServer.socketServer; public class SendMessageThread extends Thread{ socketServer parent; Object encMessage; String user;
public SendMessageThread(socketServer context, Object msg, String usrToSend){ parent = context; encMessage = msg; user = usrToSend; } public void run(){ try { sendMessage(); } catch (Exception e) { // TODO Auto-‐generated catch block e.printStackTrace(); } } public void sendMessage() throws Exception{ try {
xxxvii
System.out.println("SendMessage running"); ServerSocket srvrSocket = new ServerSocket(8998); srvrSocket.setReuseAddress(true); Socket sock; sock = srvrSocket.accept(); InputStream in = sock.getInputStream(); DataInputStream dis = new DataInputStream(in); char cosa = dis.readChar(); OutputStream out = sock.getOutputStream(); DataOutputStream dos = new DataOutputStream(out); if(encMessage instanceof byte[]){ System.out.println(new String((byte[])encMessage)); dos.writeChar('M'); dos.writeInt(((byte[])encMessage).length); if(((byte[])encMessage).length > 0){ dos.write(((byte[])encMessage), 0, ((byte[])encMessage).length); }
}else{ dos.writeChar('I'); dos.writeInt(((ArrayList)encMessage).size()); for(int i = 0; i < ((ArrayList)encMessage).size(); i++){ dos.writeInt(((byte[])((ArrayList)encMessage).get(i)).length); if(((byte[])((ArrayList)encMessage).get(i)).length > 0){ dos.write(((byte[])((ArrayList)encMessage).get(i)), 0, ((byte[])((ArrayList)encMessage).get(i)).length); } } } PrintStream Ps = new PrintStream(sock.getOutputStream()); Ps.println(user); } catch (IOException e) { // TODO Auto-‐generated catch block e.printStackTrace(); } } }
Ø TestThread.java package socketThreads; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import saveTimeServer.socketServer; public class TestThread extends Thread{ socketServer parent; public TestThread(socketServer context){ parent = context; }
public void run(){ try { receiveMessage(); } catch (Exception e) { // TODO Auto-‐generated catch block e.printStackTrace(); } } public void receiveMessage() throws Exception{ try { System.out.println("TestThread running"); ServerSocket srvrSocket = new ServerSocket(8999);
xxxviii
srvrSocket.setReuseAddress(true); Socket sock; while(true){ sock = srvrSocket.accept(); InputStream in = sock.getInputStream(); DataInputStream dis = new DataInputStream(in); char type = dis.readChar(); if(type == 'M'){ int len = dis.readInt(); System.out.println("size: "+len); byte[] data = new byte[len]; if (len > 0) { dis.readFully(data); } InputStreamReader ir = new InputStreamReader(sock.getInputStream()); BufferedReader br = new BufferedReader(ir); String toUser = br.readLine(); String fromUser = br.readLine(); parent.stopReceivingMsg(data, toUser, fromUser); }else{ int imgLen = dis.readInt(); System.out.println("size of image: "+imgLen); ArrayList<Object> image = new ArrayList<Object>();
for(int i = 0; i < imgLen; i++){ System.out.println("Receiving..."); int len = dis.readInt(); byte[] data = new byte[len]; if (len > 0) { dis.readFully(data); } image.add(data); System.out.println("Received #"+i); } System.out.println("info received: "+image.size()); InputStreamReader ir = new InputStreamReader(sock.getInputStream()); BufferedReader br = new BufferedReader(ir); String toUser = br.readLine(); String fromUser = br.readLine(); System.out.println("To user: "+toUser); System.out.println("from user: "+fromUser); parent.stopReceivingMsg(image, toUser, fromUser); } } } catch (IOException e) { // TODO Auto-‐generated catch block e.printStackTrace(); } } }
xxxix
Ø TimerThread.java package socketThreads; import saveTimeServer.socketServer; public class TimerThread extends Thread{ socketServer parent; public TimerThread(socketServer context){ parent = context; } public void run(){ try { Thread.sleep(20000); } catch (InterruptedException e) { // TODO Auto-‐generated catch block e.printStackTrace(); } System.out.println("Timer finished"); parent.changeStopLoop(); } } UpdateKeyThread.java package socketThreads; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.List; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MongoClient; public class UpdateKeyThread extends Thread { public void run(){ try { updateKeyTask(); } catch (Exception e) { // TODO Auto-‐generated catch block e.printStackTrace(); } } public void updateKeyTask() throws Exception{
//create a ServerSocket for port 8080 ServerSocket srvrSocket = new ServerSocket(9002); srvrSocket.setReuseAddress(true); Socket sock; System.out.println("UpdateKeyThread: "+"Key update socket open"); while(true){ //open socket connection sock = srvrSocket.accept(); InputStream in = sock.getInputStream(); ObjectInputStream dis = new ObjectInputStream(in); String[] user = new String[2]; user = (String[]) dis.readObject(); if(user.length != 0){ //if a message is received, print in console System.out.println("UpdateKeyThread: "+""+user[0]); System.out.println("UpdateKeyThread: "+""+user[1]); //TODO: Add user to DataBase! send a unique port number to user. MongoClient mongo = new MongoClient("localhost", 27017); /**** Get database ****/ // if database doesn't exists, MongoDB will create it for you DB db = mongo.getDB("safetimedb"); /**** Get collection / table from 'testdb' ****/ // if collection doesn't exists, MongoDB will create it for you DBCollection table = db.getCollection("users"); /****
xl
Update ****/ // search document where name="mkyong" and update it with new values BasicDBObject query = new BasicDBObject(); query.put("email", user[0]); DBCursor cursor = table.find(query); List<DBObject> csrList = cursor.toArray(); System.out.println("UpdateKeyThread: "+csrList.get(0).get("name").toString()); System.out.println("UpdateKeyThread: "+csrList.get(0).get("phone").toString()); System.out.println("UpdateKeyThread: "+csrList.get(0).get("email").toString()); System.out.println("UpdateKeyThread: "+csrList.get(0).get("password").toString()); System.out.println("UpdateKeyThread: "+csrList.get(0).get("key").toString()); BasicDBObject newDocument = new BasicDBObject(); newDocument.put("key", user[1]); BasicDBObject updateObj = new BasicDBObject(); updateObj.put("$set", newDocument); table.update(query, updateObj); BasicDBObject query2 = new BasicDBObject(); query2.put("email", user[0]); cursor = table.find(query2); csrList = cursor.toArray(); System.out.println("UpdateKeyThread: "+csrList.get(0).get("name").toString()); System.out.println("UpdateKeyThread: "+csrList.get(0).get("phone").toString()); System.out.println("UpdateKeyThre
ad: "+csrList.get(0).get("email").toString()); System.out.println("UpdateKeyThread: "+csrList.get(0).get("password").toString()); System.out.println("UpdateKeyThread: "+csrList.get(0).get("key").toString()); PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("Key successfully updated"); }else{ PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("3"); } sock.close(); } } }
xli
Appendix C: Test RSA keys Public key
A
N: 287973047397959966459171224813899804924489958240150171144632418612750012436289393
883489292547390478094515661452003404487648891297123185156001603931868101709758060
854839949352859800329224059177127529381738895709481327666740673015294901850034061
159008879133776767576897374331617835968282645031245013734438071430841271859036038
605069182960019317903533872073443874743942934512007359451933780032525716970355007
790263263221016535946736999155442475443611530939510186499607481645389483498274609
515078604074322961514399829579480338601370882132440005276219970272407684466237794
73484759682939168263552990438933236448270783096179
e: 160939886914470350804474172516213429150273668023601232814645095900670025459200230
304644355172135209280127427290074919281076382688927964778360546919274923613177775
654684802629395792000808537872208888755637137297454336251887414392965423713293041
433037548117073451047132571445088585937354286000656687823149582353153283925830167
883667036666620201187344847795225043011272129079516363716182327319675375254314722
448951792554800672650372287768303941950670829458914643309904386843878828987538610
749396912855124401308615602176079823373962777640789622131528358328099466615218788
89061341341366543520090211856990469300451442976351
Private key
A
N: 287973047397959966459171224813899804924489958240150171144632418612750012436289393
883489292547390478094515661452003404487648891297123185156001603931868101709758060
854839949352859800329224059177127529381738895709481327666740673015294901850034061
159008879133776767576897374331617835968282645031245013734438071430841271859036038
605069182960019317903533872073443874743942934512007359451933780032525716970355007
790263263221016535946736999155442475443611530939510186499607481645389483498274609
515078604074322961514399829579480338601370882132440005276219970272407684466237794
73484759682939168263552990438933236448270783096179
d: 130286134905903296878809904273909809219128868288854870690284843330319188758403650
92602163120321437241568892607436032444708019114394600985225325345978141119
Public key
B
N: 250375816420717654230341390083618198845133857389865187895448181623536720175215737
298162301587416790236753914696792070740168691581277755465981892844665279344032079
125976212548841750698664552841081756451944696489379954094399833574426518895389395
845245661651847121302424064982201516300295530730638594427374756038627538772481163
212583661719376529251612978716399036673963771202535312831189461306724400313299612
148899906147437344328591580095237534896231635413830237266245708588133793967697039
926803474180916493859329352055220340986127416405819953677016209476062898208613556
40874707113754994144032009208031199649556323224773
e: 160043651603909917991739363542657835352920347005814770669336486989694895266587929
316756426693143361273006937259401116945071669413197601790686825488357671930766433
592384957319696945946716984171843986738705652178961505176933725616075821307250323
230924754483957395151720464793300597866219411321393552930202629652278982658200187
093909761956584267608965637558793753398136709445294001102087043886572237622644790
xlii
581219866854957968076163032820298263445062213411078395088387552002975117527220656
368452276982213433947994297756918784702763953298638278115079740571615973875815210
5989976397068557238550551265514937312957717154885
Private key
B
N: 250375816420717654230341390083618198845133857389865187895448181623536720175215737
298162301587416790236753914696792070740168691581277755465981892844665279344032079
125976212548841750698664552841081756451944696489379954094399833574426518895389395
845245661651847121302424064982201516300295530730638594427374756038627538772481163
212583661719376529251612978716399036673963771202535312831189461306724400313299612
148899906147437344328591580095237534896231635413830237266245708588133793967697039
926803474180916493859329352055220340986127416405819953677016209476062898208613556
40874707113754994144032009208031199649556323224773
d: 125154922989015516313948357087251477948476674921424729140171055347407444329693363
76038257673079408354329994964643989080807755408570576427974105419136074769
xliii
Appendix D: Encryption algorithm C code tests Ø AES algorithm:
// // main.c // AESalgorithm // // Created by Ricardo Viteri on 5/10/15. // Copyright (c) 2015 Ricardo Viteri. All rights reserved. // #include <stdio.h> int cipherKey[4][4] = {{0x2b, 0x28, 0xab, 0x09}, {0x7e, 0xae, 0xf7, 0xcf}, {0x15, 0xd2, 0x15, 0x4f}, {0x16, 0xa6, 0x88, 0x3c}}; int roundKey[4][44] = {{0x2b, 0x28, 0xab, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x7e, 0xae, 0xf7, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x15, 0xd2, 0x15, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x16, 0xa6, 0x88, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; int rCon[4][10] = {{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; int mixColumnMatrix[4][4] = {{2, 3, 1, 1}, {1, 2, 3, 1}, {1, 1, 2, 3}, {3, 1, 1, 2}}; int encLookupTbl[16][16] = {{0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76}, {0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0}, {0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15}, {0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75}, {0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84}, {0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF}, {0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8}, {0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2}, {0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73}, {0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE,
0x5E, 0x0B, 0xDB}, {0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79}, {0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08}, {0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A}, {0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E}, {0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF}, {0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}}; int decLookupTbl[16][16] = {{0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB}, {0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB}, {0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E}, {0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25}, {0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92}, {0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84}, {0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06}, {0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B}, {0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73}, {0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E}, {0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B}, {0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4}, {0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F}, {0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF}, {0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61}, {0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D}}; int twoTable[16][16] = {{0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e}, {0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e}, {0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e}, {0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e}, {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x9
xliv
4,0x96,0x98,0x9a,0x9c,0x9e}, {0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe}, {0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde}, {0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe}, {0x1b,0x19,0x1f,0x1d,0x13,0x11,0x17,0x15,0x0b,0x09,0x0f,0x0d,0x03,0x01,0x07,0x05}, {0x3b,0x39,0x3f,0x3d,0x33,0x31,0x37,0x35,0x2b,0x29,0x2f,0x2d,0x23,0x21,0x27,0x25}, {0x5b,0x59,0x5f,0x5d,0x53,0x51,0x57,0x55,0x4b,0x49,0x4f,0x4d,0x43,0x41,0x47,0x45}, {0x7b,0x79,0x7f,0x7d,0x73,0x71,0x77,0x75,0x6b,0x69,0x6f,0x6d,0x63,0x61,0x67,0x65}, {0x9b,0x99,0x9f,0x9d,0x93,0x91,0x97,0x95,0x8b,0x89,0x8f,0x8d,0x83,0x81,0x87,0x85}, {0xbb,0xb9,0xbf,0xbd,0xb3,0xb1,0xb7,0xb5,0xab,0xa9,0xaf,0xad,0xa3,0xa1,0xa7,0xa5}, {0xdb,0xd9,0xdf,0xdd,0xd3,0xd1,0xd7,0xd5,0xcb,0xc9,0xcf,0xcd,0xc3,0xc1,0xc7,0xc5}, {0xfb,0xf9,0xff,0xfd,0xf3,0xf1,0xf7,0xf5,0xeb,0xe9,0xef,0xed,0xe3,0xe1,0xe7,0xe5}}; int threeTable[16][16] = {{0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09,0x18,0x1b,0x1e,0x1d,0x14,0x17,0x12,0x11}, {0x30,0x33,0x36,0x35,0x3c,0x3f,0x3a,0x39,0x28,0x2b,0x2e,0x2d,0x24,0x27,0x22,0x21}, {0x60,0x63,0x66,0x65,0x6c,0x6f,0x6a,0x69,0x78,0x7b,0x7e,0x7d,0x74,0x77,0x72,0x71}, {0x50,0x53,0x56,0x55,0x5c,0x5f,0x5a,0x59,0x48,0x4b,0x4e,0x4d,0x44,0x47,0x42,0x41}, {0xc0,0xc3,0xc6,0xc5,0xcc,0xcf,0xca,0xc9,0xd8,0xdb,0xde,0xdd,0xd4,0xd7,0xd2,0xd1}, {0xf0,0xf3,0xf6,0xf5,0xfc,0xff,0xfa,0xf9,0xe8,0xeb,0xee,0xed,0xe4,0xe7,0xe2,0xe1}, {0xa0,0xa3,0xa6,0xa5,0xac,0xaf,0xaa,0xa9,0xb8,0xbb,0xbe,0xbd,0xb4,0xb7,0xb2,0xb1}, {0x90,0x93,0x96,0x95,0x9c,0x9f,0x9a,0x99,0x88,0x8b,0x8e,0x8d,0x84,0x87,0x82,0x81}, {0x9b,0x98,0x9d,0x9e,0x97,0x94,0x91,0x92,0x83,0x80,0x85,0x86,0x8f,0x8c,0x89,0x8a}, {0xab,0xa8,0xad,0xae,0xa7,0xa4,0xa1,0xa2,0xb3,0xb0,0xb5,0xb6,0xbf,0xbc,0xb9,0xba}, {0xfb,0xf8,0xfd,0xfe,0xf7,0xf4,0xf1,0xf2,0xe3,0xe0,0xe5,0xe6,0xef,0xec,0xe9,0xea}, {0xcb,0xc8,0xcd,0xce,0xc7,0xc4,0xc1,0xc2,0xd3,0xd0,0xd5,0xd6,0xdf,0xdc,0xd9,0xda}, {0x5b,0x58,0x5d,0x5e,0x57,0x54,0x51,0x52,0x43,0x40,0x45,0x46,0x4f,0x4c,0x49,0x4a}, {0x6b,0x68,0x6d,0x6e,0x67,0x64,0x61,0x62,0x73,0x70,0x75,0x76,0x7f,0x7c,0x79,0x7a}, {0x3b,0x38,0x3d,0x3e,0x37,0x34,0x31,0x32,0x23,0x20,0x25,0x26,0x2f,0x2c,0x29,0x2a}, {0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,0x13,0x10,0x15,0x16,0x1f,0x1c,0x19,0x1a}}; void keySchedulingProcess(int rotConNum){ int keySchCol[4] = {roundKey[1][3+(rotConNum*4)], roundKey[2][3+(rotConNum*4)], roundKey[3][3+(rotConNum*4)], roundKey[0][3+(rotConNum*4)]}; int lutXaxis, lutYaxis;
for (int i = 0; i < 4; i++) { lutYaxis = (keySchCol[i]&0xf0)>>4; lutXaxis = keySchCol[i]&0x0f; keySchCol[i] = encLookupTbl[lutYaxis][lutXaxis]; } for (int j = 0; j < 4; j++) { roundKey[j][((rotConNum+1)*4)] = roundKey[j][(rotConNum*4)] ^ rCon[j][rotConNum] ^ keySchCol[j]; } for (int i = 1; i < 4; i++) { for (int j = 0; j < 4; j++) { roundKey[j][i+((rotConNum+1)*4)] = roundKey[j][i-1+((rotConNum+1)*4)] ^ roundKey[j][i+(rotConNum*4)]; } } printf("Round Key:\n"); printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n\n", roundKey[0][0], roundKey[0][1], roundKey[0][2], roundKey[0][3], roundKey[0][4], roundKey[0][5], roundKey[0][6], roundKey[0][7], roundKey[0][8], roundKey[0][9], roundKey[0][10], roundKey[0][11], roundKey[0][12], roundKey[0][13], roundKey[0][14], roundKey[0][15], roundKey[0][16], roundKey[0][17], roundKey[0][18], roundKey[0][19], roundKey[0][20], roundKey[0][21], roundKey[0][22], roundKey[0][23], roundKey[0][24], roundKey[0][25], roundKey[0][26], roundKey[0][27], roundKey[0][28], roundKey[0][29], roundKey[0][30], roundKey[0][31], roundKey[0][32], roundKey[0][33], roundKey[0][34], roundKey[0][35], roundKey[0][36], roundKey[0][37], roundKey[0][38], roundKey[0][39], roundKey[0][40], roundKey[0][41], roundKey[0][42], roundKey[0][43], roundKey[1][0], roundKey[1][1], roundKey[1][2], roundKey[1][3], roundKey[1][4], roundKey[1][5], roundKey[1][6], roundKey[1][7], roundKey[1][8], roundKey[1][9], roundKey[1][10], roundKey[1][11], roundKey[1][12], roundKey[1][13], roundKey[1][14], roundKey[1][15], roundKey[1][16], roundKey[1][17], roundKey[1][18], roundKey[1][19], roundKey[1][20], roundKey[1][21], roundKey[1][22], roundKey[1][23], roundKey[1][24], roundKey[1][25], roundKey[1][26], roundKey[1][27], roundKey[1][28], roundKey[1][29], roundKey[1][30], roundKey[1][31], roundKey[1][32], roundKey[1][33], roundKey[1][34], roundKey[1][35], roundKey[1][36], roundKey[1][37], roundKey[1][38], roundKey[1][39], roundKey[1][40], roundKey[1][41], roundKey[1][42], roundKey[1][43], roundKey[2][0], roundKey[2][1], roundKey[2][2], roundKey[2][3], roundKey[2][4], roundKey[2][5], roundKey[2][6], roundKey[2][7], roundKey[2][8], roundKey[2][9], roundKey[2][10], roundKey[2][11], roundKey[2][12], roundKey[2][13], roundKey[2][14], roundKey[2][15], roundKey[2][16], roundKey[2][17], roundKey[2][18], roundKey[2][19], roundKey[2][20], roundKey[2][21], roundKey[2][22], roundKey[2][23], roundKey[2][24], roundKey[2][25], roundKey[2][26], roundKey[2][27], roundKey[2][28], roundKey[2][29], roundKey[2][30], roundKey[2][31], roundKey[2][32], roundKey[2][33], roundKey[2][34], roundKey[2][35], roundKey[2][36], roundKey[2][37], roundKey[2][38], roundKey[2][39], roundKey[2][40], roundKey[2][41], roundKey[2][42], roundKey[2][43], roundKey[3][0], roundKey[3][1], roundKey[3][2], roundKey[3][3], roundKey[3][4], roundKey[3][5], roundKey[3][6], roundKey[3][7], roundKey[3][8], roundKey[3][9], roundKey[3][10], roundKey[3][11], roundKey[3][12], roundKey[3][13], roundKey[3][14], roundKey[3][15], roundKey[3][16], roundKey[3][17], roundKey[3][18], roundKey[3][19], roundKey[3][20], roundKey[3][21], roundKey[3][22], roundKey[3][23], roundKey[3][24],
xlv
roundKey[3][25], roundKey[3][26], roundKey[3][27], roundKey[3][28], roundKey[3][29], roundKey[3][30], roundKey[3][31], roundKey[3][32], roundKey[3][33], roundKey[3][34], roundKey[3][35], roundKey[3][36], roundKey[3][37], roundKey[3][38], roundKey[3][39], roundKey[3][40], roundKey[3][41], roundKey[3][42], roundKey[3][43]); } int main(int argc, const char * argv[]) { // insert code here... int dataIn[4][4] = {{0x32, 0x88, 0x31, 0xe0}, {0x43, 0x5a, 0x31, 0x37}, {0xf6, 0x30, 0x98, 0x07}, {0xa8, 0x8d, 0xa2, 0x34}}; int rotConNum = 0; //Initial ADDROUNDKEY for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { dataIn[j][i] = dataIn[j][i] ^ roundKey[j][i]; } } keySchedulingProcess(rotConNum); rotConNum++; for (int k = 0; k < 9; k++) { //SUBBYTES state int lutXaxis, lutYaxis; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { lutYaxis = (dataIn[j][i]&0xf0)>>4; lutXaxis = dataIn[j][i]&0x0f; dataIn[j][i] = encLookupTbl[lutYaxis][lutXaxis]; } } printf("Data after SUBBYTES Round %d\n", k+1); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //SHIFTROWS state for (int i = 1; i < 4; i++) { int shiftTemp[4] = {dataIn[i][0], dataIn[i][1], dataIn[i][2], dataIn[i][3]}; dataIn[i][0] = shiftTemp[i]; dataIn[i][1] = shiftTemp[(i+1 < 4 ? i+1 : i+1-4)]; dataIn[i][2] = shiftTemp[(i+2 < 4 ? i+2 : i+2-4)]; dataIn[i][3] = shiftTemp[(i+3 < 4 ? i+3 : i+3-4)]; } printf("Data after SHIFTROWS Round %d\n", k+1); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //MIXCOLUMNS step for (int i = 0; i < 4; i++) { int mixTemp[4] = {dataIn[0][i], dataIn[1][i], dataIn[2][i], dataIn[3][i]}; int mixResult[4]; for (int j = 0; j < 4; j++) { mixResult[j] = mixColumnMatrix[j][0]*mixTemp[0] + mixColumnMatrix[j][1]*mixTemp[1] + mixColumnMatrix[j][2]*mixTemp[2] + mixColumnMatrix[j][3]*mixTemp[3]; int lutXaxis, lutYaxis; lutYaxis = (mixTemp[0]&0xf0)>>4; lutXaxis = mixTemp[0]&0x0f; if (mixColumnMatrix[j][0] == 2) {
mixResult[j] = twoTable[lutYaxis][lutXaxis]; }else if (mixColumnMatrix[j][0] == 3){ mixResult[j] = threeTable[lutYaxis][lutXaxis]; }else{ mixResult[j] = mixTemp[0]; } lutYaxis = (mixTemp[1]&0xf0)>>4; lutXaxis = mixTemp[1]&0x0f; if (mixColumnMatrix[j][1] == 2) { mixResult[j] = mixResult[j] ^ twoTable[lutYaxis][lutXaxis]; }else if (mixColumnMatrix[j][1] == 3){ mixResult[j] = mixResult[j] ^ threeTable[lutYaxis][lutXaxis]; }else{ mixResult[j] = mixResult[j] ^ mixTemp[1]; } lutYaxis = (mixTemp[2]&0xf0)>>4; lutXaxis = mixTemp[2]&0x0f; if (mixColumnMatrix[j][2] == 2) { mixResult[j] = mixResult[j] ^ twoTable[lutYaxis][lutXaxis]; }else if (mixColumnMatrix[j][2] == 3){ mixResult[j] = mixResult[j] ^ threeTable[lutYaxis][lutXaxis]; }else{ mixResult[j] = mixResult[j] ^ mixTemp[2]; } lutYaxis = (mixTemp[3]&0xf0)>>4; lutXaxis = mixTemp[3]&0x0f; if (mixColumnMatrix[j][3] == 2) { mixResult[j] = mixResult[j] ^ twoTable[lutYaxis][lutXaxis]; }else if (mixColumnMatrix[j][3] == 3){ mixResult[j] = mixResult[j] ^ threeTable[lutYaxis][lutXaxis]; }else{ mixResult[j] = mixResult[j] ^ mixTemp[3]; } } dataIn[0][i] = mixResult[0]; dataIn[1][i] = mixResult[1]; dataIn[2][i] = mixResult[2]; dataIn[3][i] = mixResult[3]; } printf("Data after MIXCOLUMNS Round %d\n", k+1); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //ADDROUNDKEY step for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { dataIn[j][i] = dataIn[j][i] ^ roundKey[j][i]; } } printf("Data after ADDROUNDKEY Round %d\n", k+1); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); keySchedulingProcess(rotConNum);
xlvi
rotConNum++; } //final SUBBYTES state int lutXaxis, lutYaxis; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { lutYaxis = (dataIn[j][i]&0xf0)>>4; lutXaxis = dataIn[j][i]&0x0f; dataIn[j][i] = encLookupTbl[lutYaxis][lutXaxis]; } } printf("Data after SUBBYTES Round 10\n"); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //final SHIFTROWS state for (int i = 1; i < 4; i++) { int shiftTemp[4] = {dataIn[i][0], dataIn[i][1], dataIn[i][2], dataIn[i][3]}; dataIn[i][0] = shiftTemp[i]; dataIn[i][1] = shiftTemp[(i+1 < 4 ? i+1 : i+1-4)]; dataIn[i][2] = shiftTemp[(i+2 < 4 ? i+2 : i+2-4)]; dataIn[i][3] = shiftTemp[(i+3 < 4 ? i+3 : i+3-
4)]; } printf("Data after SHIFTROWS Round 10\n"); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //final ADDROUNDKEY step for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { dataIn[j][i] = dataIn[j][i] ^ roundKey[j][i]; } } printf("Data after ADDROUNDKEY Round 10\n**************CIPHERETEXT****************\n"); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); return 0; }
Ø RSA algorithm: // // main.c // RSAalgorithm // // Created by Ricardo Viteri on 5/7/15. // Copyright (c) 2015 Ricardo Viteri. All rights reserved. // #include <stdio.h> #include <math.h> #include <stdlib.h> int main(int argc, const char * argv[]) { // insert code here... /******************************** KEY GENERATION *******************************/ int p = 3, q = 13; //Obtain n int n = p*q; //use Euler totient function to obtain phi (phi(n)) int phi = n - (p + q - 1); //choose an integer e such as (1 < e < phi) and is coprime with n int e = 0; int array[100], a = 0, coprimes[100], cCounter = 0; for (int i = 2; i < phi; i++) { if (phi%i == 0) { array[a] = i; a++; } } for (int i = 2; i<phi; i++) { int temp = 0; for (int j = 0; j<a-1; j++) { if (i%array[j] == 0) { temp++; }
} if (temp == 0) { coprimes[cCounter] = i; cCounter++; } } e = coprimes[rand()%(cCounter < 5 ? cCounter : 5)]; //calculate d such as (d*e)%n = 1 int d = 0; for (int i = 0; i<n; i++) { int temp = (i*e)%phi; if (temp == 1) { d=i; break; } } printf("We have keys!!\n"); printf("Public key = (%d, %d)\n", n, e); printf("Private key = (%d, %d)\n", n, d); /******************************** ENCRYPTION *******************************/ //Message must be changed into an integer number m such that (0 <= m <= n) int m = n/8; printf("The message is: %d\n",m); //Encryption is done by encMessage = (m^e)mod(n) long encMessage = pow(m, e); encMessage = encMessage%n; printf("The encoded message is: %ld\n", encMessage); /******************************** DECRYPTION *******************************/ //Decryption is done by decMessage = (encMessage^d)mod(n)