Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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.
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.
1
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.
2
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.
3
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.
4
• 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.
5
6
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.
7
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:
8
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))
9
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.
10
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.
11
Figure
6:
SafeTime
design
flow
chart
12
13
14
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
Figure
10:
Conversation
tab
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
11:
Image
selection
window
15
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).
16
17
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):
18
19
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:
20
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).
21
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.
22
23
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
24
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.
25
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.
26
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.
27
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.
28
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.
29
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.
30
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
31
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.
32
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.
33
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.
34
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
35
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”.
36
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
37
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
38
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.
39
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.
40
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
41
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.
42
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.
43
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.
44
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
45
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{
46
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
47
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.*;
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.*;
//initialize reading
InputStreamReader IR = new InputStreamReader(sock.getInputStream());
BufferedReader BR = new BufferedReader(IR);
48
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:
49
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.
50
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:
51
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:
52
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:
53
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:
54
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.
55
56
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
57
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.
58
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.
[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_f
iles/ThreadsAndMessaging.pdf.
[Accessed:
21-‐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].
59
[16]
a
a
Abdelhafez
and
a
J.
Forsyth,
“A
Review
of
More-‐Electric
Aircraft,”
Aerosp.
Sci.
Aviat.
Technol.,
pp.
1–13,
2009.
60
ii
iii
SQLiteDatabase
db
=
this.getReadableDatabase();
Cursor
res
=
db.rawQuery(
"select
*
from
contacts",
null
);
/************
USER
INFO
TABLE
***********/
res.moveToFirst();
public
boolean
insertUser
(String
name,
while(res.isAfterLast()
==
false){
String
phone,
String
email,
String
privateKey,
String[]
contact
=
new
String[4];
String
publicKey,
String
port)
contact[0]
=
{
res.getString(res.getColumnIndex(CONTACTS_
SQLiteDatabase
db
=
COLUMN_ID));
this.getWritableDatabase();
contact[1]
=
ContentValues
contentValues
=
new
res.getString(res.getColumnIndex(CONTACTS_ ContentValues();
COLUMN_NAME));
contentValues.put("name",
name);
contact[2]
=
contentValues.put("phone",
phone);
res.getString(res.getColumnIndex(CONTACTS_
contentValues.put("email",
email);
COLUMN_EMAIL));
contentValues.put("privateKey",
contact[3]
=
privateKey);
res.getString(res.getColumnIndex(CONTACTS_
contentValues.put("publicKey",
COLUMN_KEY));
publicKey);
contentValues.put("port",
port);
ArrayList<String>
cosa
=
new
db.insert("user",
null,
contentValues);
ArrayList<String>(Arrays.asList(contact));
return
true;
}
array_list.add(contact);
res.moveToNext();
public
Cursor
getDataUser(int
id){
}
SQLiteDatabase
db
=
return
array_list;
this.getReadableDatabase();
}
Cursor
res
=
db.rawQuery(
"select
*
from
user
where
id="+id+"",
null
);
public
ArrayList<ArrayList<Object>>
return
res;
getAllCotactsWithInfoAsList()
}
{
ArrayList<ArrayList<Object>>
array_list
=
public
int
numberOfRowsUser(){
new
ArrayList<ArrayList<Object>>();
SQLiteDatabase
db
=
this.getReadableDatabase();
//hp
=
new
HashMap();
int
numRows
=
(int)
SQLiteDatabase
db
=
DatabaseUtils.queryNumEntries(db,
this.getReadableDatabase();
USER_TABLE_NAME);
Cursor
res
=
db.rawQuery(
"select
*
from
return
numRows;
contacts",
null
);
}
res.moveToFirst();
public
boolean
updateUser
(Integer
id,
String
while(res.isAfterLast()
==
false){
name,
String
phone,
String
email,
String
String[]
contact
=
new
String[4];
privateKey,
String
publicKey,
String
port)
contact[0]
=
{
res.getString(res.getColumnIndex(CONTACTS_
SQLiteDatabase
db
=
COLUMN_ID));
this.getWritableDatabase();
contact[1]
=
ContentValues
contentValues
=
new
res.getString(res.getColumnIndex(CONTACTS_ ContentValues();
COLUMN_NAME));
contentValues.put("name",
name);
contact[2]
=
contentValues.put("phone",
phone);
res.getString(res.getColumnIndex(CONTACTS_
contentValues.put("email",
email);
COLUMN_EMAIL));
contentValues.put("street",
privateKey);
contact[3]
=
contentValues.put("place",
publicKey);
res.getString(res.getColumnIndex(CONTACTS_
db.update("user",
contentValues,
"id
=
?
",
COLUMN_KEY));
new
String[]
{
Integer.toString(id)
}
);
return
true;
ArrayList<Object>
contactList
=
new
}
ArrayList<Object>(Arrays.asList(contact));
public
Integer
deleteUser
(Integer
id)
array_list.add(contactList);
{
res.moveToNext();
SQLiteDatabase
db
=
}
this.getWritableDatabase();
return
array_list;
return
db.delete("user",
}
"id
=
?
",
new
String[]
{
Integer.toString(id)
});
/*********************************************/
}
iv
v
vi
vii
Ø ConversationListTab.java
package
View
V
=
com.example.ricardoviteri.safetimeapp;
inflater.inflate(R.layout.conversation_tab,
container,
false);
import
android.content.Intent;
txtUser
=
import
android.database.Cursor;
(TextView)V.findViewById(R.id.textView16);
import
android.graphics.Bitmap;
message
=
import
(EditText)V.findViewById(R.id.editText10);
android.graphics.drawable.BitmapDrawable;
conversation
=
import
android.graphics.drawable.Drawable;
(ListView)V.findViewById(R.id.listView2);
import
android.net.Uri;
sendMessage
=
import
android.os.Bundle;
(Button)V.findViewById(R.id.button7);
import
android.os.Parcelable;
loadImg
=
import
android.provider.MediaStore;
(Button)V.findViewById(R.id.button8);
import
android.support.v4.app.Fragment;
sendImage
=
import
android.util.Log;
(Button)V.findViewById(R.id.button9);
import
android.view.LayoutInflater;
image
=
import
android.view.View;
(ImageView)V.findViewById(R.id.imageView3)
import
android.view.ViewGroup;
;
import
android.widget.Button;
layoutImage
=
import
android.widget.EditText;
(RelativeLayout)V.findViewById(R.id.imageLay
import
android.widget.ImageView;
out);
import
android.widget.ListView;
import
android.widget.RelativeLayout;
import
android.widget.TextView;
if((((ContactsTabActivity)this.getActivity()).co
import
android.widget.Toast;
ntacts2).size()
!=
0){
userInfo
=
import
java.io.ByteArrayOutputStream;
((ContactsTabActivity)this.getActivity()).conta
import
java.io.IOException;
cts2.get(activeContact);
import
java.math.BigInteger;
key
=
(String)
userInfo.get(3);
import
java.util.ArrayList;
if
(userInfo.size()
==
4){
savedConversation
=
new
/**
ArrayList<Object>();
*
Created
by
ricardoviteri
on
7/7/15.
userInfo.add(savedConversation);
*/
}else{
public
class
ConversationListTab
extends
savedConversation
=
Fragment
implements
View.OnClickListener
{
(ArrayList<Object>)
userInfo.get(4);
int
activeContact
=
0;
}
TextView
txtUser;
EditText
message;
ListView
conversation;
txtUser.setText(userInfo.get(1).toString());
Button
sendMessage,
loadImg,
sendImage;
ImageView
image;
sendMessage.setOnClickListener(this);
RelativeLayout
layoutImage;
loadImg.setOnClickListener(this);
ArrayList<Object>
userInfo;
sendImage.setOnClickListener(this);
ArrayList<Object>
savedConversation;
String
key;
ConversationAdapter
adapter
=
new
ConversationAdapter(this.getActivity(),
1,
@Override
savedConversation.toArray());
public
void
onCreate(Bundle
conversation.setAdapter(adapter);
savedInstanceState)
{
super.onCreate(savedInstanceState);
conversation.setSelection(savedConversation.s
System.out.println("Conversation
tab
ize()-‐1);
"+activeContact);
}else{
if
txtUser.setText("No
contacts");
(((ContactsTabActivity)this.getActivity()).mTa
}
bHost
!=
null){
((ContactsTabActivity)this.getActivity()).switc
hTabTo(0);
}
return
V;
}
}
@Override
@Override
public
View
onCreateView(LayoutInflater
public
void
onClick(View
v)
{
inflater,
ViewGroup
container,
switch
(v.getId()){
Bundle
savedInstanceState)
{
case
R.id.button7:
//
Inflate
the
layout
for
this
fragment
8
if
(message.getText().toString().length()>0){
bitmap.compress(Bitmap.CompressFormat.JPE
String[]
info
=
{"0",
G,
100,
stream);
message.getText().toString()};
byte[]
bitmapdata
=
ArrayList<Object>
task
=
new
stream.toByteArray();
ArrayList<Object>();
task.add("11");
new
task.add(userInfo.get(2));
EncryptPictureTask(this.getActivity(),
new
BigInteger(key.split("-‐")[0]),
new
task.add(messageEncryption((message.getText BigInteger(key.split("-‐")[1]),
().toString()).getBytes()));
(String)userInfo.get(2)).execute(bitmapdata);
break;
((ContactsTabActivity)this.getActivity()).tasks
}
ToDo.add(task);
/*SOK_CLIENT_BASIC
cosa
=
new
}
SOK_CLIENT_BASIC((message.getText().toStrin
g()).getBytes());
public
void
try
{
addPictureTask(ArrayList<Object>
task){
cosa.run();
}
catch
(Exception
e)
{
((ContactsTabActivity)this.getActivity()).tasks
e.printStackTrace();
ToDo.add(task);
}*/
}
savedConversation.add(info);
ConversationAdapter
adapter
=
new
public
String
getPath(Uri
uri)
{
ConversationAdapter(this.getActivity(),
1,
savedConversation.toArray());
//
just
some
safety
built
in
conversation.setAdapter(adapter);
if(
uri
==
null
)
{
message.setText("");
//
perform
some
logging
or
show
user
feedback
conversation.setSelection(savedConversation.s
Toast.makeText(this.getActivity(),
ize()-‐1);
"Loading
picture
failed",
Toast.LENGTH_LONG).show();
}
return
null;
break;
}
case
R.id.button8:
Intent
intent
=
new
Intent();
//
try
to
retrieve
the
image
from
the
media
intent.setType("image/*");
store
first
//
this
will
only
work
for
images
selected
intent.setAction(Intent.ACTION_GET_CONTEN from
gallery
T);
String[]
projection
=
{
MediaStore.Images.Media.DATA
};
this.getActivity().startActivityForResult(Intent.
Cursor
cursor
=
createChooser(intent,"Select
Picture"),
101);
this.getActivity().managedQuery(uri,
break;
projection,
null,
null,
null);
case
R.id.button9:
if(
cursor
!=
null
){
ArrayList<Object>
info
=
new
int
column_index
=
cursor
ArrayList<Object>();
info.add("0");
.getColumnIndexOrThrow(MediaStore.Images.
info.add(image.getDrawable());
Media.DATA);
savedConversation.add(info);
cursor.moveToFirst();
ConversationAdapter
adapter
=
new
return
cursor.getString(column_index);
ConversationAdapter(this.getActivity(),
1,
}
savedConversation.toArray());
//
this
is
our
fallback
here,
thanks
to
the
conversation.setAdapter(adapter);
answer
from
@mad
indicating
this
is
needed
message.setText("");
for
//
working
code
based
on
images
selected
conversation.setSelection(savedConversation.s using
other
file
managers
ize()-‐1);
return
uri.getPath();
}
layoutImage.setVisibility(View.INVISIBLE);
public
void
postNewMessage(){
Bitmap
bitmap
=
ConversationAdapter
adapter
=
new
((BitmapDrawable)image.getDrawable()).getBi ConversationAdapter(this.getActivity(),
1,
tmap();
savedConversation.toArray());
ByteArrayOutputStream
stream
=
new
conversation.setAdapter(adapter);
ByteArrayOutputStream();
message.setText("");
conversation.setSelection(savedConversation.s
ize()-‐1);
ix
}
}
}
public
byte[]
messageEncryption(byte[]
M){
return
encMsgBytes;
BigInteger
N
=
new
BigInteger(key.split("-‐
}else{
")[0]);
encryptedMsg
=
BigInteger
e
=
new
BigInteger(key.split("-‐ encryptedMsg.modPow(e,
N);
")[1]);
byte[]
encMsgBytestemp
=
encryptedMsg.toByteArray();
BigInteger
encryptedMsg
=
new
byte[]
encMsgBytes
=
new
BigInteger(M);
byte[encMsgBytestemp.length+1];
if
(encryptedMsg.signum()
!=
1){
for
(int
i
=
0;
i<encMsgBytes.length;
i++){
encryptedMsg
=
if
(i
==
encMsgBytes.length-‐1){
encryptedMsg.multiply(BigInteger.valueOf(-‐
encMsgBytes[i]
=
(byte)2;
1));
}else{
encryptedMsg
=
encMsgBytes[i]
=
encryptedMsg.modPow(e,
N);
encMsgBytestemp[i];
byte[]
encMsgBytestemp
=
}
encryptedMsg.toByteArray();
}
byte[]
encMsgBytes
=
new
return
encMsgBytes;
byte[encMsgBytestemp.length+1];
}
for
(int
i
=
0;
i<encMsgBytes.length;
i++){
//return
encryptedMsg.toByteArray();
if
(i
==
encMsgBytes.length-‐1){
//return
(new
BigInteger(M)).modPow(e,
encMsgBytes[i]
=
(byte)1;
N).toByteArray();
}else{
}
encMsgBytes[i]
=
}
encMsgBytestemp[i];
Ø ConversationAdapter.java
package
LayoutInflater
inflater
=
com.example.ricardoviteri.safetimeapp;
((FragmentActivity)context).getLayoutInflater(
);
import
android.content.Context;
if
(conversation[position]
instanceof
import
android.graphics.drawable.Drawable;
String[]){
import
convertView
=
android.support.v4.app.FragmentActivity;
inflater.inflate(R.layout.conversation_cell,
import
android.view.Gravity;
parent,
false);
import
android.view.LayoutInflater;
import
android.view.View;
TextView
name;
import
android.view.ViewGroup;
import
android.widget.ArrayAdapter;
if
import
android.widget.ImageView;
(Integer.parseInt(((String[])conversation[posit
import
android.widget.TextView;
ion])[0])
==
0){
name
=
import
java.util.ArrayList;
(TextView)convertView.findViewById(R.id.text
View18);
/**
}else{
*
Created
by
ricardoviteri
on
7/20/15.
name
=
*/
(TextView)convertView.findViewById(R.id.text
public
class
ConversationAdapter
extends
View17);
ArrayAdapter
{
}
Object[]
conversation;
name.setText(((String[])conversation[position
Context
context;
])[1]);
}else{
public
ConversationAdapter(Context
ctx,
int
convertView
=
resource,
Object[]
objects)
{
inflater.inflate(R.layout.conversation_image_cel
super(ctx,
resource,
objects);
l,
parent,
false);
conversation
=
objects;
ImageView
image;
context
=
ctx;
}
if
(Integer.parseInt((String)
((ArrayList<Object>)conversation[position]).g
@Override
et(0))
==
0){
public
View
getView(int
position,
View
image
=
convertView,
ViewGroup
parent)
{
(ImageView)convertView.findViewById(R.id.i
mageView5);
//
inflate
the
layout
}else{
x
image
=
(ImageView)convertView.findViewById(R.id.i
}
mageView4);
}
image.setImageDrawable((Drawable)
return
convertView;
((ArrayList<Object>)conversation[position]).g
}
et(1));
}
Ø AddContactTab.java
package
String
mail
=
com.example.ricardoviteri.safetimeapp;
userEdt.getText().toString();
for
(int
i
=
0;
i
<
contacts.size();
i++){
import
android.content.DialogInterface;
if
(contacts.get(i).equals(mail)){
import
android.database.Cursor;
userExists
=
true;
import
android.os.Bundle;
break;
import
android.support.v4.app.Fragment;
}
import
android.view.LayoutInflater;
}
import
android.view.View;
if
(userExists){
import
android.view.ViewGroup;
Toast
toast
=
import
android.widget.Button;
Toast.makeText(this.getActivity(),
"Contact
import
android.widget.EditText;
already
added",
Toast.LENGTH_SHORT);
import
android.widget.RelativeLayout;
toast.show();
import
android.widget.Toast;
}else{
//new
AddContactTask(this,
import
java.util.ArrayList;
userEdt.getText().toString()).execute();
ArrayList<Object>
addUser
=
new
/**
ArrayList<Object>();
*
Created
by
ricardoviteri
on
7/7/15.
addUser.add("10");
*/
public
class
AddContactTab
extends
Fragment
addUser.add(userEdt.getText().toString());
implements
View.OnClickListener
{
((ContactsTabActivity)
this.getActivity()).tasksToDo.add(addUser);
public
EditText
userEdt;
}
public
Button
btnAdd;
}else{
public
RelativeLayout
loadingLayout;
//new
AddContactTask(this,
userEdt.getText().toString()).execute();
@Override
ArrayList<Object>
addUser
=
new
public
View
onCreateView(LayoutInflater
ArrayList<Object>();
inflater,
ViewGroup
container,
addUser.add("10");
Bundle
savedInstanceState)
{
//
Inflate
the
layout
for
this
fragment
addUser.add(userEdt.getText().toString());
View
V
=
((ContactsTabActivity)
inflater.inflate(R.layout.add_contact_tab,
this.getActivity()).tasksToDo.add(addUser);
container,
false);
}
userEdt
=
(EditText)
V.findViewById(R.id.editText9);
btnAdd
=
(Button)
}
V.findViewById(R.id.button6);
}
loadingLayout
=
(RelativeLayout)
V.findViewById(R.id.loadingLayout);
public
void
addContact(String[]
newContact){
btnAdd.setOnClickListener(this);
System.out.println(newContact[0]);
System.out.println(newContact[1]);
return
V;
System.out.println(newContact[2]);
}
DBHelper
db
=
new
DBHelper(this.getActivity());
@Override
db.insertContact(newContact[0],
public
void
onClick(View
v)
{
newContact[1],
newContact[2]);
if
(userEdt.getText().toString().length()
>
0){
((ContactsTabActivity)this.getActivity()).refres
DBHelper
db
=
new
hContacts();
DBHelper(this.getActivity());
}
ArrayList<String>
contacts
=
db.getAllCotacts();
public
void
contactNotFound(){
boolean
userExists
=
false;
Toast
toast
=
if
(contacts.size()
>
0){
Toast.makeText(this.getActivity(),
"User
not
found",
Toast.LENGTH_SHORT);
xi
toast.show();
}
}
Ø LoginActivity.java
package
if
(isComplete){
com.example.ricardoviteri.safetimeapp;
loadingView.setVisibility(View.VISIBLE);
import
android.app.Activity;
new
LoginTask(this,
import
android.content.Intent;
txtUsername.getText().toString(),
import
android.os.Bundle;
txtPassword.getText().toString()).execute();
import
android.view.View;
}else{
import
android.widget.Button;
Toast
toast
=
Toast.makeText(this,
import
android.widget.EditText;
"Fields
are
not
complete",
import
android.widget.RelativeLayout;
Toast.LENGTH_SHORT);
import
android.widget.Switch;
toast.show();
import
android.widget.Toast;
}
break;
import
java.math.BigInteger;
case
R.id.button3:
import
java.util.ArrayList;
Intent
intent
=
new
Intent(this,
RegisterActivity.class);
/**
startActivity(intent);
*
Created
by
ricardoviteri
on
6/28/15.
//this.finish();
*/
break;
public
class
LoginActivity
extends
Activity
}
implements
View.OnClickListener{
}
EditText
txtUsername,
txtPassword;
Button
btnRegister,
btnLogin;
public
void
loginAction(int
code,
String[]
BigInteger
N,
e,
d;
user){
String[]
userInfo
=
new
String[3];
/**
RelativeLayout
loadingView;
*
1:
User
not
found
*
2:
Correct
password
@Override
*
3:
Incorrect
password
protected
void
onCreate(Bundle
*
4:
Info
not
received
savedInstanceState)
{
**/
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
switch
(code){
case
1:
txtUsername
=
(EditText)
executeToast("User
not
registered");
findViewById(R.id.editText5);
break;
txtPassword
=
(EditText)
case
2:
findViewById(R.id.editText6);
System.out.println(user[0]);
System.out.println(user[1]);
loadingView
=
(RelativeLayout)
System.out.println(user[2]);
findViewById(R.id.loadingLayout);
System.out.println(user[3]);
userInfo
=
user;
btnLogin
=
(Button)
new
findViewById(R.id.button2);
KeyGenerationTask(this).execute();
btnRegister
=
(Button)
break;
findViewById(R.id.button3);
case
3:
executeToast("Incorrect
password");
btnLogin.setOnClickListener(this);
break;
btnRegister.setOnClickListener(this);
default:
executeToast("Connection
error");
}
}
}
@Override
public
void
onClick(View
v)
{
public
void
keysGenerated(BigInteger[]
switch
(v.getId()){
keys){
case
R.id.button2:
N
=
keys[0];
boolean
isComplete
=
true;
e
=
keys[1];
if
d
=
keys[2];
(txtUsername.getText().toString().length()
==
0
||
txtPassword.getText().toString().length()
new
UpdateKeyTask(this,
""+N+"-‐"+e,
==
0){
userInfo[2]).execute();
isComplete
=
false;
}
}
xii
xiii
isComplete
=
false;
}
//Making
sure
that
e
is
coprime
with
N
while
if
(txtPass.getText().toString().length()
>
(phi.gcd(e).compareTo(BigInteger.ONE)
>
0
0){
&&
e.compareTo(phi)
<
0
)
{
password
=
txtPass.getText().toString();
e.add(BigInteger.ONE);
}else{
}
isComplete
=
false;
}
//Obtain
the
private
key
by
calculating
e
inverse
module
of
phi
if
(txtRepPass.getText().toString().length()
d
=
e.modInverse(phi);
>
0){
if
System.out.println("Finish
key
(!txtRepPass.getText().toString().equals(passw generation");
ord)){
passMatch
=
false;
/*
}
Drawable
d
=
}else{
getResources().getDrawable(R.drawable.shefu
isComplete
=
false;
ni);
}
Bitmap
bitmap
=
((BitmapDrawable)d).getBitmap();
if
(isComplete){
ByteArrayOutputStream
stream
=
new
if
(passMatch){
ByteArrayOutputStream();
System.out.println("Register
Successful");
bitmap.compress(Bitmap.CompressFormat.JPE
//keyGeneration();
G,
100,
stream);
byte[]
bitmapdata
=
stream.toByteArray();
new
KeyGenerationTask(this).execute();
Drawable
d2
=
getResources().getDrawable(R.drawable.banan
}else{
a);
Toast
toast
=
Toast.makeText(this,
Bitmap
bitmap2
=
"Passwords
does
not
match",
((BitmapDrawable)d2).getBitmap();
Toast.LENGTH_SHORT);
ByteArrayOutputStream
stream2
=
new
toast.show();
ByteArrayOutputStream();
}
}else{
bitmap2.compress(Bitmap.CompressFormat.JP
Toast
toast
=
Toast.makeText(this,
EG,
100,
stream2);
"Fields
are
not
complete",
byte[]
bitmapdata2
=
Toast.LENGTH_SHORT);
stream2.toByteArray();
toast.show();
}
int
counter
=
0;
//keyGeneration();
for
(int
i
=
0;
i
<
(bitmapdata.length
<
}
bitmapdata2.length
?
bitmapdata.length
:
bitmapdata2.length);
i++){
public
void
keyGeneration(){
if
((int)bitmapdata[i]
==
//Generate
a
random
number
and
look
for
(int)bitmapdata2[i]){
two
prime
numbers
of
"bitlength"
size
counter++;
r
=
new
Random();
}else{
firstPrime
=
break;
BigInteger.probablePrime(bitlength,
r);
}
secondPrime
=
}
BigInteger.probablePrime(bitlength,
r);
//163
header
//First
we
need
to
obtain
the
number
N
=
firstPrime*secondPrime
System.out.println("Size
of
picture
1
is:
N
=
firstPrime.multiply(secondPrime);
"+bitmapdata.length+"
bytes");
System.out.println("Size
of
picture
2
is:
//use
Euler
totient
function
to
obtain
phi
"+bitmapdata2.length+"
bytes");
(phi(N))
System.out.println("Header
size
of
pictures
BigInteger
phi
=
is:
"+counter+"
bytes");
N.subtract(firstPrime.add(secondPrime).subtr
act(BigInteger.ONE));
//Obtain
a
prime
number
between
0
and
N
new
(should
be
coprime
with
phi)
EncryptPictureTask(this).execute(bitmapdata)
e
=
BigInteger.probablePrime(bitlength/2,
;
r);
txtProgress.setText("Encrypting...");
txtProgress.setVisibility(View.VISIBLE);
xiv
progBar.setVisibility(View.VISIBLE);
encryptedMsg
=
*/
encryptedMsg.modPow(e,
N);
}
byte[]
encMsgBytestemp
=
encryptedMsg.toByteArray();
public
void
keysGenerated(BigInteger[]
byte[]
encMsgBytes
=
new
keys){
byte[encMsgBytestemp.length+1];
N
=
keys[0];
for
(int
i
=
0;
i<encMsgBytes.length;
i++){
e
=
keys[1];
if
(i
==
encMsgBytes.length-‐1){
d
=
keys[2];
encMsgBytes[i]
=
(byte)1;
}else{
new
RegisterUserTask(this,
name,
phone,
encMsgBytes[i]
=
email,
password,
""+N+"-‐"+e).execute();
encMsgBytestemp[i];
}
}
}
public
void
startApp(int
result,
String
port){
return
encMsgBytes;
loadingView.setVisibility(View.INVISIBLE);
}else{
/**
encryptedMsg
=
*
1:
Successfully
added
encryptedMsg.modPow(e,
N);
*
2:
Email
already
registered
byte[]
encMsgBytestemp
=
*
3:
User
not
received
encryptedMsg.toByteArray();
**/
byte[]
encMsgBytes
=
new
switch(result){
byte[encMsgBytestemp.length+1];
case
1:
for
(int
i
=
0;
i<encMsgBytes.length;
i++){
DBHelper
db
=
new
DBHelper(this);
if
(i
==
encMsgBytes.length-‐1){
db.insertUser(name,
phone,
email,
encMsgBytes[i]
=
(byte)2;
""+N+"-‐"+d,
""+N+"-‐"+e,
port);
}else{
System.out.println("User
saved
in
encMsgBytes[i]
=
DB");
encMsgBytestemp[i];
ArrayList<String>
userSaved
=
}
db.getUser();
}
return
encMsgBytes;
System.out.println(""+userSaved.get(0)+"\n"+
}
userSaved.get(1)+"\n"+userSaved.get(2)+"\n"
//return
encryptedMsg.toByteArray();
+userSaved.get(3)+"\n"+userSaved.get(4)+"\n
//return
(new
BigInteger(M)).modPow(e,
"+userSaved.get(5)+"\n"+userSaved.get(6)+"\ N).toByteArray();
n");
}
public
byte[]
messageDecryption(byte[]
D){
Intent
intent
=
new
Intent(this,
byte[]
msgToDecrypt
=
new
byte[D.length-‐
ContactsTabActivity.class);
1];
startActivity(intent);
for
(int
i
=
0;
i<D.length-‐1;
i++){
this.finish();
msgToDecrypt[i]
=
D[i];
break;
}
case
2:
System.out.println(""+D[D.length-‐1]);
executeToast("Email
already
BigInteger
encryptedMsg
=
new
registered");
BigInteger(msgToDecrypt);
break;
default:
encryptedMsg
=
encryptedMsg.modPow(d,
executeToast("Connection
error");
N);
}
if
(D[D.length-‐1]
==
(byte)1){
}
encryptedMsg
=
encryptedMsg.multiply(BigInteger.valueOf(-‐
public
void
executeToast(String
msg){
1));
Toast
toast
=
Toast.makeText(this,
msg,
}
Toast.LENGTH_SHORT);
toast.show();
return
encryptedMsg.toByteArray();
}
//return
(new
BigInteger(D)).modPow(d,
N).toByteArray();
/*
}
public
byte[]
messageEncryption(byte[]
M){
BigInteger
encryptedMsg
=
new
private
static
String
bytesToString(byte[]
BigInteger(M);
encrypted)
{
if
(encryptedMsg.signum()
!=
1){
String
test
=
"";
encryptedMsg
=
for
(byte
b
:
encrypted)
{
encryptedMsg.multiply(BigInteger.valueOf(-‐
test
+=
Byte.toString(b);
1));
}
return
test;
}
xv
public
void
public
static
boolean
isPrime(long
n)
{
imageWasEncrypted(ArrayList<byte[]>
if
(n
<=
3)
{
encImg){
return
n
>
1;
new
DecryptPictureTask(this,
}
else
if
(n
%
2
==
0
||
n
%
3
==
0)
{
"").execute(encImg);
return
false;
txtProgress.setText("Decrypting...");
}
else
{
}
for
(int
i
=
5;
i
*
i
<=
n;
i
+=
6)
{
if
(n
%
i
==
0
||
n
%
(i
+
2)
==
0)
{
public
void
displayDecriptedImg(Drawable
return
false;
img){
}
imgTest.setImageDrawable(img);
}
txtProgress.setText("Done!!");
return
true;
progBar.setVisibility(View.INVISIBLE);
}
}
}
}
*/
Ø ServerThread.java
package
}
catch
(IOException
e)
{
com.example.ricardoviteri.safetimeapp;
e.printStackTrace();
}
import
android.widget.Toast;
//TODO:
sent
this
depending
on
if
there
is
something
to
send
or
not
import
java.io.BufferedReader;
if
(parent.tasksToDo.size()
>
0){
import
java.io.DataInputStream;
PS.println("1");
import
java.io.DataOutputStream;
}else{
import
java.io.IOException;
PS.println("0");
import
java.io.InputStream;
}
import
java.io.InputStreamReader;
import
java.io.OutputStream;
import
java.io.PrintStream;
import
java.net.ServerSocket;
//initialize
reading
import
java.net.Socket;
InputStreamReader
IR
=
null;
import
java.util.ArrayList;
try
{
IR
=
new
/**
InputStreamReader(sock.getInputStream());
*
Created
by
ricardoviteri
on
7/20/15.
}
catch
(IOException
e)
{
*/
e.printStackTrace();
public
class
ServerThread
extends
Thread
{
}
BufferedReader
BR
=
new
ContactsTabActivity
parent;
BufferedReader(IR);
String
thisUser;
//look
for
messages
that
might
be
received
by
the
server
public
ServerThread(ContactsTabActivity
String
MESSAGE
=
null;
context,
String
user)
{
try
{
parent
=
context;
MESSAGE
=
BR.readLine();
thisUser
=
user;
if
(MESSAGE
==
null){
}
MESSAGE
=
"20";
}
public
void
run(){
//System.out.println(MESSAGE);
}
catch
(Exception
e)
{
while(true){
e.printStackTrace();
MESSAGE
=
"20";
Socket
sock
=
null;
}
try
{
sock
=
new
Socket("192.168.1.103",
/**
parent.Port);
*
1:
Listen
}
catch
(IOException
e)
{
*
2:
Send
data
//System.out.println("No
**/
connection");
if
(Integer.parseInt(MESSAGE)
==
1){
}
System.out.println("Recieving
something
from
server");
if
(sock
!=
null){
try
{
PrintStream
PS
=
null;
MESSAGE
=
BR.readLine();
try
{
//System.out.println(MESSAGE);
PS
=
new
}
catch
(Exception
e)
{
PrintStream(sock.getOutputStream());
e.printStackTrace();
xvi
xvii
xviii
xix
xx
xxi
xxii
xxiii
xxiv
xxv
//initialize
reading
InputStreamReader
IR
=
null;
@Override
try
{
protected
void
onPreExecute()
{
IR
=
new
super.onPreExecute();
InputStreamReader(sock.getInputStream());
}
}
catch
(IOException
e)
{
e.printStackTrace();
@Override
}
protected
void
onPostExecute(String
string)
BufferedReader
BR
=
new
{
BufferedReader(IR);
super.onPostExecute(string);
//look
for
messages
that
might
be
received
by
the
server
((LoginActivity)context).keysUpdated(string);
String
MESSAGE
=
null;
}
try
{
MESSAGE
=
BR.readLine();
@Override
System.out.println(MESSAGE);
protected
void
onProgressUpdate(Integer...
}
catch
(IOException
e)
{
values)
{
e.printStackTrace();
super.onProgressUpdate(values);
}
}
return
MESSAGE;
}
}
Ø SOK_CLIENT.java
package
sock
=
new
Socket("192.168.1.103",
com.example.ricardoviteri.safetimeapp;
9000);
import
android.os.AsyncTask;
}
catch
(IOException
e)
{
e.printStackTrace();
import
java.io.*;
}
import
java.net.*;
//print
a
message
to
be
sent
to
the
server
/**
PrintStream
PS
=
null;
*
Created
by
ricardoviteri
on
7/7/15.
try
{
*/
PS
=
new
public
class
SOK_CLIENT
{
PrintStream(sock.getOutputStream());
byte[]
encMessage;
}
catch
(IOException
e)
{
String
key;
e.printStackTrace();
}
public
SOK_CLIENT(byte[]
msg,
String
key)
{
PS.println(key);
encMessage
=
msg;
this.key
=
key;
}
OutputStream
out
=
null;
try
{
public
void
run()
throws
Exception{
out
=
sock.getOutputStream();
new
MyAsyncTask().execute();
}
catch
(IOException
e)
{
}
e.printStackTrace();
}
private
class
MyAsyncTask
extends
DataOutputStream
dos
=
new
AsyncTask<Void,
Void,
Void>
DataOutputStream(out);
{
@Override
try
{
protected
void
onPostExecute(Void
result)
dos.writeInt(encMessage.length);
{
}
catch
(IOException
e)
{
//Task
you
want
to
do
on
UIThread
after
e.printStackTrace();
completing
Network
operation
}
//onPostExecute
is
called
after
if
(encMessage.length
>
0)
{
doInBackground
finishes
its
task.
try
{
}
dos.write(encMessage,
0,
encMessage.length);
@Override
}
catch
(IOException
e)
{
protected
Void
doInBackground(Void...
e.printStackTrace();
params)
{
}
//Do
your
network
operation
here
}
//create
a
socket
for
port
1500
at
the
Localhost
Socket
sock
=
null;
//initialize
reading
try
{
InputStreamReader
IR
=
null;
xxvi
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;
}
}
}
xxvii
xxviii
xxix
xxx
xxxi
xxxii
System.out.println(""+d);
PrintStream
PS
=
new
PrintStream(sock.getOutputStream());
System.out.println("Checkpoint
2");
PS.println("MESSAGE
recieved");
}
MESSAGE
=
"now
the
message...";
System.out.println("Checkpoint
5");
InputStream
in
=
sock.getInputStream();
/*byte[]
decMessage
=
messageDecryption(data);
DataInputStream
dis
=
new
DataInputStream(in);
System.out.println(new
String(decMessage));
int
len
=
N
=
dis.readInt();
BigInteger.valueOf(0);
d
=
BigInteger.valueOf(0);
System.out.println("size:
"+len);
*/
data
=
null;
sock.close();
System.out.println("Checkpoint
3");
}
byte[]
data
=
}
new
byte[len];
if
(len
>
0)
{
public
byte[]
dis.readFully(data);
messageDecryption(byte[]
D){
}
BigInteger
encryptedMsg
=
new
BigInteger(D);
encryptedMsg
=
encryptedMsg.modPow(d,
System.out.println("Checkpoint
4");
N);
return
encryptedMsg.toByteArray();
System.out.println(new
//return
(new
BigInteger(D)).modPow(d,
String(data));
N).toByteArray();
}
if(data.length
!=
0){
//if
}
a
message
is
received,
print
in
console
Ø LoginUserThread.java
package
socketThreads;
}
catch
(Exception
e)
{
//
TODO
Auto-‐
import
java.io.BufferedReader;
generated
catch
block
import
java.io.InputStream;
import
java.io.InputStreamReader;
e.printStackTrace();
import
java.io.ObjectInputStream;
}
import
java.io.PrintStream;
}
import
java.net.ServerSocket;
import
java.net.Socket;
public
void
loginUserTask()
throws
import
java.util.List;
Exception{
import
com.mongodb.BasicDBObject;
//create
a
ServerSocket
import
com.mongodb.DB;
for
port
8080
import
com.mongodb.DBCollection;
ServerSocket
srvrSocket
=
import
com.mongodb.DBCursor;
new
ServerSocket(9001);
import
com.mongodb.DBObject;
import
com.mongodb.MongoClient;
srvrSocket.setReuseAddress(true);
Socket
sock;
public
class
LoginUserThread
extends
Thread
{
System.out.println("LoginUserThrea
public
void
run(){
d:
"+"Login
socket
open");
try
{
while(true){
loginUserTask();
//open
socket
xxxiii
connection
*
3:
sock
=
Incorrect
password
srvrSocket.accept();
*
4:
Info
not
received
InputStream
in
**/
=
sock.getInputStream();
List<DBObject>
csrList
=
ObjectInputStream
dis
=
new
cursor.toArray();
ObjectInputStream(in);
if
String[]
user
=
(csrList.size()
>
0)
{
new
String[2];
String
pass
=
user
=
csrList.get(0).get("password").toString();
(String[])
dis.readObject();
System.out.println(pass);
if(user.length
!=
0){
if(pass.equals(user[1])){
//if
a
message
is
received,
print
in
console
PrintStream
PS
=
new
PrintStream(sock.getOutputStream());
System.out.println("LoginUserThrea
d:
"+""+user[0]);
PS.println("2");
System.out.println("LoginUserThrea
d:
"+""+user[1]);
PS.println(csrList.get(0).get("name"
).toString());
//TODO:
Add
user
to
DataBase!
send
a
unique
port
number
to
user.
PS.println(csrList.get(0).get("phone"
).toString());
MongoClient
mongo
=
new
MongoClient("localhost",
27017);
PS.println(csrList.get(0).get("email"
).toString());
/****
Get
database
****/
//
if
PS.println(csrList.get(0).get("port").
database
doesn't
exists,
MongoDB
will
create
it
toString());
for
you
DB
db
=
mongo.getDB("safetimedb");
InputStreamReader
IR
=
/****
new
Get
collection
/
table
from
'testdb'
****/
InputStreamReader(sock.getInputStream());
//
if
collection
doesn't
exists,
MongoDB
will
create
BufferedReader
BR
=
new
it
for
you
BufferedReader(IR);
DBCollection
table
=
db.getCollection("users");
//check
for
messages
/****
received
from
the
socket
Find
and
display
****/
String
MESSAGE
=
BasicDBObject
searchQuery
=
new
BR.readLine();
BasicDBObject();
searchQuery.put("email",
user[0]);
System.out.println(MESSAGE);
DBCursor
cursor
=
table.find(searchQuery);
}else{
/**
PrintStream
PS
=
new
*
1:
PrintStream(sock.getOutputStream());
User
not
found
*
2:
PS.println("3");
Correct
password
xxxiv
}
PrintStream
PS
=
new
PrintStream(sock.getOutputStream());
}else{
PS.println("4");
}
PrintStream
PS
=
new
PrintStream(sock.getOutputStream());
sock.close();
}
PS.println("1");
}
}
}
}else{
Ø NewUserThread.java
package
socketThreads;
ObjectInputStream
dis
=
new
ObjectInputStream(in);
import
java.io.InputStream;
import
java.io.ObjectInputStream;
String[]
user
=
import
java.io.PrintStream;
new
String[5];
import
java.net.ServerSocket;
import
java.net.Socket;
user
=
(String[])
dis.readObject();
import
com.mongodb.BasicDBObject;
import
com.mongodb.DB;
if(user.length
import
com.mongodb.DBCollection;
!=
0){
import
com.mongodb.DBCursor;
//if
import
com.mongodb.MongoClient;
a
message
is
received,
print
in
console
public
class
NewUserThread
extends
Thread
{
System.out.println("NewUserThread
:
"+""+user[0]);
public
void
run(){
try
{
System.out.println("NewUserThread
:
"+""+user[1]);
runNewUserTask();
}
catch
(Exception
e)
{
System.out.println("NewUserThread
//
TODO
Auto-‐ :
"+""+user[2]);
generated
catch
block
System.out.println("NewUserThread
e.printStackTrace();
:
"+""+user[3]);
}
}
System.out.println("NewUserThread
:
"+""+user[4]);
public
void
runNewUserTask()
throws
Exception{
//TODO:
Add
user
to
DataBase!
send
//create
a
ServerSocket
a
unique
port
number
to
user.
for
port
8080
ServerSocket
srvrSocket
=
new
ServerSocket(9000);
MongoClient
mongo
=
new
MongoClient("localhost",
27017);
srvrSocket.setReuseAddress(true);
Socket
sock;
/****
Get
database
****/
System.out.println("NewUserThread
//
if
:
"+"Registration
socket
open");
database
doesn't
exists,
MongoDB
will
create
it
for
you
while(true){
DB
//open
socket
db
=
mongo.getDB("safetimedb");
connection
sock
=
/****
srvrSocket.accept();
Get
collection
/
table
from
'testdb'
****/
//
if
InputStream
in
collection
doesn't
exists,
MongoDB
will
create
=
sock.getInputStream();
it
for
you
xxxv
xxxvi
System.out.println("SendMessage
}else{
running");
ServerSocket
dos.writeChar('I');
srvrSocket
=
new
ServerSocket(8998);
srvrSocket.setReuseAddress(true);
dos.writeInt(((ArrayList)encMessag
Socket
sock;
e).size());
sock
=
srvrSocket.accept();
for(int
i
=
0;
i
<
InputStream
in
((ArrayList)encMessage).size();
i++){
=
sock.getInputStream();
dos.writeInt(((byte[])((ArrayList)en
DataInputStream
dis
=
new
cMessage).get(i)).length);
DataInputStream(in);
if(((byte[])((ArrayList)encMessage)
char
cosa
=
.get(i)).length
>
0){
dis.readChar();
OutputStream
out
=
sock.getOutputStream();
dos.write(((byte[])((ArrayList)encM
essage).get(i)),
0,
DataOutputStream
dos
=
new
((byte[])((ArrayList)encMessage).get(i)).lengt
DataOutputStream(out);
h);
if(encMessage
}
instanceof
byte[]){
}
}
System.out.println(new
String((byte[])encMessage));
PrintStream
Ps
=
new
PrintStream(sock.getOutputStream());
dos.writeChar('M');
Ps.println(user);
dos.writeInt(((byte[])encMessage).l
}
catch
(IOException
e)
{
ength);
//
TODO
Auto-‐
generated
catch
block
if(((byte[])encMessage).length
>
0){
e.printStackTrace();
}
dos.write(((byte[])encMessage),
0,
}
((byte[])encMessage).length);
}
}
Ø TestThread.java
package
socketThreads;
public
void
run(){
import
java.io.BufferedReader;
try
{
import
java.io.DataInputStream;
import
java.io.IOException;
receiveMessage();
import
java.io.InputStream;
}
catch
(Exception
e)
{
import
java.io.InputStreamReader;
//
TODO
Auto-‐
import
java.net.ServerSocket;
generated
catch
block
import
java.net.Socket;
import
java.util.ArrayList;
e.printStackTrace();
}
import
saveTimeServer.socketServer;
}
public
class
TestThread
extends
Thread{
public
void
receiveMessage()
throws
Exception{
socketServer
parent;
try
{
public
TestThread(socketServer
System.out.println("TestThread
context){
running");
parent
=
context;
ServerSocket
}
srvrSocket
=
new
ServerSocket(8999);
xxxvii
srvrSocket.setReuseAddress(true);
Socket
sock;
for(int
i
=
0;
i
<
imgLen;
i++){
while(true){
sock
System.out.println("Receiving...");
=
srvrSocket.accept();
int
len
=
dis.readInt();
InputStream
in
=
byte[]
data
=
new
sock.getInputStream();
byte[len];
DataInputStream
dis
=
new
if
(len
>
0)
{
DataInputStream(in);
char
dis.readFully(data);
type
=
dis.readChar();
}
if(type
==
'M'){
image.add(data);
int
len
=
dis.readInt();
System.out.println("Received
#"+i);
}
System.out.println("size:
"+len);
System.out.println("info
received:
"+image.size());
byte[]
data
=
new
byte[len];
if
(len
>
0)
{
InputStreamReader
ir
=
new
InputStreamReader(sock.getInputStream());
dis.readFully(data);
BufferedReader
br
=
new
}
BufferedReader(ir);
InputStreamReader
ir
=
new
String
toUser
=
br.readLine();
InputStreamReader(sock.getInputStream());
String
fromUser
=
br.readLine();
BufferedReader
br
=
new
BufferedReader(ir);
System.out.println("To
user:
"+toUser);
String
toUser
=
br.readLine();
System.out.println("from
user:
String
fromUser
=
br.readLine();
"+fromUser);
parent.stopReceivingMsg(data,
toUser,
fromUser);
parent.stopReceivingMsg(image,
}else{
toUser,
fromUser);
}
int
imgLen
=
dis.readInt();
}
System.out.println("size
of
image:
}
catch
(IOException
e)
{
"+imgLen);
//
TODO
Auto-‐
generated
catch
block
e.printStackTrace();
ArrayList<Object>
image
=
new
}
ArrayList<Object>();
}
}
xxxviii
Ø TimerThread.java
package
socketThreads;
//create
a
ServerSocket
import
saveTimeServer.socketServer;
for
port
8080
ServerSocket
srvrSocket
=
public
class
TimerThread
extends
Thread{
new
ServerSocket(9002);
socketServer
parent;
srvrSocket.setReuseAddress(true);
Socket
sock;
public
TimerThread(socketServer
context){
System.out.println("UpdateKeyThre
parent
=
context;
ad:
"+"Key
update
socket
open");
}
while(true){
public
void
run(){
//open
socket
try
{
connection
sock
=
Thread.sleep(20000);
srvrSocket.accept();
}
catch
(InterruptedException
e)
{
InputStream
in
//
TODO
Auto-‐ =
sock.getInputStream();
generated
catch
block
ObjectInputStream
dis
=
new
e.printStackTrace();
ObjectInputStream(in);
}
String[]
user
=
System.out.println("Timer
new
String[2];
finished");
parent.changeStopLoop();
user
=
}
(String[])
dis.readObject();
}
if(user.length
!=
0){
UpdateKeyThread.java
//if
a
message
is
received,
print
in
console
package
socketThreads;
System.out.println("UpdateKeyThre
import
java.io.InputStream;
ad:
"+""+user[0]);
import
java.io.ObjectInputStream;
import
java.io.PrintStream;
System.out.println("UpdateKeyThre
import
java.net.ServerSocket;
ad:
"+""+user[1]);
import
java.net.Socket;
import
java.util.List;
//TODO:
Add
user
to
DataBase!
send
import
com.mongodb.BasicDBObject;
a
unique
port
number
to
user.
import
com.mongodb.DB;
import
com.mongodb.DBCollection;
import
com.mongodb.DBCursor;
MongoClient
mongo
=
new
import
com.mongodb.DBObject;
MongoClient("localhost",
27017);
import
com.mongodb.MongoClient;
/****
public
class
UpdateKeyThread
extends
Thread
Get
database
****/
{
//
if
database
doesn't
exists,
MongoDB
will
create
it
public
void
run(){
for
you
try
{
DB
db
=
mongo.getDB("safetimedb");
updateKeyTask();
}
catch
(Exception
e)
{
/****
//
TODO
Auto-‐ Get
collection
/
table
from
'testdb'
****/
generated
catch
block
//
if
collection
doesn't
exists,
MongoDB
will
create
e.printStackTrace();
it
for
you
}
}
DBCollection
table
=
db.getCollection("users");
public
void
updateKeyTask()
throws
Exception{
/****
xxxix
xl
e:
160939886914470350804474172516213429150273668023601232814645095900670025459200230
304644355172135209280127427290074919281076382688927964778360546919274923613177775
654684802629395792000808537872208888755637137297454336251887414392965423713293041
433037548117073451047132571445088585937354286000656687823149582353153283925830167
883667036666620201187344847795225043011272129079516363716182327319675375254314722
448951792554800672650372287768303941950670829458914643309904386843878828987538610
749396912855124401308615602176079823373962777640789622131528358328099466615218788
89061341341366543520090211856990469300451442976351
Private
key
N:
A
287973047397959966459171224813899804924489958240150171144632418612750012436289393
883489292547390478094515661452003404487648891297123185156001603931868101709758060
854839949352859800329224059177127529381738895709481327666740673015294901850034061
159008879133776767576897374331617835968282645031245013734438071430841271859036038
605069182960019317903533872073443874743942934512007359451933780032525716970355007
790263263221016535946736999155442475443611530939510186499607481645389483498274609
515078604074322961514399829579480338601370882132440005276219970272407684466237794
73484759682939168263552990438933236448270783096179
d:
130286134905903296878809904273909809219128868288854870690284843330319188758403650
92602163120321437241568892607436032444708019114394600985225325345978141119
Public
key
N:
B
250375816420717654230341390083618198845133857389865187895448181623536720175215737
298162301587416790236753914696792070740168691581277755465981892844665279344032079
125976212548841750698664552841081756451944696489379954094399833574426518895389395
845245661651847121302424064982201516300295530730638594427374756038627538772481163
212583661719376529251612978716399036673963771202535312831189461306724400313299612
148899906147437344328591580095237534896231635413830237266245708588133793967697039
926803474180916493859329352055220340986127416405819953677016209476062898208613556
40874707113754994144032009208031199649556323224773
e:
160043651603909917991739363542657835352920347005814770669336486989694895266587929
316756426693143361273006937259401116945071669413197601790686825488357671930766433
592384957319696945946716984171843986738705652178961505176933725616075821307250323
230924754483957395151720464793300597866219411321393552930202629652278982658200187
093909761956584267608965637558793753398136709445294001102087043886572237622644790
xli
581219866854957968076163032820298263445062213411078395088387552002975117527220656
368452276982213433947994297756918784702763953298638278115079740571615973875815210
5989976397068557238550551265514937312957717154885
Private
key
N:
B
250375816420717654230341390083618198845133857389865187895448181623536720175215737
298162301587416790236753914696792070740168691581277755465981892844665279344032079
125976212548841750698664552841081756451944696489379954094399833574426518895389395
845245661651847121302424064982201516300295530730638594427374756038627538772481163
212583661719376529251612978716399036673963771202535312831189461306724400313299612
148899906147437344328591580095237534896231635413830237266245708588133793967697039
926803474180916493859329352055220340986127416405819953677016209476062898208613556
40874707113754994144032009208031199649556323224773
d:
125154922989015516313948357087251477948476674921424729140171055347407444329693363
76038257673079408354329994964643989080807755408570576427974105419136074769
xlii
xliii
xliv
lutYaxis = (mixTemp[1]&0xf0)>>4;
int main(int argc, const char * argv[]) { lutXaxis = mixTemp[1]&0x0f;
// insert code here...
int dataIn[4][4] = {{0x32, 0x88, 0x31, 0xe0}, if (mixColumnMatrix[j][1] == 2) {
{0x43, 0x5a, 0x31, 0x37}, mixResult[j] = mixResult[j] ^
{0xf6, 0x30, 0x98, 0x07}, twoTable[lutYaxis][lutXaxis];
{0xa8, 0x8d, 0xa2, 0x34}}; }else if (mixColumnMatrix[j][1] == 3){
mixResult[j] = mixResult[j] ^
int rotConNum = 0; threeTable[lutYaxis][lutXaxis];
}else{
//Initial ADDROUNDKEY mixResult[j] = mixResult[j] ^
for (int i = 0; i < 4; i++) { mixTemp[1];
for (int j = 0; j < 4; j++) { }
dataIn[j][i] = dataIn[j][i] ^
roundKey[j][i];
} lutYaxis = (mixTemp[2]&0xf0)>>4;
} lutXaxis = mixTemp[2]&0x0f;
keySchedulingProcess(rotConNum);
rotConNum++; if (mixColumnMatrix[j][2] == 2) {
mixResult[j] = mixResult[j] ^
for (int k = 0; k < 9; k++) { twoTable[lutYaxis][lutXaxis];
//SUBBYTES state }else if (mixColumnMatrix[j][2] == 3){
int lutXaxis, lutYaxis; mixResult[j] = mixResult[j] ^
for (int i = 0; i < 4; i++) { threeTable[lutYaxis][lutXaxis];
for (int j = 0; j < 4; j++) { }else{
lutYaxis = (dataIn[j][i]&0xf0)>>4; mixResult[j] = mixResult[j] ^
lutXaxis = dataIn[j][i]&0x0f; mixTemp[2];
}
dataIn[j][i] =
encLookupTbl[lutYaxis][lutXaxis];
} lutYaxis = (mixTemp[3]&0xf0)>>4;
} lutXaxis = mixTemp[3]&0x0f;
printf("Data after SUBBYTES Round %d\n", k+1);
printf("%02x %02x %02x %02x\n%02x %02x %02x if (mixColumnMatrix[j][3] == 2) {
%02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", mixResult[j] = mixResult[j] ^
dataIn[0][0], dataIn[0][1], dataIn[0][2], twoTable[lutYaxis][lutXaxis];
dataIn[0][3], dataIn[1][0], dataIn[1][1], }else if (mixColumnMatrix[j][3] == 3){
dataIn[1][2], dataIn[1][3], dataIn[2][0], mixResult[j] = mixResult[j] ^
dataIn[2][1], dataIn[2][2], dataIn[2][3], threeTable[lutYaxis][lutXaxis];
dataIn[3][0], dataIn[3][1], dataIn[3][2], }else{
dataIn[3][3]); mixResult[j] = mixResult[j] ^
mixTemp[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[0][i] = mixResult[0];
dataIn[i][1] = shiftTemp[(i+1 < 4 ? i+1 : dataIn[1][i] = mixResult[1];
i+1-4)]; dataIn[2][i] = mixResult[2];
dataIn[i][2] = shiftTemp[(i+2 < 4 ? i+2 : dataIn[3][i] = mixResult[3];
i+2-4)]; }
dataIn[i][3] = shiftTemp[(i+3 < 4 ? i+3 : printf("Data after MIXCOLUMNS Round %d\n",
i+3-4)]; k+1);
} printf("%02x %02x %02x %02x\n%02x %02x %02x
printf("Data after SHIFTROWS Round %d\n", %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n",
k+1); dataIn[0][0], dataIn[0][1], dataIn[0][2],
printf("%02x %02x %02x %02x\n%02x %02x %02x dataIn[0][3], dataIn[1][0], dataIn[1][1],
%02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[1][2], dataIn[1][3], dataIn[2][0],
dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[2][1], dataIn[2][2], dataIn[2][3],
dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[3][0], dataIn[3][1], dataIn[3][2],
dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[3][3]);
dataIn[2][1], dataIn[2][2], dataIn[2][3],
dataIn[3][0], dataIn[3][1], dataIn[3][2], //ADDROUNDKEY step
dataIn[3][3]); for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
//MIXCOLUMNS step dataIn[j][i] = dataIn[j][i] ^
for (int i = 0; i < 4; i++) { roundKey[j][i];
int mixTemp[4] = {dataIn[0][i], }
dataIn[1][i], dataIn[2][i], dataIn[3][i]}; }
int mixResult[4];
printf("Data after ADDROUNDKEY Round %d\n",
for (int j = 0; j < 4; j++) { k+1);
mixResult[j] = printf("%02x %02x %02x %02x\n%02x %02x %02x
mixColumnMatrix[j][0]*mixTemp[0] + %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n",
mixColumnMatrix[j][1]*mixTemp[1] + dataIn[0][0], dataIn[0][1], dataIn[0][2],
mixColumnMatrix[j][2]*mixTemp[2] + dataIn[0][3], dataIn[1][0], dataIn[1][1],
mixColumnMatrix[j][3]*mixTemp[3]; dataIn[1][2], dataIn[1][3], dataIn[2][0],
int lutXaxis, lutYaxis; dataIn[2][1], dataIn[2][2], dataIn[2][3],
lutYaxis = (mixTemp[0]&0xf0)>>4; dataIn[3][0], dataIn[3][1], dataIn[3][2],
lutXaxis = mixTemp[0]&0x0f; dataIn[3][3]);
if (mixColumnMatrix[j][0] == 2) { keySchedulingProcess(rotConNum);
xlv
rotConNum++; 4)];
} }
printf("Data after SHIFTROWS Round 10\n");
//final SUBBYTES state printf("%02x %02x %02x %02x\n%02x %02x %02x
int lutXaxis, lutYaxis; %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n",
for (int i = 0; i < 4; i++) { dataIn[0][0], dataIn[0][1], dataIn[0][2],
for (int j = 0; j < 4; j++) { dataIn[0][3], dataIn[1][0], dataIn[1][1],
lutYaxis = (dataIn[j][i]&0xf0)>>4; dataIn[1][2], dataIn[1][3], dataIn[2][0],
lutXaxis = dataIn[j][i]&0x0f; dataIn[2][1], dataIn[2][2], dataIn[2][3],
dataIn[3][0], dataIn[3][1], dataIn[3][2],
dataIn[j][i] = dataIn[3][3]);
encLookupTbl[lutYaxis][lutXaxis];
} //final ADDROUNDKEY step
} for (int i = 0; i < 4; i++) {
printf("Data after SUBBYTES Round 10\n"); for (int j = 0; j < 4; j++) {
printf("%02x %02x %02x %02x\n%02x %02x %02x dataIn[j][i] = dataIn[j][i] ^
%02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", roundKey[j][i];
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], printf("Data after ADDROUNDKEY Round
dataIn[3][0], dataIn[3][1], dataIn[3][2], 10\n**************CIPHERETEXT****************\n");
dataIn[3][3]); printf("%02x %02x %02x %02x\n%02x %02x %02x
%02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n",
//final SHIFTROWS state dataIn[0][0], dataIn[0][1], dataIn[0][2],
for (int i = 1; i < 4; i++) { dataIn[0][3], dataIn[1][0], dataIn[1][1],
int shiftTemp[4] = {dataIn[i][0], dataIn[1][2], dataIn[1][3], dataIn[2][0],
dataIn[i][1], dataIn[i][2], dataIn[i][3]}; dataIn[2][1], dataIn[2][2], dataIn[2][3],
dataIn[i][0] = shiftTemp[i]; dataIn[3][0], dataIn[3][1], dataIn[3][2],
dataIn[i][1] = shiftTemp[(i+1 < 4 ? i+1 : i+1- dataIn[3][3]);
4)];
dataIn[i][2] = shiftTemp[(i+2 < 4 ? i+2 : i+2-
4)]; return 0;
dataIn[i][3] = shiftTemp[(i+3 < 4 ? i+3 : i+3- }
Ø RSA
algorithm:
// }
// main.c if (temp == 0) {
// RSAalgorithm coprimes[cCounter] = i;
// cCounter++;
// Created by Ricardo Viteri on 5/7/15. }
// Copyright (c) 2015 Ricardo Viteri. All rights }
reserved.
// e = coprimes[rand()%(cCounter < 5 ? cCounter :
5)];
#include <stdio.h>
#include <math.h> //calculate d such as (d*e)%n = 1
#include <stdlib.h> int d = 0;
for (int i = 0; i<n; i++) {
int main(int argc, const char * argv[]) { int temp = (i*e)%phi;
// insert code here... if (temp == 1) {
d=i;
/******************************** KEY GENERATION break;
*******************************/ }
int p = 3, q = 13; }
xlvi
xlvi