112
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.

SafeTime Android Application

Embed Size (px)

Citation preview

 

         

   

   

Department  of  Electronic  &  Electrical  Engineering  

 MSc  Avionic  Systems  Engineering  

 Dissertation  2015  

     

SafeTime  Application    

 Student:     Viteri  Buendía,  Ricardo  Mauricio    Registration:   140209688    Date:       August  28,  2015        Supervisor:     Dr.  Jonathan  M  Rigelsford    Second  Marker:     Dr.  Gregory  Cook    

 This  dissertation  is  a  part  requirement  for  the  degree  of  MSc  in  Avionic  

Systems  Engineering.  

 

 

                                                                   

 

 

               Abstract    

Communication   is  a  basic  part  of  our   lives   in  a  daily  basis,  messages  come  and  go  

from  various  places  worldwide  as  long  as  the  user  have  access  to  the  web.  All  those  

messages  transform  in  sets  of  bytes  that  will  be  “surfing”  through  the  net  to  get  to  

their   destination,   but   not   necessarily   in   a   secure   way.   Lately,   many   issues  

concerning  security  have  been  announced   in  the  news,  some  of   them  are  personal  

cases   such   as   photos   and   messages   hacked   from   celebrities   phones,   others  

concerning  big  companies  such  as  NBC.  

The   world   is   becoming  more   accessible   day-­‐by-­‐day   and   personal   security   is   also  

becoming   more   important.   This   project’s   aim   is   to   develop   an   instant   messaging  

application  in  Android  platform  that  will,  by  all  means  necessary,  protect  the  user’s  

data,  not  by  preventing  it  to  be  stolen,  but  preventing  it  to  be  read  by  any  peer  not  

involved  in  the  communication  nor  the  server  managing  the  communication.  

 

 

           Acknowledgements    

To  my  supervisor,  Dr.  Jonathan  Rigelsford  for  his  support  and  help  during  

the  developing  of  this  project  and  helping  me  focus  my  ideas  and  objectives  

in  order  to  successfully  complete  not  only  what  was  intended,  but  more.  To  

my   family   and   friends   that   were   always   there   to   support   me   not   only  

during  my  studies,  but  throughout  my  life.  To  Pamela  Garcia  for  being  my  

biggest  support  in  the  most  stressful  moments  and  being  as  crazy  as  me  in  

my  craziest  moments.  

Juan   Marito,   this   is   what   your   uncle   was   doing   while   you   were   so   busy  

being  born.  

 

   

 

 

Table  of  Contents  1.  Introduction  ..........................................................................................................................  1  2.  Background  ...........................................................................................................................  2  2.1  Instant  messaging  ......................................................................................................................  2  2.2  Android  programming  .............................................................................................................  3  2.3  Client/Server  communication  ...............................................................................................  4  2.4  TCP/IP  sockets  ............................................................................................................................  6  2.5  Encryption  algorithms  .............................................................................................................  7  2.5.1  AES  algorithm  ........................................................................................................................................  8  2.5.2  RSA  algorithm  ........................................................................................................................................  9  

3.  What  is  SafeTime?  ............................................................................................................  10  3.1  How  it  works?  ...........................................................................................................................  11  3.2  Application  flow  diagram  .....................................................................................................  12  3.3  SafeTime  screen  by  screen  ...................................................................................................  13  3.3.1  Login  screen  .........................................................................................................................................  13  3.3.2  Register  screen  ....................................................................................................................................  14  3.3.3  User  list  tab  ...........................................................................................................................................  14  3.3.4  Conversation  tab  ................................................................................................................................  15  3.3.5  Add  contacts  tab  .................................................................................................................................  16  

3.4  Android  application  tasks  ....................................................................................................  16  3.5  Server  tasks  ...............................................................................................................................  17  

4.  Research  methods  ............................................................................................................  18  4.1  Development  tools  ..................................................................................................................  18  4.1.1  Android  studio  ....................................................................................................................................  18  4.1.2  Linux  server  ..........................................................................................................................................  19  4.1.3  Eclipse  Mars  .........................................................................................................................................  19  4.1.4  MongoDB  ...............................................................................................................................................  19  4.1.5  TeamViewer  .........................................................................................................................................  20  

4.2  Encryption  algorithm  implemented  .................................................................................  21  5.  SafeTime  main  processes  ..............................................................................................  23  5.1  Registration  process  ...............................................................................................................  23  5.2  Login  process  ............................................................................................................................  27  5.3  Add  contact  process  ................................................................................................................  31  5.4  Encryption  process  .................................................................................................................  35  5.5  Decryption  process  .................................................................................................................  38  5.6  Message  send/receive  process  ...........................................................................................  41  

6.  SafeTime  tests  ...................................................................................................................  45  6.1  Test  1:  Key  generation,  Encryption  and  Decryption  ....................................................  45  6.2  Test  2:  TCP  socket  communication  ....................................................................................  48  6.3  Test  3:  Encryption  and  decryption  of  plain  text  with  one  set  of  keys  ....................  49  6.4  Test  4:  Encryption  and  decryption  of  plain  text  with  two  different  set  of  keys  .  51  6.5  Test  5:  Encryption  and  decryption  of  images  with  one  set  of  keys  .........................  52  6.6  Test  6:  Encryption  and  decryption  of  images  with  two  different  set  of  keys  ......  54  

7.  Discussion  ...........................................................................................................................  55  7.1  Achievements  of  SafeTime  ...................................................................................................  55  7.2  Limitations  and  upgrades  .....................................................................................................  56  7.3  SafeTime’s  use  for  industry  ..................................................................................................  57  

8.  Conclusions  ........................................................................................................................  57  

 

 

9.  Bibliography  ......................................................................................................................  59  Appendix  A:  Application  codes  ............................................................................................  i  Appendix  B:  Server  codes  ..............................................................................................  xxvii  Appendix  C:  Test  RSA  keys  ...................................................................................................  xl  Appendix  D:  Encryption  algorithm  C  code  tests  ........................................................  xlii      

 

 1  

 1. Introduction  

Cyber   security   is   a   term   that   has   been   sounding   very   loudly   lately.   All   of   us,  

smartphone  users,  have  heard  of  this  term  at  least  once,  but  are  we  sure  of  what  

that  means?  

As  taken  from  the  Oxford  English  dictionary:  “Cyber  security  is  the  state  of  being  

protected   against   criminal   or   unauthorized   use   of   electronic   data   or   the  

measures  to  achieve  this”.   It  considers  defending  against  attacks  to  all  kinds  of  

computer  systems  [1].  So  we  now  understand  the  importance  of  this.  Every  day  

we   as   individuals   keep   in   touch   with   our   loved   ones,   colleagues,   bosses   and  

other   people   through   instant   messaging   applications   sharing   personal  

information,  pictures  and  other   files   taking  the  risk  of  being  hacked.   It  will  not  

seem  that  much  of  a  big  deal  if  we  just  take  into  consideration  simple  messages  

and   conversations,   but   what   if   we   reveal   our   passwords   for   some   reason,   or  

credit   card   information,   or   bank   information,   and   that’s   only   speaking   about  

personal  use,  for  big  companies  that  kind  of  information  can  involve  thousands  

of  pounds.  With   this  project,   I’m  developing  a  way  to  communicate   in  a  secure  

way,  using  as  my  interface  an  Android  application.  But  the  principles  taken  from  

this   research   can   be   applicable   for   other   kind   of   communications   in   more  

delicate   fields   such   as   the   government   or   the  military.   This   way,   some   of   the  

latest   concerns   in   cyber   security   can   be   covered   in   both   civil   and   military  

applications.  

In   this   dissertation,   first   of   all,   the   theory   behind   the   application   will   be  

explained,  instant  messaging,  Android  and  Client/Server  communication,  so  that  

the  later  explanation  of  the  project  can  make  more  sense  and  finally,  the  process  

in  which   it   has  been  developed  along  with   their   achievements,   limitations   and  

conclusions.  

 

 

 

 

 2  

2. Background  2.1. Instant  messaging  Messaging   applications   like   Whatsapp,   Facebook   messenger   and   Skype   are  

amongst  the  most  downloaded  and  used  applications   in  the  Google  market  [2].  

The   main   objective   of   these   applications   is   to   provide   the   user   with   a  

communication  service  between  themselves  and  other  users  with  an  account  in  

it.  In  general,  the  way  in  which  the  IM  communications  work  is  that,  users,  which  

are   the  clients  and  have  an  account  authenticated  by   the  server,   send  a  packet  

with   a   set   of   information   such   as:   its   own   client   ID,   the   client   ID  of  whom   the  

message  is  sent  to  and  the  message  itself.  That  packet  is  sent  through  internet  to  

a   main   server,   which   is   going   to   be   the   one   that   will   manage   the   connection  

between  the  two  clients,   like  the  post  service,   the  server  will   look   for  the  ID  of  

the   second  client,   confirm   it   is   actually  a   client  and  not   corrupt  data,   and   then  

send   the  packet   to   its  destination.  The   following  diagram  represents   this  basic  

communication:  

 

 Figure  1:  Basic  point  to  point  communication  

 

In  this  model,  which  is  the  one  that  will  be  used  for  this  project,  represent  how  

the   clients   uniquely   communicate   with   the   server,   therefore,   it   works   as   a  

mediator   between   the   clients   [3].   In   order   to   make   this   model   possible,  

client/server   communication   is   needed.   This   communication   structure  will   be  

explained  in  detail  later  on.  

 

 3  

 

2.2. Android  programming  Android   is  a  mobile  operating  system  created   in  2003  by  Android   Inc.   In  2005  

Google   acquired   Android   Inc.   and   started   to   work   on   their   new   mobile  

development  branch.  In  2010,  Google  finally  released  their  phone  Nexus  with  the  

new   Linux   kernel   based   operating   system   Android   2.2   (Froyo).   From   the   on,  

Android  OS  has  positioned  itself  as  one  of  the  most  important  mobile  system  in  

the  last  few  years.  Because  of  its  Linux  roots  and  Google’s  open  source  mentality,  

it’s  one,  if  not  the  most,  accessible  and  affordable  OS  for  developers  worldwide,  

for  this  reason  Android  OS  has  been  chosen  as  the  platform  in  which  this  project  

will  be  worked.  

Android   development   is   based   in   the   object   oriented   programming   language  

Java,  designed  by  Oracle  Corporation,  and  its  structure  is  based  in  4  main  blocks  

and  5  main  features  at  the  developers  disposal  [4].    

 

Main  blocks:  

• Activities:  Is  the  building  block  of  the  user  interface,  the  main  window  in  

which  the  developer  will  be  programming  what  the  app  is  going  to  do.  

• Content  providers:  provides  a  level  of  abstraction  for  the  data  stored  by  

an  application.  By  having  this,  data  can  be  accessed  by  other  applications  

while  maintaining  complete  control  of  such  data.  

• Intents:   These   are   system  messages   in   the   device.   This   messages   can  

notify   an   app   of   various   events   which   could   be:   hardware   events,  

incoming  data  of  application  events.  

• Services:  Are  features  in  an  app  that  can  keep  running  even  though  the  

application   is  no   longer  operating.  Different  than  the  Activities,  Content  

providers   and   Intents,   which   are   short-­‐lived,   Services   can   stay   “alive”  

waiting   for   events   an   app   may   be   waiting,   for   example   waiting   for   a  

message  from  the  server.  

 

 

 4  

Main  features:  

• Storage:   an   application’s   data   files   can   be   stored   either   in   the   phone’s  

internal  memory  or  an  external  memory  provided  by  the  user  (SD  card).  

• Network:   generally,   Android   apps   are   Internet   ready,   and   is   able   to  

access   it   in   order   to   load  or   send  data,   for   example,   Java   sockets  which  

will  be  widely  used  in  this  project.  

• Multimedia:  Depending  on  the  device,  an  app  can  access  video  and  audio  

recorders  and  players  and  also  camera  and  picture  galleries.  

• GPS:  With  this,  an  application  can  access  the  user’s  location  in  the  earth.  

• Phone   services:   applications   can   dial   calls   or   send   and   receive   SMS  

messages.  

For   an   application   to   be   able   to   use   these   services,   the   user   must   grant  

permission.   These   permissions   will   be   typically   asked   for   while   installing   an  

application.  

Various  software  can  be  used  to  develop  Android  applications.  The  two  that  are  

mainly  used  are  Eclipse  and  Android  Studio.  For  this  project,  I’ve  decided  to  use  

Android  Studio  because   it   simplicity  and  quick   installation  process,  also   taking  

into   account   that,   since   the   release   of   their   first   stable   version   in   December  

2014,   it   has   become   officially   the   principal   development   environment   for  

Android.  

 

2.3. Client/Server  communication  Client/Server   is   an   information   sharing   mode   widely   used   in   information  

systems  [5].   Is   the  communication  between  three  main  components,   the  client,  

the  server  and  the  network  system.  

• Client:   the   workstation,   in   this   project’s   case,   the   application   that  

provides  the  user  with  a  friendly  interface  to  be  used.  

• Server:   the   one   that   holds   the   information.  A   database   server   provides  

the  clients  with  a  main  information  center  were  they  have  access  and  can  

also  share  new  information.  

 

 5  

• Network  system:   is  the  link  between  client  and  server.  This  link  can  be  

done  through  LAN,  WAN  or  Internet.  

 

The  way  in  which  this  model  works  is  quite  simple.  The  client  will  send  a  request  

to  the  server,  once  the  server  processes  de  request  it  will  send  a  response  back  

to  the  client.  An  example  for  this  is  illustrated  as  follows:  

 Figure  2:  Client/Server  model  

 

For  this  example,  I’m  considering  a  basic  instant  messaging  system  in  which  the  

server   may   act   as   an   intermediary   between   two   clients.   Client   1   is   sending   a  

message  to  another  client;  the  process  will  follow  these  steps:  

1. Client   1   assembles   a   data   packet   and   sends   the   request   to   the   server  

through  the  network.  

2. The  server  receives  the  packet  and  processes  the  request.  It  identifies  the  

client  to  whom  the  packet  must  be  sent.  

3. The  server  sends  the  packet  to  the  receiver  client  through  the  network.  

4. The  server  sends  an  acknowledgment  packet  to  Client  1  confirming  that  

the  packet  has  been  sent  to  the  destination  client.  

Once   understood   client/server   communication,   it’s   important   to   understand  

how   a   connection   between   client   and   server   must   be   established.   In   this  

project’s  case,  the  most  suitable  are  the  TCP/IP  Sockets.  

 

 

 6  

2.4. TCP/IP  sockets  TCP/IP:  

In   order   to   initiate   a   point-­‐to-­‐point   client/server   connection   a   communication  

protocol  must   be   used.   The   Transmission   Control   Protocol   is   one   of   the  most  

widely   used   because   of   its   reliability.   TCP   guarantees   the   delivery   of   data   it  

transmits  in  form  of  packets  to  its  final  destination.  If  a  packet  is  damaged,  TCP  

will  resend  the  data  until  the  packets  are  successfully  transmitted.  

 

Socket:  

A  socket  is  an  endpoint  of  the  two-­‐way  communication  link  used  to  send  packets  

between  server  and  client.  A  socket   is  established  by  a  combination  of  both   IP  

address  and  port  number,  because  of  this,  multiple  connections  can  be  initiated  

between  client  and  server  making  every  connection  unique.  

To  establish  a  connection,  both  client  and  server  must  bind  a  socket  to  their  end  

of   connection.   Once   that   is   done,   both   can   read   from   and  write   to   the   socket  

when  communicating.  

 

Establishing  a  connection:  

The   process   to   create   sockets   varies   depending   if   it’s   a   client   or   a   server.   A  

socket   created   in   the   server   is   called   a   “passive   socket”   since   it  waits   for   and  

responds   to   clients.   A   socket   created   for   clients   in   the   other   hand   are   called  

“active  sockets”  and  will  be  initiated  with  the  main  goal  of  sending  a  message  to  

the  server,  for  that,  the  client  must  know  the  IP  address  and  port  number  of  the  

server’s  socket  [6].  So  the  lifecycle  of  a  socket  can  be  represented  in  this  way:  

 

 

 7  

 Figure  3:  Client  and  Server  Sockets  

 

2.5. Encryption  algorithms  This  projects  main  goal  is  to  achieve  secure  communication  between  two  clients.  

The   way   in   which   such   communication   will   be   possible   is   by   encrypting  

messages  so  that  no  one  can  understand  the  contents  of  a  packet  without  having  

the  key  to  decipher  it.  Many  encryption  algorithms  may  be  useful,  the  ones  that  I  

consider  more  relevant  and  for  this  project  are:  

 

• Data  Encryption  Standard  (DES)  

• Advanced  Encryption  Standard  (AES)  

• RSA  

 

Because  of  the  small  key  size  of  DES  algorithm  (56  bits)  and  considering  that  the  

National  Institute  of  Standards  and  Technology  withdrew  it  as  a  standard,  I  have  

neglected  DES  from  my  project.  

 

 

 8  

2.5.1.  Advanced  Encryption  Standard  (AES)  algorithm  Is   a   symmetric   block   cipher   based   on   Rijndael   Cypher,   and   designed   by  

Vincent  Rijmen  and  Joan  Daemen  in  1998.  A  symmetric  block  cipher  means  

that   its   key   is   also   symmetric,  meaning   that   the   same   key   can   be   used   for  

both  encrypting  and  decrypting  data.  

This   cipher   can   process   data   blocks   of   128   bits   using   different   sizes   of  

cryptographic   keys   of   128,   192   and   256   bits   [7].   In   2002   AES   became   a  

federal  government  standard  in  the  United  States  of  America.  

 

This   algorithm  works   in   a   4x4  matrix   of   bytes   named   “state”.   The   key   size  

defines  the  amount  of  transformations  from  the  input  are  done  to  convert  it  

on  the  output:  

   Table  1:  Repetitions  for  key  sizes  

   

A  cycle  consists  of  four  main  steps:  

1. AddRoundKey:  using  bitwise  xor,  each  bite  is  combined  with  a  block  

of  the  round  key.  

2. SubBytes:   each   byte   is   replaced  with   another   using   a   lookup   table.  

(non-­‐linear).  

3. ShiftRows:   The   last   three   rows  of   the   state   are   shifted   a  number  of  

steps  (transposition).  

4. MixColumns:  it  combines  all  the  bytes  within  each  column  (mixing).  

 

How  the  cycles  work  is  demonstrated  by  the  following  diagram:  

 

 9  

 Figure  4:  AES  cycle  structure  

 

2.5.2. RSA  algorithm  First  published  in  1977  by  Ron  Rivest,  Adi  Shamir  and  Leonard  Adleman,  RSA  

is  an  asymmetric  public-­‐key  cryptosystem.  It  works  with  two  keys:  a  public  

encryption  key  and  a  secret  decryption  key  [8].  

 

This   algorithm   work   by   3   main   steps:   key   generation,   encryption   and  

decryption.  

• Key   generation:   Two   different   prime   numbers   (p   and   q)   must   be  

selected,  and  multiplied  amongst  each  other  to  generate:  

n  =  p*q  

Now,  Euler’s  totient  function  has  to  be  used  to  get:  

φ(n)  =  n  –  (p  +  q  -­‐  1)  

Choose  an   integer  e  such  as  1  <  e  <  φ,   this  number  must  be  coprime  

with    φ(n).  Using  e,  d  can  be  calculated:  

d  ≡  e  –  1  (mod  φ(n))  

 

 10  

Finally,  values  of  p  and  q  must  be  erased  and  the  keys  are  ready:  

o Public  key  =  (n,  e)  

o Private  key  =  (n,  d)  

• Encryption:   Client_1,   which   already   generated   its   keys,   sends   the  

public   key   to   Client_2   and   keeps   the   private   key.  With   the   acquired  

key,  Client_2  encrypts  a  message  M  using  the  following  steps:  

o Turn  M  into  an  integer  m  such  that  0  ≤  m  ≤  n  using  a  padding  

scheme.  

o Now  compute  cypher  text  c:  

c  ≡  me  (mod  n)  

o Client_2  transmits  c  to  Client_1.  

• Decryption:   Client_1   receives   the   ciphertext   c   from   Client_2   and   in  

order  to  recover  m  the  following  steps  must  be  done:  

o Calculate  m  using:  

m  ≡  cd  (mod  n)  

o Reversing  the  padding  scheme,  message  M  can  be  recovered.  

 

3. What  is  SafeTime?  SafeTime  is  an  instant  messaging  application  programmed  in  Android  platform.  Its  

main  objective   is   to  guarantee  a  secure  communication  between  two  users,  not  by  

preventing  data   sent  by  users   to  be   intercepted  or  hacked,  but  by  preventing   that  

data  to  be  read.  The  way  to  do  this  is  by  encrypting  the  messages  sent  by  the  users  

using  an  encryption  algorithm  RSA  so  that  people  trying  to  intercept  those  messages  

either   via   an   sniffer   reading   packets   or   hacking   into   the   main   server.   For   this  

version  of   the  application,   encryption  of  plain   text  messages  and   images  has  been  

developed.  

 

 

 

 

 11  

3.1. How  it  works?  The   way   in   which   this   application   will   work   is   represented   in   the   following  

diagram:  

 Figure  5:  SafeTime  communication  flow  

 

Based  on  the  figure  shown,  the  way  in  which  the  app  will  work  is  explained:  

1. User_1  writes  a  message  in  plain  text,  once  finished,  the  message  is  then  

sent  to  the  encryption  process.  

2. Here  the  message  will  be  encrypted  using  the  RSA  public  key,  the  packet  

with  the  user  IDs  and  the  cyphered  message  is  then  sent  to  the  server.  

3. Using  sockets,  configuring  the  correct  port  and  IP  address,  the  packet  will  

go  to  the  server.  

4. The   server   will   check   to   which   user   the   packet   must   be   sent   and   will  

configure  the  socket  that  will  be  used  for  communicate  with  that  user.  

5. The   encrypted   packet   will   be   sent   through   the   socket   to   the   receiving  user.  

6. The   application  will   open   the   packet   and  with   its   RSA   private   key  will  

begin  the  process  of  decrypting  the  message.  

 

 12  

7. Once   the   message   is   decrypted   to   plain   text   or   image   again,   it   will   be  

displayed  in  the  user  interface  of  both  end  users.  

 

3.2. Application  flow  diagram  For  the  application,  the  following  flow  chart  represents  the  sequence  of  windows  

it  will  have:  

 Figure  6:  SafeTime  design  flow  chart  

Five  different  screens  are  planned  for  the  basic  application:  

• Login   screen:   is   the   first   screen   to   be   shown   by   the   app.   If   the   user  

already  has  an  account,  it  will  be  able  to  insert  the  email  and  password  in  

 

 13  

order  to  start  sending  messages  to  its  contacts.  If  not  registered,  a  button  

to  go  to  the  register  screen  is  provided.  

• Register  screen:  If  a  user  is  not  registered  to  the  app,  in  this  screen  with  

a  simple  form,  which  will  be  sent  to  authenticate.  

• Multi-­‐fragment   Tabhost:   This   view   consists   on   3   different   tabs  which  

will  fulfill  three  main  purposes:  

o User  list  tab:  Once  logged  into  the  app,  the  user  will  be  able  to  see  

the   list   of   its   contacts,  which   can   be   selected   in   order   to   open   a  

new  conversation.  

o Conversation  tab:  The  screen  in  which  the  user  will  be  able  to  see  

the  messages  received  from  other  user  and  in  which  it  will  be  able  

to  write  and  send  new  messages.  

o Add  contacts  tab:  In  this  last  screen,  the  user  will  be  able  to  add  a  

new  user  to  his  contacts  by  writing   its  email  and  requesting   it   to  

the  server.  

 

3.3. SafeTime  screen  by  screen  

3.3.1. Login  screen  Login  screen  is  the  one  that  will  enable  a  user  to  log  

into   their   already   registered   account   of   SafeTime  

app.  This  screen  has  5  main  components:  

A. App  title:  This  is  a  field  dedicated  to  show  the  

name  of  the  app,  developer  and  supervisor  of  

the  app.  

B. Text  fields:  In  this  fields  the  user  will  be  able  

to  write  its  email  and  password  in  order  to  log  

into  the  application.  

C. Login  button:  Will  execute  the  login  action.  D. Register  button:  Will  open  the  “Register  screen”.  

 

Figure  7:  Login  screen  

 

 14  

3.3.2. Register  screen  In  this  screen  the  user  will  be  able  to  register  a  new  

account  in  SafeTime.  Its  main  components  are:  

A. Text   fields:   In   this   fields,   the   basic  

information  of  the  user  can  be  filled.  

B. Generate   keys   and   register   button:   By  

pressing   this  button,   the   registration  process  

will  start.  

 

 

3.3.3. User  list  tab  This   screen   is   part   of   the   Multi-­‐fragment   Tabhost  

along   with   the   “conversation”   and   “add   contacts”  

tabs.  Here,  a  list  with  the  contacts  added  by  the  user  

is  shown.  The  main  components  in  this  screen  are:  

A. Tabhost  manager:  Used  by  the  user  in  order  

to  switch  tabs.  

B. User   list:  Here  the   list  of   the  users  added  by  

the  user  is  displayed.  If  the  user  taps  in  one  of  

the  items  in  the  list,  the  conversation  window  

for  that  user  will  be  opened.  

 

 

 

 

 

 

 

 

Figure  8:  Registration  screen  

Figure  9:  User  list  tab  

 

 15  

 

3.3.4. Conversation  tab  It’s   the   window   in   which   the   user   will   write  

messages   to   another   user   previously   added   to   the  

user   list.   Plain   text   and   images   can   be   sent   to   the  

other  user.  Its  main  components  are:  

A. Tabhost  manager:  Used  by  the  user  in  order  

to  switch  tabs.  

B. User’s  name:  This   is  the  name  of  the  user  to  

whom  the  message  will  be  sent.  

C. Conversation   field:   In   this   space,   the  

conversation   between   the   two   users   will   be  

displayed.  Messages   focused   on   the   right   side  

are  messages  sent  by  the  user  and  the  ones  focused  on  the  left  are  the  

ones  received.  

D. Text  field:  In  this  field,  the  user  can  write  a  text  message  to  be  sent.  E. Send   button:   By   pressing   this   button,   the   message   written   in   the  

“Text  field”  will  be  sent.  

F. Image  button:  When  this  button  is  pressed,  the  

phone’s  gallery  will  be  opened  so  that  the  user  

can  select  an  image  to  be  sent.  Once  selected,  a  

pop-­‐up   will   appear   with   the   following  

components:  

a. Image:   This   is   a   sample   of   the   image   to  

be  sent.    

b. Send  picture  button:  Once  this  button   is  

pressed,  the  image  message  will  be  sent.    

 

 

 

Figure  10:  Conversation  tab  

Figure  11:  Image  selection  window  

 

 16  

3.3.5. Add  contacts  tab  In  this  tab,  the  user  can  add  a  new  contact  to  its  list.  

This  can  be  done  by  writing  the  other  user’s  email  

and  sending  the  request.  Its  main  components  are:  

A. Tabhost  manager:  Used  by  the  user  in  order  

to  switch  tabs.  

B. Text   field:   In   this   field,   the   user   will   write  

the  email  of  the  user  that  will  be  added.  

C. Add   contact   button:   Once   this   button   is  

pressed,  the  request  will  be  sent.  

 

 

3.4. Android  application  tasks  The  Android  application  is  the  interface  in  which  a  user  can  interact  with  other  

users  and  manage  its  own  account  in  SafeTime.  The  application  is  designed  so  it  

has  two  simultaneous  running  threads:  

o Main   thread:   This   thread   is   the   one   that   can  be   visualized  by   the  user  

and  hence  can  interact  with  it.  Here  is  were  the  user  can  use  the  screens  

shown   in   the   last   chapter  which   consists   on   the  main   functionalities   of  

the   app.   A   number   of   Android   simultaneous   tasks,   called  Asynctasks[9]  

are  executed  for  various  purposes  like  sending  text  and  image  messages,  

sending   contact   requests,   encrypting/   decrypting   processes,   login   task  

and   registration   task  which  will  be   running   in   the  background  until   the  

task  at  hand  is  done.  

o Listening   thread:   This   thread   is   always   running   in   the  background.   Its  

main   purpose   is   to   scan   for   a   socket   connection   with   the   server,  

whenever   a   connection   is   established   between   the   application   and   the  

server,   this   thread  gets   in   charge  of  managing  upcoming   tasks   from   the  

server  and  if  needed,  send  tasks  to  the  server  (messages  or  requests).  

 

Figure  12:  Add  contacts  tab  

 

 17  

3.5. Server  tasks  The  server  can  be  considered  the  “manager”  of  the  information  flowing  between  

users   of   SafeTime.   It  will   receive   every   request   or  message   from   the   different  

users  and  either  process   it  or  resend   it  depending  on  the  situation.   In  order  to  

manage  all   this  different   tasks,  7  different   threads  were  developed  and   can  be  

seen  in  the  Appendix  A.  These  threads  are  the  following:  

o socketServer:  This  is  the  main  thread,  it  will  manage  messages  between  

users  and  contact  requests.  This  task  will  loop  infinitely  creating  a  socket  

connection  with  the  ports  assigned  to  the  users,  this  way,  it  can  listen  and  

send  information  to  the  user  with  which  is  connected  at  its  turn.  When  a  

message  or  contact  request  is  received,  the  task  will  store  the  information  

received   into   a   “pending   task   stack”   which   will   be   read   every   time   it  

opens  a  new  connection  with  a  user,  at  that  moment  it  will  check  if  it  has  

something  to  send  to  that  particular  user  and  will  also  listen  to  that  user  

in  order  to  receive  new  information.  

o TimerThread:   The   port   scanning   done   by   the   “socketServer”   thread   is  

managed  by  time  in  case  that  it  finds  no  connection  with  a  user.  In  order  

to   do   so,   this   thread   is   executed   every   time   a   new   connection   is  

established  in  “socketServer”,  this  will  initialize  a  timer  that  will  serve  as  

a  process  timer,  when  the  timer  is  over,  a  signal  is  sent  to  the  main  thread  

so   it   can   terminate   the   actual   connection   and   proceed   to   scan   the   next  

port.  

o NewUserThread:   This   thread   keeps   a   socket   connection   open   at   port  

9003   so   that   any   application   that   sends   a   registration   request   can  

communicate   with   the   server.   This   task   will   receive   that   registration  

request  and  send  a  response  back  to  the  user  and  then  go  back  to  wait  for  

a  new  request.  

o LoginUserThread:  The  way   this   thread  works   is  about   the  same  as   the  

“NewUserThread”,   that   means,   it   will   wait   for   a   request,   when   it   is  

received,  it  is  solved,  send  a  response  back  to  the  app  and  return  to  wait  

 

 18  

for  a  new  request.  This  thread  will  manage  all  the  login  requests  on  port  

9001.  

o UpdateKeyThread:   When   a   user   logs   into   the   application   on   a   new  

device,  a  new  set  of  encryption  keys  need  to  be  generated.  This  thread  is  

the  one  in  charge  of  receiving  and  updating  in  the  database  the  new  key  

for  a  given  user.  

o TestThread:   This   thread   is   the   one   in   charge   of   receiving   the  message  

data  sent  from  users.  For  this  process,  the  “socketServer”  thread  receives  

the   command   from   the   application   to   receive   a   new  message   and   then,  

this   thread   will   be   ready   for   listening   and   store   the   message   into   the  

“pending  task  stack”.  

o SendMessageTask:   This   thread   will   send   a   message   stored   in   the  

“pending   task   stack”  and   send   it   to   its  destination.  For   this  process,   the  

“socketServer”  will  send  a  command  to  the  application  so  it  can  be  ready  

to  listen  to  this  thread  sending  a  given  message.  

 

4. Research  methods  4.1. Development  tools  

4.1.1. Android  studio  1.1.0  The   latest   version   of   Google’s   software   for   Android   developers.   Once  

installed,   developers   are   already   provided   with   the   Android   SDK   and  

therefore   ready   to   develop   new   applications.   Java   is   the   programming  

language   used   to   program   most   of   the   application,   since   the   graphic   user  

interface  is  programmed  in  xml.  

 

Testing  device  

To   test   the   application,   two   different   devices   are   used:   an   Android   virtual  

device  provided  by  the  Android  Studio  IDE  and  a  Samsung  Galaxy  S3  phone.  

The  specifications  for  both  devices  are:  

• Android  virtual  device  (AVD):  

 

 19  

o Running  Android  4.4  

o API  level  19  

o Adjustable  screen  

• Samsung  Galaxy  S3:  

o Running  Android  4.3.1  

o API  level  15  

o 4.8  inches  screen  

 

4.1.2. Linux  server  A  CPU  Linux  box  with  is  used  as  the  server  for  SafeTime.  This  computer  has  

the  following  specifications:  

o Operating  system:  Ubuntu  14.04  LTS  –  32-­‐bit  

o Memory:  3.9  GiB  

o Processor:  Intel  Core  2  Quad  CPU  !8400  @  2.66GHz  x  4  

o Disk:  134.9  GiB  

 

4.1.3. Eclipse  Mars  Eclipse   Mars   is   the   latest   version   of   the   Eclipse   integrated   development  

environment  (IDE).  This  is  a  computer  application  that  provide  programmers  

with   a   friendly   environment   to   develop   software   in   various   programming  

languages   [10].     This   IDE   is   widely   used   by   programmers   due   to   its  

practicality  and  the  number  of  tools  and  libraries  that  can  be  used  in  order  to  

develop   complex   projects.   For   SafeTime   project,   this   IDE   will   be   used   to  

develop   the   server   application.   For   this,   Eclise   Mars   linux   version   was  

downloaded  and  installed  using  the  Ubuntu  software  centre.  

 

4.1.4. MongoDB  MongoDB  is  an  open  source  document  database.  It’s  a  high  performance  and  

salable  database  that  lets  a  developer  create,  manage  and  develop  databases  

for   any   type   of   applications.   One   of   the   main   reasons   this   database   was  

 

 20  

chosen   to  be  used   for   this  application   is  because  of   its  practical   libraries   in  

Java.  With   a   few   simple   java   code   lines,   a  wide   range   of   commands   can  be  

done  such  as:  

o Initialize  MongoDB  client:  

MongoClient  mongo  =  null;    

mongo  =  new  MongoClient("localhost",  27017);  

o Get  or  create  a  new  database:  

//  if  database  doesn't  exists,  MongoDB  will  create  it  for  you    

DB  db  =  mongo.getDB("safetimedb");              

/****  Get  collection  /  table  from  'testdb'  ****/        

//  if  collection  doesn't  exists,  MongoDB  will  create  it  for  you    

  DBCollection  table  =  db.getCollection("users");  

o Create   search   queries   and   cursors   to   search   for   objects   in  

database:  

BasicDBObject  searchQuery  =  new  BasicDBObject();    

searchQuery.put("email",  toUser);  

DBCursor  cursor  =  table.find(searchQuery);  

 

4.1.5. TeamViewer  This  is  a  software  with  which  a  user  can  be  able  to  access  and  control  another  

computer   or   device   remotely.   In   order   to   do   so,   a   user   can   create   a   free  

account  and  register  their  different  devices  on  it  so  it  can  be  easily  connected  

at  any  given  time  by  selecting  the  device  from  the  “My  Computers”  list:  

 

 21  

 Figure  13:  TeamViewer  main  window  

Once  a  device  is  selected,  a  window  will  open  displaying  its  desktop:  

 Figure  14:  TeamViewer  shared  screen  window  

By  enabling   the   “Remote   control”   feature,   the  user   is   able   to   interact  with  

that  computer  and  all  its  components.  

 

4.2. Encryption  algorithm  implemented  Two   different   encryption   algorithms   were   considered   and   explained   for   this  

project,  AES  and  RSA  algorithms.  In  order  to  understand  them  an  get  to  test  their  

functionality,  both  were  developed  first   in  a  basic  way   in  C  code  (Appendix  D).  

 

 22  

Once  considering  the  programming  complexity  and  functionality  in  terms  of  the  

project’s  objectives,   it  was  concluded  that   the  RSA  algorithm  is   the  best  option  

for   encrypting  messages   in   this  proyect.  The   factors   taken   into   account   in   this  

consideration  were  the  following:  

o Programming  complexity:  Both  algorithms  were  developed  and  it  could  

be  concluded  that  AES  is,  by  not  too  far,  more  complex  to  develop.  AES  has  

in   fact   more   stages   to   follow   in   order   to   generate   the   key,   but   those  

individual  stages  are  not  so  difficult  to  program  and  can  be  executed  in  a  

loop.  RSA  is  simpler,  but   its  mathematical  calculations  are  more  complex  

and   a   library   called   “BigIntegers”   needed   to   be   imported   in   order   to   be  

able  to  handle  such  big  numbers.  This  was  not  a  crucial  factor  in  the  final  

consideration.  

o Key  management:  AES  algorithm  will  generate  a  key  of  128  bits  (or  192  

or  256  depending  on  the  complexity)  for  every  data  block  of  128  bits  [11],  

while   RSA   will   generate   two   bigger   keys   based   on   two   prime   numbers  

with   a   length   of   1024   that   can   cypher   a   block   of   up   to   256   bytes.   Since  

SafeTime   is  an   instant  messaging  application,  generating  a  key   for  every  

block  of  128  bits   (16  bytes)   that  has   to  be  sent  along  with   the  cyphered  

message  in  order  to  be  decrypted  represents  a  problem  in  terms  of  data  to  

be  sent,  since  practically  the  double  of  the  data  size  would  be  needed  to  be  

sent   (data+key),   which   means   data   consumption   for   the   user   and  

encryption/decryption  processing  times,  since  for  every  message  every  16  

byte  block  needed  to  be  encrypted  generating  the  key,  which  would  take  

considerable   amount   of   processing   time,   as   well   as   in   the   decryption  

processes.  On   the   other   side,  RSA  would   generate   at   the  moment   a   new  

user  registers  or   logs   in  a  new  set  of  keys  which  will  stay  the  same  until  

the   user   logs   into   another   device,   meaning   that   the   generation   process,  

which  does  takes  time  (about  1  second),  will  be  done  once,  from  then  on  

just   the   encryption   and   decryption   processes  will   be   done   every   time   a  

message  is  sent  or  received,  making  this  algorithm  more  practical  for  this  

application.  This  was  a  crucial  factor  in  the  final  consideration.  

 

 23  

o Data   block   size:   As   it  was  mentioned  before,  AES   cyphers   blocks   of   16  

bytes.  In  terms  of  plain  text  that  means  16  letters,  so  a  plain  text  message  

bigger  than  that  will  require  to  cypher  multiple  blocks  generating  multiple  

keys.  The  RSA  algorithm  considered  for  this  app  permits  to  cypher  a  data  

block  of  256  bytes  not  needing  to  generate  new  keys.  This  was  a  relevant  

factor  in  the  final  consideration.  

o Algorithm   security:  AES   is   the  actual  official  encryption  algorithm  used  

by  various  government  and  military  branches  around  the  world  including  

the   US   government   [12],   so   it   has   been   proven   as   the   most   robust  

encryption  algorithm  nowadays.  Still,  RSA  is  almost  as  secure  as  AES  or  at  

least,   in   terms   of   this   project,   more   than   enough   considering   that   an  

attempt  on  factoring  a  public  key  of  500  characters  in  order  to  figure  out  

the  private  key  could  take  4.2  x  1025  years  [8],  and  for  this  application,  a  

key   can   have   approximately   617   characters   depending   on   the   prime  

numbers.  

 

5. SafeTime  main  processes  5.1. Registration  process  Registration  is  the  process  in  which  a  user  will  be  able  to  activate  an  account  on  

SafeTime.  In  order  to  do  so,  a  form  will  have  to  be  filled  by  the  user;  pressing  the  

“Register”  button  in  the  application’s  main  screen  can  do  this.  

 

 

 24  

 Figure  15:  Login  to  Registration  flow  

 

This   form   has   to   be   filled   with   basic   information   about   the   user   in   the  

application:  

• Name:   it  will   be  used   to  display   the  name  of   the   registered  user   in   the  

contact  list  of  other  users  that  has  been  added.  

• Phone:  not  used  in  this  version  of  the  application,  it  is  asked  in  order  to  

be  able  to  be  used  in  future  versions  (scalability  of  the  application).  

• E-­‐mail:  is  the  main  id  of  the  user  used  for  internal  processing.  There  can  

only  be  one  user  per  email  address.  

• Password:  is  the  password  designated  by  the  user  in  order  to  be  able  to  

log  back  into  the  app  in  any  other  device.  

• Repeat   password:   it   is  used   to  confirm  that   the  password   typed   in   the  

“Password”  section  and  this  section  is  the  same  and  hence,  the  password  

the  user  intended  to  type.  

 

Validations:  

For  this  screen,  two  validations  were  developed  in  order  to  be  able  to  start  the  

registration  process  with  the  server.  The  first  validation  is  to  make  sure  that  all  

the   fields   on   the   form   are   filled,   if   this   condition   is   not   met,   a   toast   with   the  

message   “Fields   are  not   complete”  will   be   shown.  The   second  validation   is   for  

 

 25  

the  passwords,   if  both  password   fields  do  not  match,  a   toast  with   the  message  

“Passwords  does  not  match”  will  be  shown.  

 

Process:  

The  registration  process  will  require  a  communication  between  the  application  

and  the  server.  With  the  information  provided  by  the  application,  the  server  will  

register   the  new  user   in   the  database  and  assign  a  port  number   for   it  and  will  

send  it  back  to  the  user.  The  detailed  process  on  how  it  goes  is  the  following:  

1) Server:   The   “NewUserThread”,   which   is   the   registration   thread,   is   already  

running  in  the  server  with  a  socket  set  on  port  number  #9000.  

2) Application:  The  user   fills   the   registration   form  with  all   its  details   and   taps  

the  “Generate  keys  and  register”  button.  

3) Application:   The   form   is   checked   by   the   app   to   see   if   the   form   is   filled  

correctly,  if  not,  a  toast  is  shown  to  the  user  saying  what  is  the  problem  so  he  

can  correct  it.  

4) Application:   Once   the   information   is   correctly   filled,   the   RSA   keys   are  

generated.  

5) Application:   A   connection   is   established   with   the   server   by   initializing   a  

socket  in  the  port  #9000.  

6) Application:   A   string   array   “UserInfo”   with   the   user’s   information   and   the  

public  RSA  key  is  initialized  and  sent  through  a  socket  so  it  can  be  read  by  the  

server.  “UserInfo”  will  be  filled  with  the  following  information:  

 Table  2:  Registration  variables  

Variable   Description  

usrName   The  name  of  the  user.  

usrPhone   The  phone  number  of  the  user.  

usrEmail   The  email  of  the  user.  

usrPass   The  password  set  by  the  user.  

usrPKey   The  RSA  public  key  generated  for  the  user.  

 

 26  

 

7) Server:  The  server  successfully   receives   the   “UserInfo”  string  array   through  

the  socket.  

8) Server:  The  server  searches   in   it’s  database   for   the   “usrEmail”   to  check   if   it  

already  exists  and  will  assign  a  CODE  to  be  sent  to  the  application:  

 Table  3:  Registration  server  CODEs  

CODE   Description  

1   usrEmail  is  not  registered  

2   usrEmail  is  registered  

 

9) Server:  If  the  usrEmail  is  not  registered,  a  port  number  is  designated  to  that  

user,   this   port   is   assigned   sequentially   considering  what  was   the   last   port  

assigned   before   (i.e.   the   last   user   registered   port   was   #9005,   so   the   port  

assigned   to   this   user  will   be  #9006).   The  port   number   and   the  UserInfo   is  

then   inserted   to   the   “User   Info   Table”   in   the   server’s   database.   Finally   the  

port  number  and  the  CODE  are  sent  to  the  application  through  the  socket.  If  

the   usrEmail   is   already   registered,   only   the   CODE   will   be   sent   to   the  

application.  After  this,  the  server  returns  to  a  listening  state  waiting  for  other  

registration  request.  

10)  Application:  The  CODE  sent  by  the  server  is  received.  If  CODE  is  equal  to  “1”  

the  port  number  is  read  from  the  socket  and  added  to  the  “User  Info  Table”  in  

the  device’s  database  and  an  Intent  to  the  main  application  window  is  done.  

If  CODE  is  equal  to  “2”,  then  a  toast  with  the  text:  “Email  already  registered”  

is  displayed  in  the  screen  and  no  further  action  is  taken.  

 

Once   this   process   has   been   done   successfully,   the   new   registered   user   is   now  

able  to  use  SafeTime  application’s  functions  and  also  log  into  other  devices.  

 

 

 27  

 Figure  16:  Registration  flow  chart  

 

5.2. Login  process  Once   a   user   has   been   registered   in   the   server   and  hence   its   basic   information  

stored   in   the  server,   that  user  will  be  able   to   log   into  his  account  by  using   the  

email   address   provided   in   the   registration   process   and   the   password   also   set.  

 

 28  

The  server  will  be  in  charge  of  authenticate  the  user  comparing  that  information  

with  the  one  stored  in  its  database.  

 

Process:  

The   login  process  will  require  communication  between  the  application  and  the  

server.   For   this   task,   the   server   has   an   individual   thread   waiting   for   a   login  

request  at  all  times  in  a  socket  set  on  port  #9001.  The  process  in  which  a  user  in  

logging  into  its  account  is  the  following:  

1) Server:  The  “LoginThread”  which  is  the  thread  in  charge  of  the  login  requests,  

is  already  running  in  the  server  with  a  socket  set  at  the  port  #9001.  

2) Application:  The  user  fills  the  fields  shown  in  the  main  screen  of  the  SafeTime  

application:  

a. Username:  The  user’s   email   address  provided  during   the   registration  

process.  

b. Password:   The   user’s   password   provided   during   the   registration  

process.  

Once  the  information  is  written,  the  user  taps  the  “Login”  button.  

3) Application:   The   fields   are   checked  by   the   app   to  make   sure   they   are   filled  

correctly,  if  not,  a  toast  with  the  message  “Fields  are  not  complete”  is  shown.  

4) Application:  Once  the  form  is  correctly  filled,  a  connection  is  established  with  

the  server  by  initializing  a  socket  in  port  #9001.  

5) Application:   A   string   array   “LoginInfo”   is   initialized   with   the   basic  

information  needed  to  perform  the  login  task:  

 Table  4:  Login  variables  

Variable   Description  

usrName   The  email  of  the  user  intending  to  log  in.  

usrPass   The  password  corresponding  to  that  user.  

 

 

 29  

6) Server:  The  server  successfully  receives  “LoginInfo”  string  array  through  the  

socket.  

7) Server:   The   server   checks   on   its   database   for   the   user   with   the   email  

provided,  if  not  found,  the  user  will  be  notified  that  such  user  doesn’t  exist.  If  

found,   its  password  is  retrieved  and  compared  with  the  one  received  in  the  

socket.  If  the  passwords  match,  the  main  information  of  the  user  is  retrieved  

from  the  database  and   is  prepared  to  be  sent   to   the  application.  Depending  

on  the  scenario,  a  CODE  is  sent  to  the  application:  

 Table  5:  Login  server  CODEs  

CODE   Description  

1   usrName  is  not  registered.  

2   Correct  usrPass  for  usrName.  

3   Incorrect  usrPass  for  usrName.  

 

8) Server:  The  CODE  is  sent  to  the  application  through  the  socket.  If  the  usrPass  

matched   for   the   usrName,   the   information   already   retrieved   from   the  

database  is  also  sent  through  the  socket.  

9) Application:   The  CODE  sent  by   the   server   is   received   through   the   socket.   If  

the   CODE   is   “1”,   a   toast   displaying   the   message   “User   not   registered”   is  

shown.   If   the   CODE   signal   is   “3”,   a   toast   with   the   message   “Incorrect  

password”  is  displayed.  If  CODE  is  “2”,  then  the  user  information  also  sent  by  

the  server  is  received.  

10)  Application:   A  new  set   of  RSA  keys   is   generated  by   the   application.  This   is  

done  because,  since  the  previous  private  key  generated  at  the  registration  (or  

past  login)  is  already  erased  from  the  device’s  database.  Since  the  user  is  able  

to   login  at  any  device  with  SafeTime  app   installed,   this   is   the  way   in  which  

the   user   can   be   sure   that   encrypted   communication  will  work   only   in   one  

device,   since   the   private   key   is   never   shared   with   the   server   and   hence  

cannot  be  saved.  

 

 30  

11)  Application:   Once   the  new  keys   are   generated,   the  user   info   received   from  

the  server  and   the  keys  are  saved   into   the  “User   Info  Table”   in   the  device’s  

database.  

12)  Application:  The  public  key  generated   is  sent   to   the  server  using   the  active  

socket  and  an  Intent  to  the  main  application  window  is  done.  

13)  Server:  The  public  key  received  through  the  socket  is  used  to  update  the  key  

field  in  the  server’s  database  for  the  user  with  usrName.  After  this,  the  server  

returns  to  a  listening  state  waiting  for  other  login  request.  

 

Once  this  process  is  done  successfully,  the  user  will  be  logged  on  its  account  in  

the  SafeTime  app.  

 

 

 31  

 Figure  17:  Login  flow  chart  

 

 

5.3. Add  contact  process  This  process  is  the  one  that  actually  lets  a  user  add  another  user  to  his  contact  

list,   hence   allowing   communication   between   both   users.   For   this   version   of  

SafeTime  app,  only  the  email  of  a  user  is  needed  in  order  to  add  it  to  the  contacts  

 

 32  

list.   The   process   to   do   so   is   the   following,   given   the   case   in  which   a  User_1   is  

adding  User_2  to  his  contact  list:  

 

Process:  

1) App  User_1:  User_1  writes  User_2’s  email   in   the  available   field   in   the   “+Add  

Contact”  tab  and  taps  the  “Add  Contact”  button.  

2) App  User_1:   The   add   contact   task   is   added   to   the   “task   stack”  waiting   for   a  

“receiving”  signal  from  the  server.  

3) Server:  The  server’s  main  thread  is  scanning  the  user  ports  and  arrives  to  the  

User_1  port  turn.  

4) Server:  Given  the  case  that  in  its  own  task  stack  it  has  nothing  to  send  User_1,  

the   server   sends   a   “receiving”   signal   through   the   socket   initialized   on  

User_1’s  port  and  waits  for  a  response.  

5) App   User_1:   “receiving”   signal   is   detected   from   the   socket.   And   sends   a  

TaskID  of  “10”  back  to  the  server.  

6) App   User_1:   The   task   with   the   message   that   includes   the   following  

information  is  sent  to  the  server  through  an  active  socket  on  port  #9003:  

 Table  6:  Add  contact  variables  

Variable   Description  

usrToAdd   The  email  of  the  user  that  wants  to  be  added  (User_2).  

 

7) Server:  TaskID   of   “10”   is   received,   so   the   server   knows   that   a   message   is  

about   to   arrive.   The  TaskID’s  will   let   know   the   server  what   kind   of   task   is  

about  to  receive:  Table  7:  Add  contact  TaskIDs  

TaskID   Description  

10   Add  contact  task.  

11   Message  task.  

 

 

 33  

 

8) Server:  Listens   to   the   “AddContactTask”   that  has  a  socket   initialized   in  port  

#9003  and  receives  the  “usrToAdd”  sent  by  User_1.  

9) Server:   It   searches   for   “usrToAdd”  email   in   the   “Users”   table   in   the  server’s  

database.   If   the  user   is  not   found,  a  CODE  will  be  sent   to   the  user  notifying  

that   the   user   does   not   exist.   If   it   is   actually   found,   then   a   different   CODE  

confirming  the  existence  of  the  user  is  sent:  

 Table  8:  Add  contact  server  CODEs  

CODE   Description  

1   User  exists  

2   User  not  found  

 

10)  Server:  CODE  signal  is  sent  to  User_1.  If  the  user  was  found,  the  information  

about  that  user  (in  this  case  User_2)  is  retrieved  from  the  server’s  database  

and  is  sent  to  User_1  through  the  port  #9003  socket.  

11)  Server:  Using  the  number  of  the  active  port  in  the  main  thread  (User_1’s  port  

in  this  case),  the  server  retrieves  the  information  of  the  User_1  and  creates  a  

new  task  to  send  the  User_1’s   information  to  User_2.  The   information  to  be  

sent  is  the  following:  Table  9:  Add  contact  server  variables  

Variable   Description  

11   TaskID  for  “Add  contacts”.  

usrName   Name  of  the  user  to  be  added  to  contact  list.  

usrEmail   Email  of  the  user  to  be  added  to  contact  list.  

usrKey   Public  key  of  the  user  to  be  added  to  contact  list.  

 

12)  App  User_1:  User_1  receives  the  CODE  signal.  If  its  value  is  a  “2”,  a  toast  with  

the  message  “User  not  found”  is  displayed  in  the  screen  and  no  further  action  

is  taken.  If  the  CODE  was  “1”,  then  the  User_2’s  info  is  read  from  the  socket.  

 

 34  

13)  App   User_1:   The   information   received   by   the   server   is   now   stored   in   the  

“contacts”  table  in  the  device’s  database.  

14)  App  User_1:  The  contact  list  window  is  refreshed.  

15)  Server:  The  server  scans  through  ports  until  it  reaches  User_2’s  port.  Since  it  

has   a   task   to   send   to   User_2,   it   sends   a   “listen”   signal   through   the   socket  

initialized  with  User_2’s  port  number.  

16)  App   User_2:   “ServerThread”   is   looping   until   it   receives   a   signal   from   the  

server.  In  this  case,  it  receives  a  “listen”  signal.  

17)  App  User_2:  Sends  “acknowledge”  signal  to  the  server.  

18)  Server:   Once   received   the   “acknowledge”   signal,   the   server   sends   the  

User_1’s  info  task  to  User_2.  

19)  App  User_2:   User_1’s   info   is   received   from   the   server   and   is   stored   in   the  

“contacts”  table  in  the  device’s  database.  

20)  App  User_2:  The  contact  list  window  is  refreshed.  

 

Is  important  to  point  out  that  in  this  version  of  SafeTime,  when  User_1  requests  

to   add   User_2   to   its   contact   list,   the   server   will   provide   User_1   with   User_2’s  

information  and  at  the  same  time  will  provide  User_2  with  User_1’s  information  

in  order  to  achieve  communitation  between  both  users.  

 

 

 35  

 Figure  18:  Add  contact  flow  diagram  

 

 

5.4. Encryption  process  Encryption   is   the   core   and  most   important   part   of   SafeTime   application   (with  

Decryption).  This  process  is  the  responsible  of  using  the  RSA  public  key  assigned  

to  the  user  to  whom  the  message  is  going  to  be  sent  to  cypher  it  and  therefore  

protect  it  from  potential  intruders  or  sniffers  trying  to  read  them.  There  are  two  

possible   types   of   messages   developed   for   SafeTime,   plain   text   or   images.   For  

 

 36  

both  cases  the  main  process  of  encryption  is  the  same,  but  the  way  in  which  the  

size  of  the  data  is  treated  is  different.  Given  that  the  amount  of  data  that  can  be  

encrypted  with  the  RSA  algorithm  is  256  bytes,   images  have  to  be  divided   into  

sets   of   bytes   in  order   to  be   able   to   encrypt   them  but   text  messages   (with  256  

characters   or   less)   can   be   encrypted   in   the   same   block.   Assuming   a   User_1   is  

sending  a  message  to  User_2,  the  process  to  do  so  is  the  following:  

 

Plain  text:  

1. User_1  writes  a  message  for  User_2  in  the  text  field  and  taps  “SEND”.  

2. The  string  is  read  from  the  text  field  and  is  converted  to  a  byte  array  by  

using  the  “getBytes()”  function  in  java.  

3. The  byte  array  obtained  is  used  to  initialize  a  new  BigInteger  “M”.  

4. By   using   “M”   and   the   public   key   of   User_2,   the   message   is   encrypted  

giving  as  a  result  the  cypher-­‐text  “C”.  

5. C   is   the   converted   to   a  byte   array  using   the   function   “toByteArray()”   in  

the  BigInteger  library.  

6. This  byte  array  is  now  ready  to  be  sent  to  the  SafeTime  server  and  hence,  

to  User_2.  

 

Image:  

1. User_1  selects  an  image  from  the  gallery  and  taps  “SEND  PICTURE”  in  the  

confirmation  window.  

2. The   image   is   taken   as   a  drawable,  which  will   be   converted   to   a  Bitmap  

“B”.  

3. B   is   then   compressed   in   a   JPEG   format   into   a   ByteArrayOutputStream  

“stream”.  

4. “stream”  is  now  converted  to  byte  array  “I”  by  using  the  “toByteArray()”  

function.  

5. Since  “I”  is  bigger  than  256,  the  whole  byte  array  is  divided  into  blocks  of  

255   bytes   (as   a   safe   size)   and   that   are   introduced   in   order   into   an  

ArrayList  “L”.  

 

 37  

6. Each  byte  array  goes  through  the  encryption  process  individually:  

6.1.  Byte  array  is  used  to  initialize  a  new  BigInteger  “M”.  

6.2. If   “M”   is  negative,   it   is  multiplied  by   -­‐1   in  order   to  make   it  positive  

and  a  sign  variable  “s”  is  set  to  “1”.  If  “M”  is  positive,  it  is  left  as  it  is  

and   the  sign  variable   “s”   is   set   to   “2”.  This   is  done  because   the  RSA  

algorithms  permits  encryption  on  numeric  values  greater   than  zero  

and   less   than   the   “N”  value  of   the  key.  The  sign  variable   “s”  will   let  

User_2   know   if   the   BigInteger   value   obtained   after   the   decryption  

process   is   supposed   to   be   positive   or   negative,   so   it   can   do   the  

calculations  necessary  to  make  the  value  be  the  same  as  it  was  before  

encryption.  

6.3. By  using  “M”  and  the  public  key  of  User_2,  M  is  encrypted  giving  as  a  

result  a  cypher-­‐section  “C”.  

6.4. “C”   is   then   converted   to   a   byte   array   using   the   function  

“toByteArray()”  in  the  BigInteger  library.  

6.5. A  byte  with  the  value  “s”  is  added  at  the  end  of  the  byte  array.  

6.6. This  byte  array  is  then  replaced  in  the  ArrayList.  

7. Once  every  byte  array  in  the  ArrayList  is  encrypted,  the  cyphered  image  

is  ready  to  be  sent  to  the  server  and  hence,  to  User_2.  

The  encrypted  message   is  now  ready   to  be  sent   to   the  server,   so   the   following  

task  ArrayList  is  added  to  the  tasks  queue  in  the  SafeTime  main  thread:  

 Table  10:  Encryption  task  ArrayList  

Field   Description  

“11”   Id  given  to  the  message  task.  

User_2  email   Email  of  the  user,  which  will  receive  the  

message.    

message   The  data  to  be  sent  to  the  receiving  user:  

• If  plain  text    -­‐>    byte  array.  

• If  Image                -­‐>    ArrayList  

 

 38  

 

 Figure  19:  Encryption  process  flow  diagram  

 

 

5.5. Decryption  process  Decryption  is  the  process  by  which  a  user  decrypts  the  cypher-­‐text  or  cyphered  

image  received  from  another  user.  This  message,  as  explained  in  the  encryption  

 

 39  

process,   can   be   either   plain   text   or   an   image.   The   type   can   be   identified  

depending  on  the  type  of  data  received,  a  byte  array   in  case  of  plain  text  or  an  

ArrayList  of  byte  arrays  in  case  of  an  image  and  both  types  are  treated  differenty  

due   to   the   amount   of   information   they   carry.   Continuing   with   the   scenario  

previously  explained  for  the  encryption  process,  a  User_2  is  receiving  a  message  

from  User_1:  

 

Plain  text:  

1. User_2  receives  a  cyphered  message  “M”  (byte  array)  from  the  server.  

2. A  BigInteger  “m”  is  initialized  with  the  byte  array  “M”.  

3. By  using  “m”  and  User_2’s  private  key,  the  message  is  decrypted  into  the  

BigInteger  number  “d”.  

4. “d”   is   now   converted   into   a   deciphered     byte   array   “D”   by   using   the  

“toByteArray()”  function  in  the  BigInteger  library.  

5. “D”   will   finally   be   used   to   initialize   a   new   String   that   will   be   the  

deciphered  message  as  the  User_1  wrote  it.  

6. The  conversation  window  with  User_1  is  now  refreshed.  

 

Image:  

1. User_2  receives  a  cyphered  message  “M”  (ArrayList)  from  the  server.  

2. Each   byte   array   in   the   ArrayList   goes   through   the   decryption   process  

individually:  

2.1. The   last  byte  of   the  byte  array   is   removed  and  set   into   the  variable  

“t”.   This   byte  will   determine  whether   the   BigInteger   obtained   after  

decryption  must  be  negative  or  not.  

2.2. A  BigInteger  “m”  is  initialized  using  the  rest  of  the  byte  array.  

2.3. By  using   “m”  and  User_2’s  private  key,   the  section   “m”   is  decrypted  

into  the  BigInteger  number  “D”.  

2.4. Depending  on  the  value  of  “t”,  “D”  will  change.  If  “t”  is  “1”,  then  “D”  is  

multiplied  by  -­‐1.  If  “t”  is  “2”,  then  “D”  is  left  as  it  is.  

 

 40  

2.5. “D”   is  now  converted   into  a  byte  array  by  using  the  “toByteArray()”  

function   in   the   BigInteger   library.   At   this   point,   in   some   cases,   the  

byte  array   results   to  be  1  byte   shorter   than  what   it   should  be   (254  

bytes   instead   of   255).   This   happens   because   at   the   encryption  

process  made  by  User_1,   the  byte  array  that  was  converted   into  the  

BigInteger  that  was  encrypted  started  with  a  0  as  it  first  byte,  which  

resulted   in   a   BigInteger   number   with   a   leading   zero,   which   is  

neglected  by  the  initialization.  So  in  order  to  compensate  for  it,  every  

time  a  byte  array  falls  short  by  a  byte,  a  ‘0’  byte  is  added  as  the  first  

value  of  the  byte  array.  

2.6. This  byte  array  is  the  replaced  in  the  ArrayList.  

3. Once  all  the  sections  has  been  decrypted,  all  byte  arrays  are  padded  one  

next   to   the   other   in   one   big   byte   array.   This   is   the   byte   array  

corresponding  to  the  image  sent  by  User_1.  

4. This  big  byte  array  is  used  to  initialize  a  drawable.  

5. The  conversation  window  with  User_1  is  now  refreshed.  

 

 

 41  

 Figure  20:  Decryption  flow  diagram  

 

 

5.6. Message  send/receive  process  Messaging   is   the   whole   point   of   SafeTime   app.   It   provides   a   communication  

between  two  users  of  the  application  in  a  secure  manner  by  using  each  other’s  

public  key  to  encrypt  and  their  own  private  key  to  decrypt  the  received  message.  

In  this  process,  the  server  works  as  a  conduit  for  the  two  users,  it  doesn’t  read  or  

 

 42  

stores   the  message   received,   but   just   resends   it   to   the   intended   user.   For   this  

process,   because   of   the  density   of   information   that   can  be   sent   (in   the   case   of  

images)  two  different  ports  were  assigned  in  order  to  let  the  server  receive  (port  

#8999)   and   send   (port   #8998)  messages.   The   only   task   of   these   threads   is   to  

receive   or   send   messages   from   and   to   the   applications,   this   way,   a   potential  

problem  regarding  saturation  of  ports  is  prevented.  

 

Process:  

This  process  describes  the  communication  between  two  users,  User_1  is  sending  

a  message  to  User_2  like  the  example  below:  

 

 Figure  21:  Message  send  flow  

 

1) App   User_1:   A   message   (text   or   image)   is   introduced   and   in   the   User_2  

conversation  window  and  the  “Send”  button  is  tapped.  

2) App  User_1:  The  message  goes  through  the  encryption  process  using  User_2’s  

public   key   and   a  message   task   is   added   to   the   “task   stack”   in   the   app   and  

waits   for   a   “receiving”   signal   from   the   server.   Also   the   sent   message   is  

displayed  on  the  conversation  window  with  User_2.  

3) Server:  The  server’s  main  thread  is  scanning  the  user  ports  and  arrives  to  the  

User_1  port  turn.  

 

 43  

4) Server:  Given  the  case  that  in  its  own  task  stack  it  has  nothing  to  send  User_1,  

the   server   sends   a   “receiving”   signal   through   the   socket   initialized   on  

User_1’s  port  and  waits  for  a  response.  

5) App   User_1:   “receiving”   signal   is   detected   from   the   socket.   And   sends   a  

TaskID  of  “11”  back  to  the  server.  

6) App   User_1:   The   task   with   the   message   that   includes   the   following  

information  is  sent  to  the  server  through  an  active  socket  on  port  #8999:  Table  11:  Message  sending  task  variables  

Variable   Description  

“M”  or  “I”   The  type  of  message  that  will  be  sent:  

M:  text  message.  

I:  image.  

encMessage   The  encrypted  message  to  be  sent.  

toUser   The  email  of  the  user  to  whom  the  message  is  destined  (User_2).  

fromUser   The  email  of  the  user  that  sends  the  message  (User_1)  

 

7) Server:  TaskID   of   “11”   is   received,   so   the   server   knows   that   a   message   is  

about   to   arrive.   The  TaskID’s  will   let   know   the   server  what   kind   of   task   is  

about  to  receive:  Table  12:  Messaging  server  TaskID  

TaskID   Description  

10   Add  contact  task.  

11   Message  task.  

 

8) Server:   The   message   task   is   received   through   the   “receiveMessageTask”  

initialized   in   port  #8999   and   a   new   server  message   task   is   initialized  with  

the   port   number   of   the   User_2.   That   information   is   retrieved   from   the  

server’s  database.  Then  the  server  returns  to  the  “scanning  ports”  loop.  

 

 44  

9) Server:   The   server   arrives   the   port   number   of  User_2.   It   finds   that   there   is  

one   pending   task   for   User_2   and   sends   through   the   socket   initialized  with  

User-­‐2’s  port  number  a  “listening”  signal.  

10) App  User_2:   User_2   is   constantly   scanning   its   port   for   an   active   connection  

with  the  server.  If  a  connection  is  not  found,  it  keeps  looping.  If  a  connection  

is  found,  it  reads  the  signal  sent  by  the  server:  Table  13:  Message  receiving  task  variables  

Signal   Description  

“1”   “listening”  signal,  the  server  will  send  data  to  the  application  and  it  

must  be  ready  to  receive  it.  

“2”   “receiving”  signal,   the  server  has  nothing   to  send  and  will  wait   for  

the  application  to  send  a  task  if  there  is  one.  

No  signal   Nothing  happens,  the  server  will  continue  scanning  ports.  

 

11)  App   User_2:   “listening”   signal   is   received   from   the   server.   Initialized  

connection   with   socket   in   port   #8998   and   sends   an   “acknowledgement”  

signal  to  the  server  through  the  socket  initialized  with  User_2’s  port.  

12)  Server:   “acknowledgement”   signal   is   received   from  User_2.  Now   the   server  

will   start   transmitting   the   message   through   the   “sendMessageThread”  

initialized  in  port  #8998.  

13)  App   User_2:   Message   is   received   from   the   server   through   the   socket  

previously  initialized  in  port  #8998  with  the  information  of  from  whom  the  

message  was  sent  (User_1)  and  the  type  (image  or  plain  text).  

14)  App  User_2:  The  message  goes  through  the  decryption  process  using  User_2’s  

private  key.  

15)  App  User_2:  The  decrypted  message  is  displayed  in  the  conversation  window  

with  User_1.  

 

 

 45  

 Figure  22:  Message  send/receive  flow  diagram  

 

 

6. SafeTime  tests  A  number  of  tests  were  made  in  order  to  ensure  the  functionality  of  the  application.  

Some  of  them  to  test  the  RSA  algorithm  for  encryption  and  decryption,  some  for  the  

fragmentation  and  rebuild  of  images  and  others  for  communication.  

 6.1. Test  1:  Key  generation,  Encryption  and  Decryption  

 

 46  

For   this   application,   RSA   keys   must   be   generated   in   order   to   ensure   secure  

communication  as  well  as   the  encryption  and  decryption  processes.  One  of   the  

most  notorious   concerns   is   the   time   it   takes   to  generate   such  keys,   encrypting  

and  decrypting  messages,  so  in  order  to  figure  that  out,  the  following  code  was  

used  to  generate  both  public  and  private  keys:  //Generate  a  random  number  and  look  for  two  prime  numbers  of  "bitlength"  size                  r  =  new  Random();                  firstPrime  =  BigInteger.probablePrime(bitlength,  r);                  secondPrime  =  BigInteger.probablePrime(bitlength,  r);                    //First  we  need  to  obtain  the  number  N  =  firstPrime*secondPrime                  N  =  firstPrime.multiply(secondPrime);                    //use  Euler  totient  function  to  obtain  phi  (phi(N))                  BigInteger  phi  =  N.subtract(firstPrime.add(secondPrime).subtract(BigInteger.ONE));                    //Obtain  a  prime  number  between  0  and  N  (should  be  coprime  with  phi)                  e  =  BigInteger.probablePrime(bitlength/2,  r);                    //Making  sure  that  e  is  coprime  with  N                  while  (phi.gcd(e).compareTo(BigInteger.ONE)  >  0  &&  e.compareTo(phi)  <  0  )  {                          e.add(BigInteger.ONE);                  }                    //Obtain  the  private  key  by  calculating  e  inverse  module  of  phi                  d  =  e.modInverse(phi);                    System.out.println("Finish  key  generation");                  keys[0]  =  N;                  keys[1]  =  e;                  keys[2]  =  d;    

This  keys  were  obtained  by  generating   two  prime  numbers  with  a  bitlength  of  

1024.  

Encryption  of  a  standard  message  of  a  size  of  256  or  less  bytes  is  done  with  the  

following  code:  public  byte[]  messageEncryption(byte[]  M){                  BigInteger  N  =  new  BigInteger(key.split("-­‐")[0]);                  BigInteger  e  =  new  BigInteger(key.split("-­‐")[1]);                    BigInteger  encryptedMsg  =  new  BigInteger(M);                  if  (encryptedMsg.signum()  !=  1){                          encryptedMsg  =  encryptedMsg.multiply(BigInteger.valueOf(-­‐1));                          encryptedMsg  =  encryptedMsg.modPow(e,  N);                          byte[]  encMsgBytestemp  =  encryptedMsg.toByteArray();                          byte[]  encMsgBytes  =  new  byte[encMsgBytestemp.length+1];                          for  (int  i  =  0;  i<encMsgBytes.length;  i++){                                  if  (i  ==  encMsgBytes.length-­‐1){                                          encMsgBytes[i]  =  (byte)1;                                  }else{  

 

 47  

                                       encMsgBytes[i]  =  encMsgBytestemp[i];                                  }                          }                          return  encMsgBytes;                  }else{                          encryptedMsg  =  encryptedMsg.modPow(e,  N);                          byte[]  encMsgBytestemp  =  encryptedMsg.toByteArray();                          byte[]  encMsgBytes  =  new  byte[encMsgBytestemp.length+1];                          for  (int  i  =  0;  i<encMsgBytes.length;  i++){                                  if  (i  ==  encMsgBytes.length-­‐1){                                          encMsgBytes[i]  =  (byte)2;                                  }else{                                          encMsgBytes[i]  =  encMsgBytestemp[i];                                  }                          }                          return  encMsgBytes;                  }    

Decryption  of  a  standard  message  of  256  bytes  or  less  is  done  with  the  following  

code:  public  byte[]  messageDecryption(byte[]  D){                  byte[]  msgToDecrypt  =  new  byte[D.length-­‐1];                  for  (int  i  =  0;  i<D.length-­‐1;  i++){                          msgToDecrypt[i]  =  D[i];                  }                  System.out.println(""+D[D.length-­‐1]);                  BigInteger  encryptedMsg  =  new  BigInteger(msgToDecrypt);                    encryptedMsg  =  encryptedMsg.modPow(d,  N);                    if  (D[D.length-­‐1]  ==  (byte)1){                          encryptedMsg  =  encryptedMsg.multiply(BigInteger.valueOf(-­‐1));                  }                    return  encryptedMsg.toByteArray();                  //return  (new  BigInteger(D)).modPow(d,  N).toByteArray();          }  

 

Result:   The   following   table   of   processing   times   was   obtained   by   running   this  

codes  on  the  Android  Studio  simulator:  

 Table  14:  RSA  processing  times  

Process   Processing  time  (seconds)  

Key  generation   0.252  

Encryption  process   0.008  

Decryption  process   0.018  

 

 

 48  

Given  the  results  on  this  table,  it  can  be  concluded  that  the  processes  are  done  in  

a  more  than  acceptable  time.  

 

6.2. Test  2:  TCP  socket  communication  In   order   to   establish   communication   between   the   android   application   and   the  

server,  TCP  sockets  were  developer.  So  communication  between  two  points  was  

tested,   this   was   done   by   programming   a   Server   socket   and   a   Client   socket   as  

follows:  

• Server  socket:  import java.io.*; import java.net.*; public class SOK_SERVER { public static void main(String[] args) throws Exception{ SOK_SERVER SERVER = new SOK_SERVER(); SERVER.run(); } public void run() throws Exception{ //create a ServerSocket for port 1500 ServerSocket srvrSocket = new ServerSocket(1500); //open socket connection Socket sock = srvrSocket.accept(); InputStreamReader IR = new InputStreamReader(sock.getInputStream()); BufferedReader BR = new BufferedReader(IR); //check for messages received from the socket String MESSAGE = BR.readLine(); System.out.println(MESSAGE); if(MESSAGE != null){ //if a message is received, print in console PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("MESSAGE recieved"); } } }  

 

• Client  socket:  import java.io.*; import java.net.*; public class SOK_CLIENT { public static void main(String[] args) throws Exception{ SOK_CLIENT CLIENT = new SOK_CLIENT(); CLIENT.run(); } public void run() throws Exception{ //create a socket for port 1500 at the Localhost Socket sock = new Socket("localhost", 1500); //print a message to be sent to the server PrintStream PS = new PrintStream(sock.getOutputStream()); PS.println("Hello! I am Client_1"); //initialize reading InputStreamReader IR = new InputStreamReader(sock.getInputStream()); BufferedReader BR = new BufferedReader(IR);

 

 49  

//look for messages that might be received by the server String MESSAGE = BR.readLine(); System.out.println(MESSAGE); } }  

 

Result:   communication   was   successful   as   shown   in   the   logs   presented   on  

console.  

• ServerSocket  console:  

 Figure  23:  ServerSocket  console  screen  

The  message  sent  by  the  Client  socket  was  received  by  the  server,  and  the  

server  sent  an  acknowledgment  message.  

• ClientSocket   console:  

 Figure  24:  ClientSocket  console  screen  

Client   sent   the  message   “Hello!   I   am   Client_1”,   the   server   received   the  

message  and  sent  a  message  “MESSAGE  received”  in  response.  6.3. Test  3:  Encryption  and  decryption  of  text  with  one  set  of  

keys  This  test  consists  on  generating  a  set  of  keys  using  the  RSA  algorithm  in  order  to  

test   its   actual   functionality.   First   the   RSA   keys   “A”   in   the   Appendix   C   were  

generated.  

Now,  using  the  public  key  A,  the  message  “hello  bruce”  written  by  a  user  will  be  

encrypted  and  sent  to  the  server:  

 

 50  

 Figure  25:    Sender  text  message  

 

The  cyphered  message  received  by  the  server  represents  a  lot  of  characters  that  

makes  no  sense  as  shown  in  this  print  from  the  server’s  console:  

 Figure  26:  Server  log  when  a  text  message  is  received  

 

Here,  the  information  about  the  sender  and  recipient  can  be  seen  as  well  as  the  

cyphered  message,   at   the   end   of   this   print,   it   can   be   seen   that   the  message   is  

being   sent   to   the   recipient,   who   will   receive   the   message   and   will   decrypt   it  

using  the  private  key  A.  

 

 51  

 Figure  27:  Received  decrypted  text  message  

 

Result:  The  message  encrypted  is  received  by  the  other  user  and  is  successfully  

decrypted  so   it  can  be  readable  again,   this  works  well  because  the  pair  of  keys  

generated  are  the  ones  that  are  used,  that  means,  that  the  public  key  generated  

will  have  only  one  way  to  decrypt  which  is  the  private  key.  

 

6.4. Test   4:   Encryption   and   decryption   of   text   with   two  

different  set  of  keys  This   test   is  done   in   just   about   the   same  way   the   last  one   is  done,  but   its  main  

objective   is   to   show  what  will   happen   if   a  message   encrypted  with   one  public  

key  is  tried  to  be  decrypted  with  a  private  key  not  corresponding  to  it.  For  this,  

two  different  set  of  keys  in  the  Appendix  C  are  used.  

We   now   get   the   message   “hello   bruce”   just   like   it   was   done   in   Test   1.   The  

message  is  then  encrypted  using  the  Public  key  A  and  is  sent  to  the  server  and  

later  on  is  received  by  the  other  user.  At  this  point,  instead  of  using  the  Private  

key  A,  which  is  the  one  corresponding  to  the  public  key  used,  Private  key  B  will  

be  used  for  decryption  and  the  result  is  the  following:  

 

 52  

 Figure  28:  Received  decrypted  message  with  wrong  key  

 

Result:   As   it   can   be   seen,   the   message   was   not   successfully   decrypted.   This  

happens  because  the  both  public  and  private  keys  must  be  generated  in  the  same  

process   using   the   same   prime   numbers,   if   this   is   not   done   this   way   the  

calculation   done   at   the   decryption   process   will   return   a   wrong   number   and  

hence  a  wrong  set  of  bytes  that  will  end  up  in  a  group  of  characters  that  make  no  

sense  as  it  can  be  seen  in  Figure  28.  

 

6.5. Test   5:   Encryption   and   decryption   of   images  with   one  

set  of  keys  The   objective   of   this   test   is   to   show   the   functionality   of   the   image   encryption  

process.   For   this,   the   same   set  of   keys   in  Test  1   is   going   to  be  used.  Using   the  

public  key,  the  image  chosen  to  be  sent  is  encrypted  and  sent  to  the  server:  

 

 53  

 Figure  29:  Sender  image  message  

Since  is  an  image,  a  number  of  different  encrypted  blocks  of  255  bytes  are  going  

to  be  sent  to  the  server  in  order  to  be  sent  to  the  receiving  user.    

 

 Figure  30:  Server  log,  receiving  image  

Once   the   end   user   receives   those   packets,   they   go   through   the   decryption  

process  using  the  private  key  and  reassemble  of  the  image  to  finally  display  it  on  

the  conversation  window:  

 

 54  

 Figure  31:  Received  image  message  

Result:  The  image  sent  by  the  sending  user  was  received  successfully  by  the  end  

user,   which   means   that   both   processes   of   encryption   and   decryption   worked  

perfectly.   Also   the   process   of   segmentation   and   reassemble   of   the   image   was  

successful.  

 

6.6. Test   6:   Encryption   and   decryption   of   images  with   two  

different  set  of  keys  Using  the  two  set  of  keys  in  Test  2,  the  same  process  as  in  Test  3  is  repeated,  but  

this   time   the   encryption  process   is   done  with   the  public   key  A  by   the   sending  

user  and  is  later  decrypted  by  the  end  user  using  the  private  key  B:  

 

 55  

 Figure  32:  Received  corrupted  image  

Result:   The   blank   space   at   the   bottom   of   the   list   in   Figure   31   shows   that   the  

image  was  not  successfully  displayed.  This  happened  because  at  the  moment  of  

decryption  a  private  key  not  corresponding  to  the  public  key  used  for  encryption  

was   used.   Because   of   that,   the   correct   pattern   of   bytes   for   the   image   at   the  

process   of   reassemble   was   not   obtained;   hence   the   drawable   could   not   be  

assembled  and  resulted  in  a  corrupted  file.  

 

7. Discussion  7.1. Achievements  of  SafeTime  At   the   beginning   of   this   project,   encryption   of   just   plain   text   messages   was  

considered.  Since  that  task  could  be  completed  promptly,  the  idea  of  encrypting  

files  like  images  was  considered.  Since  an  image  was  a  type  of  file  that  could  be  

considered  a  little  more  complex  than  text  files,  this  became  the  goal  from  then  

on.   After   some   time   working   on   the   processes   to   encrypt/decrypt   images  

explained  previously,   this  could  be  achieved  proving   that  encryption  of   images  

using  RSA  algorithm  based  on  the  fragmentation  of  an  image  was  possible.  This  

proves  that  also  files  can  be  encrypted  and  sent  in  a  secure  way  to  other  peers  

guaranteeing  confidentiality  of  files  while  they  are  transmitted.  

 

 56  

Also,   with   the   success   of   this   application,   it   could   be   demonstrated   that  

encrypted  communication  can  be  fast  and  not  much  heavier  in  terms  of  data  size  

than  conventional   communication  which  will  be  appealing   for   the  actual   cyber  

security  concerns  [13].  

 

7.2. Limitations  and  upgrades  In   this   version   of   SafeTime,   some   limitations   have   been   detected   in   terms   of  

communication,  development  and  design:  

o Amount   of   users   supported:   Because   of   its   port   based   socket  

communication,  SafeTime’s  server  has  a  limited  number  of  ports  for  its  ip  

address.   For   TCP   communication,   the   ports   in   a   range   from   32768   to  

65535  are  the  ones  considered  as  “Ephemeral  ports”  which  are  the  ports  

typically  used  for  client  communication.  This  port  connections  are  short  

lived  and  will   exist  as   long  as   the  client  needs   its   service   [14].  This  will  

leave  SafeTime  with  a  maximum  capacity  32,767  users.  

This  can  be  upgraded  by  changing  the  socket  communication  model  for  a  

more  scalable  model   that  can  permit  an  exponentially  bigger  amount  of  

users   to  register  and  send  requests  and  messages   to   the  server  without  

depending  on  a  single  port  connection.  

o Data  size:  Socket  communication  can  get  saturated  due  to  the  amount  of  

information  that  is  being  sent.  In  case  of  images,  which  are  substantially  

bigger   than   plain   text,   saturation   of   ports   in   the   middle   of   the  

transmission  is  possible,  truncating  communication  and  making  possible  

the  lost  of  data.  

This   can   be   fixed   with   the   same   solution   as   the   last   point,   by   using  

another  communication  model.  

o Limitation  of   file   types:  At   the  moment,   the  app  can  send  plain   text  and  

image  messages,  but  with  the  code  already  developed,  inclusion  of  other  

file  types  such  as  .txt,  .doc  or  even  .pdf  can  be  possible  in  a  way  similar  as  

the   images.   With   this   same   principle,   but   with   more   complex   features  

 

 57  

developed   in  Android,   encrypted  half  duplex  communication   [15]  might  

be  possible.  Full  duplex  would  be  less  likely  due  to  the  processing  times  

for   encrypting   data   which   will   not   permit   a   real   simultaneous  

communication.  

o Application   design:   A   more   user   friendly   design   of   the   app   with   more  

appealing  user  interface  can  be  done  with  more  time  of  development.  

 

7.3. SafeTime’s  use  for  industry  Companies  managing   and  working   on  projects   that   are   competing  with   others  

and  need  to  maintain  a  secure  communication  between  its  developers,  managers  

and   executives   in   order   to   prevent   a   potential   intruder   trying   to   read   their  

messages   while   they   are   being   transmitted   by   using   a   sniffer.   With   a   system  

using   the   same   type   of   communication   as   SafeTime   the   packages   read   by   this  

hypothetical  intruder  will  be  of  no  use  because  of  the  way  its  encrypted.  This  can  

ensure  full  disclosure  of  the  project  in  terms  of  internal  communication.  

 

Many   industries   today   are   getting   more   concerned   on   their   communication  

security.   For   example,   due   to   the   increasing   digitalization   of   aviation   systems  

because   of   the   “More   electric   aircraft   [16]”   tendency   and   the   centralization   of  

information   and   control   with   the   FMS   (Flight   management   system),   very  

sensitive   information   about   flights   is   transmitted   from   the   airplane   to   other  

peers   such   as   the   engine   providers,   airplane   assemblers   or   airline   companies.  

This   communications   can   be   vulnerable   without   the   proper   security   in   their  

transmissions,  this  can  be  managed  with  a  model  like  the  one  used  for  SafeTime  

which  can  be  fast  enough.  

 

8. Conclusions  Developing  SafeTime  application  turned  out   to  be  as  complex  as  was  expected.  

Instant  messaging  represents  a  difficulty  while  developing  because  of  the  speed  

at   which   messages   are   expected   to   arrive,   and   that   expectation   has   been  

 

 58  

guarantied   within   its   limitations.   Cyber   security   has   been   one   of   the   most  

important   topics   lately   regarding   digitalization   of   information,   many   scandals  

regarding   this   can   be   seen   more   and   more   in   the   media   this   past   few   years.  

Whether   it   is   in  how  the  information  is  stored,  or  how  is  transmitted  and  even  

on  how  easy   can  be   for   a   skilled  hacker   to   access   remotely   to   systems   and  be  

able  to  obtain  confidential  information,  work  in  this  field  concerning  security  has  

been   increasing.   The   main   purpose   of   developing   this   application   is   to  

demonstrate   how   encryption   algorithms   (in   this   case   RSA)   can   be   used   in  

something  as  delicate  as  the  transmission  of  data.  It  could  be  demonstrated  that  

various  types  of  files  can  be  encrypted  in  a  relatively  fast  way  and  be  transmitted  

without  the  fear  of  getting  that  information  stolen  since,  while  been  transmitted,  

it   is   actually   nonsense  without   a   private   key   to   decrypt   it.   I   believe   this   same  

model   can   be   used   in   other   security   sensitive   systems   based   on   the   model  

described   in   this  paper.  For   this  purpose   I’ve   taken  as  one  of  my  examples   the  

digital  security  in  actual  civil  aviation,  which  is  known  for  its  flight  management  

systems  that   function  as  a  central  computer  controlling  the  airplane,  managing  

transmissions   and   sending   signals   to   actuators.   In   April   2015,   a   professional  

security  researcher  managed  to  hack  an  airplane  inflight  in  the  United  States  and  

was  able  to  modify  its  flight  path  slightly  of  course  [17].  The  fact  that  this  could  

be  done   indicates  how  vulnerable   these   systems  actually   are.   I   believe   that   by  

using  encrypted  commands  transmitted  to  the  systems,  this  kind  of  issues  can  be  

prevented  and  hence  guarantee  more  inflight  security  considering  the  estimated  

times  for  breaking  RSA  keys  is  substantially  less  than  the  time  an  airplane  stays  

in  the  air.  

This  is   just  an  example  of  how  a  model  like  the  one  used  on  SafeTime  can  help  

enhance   security   not   only   in   the   aviation   industry,   but   also   in   any   other   that  

depends  on  digital  technologies  management  systems.    

 

 

 

 

 59  

9. Bibliography  

[1]   J.  Pindar  and  J.  Rigelsford,  “Cybersecurity  and  Information  Assurance,”  2011.  

[2]   “Top  Apps  –  Android  Apps  on  Google  Play.”  [Online].  Available:  https://play.google.com/store/apps/collection/topselling_free?hl=en_GB.  [Accessed:  30-­‐Apr-­‐2015].  

[3]   M.  Mannan  and  P.  C.  Van  Oorschot,  “Secure  Public  Instant  Messaging :  A  Survey,”  Proc.  2nd  Annu.  Conf.  Privacy,  Secur.  Trust.,  pp.  69–77,  2004.  

[4]   M.  L.  Murphy,  Beginning  Android.  New  York,  2009.  

[5]   M.  Xue  and  C.  Zhu,  “The  socket  programming  and  software  design  for  communication  based  on  client/server,”  Proc.  2009  Pacific-­‐Asia  Conf.  Circuits,  Commun.  Syst.  PACCS  2009,  pp.  775–777,  2009.  

[6]   K.  L.  Calvert,  “TCP  /  IP  Sockets  in  C :  Practical  Guide  for  Programmers.”  

[7]   M.  Y.  Rhee,  Advanced  Encryption  Standard  and  Elliptic  Curve  Cryptosystems.  2009.  

[8]   E.  Milanov,  “The  RSA  Algorithm,”  no.  June,  pp.  1–11,  2009.  

[9]   A.  Porter,  “Programming  the  Android  Platform  -­‐  Threads,  Asynctasks  &  Handlers.”  [Online].  Available:  http://www.cs.umd.edu/class/fall2011/cmsc436/CMSC436/Lectures_Labs_files/ThreadsAndMessaging.pdf.  [Accessed:  21-­‐Aug-­‐2015].  

[10]   “Eclipse  Platform  Technical  Overview,”  2006.  

[11]   “Advanced  Encryption  Standard,”  National  Institute  of  Standards  and  Technology.  [Online].  Available:  http://csrc.nist.gov/publications/fips/fips197/fips-­‐197.pdf.  [Accessed:  22-­‐Aug-­‐2015].  

[12]   “National  Policy  on  the  Use  of  the  Advanced  Encryption  Standard  (AES)  to  Protect  National  Security  Systems  and  National  Security  Information,”  National  Institute  of  Standards  and  Technology.  [Online].  Available:  http://csrc.nist.gov/groups/ST/toolkit/documents/aes/CNSS15FS.pdf.  [Accessed:  22-­‐Aug-­‐2015].  

[13]   “Special  Eurobarometer  423  ‘Cyber  security,’”  European  Commission.  [Online].  Available:  http://ec.europa.eu/public_opinion/archives/ebs/ebs_423_en.pdf.  [Accessed:  22-­‐Aug-­‐2015].  

 

 60  

[14]   P.  Schneider,  “TCP/IP  Traffic  Classification  Based  on  Port  Numbers,”  Schneidergrinch,  pp.  2–7,  1992.  

[15]   “Simplex,  Half  Duplex,  Full  Duplex  Communication  Channel.”  [Online].  Available:  http://www.idc-­‐online.com/technical_references/pdfs/electronic_engineering/Simplex.pdf.  [Accessed:  22-­‐Aug-­‐2015].  

[16]   a  a  Abdelhafez  and  a  J.  Forsyth,  “A  Review  of  More-­‐Electric  Aircraft,”  Aerosp.  Sci.  Aviat.  Technol.,  pp.  1–13,  2009.  

[17]   M.  Hurley,  “Warrant  for  Chris  Robberts,”  pp.  1–22,  2015.    

 

 ii  

Appendix  A:  Application  codes    

Ø SplashScreenActivity.javapackage  com.example.ricardoviteri.safetimeapp;    import  android.content.Intent;  import  android.support.v7.app.ActionBarActivity;  import  android.os.Bundle;  import  android.view.Menu;  import  android.view.MenuItem;    import  java.util.ArrayList;      public  class  SplashScreenActivity  extends  ActionBarActivity  {            private  DBHelper  myDataBase;          public  ArrayList<String>  myUser;              @Override          protected  void  onCreate(Bundle  savedInstanceState)  {                  super.onCreate(savedInstanceState);                  setContentView(R.layout.activity_splash_screen);                  myDataBase  =  new  DBHelper(this);                  if  (myDataBase.numberOfRowsUser()  !=  0){                          /**  LOAD  THE  USER'S  INFO  AND  CONTACTS  **/                          Intent  intent  =  new  Intent(this,  ContactsTabActivity.class);                          startActivity(intent);                          this.finish();  

               }else{                          /**  RUN  SAFETIME'S  MAIN  LOGIN  WINDOW  **/                          Intent  intent  =  new  Intent(this,  LoginActivity.class);                          startActivity(intent);                          this.finish();                  }            }              @Override          public  boolean  onCreateOptionsMenu(Menu  menu)  {                  //  Inflate  the  menu;  this  adds  items  to  the  action  bar  if  it  is  present.                  getMenuInflater().inflate(R.menu.menu_splash_screen,  menu);                  return  true;          }            @Override          public  boolean  onOptionsItemSelected(MenuItem  item)  {                  int  id  =  item.getItemId();                    if  (id  ==  R.id.action_settings)  {                          return  true;                  }                    return  super.onOptionsItemSelected(item);          }  }  

 Ø DBHelper.java  

package  com.example.ricardoviteri.safetimeapp;    /**    *  Created  by  ricardoviteri  on  6/18/15.    */  import  java.util.ArrayList;  import  java.util.Arrays;  import  java.util.HashMap;  import  java.util.Hashtable;  import  android.content.ContentValues;  import  android.content.Context;  import  android.database.Cursor;  import  android.database.DatabaseUtils;  import  android.database.sqlite.SQLiteOpenHelper;  import  android.database.sqlite.SQLiteDatabase;    public  class  DBHelper  extends  SQLiteOpenHelper  {    

       public  static  final  String  DATABASE_NAME  =  "MyDBName.db";          /*******  CONTACTS  TABLE  ***********/          public  static  final  String  CONTACTS_TABLE_NAME  =  "contacts";          public  static  final  String  CONTACTS_COLUMN_ID  =  "id";          public  static  final  String  CONTACTS_COLUMN_NAME  =  "name";          public  static  final  String  CONTACTS_COLUMN_EMAIL  =  "email";          public  static  final  String  CONTACTS_COLUMN_KEY  =  "key";          /*********************************************/            /*******  USER  INFO  TABLE  ***********/          public  static  final  String  USER_TABLE_NAME  =  "user";          public  static  final  String  USER_COLUMN_ID  =  "id";          public  static  final  String  USER_COLUMN_NAME  =  "name";  

 

 iii  

       public  static  final  String  USER_COLUMN_PHONE  =  "phone";          public  static  final  String  USER_COLUMN_EMAIL  =  "email";          public  static  final  String  USER_COLUMN_PRIVATE  =  "privateKey";          public  static  final  String  USER_COLUMN_PUBLIC  =  "publicKey";          public  static  final  String  USER_COLUMN_PORT  =  "port";          /********************************************/            private  HashMap  hp;            public  DBHelper(Context  context)          {                  super(context,  DATABASE_NAME  ,  null,  1);          }            @Override          public  void  onCreate(SQLiteDatabase  db)  {                  //  TODO  Auto-­‐generated  method  stub                  db.execSQL(                                  "create  table  contacts  "  +                                                  "(id  integer  primary  key,  name  text,email  text,  key  text)"                  );                    db.execSQL(                                  "create  table  user  "  +                                                  "(id  integer  primary  key,  name  text,  phone  text,  email  text,  privateKey  text,  publicKey  text,  port  text)"                  );          }            @Override          public  void  onUpgrade(SQLiteDatabase  db,  int  oldVersion,  int  newVersion)  {                  //  TODO  Auto-­‐generated  method  stub                  db.execSQL("DROP  TABLE  IF  EXISTS  contacts");                  db.execSQL("DROP  TABLE  IF  EXISTS  user");                  onCreate(db);          }            /*********  CONTACTS  TABLE  **********/            public  boolean  insertContact    (String  name,  String  email,  String  key)          {                  SQLiteDatabase  db  =  this.getWritableDatabase();                  ContentValues  contentValues  =  new  ContentValues();                  contentValues.put("name",  name);                  contentValues.put("email",  email);                  contentValues.put("key",  key);                  db.insert("contacts",  null,  contentValues);                  return  true;          }            public  Cursor  getDataContact(String  name){                  SQLiteDatabase  db  =  this.getReadableDatabase();  

               Cursor  res  =    db.rawQuery(  "select  *  from  contacts  where  name="+name+"",  null  );                  System.out.println(res);                  return  res;          }            public  int  numberOfRowsContacts(){                  SQLiteDatabase  db  =  this.getReadableDatabase();                  int  numRows  =  (int)  DatabaseUtils.queryNumEntries(db,  CONTACTS_TABLE_NAME);                  return  numRows;          }            public  boolean  updateContact  (Integer  id,  String  name,  String  email,  String  key)          {                  SQLiteDatabase  db  =  this.getWritableDatabase();                  ContentValues  contentValues  =  new  ContentValues();                  contentValues.put("name",  name);                  contentValues.put("email",  email);                  contentValues.put("key",  key);                  db.update("contacts",  contentValues,  "id  =  ?  ",  new  String[]  {  Integer.toString(id)  }  );                  return  true;          }            public  Integer  deleteContact  (Integer  id)          {                  SQLiteDatabase  db  =  this.getWritableDatabase();                  return  db.delete("contacts",                                  "id  =  ?  ",                                  new  String[]  {  Integer.toString(id)  });          }            public  ArrayList<String>  getAllCotacts()          {                  ArrayList<String>  array_list  =  new  ArrayList<String>();                    //hp  =  new  HashMap();                  SQLiteDatabase  db  =  this.getReadableDatabase();                  Cursor  res  =    db.rawQuery(  "select  *  from  contacts",  null  );                  res.moveToFirst();                    while(res.isAfterLast()  ==  false){                          array_list.add(res.getString(res.getColumnIndex(CONTACTS_COLUMN_EMAIL)));                          res.moveToNext();                  }                  return  array_list;          }            public  ArrayList<String[]>  getAllCotactsWithInfo()          {                  ArrayList<String[]>  array_list  =  new  ArrayList<String[]>();                    //hp  =  new  HashMap();  

 

 iv  

               SQLiteDatabase  db  =  this.getReadableDatabase();                  Cursor  res  =    db.rawQuery(  "select  *  from  contacts",  null  );                  res.moveToFirst();                    while(res.isAfterLast()  ==  false){                          String[]  contact  =  new  String[4];                          contact[0]  =  res.getString(res.getColumnIndex(CONTACTS_COLUMN_ID));                          contact[1]  =  res.getString(res.getColumnIndex(CONTACTS_COLUMN_NAME));                          contact[2]  =  res.getString(res.getColumnIndex(CONTACTS_COLUMN_EMAIL));                          contact[3]  =  res.getString(res.getColumnIndex(CONTACTS_COLUMN_KEY));                            ArrayList<String>  cosa  =  new  ArrayList<String>(Arrays.asList(contact));                            array_list.add(contact);                          res.moveToNext();                  }                  return  array_list;          }            public  ArrayList<ArrayList<Object>>  getAllCotactsWithInfoAsList()          {                  ArrayList<ArrayList<Object>>  array_list  =  new  ArrayList<ArrayList<Object>>();                    //hp  =  new  HashMap();                  SQLiteDatabase  db  =  this.getReadableDatabase();                  Cursor  res  =    db.rawQuery(  "select  *  from  contacts",  null  );                  res.moveToFirst();                    while(res.isAfterLast()  ==  false){                          String[]  contact  =  new  String[4];                          contact[0]  =  res.getString(res.getColumnIndex(CONTACTS_COLUMN_ID));                          contact[1]  =  res.getString(res.getColumnIndex(CONTACTS_COLUMN_NAME));                          contact[2]  =  res.getString(res.getColumnIndex(CONTACTS_COLUMN_EMAIL));                          contact[3]  =  res.getString(res.getColumnIndex(CONTACTS_COLUMN_KEY));                            ArrayList<Object>  contactList  =  new  ArrayList<Object>(Arrays.asList(contact));                            array_list.add(contactList);                          res.moveToNext();                  }                  return  array_list;          }          /*********************************************/  

             /************  USER  INFO  TABLE  ***********/            public  boolean  insertUser    (String  name,  String  phone,  String  email,  String  privateKey,  String  publicKey,  String  port)          {                  SQLiteDatabase  db  =  this.getWritableDatabase();                  ContentValues  contentValues  =  new  ContentValues();                  contentValues.put("name",  name);                  contentValues.put("phone",  phone);                  contentValues.put("email",  email);                  contentValues.put("privateKey",  privateKey);                  contentValues.put("publicKey",  publicKey);                  contentValues.put("port",  port);                  db.insert("user",  null,  contentValues);                  return  true;          }            public  Cursor  getDataUser(int  id){                  SQLiteDatabase  db  =  this.getReadableDatabase();                  Cursor  res  =    db.rawQuery(  "select  *  from  user  where  id="+id+"",  null  );                  return  res;          }            public  int  numberOfRowsUser(){                  SQLiteDatabase  db  =  this.getReadableDatabase();                  int  numRows  =  (int)  DatabaseUtils.queryNumEntries(db,  USER_TABLE_NAME);                  return  numRows;          }            public  boolean  updateUser  (Integer  id,  String  name,  String  phone,  String  email,  String  privateKey,  String  publicKey,  String  port)          {                  SQLiteDatabase  db  =  this.getWritableDatabase();                  ContentValues  contentValues  =  new  ContentValues();                  contentValues.put("name",  name);                  contentValues.put("phone",  phone);                  contentValues.put("email",  email);                  contentValues.put("street",  privateKey);                  contentValues.put("place",  publicKey);                  db.update("user",  contentValues,  "id  =  ?  ",  new  String[]  {  Integer.toString(id)  }  );                  return  true;          }            public  Integer  deleteUser  (Integer  id)          {                  SQLiteDatabase  db  =  this.getWritableDatabase();                  return  db.delete("user",                                  "id  =  ?  ",                                  new  String[]  {  Integer.toString(id)  });          }    

 

 v  

       public  ArrayList<String>  getUser()          {                  ArrayList<String>  array_list  =  new  ArrayList<String>();                    //hp  =  new  HashMap();                  SQLiteDatabase  db  =  this.getReadableDatabase();                  Cursor  res  =    db.rawQuery(  "select  *  from  user",  null  );                  res.moveToFirst();                    array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_ID)));                  array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_NAME)));                  array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_PHONE)));  

               array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_EMAIL)));                  array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_PRIVATE)));                  array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_PUBLIC)));                  array_list.add(res.getString(res.getColumnIndex(USER_COLUMN_PORT)));                    return  array_list;          }          /********************************************/  }  

 Ø ContactsTabActivity.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.content.Intent;  import  android.net.Uri;  import  android.os.Bundle;  import  android.support.annotation.NonNull;  import  android.support.v4.app.FragmentActivity;  import  android.support.v4.app.FragmentTabHost;  import  android.util.AttributeSet;  import  android.view.View;  import  android.widget.Toast;    import  java.lang.reflect.Array;  import  java.math.BigInteger;  import  java.util.ArrayList;  import  java.util.Arrays;    /**    *  Created  by  ricardoviteri  on  7/2/15.    */    public  class  ContactsTabActivity  extends  FragmentActivity{            public  FragmentTabHost  mTabHost;          ArrayList<String[]>  contacts;          ArrayList<ArrayList<Object>>  contacts2;          ArrayList<ArrayList<Object>>  tasksToDo;          String  thisUser;          int  Port;          BigInteger  N,  d;            @Override          protected  void  onCreate(Bundle  savedInstanceState)  {                    super.onCreate(savedInstanceState);                  setContentView(R.layout.contacts_layout);                    DBHelper  db  =  new  DBHelper(this);  

               contacts  =  db.getAllCotactsWithInfo();                  contacts2  =  db.getAllCotactsWithInfoAsList();                  tasksToDo  =  new  ArrayList<ArrayList<Object>>();                  Port  =  Integer.parseInt(db.getUser().get(6));                    thisUser  =  db.getUser().get(3);                  N  =  new  BigInteger(db.getUser().get(4).split("-­‐")[0]);                  d  =  new  BigInteger(db.getUser().get(4).split("-­‐")[1]);                    mTabHost  =  (FragmentTabHost)findViewById(android.R.id.tabhost);                  mTabHost.setup(this,  getSupportFragmentManager(),  R.id.realtabcontent);                      mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Contacts"),                                  ContactListTab.class,  null);                  mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Conv."),                                  ConversationListTab.class,  null);                  mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator("+Add  contact"),                                  AddContactTab.class,  null);                  mTabHost.setCurrentTab(1);              }            @Override          protected  void  onStart()  {                  super.onStart();                  ServerThread  listeningThread  =  new  ServerThread(this,  thisUser);  

 

 vi  

               listeningThread.start();          }            @Override          public  void  onActivityResult(int  requestCode,  int  resultCode,  Intent  data)  {                  super.onActivityResult(requestCode,  resultCode,  data);                  System.out.println("In  Activity");                  ConversationListTab  activeConv  =  (ConversationListTab)this.getSupportFragmentManager().findFragmentByTag("tab2");                  Uri  selectedImageUri  =  data.getData();                  String  selectedImagePath  =  activeConv.getPath(selectedImageUri);                  activeConv.image.setImageURI(selectedImageUri);                  activeConv.layoutImage.setVisibility(View.VISIBLE);            }            public  void  switchTabTo(int  index){                  mTabHost.setCurrentTab(index);          }            public  void  openConversation(int  contact){                  ConversationListTab  activeConv  =  (ConversationListTab)this.getSupportFragmentManager().findFragmentByTag("tab2");                  activeConv.activeContact  =  contact;                  activeConv.key  =  (String)  contacts2.get(contact).get(3);                  mTabHost.setCurrentTab(1);          }            public  void  addContact(String[]  newContact){                  System.out.println(newContact[0]);                  System.out.println(newContact[1]);                  System.out.println(newContact[2]);                  DBHelper  db  =  new  DBHelper(this);                  db.insertContact(newContact[0],  newContact[1],  newContact[2]);                  refreshContacts();          }            public  void  contactNotFound(String  contact){                  Toast  toast  =  Toast.makeText(this,  "User  "+contact+"  not  found",  Toast.LENGTH_SHORT);                  toast.show();          }            public  void  refreshContacts(){                  DBHelper  db  =  new  DBHelper(this);                  contacts  =  db.getAllCotactsWithInfo();                  contacts2  =  db.getAllCotactsWithInfoAsList();          }            public  void  addToConversation(String  fromUser,  Object  message){                  int  contactsId  =  0;                  for  (int  i  =  0;  i  <  contacts.size();  i++){  

                       if  (contacts.get(i)[2].equals(fromUser)){                                  contactsId  =  i;                          }                  }                      ArrayList<Object>  userInfo  =  contacts2.get(contactsId);                    Object  info  =  null;                  if  (message  instanceof  byte[]){                          System.out.println("Actual  message:  "+new  String((byte[])message));                          System.out.println("Actual  fromUser:  "+fromUser);                            info  =  new  String[]{"1",  new  String(messageDecryption((byte[])  message))};                  }else{                          info  =  new  ArrayList<Object>();                          ((ArrayList)info).add("1");                          ((ArrayList)info).add(message);                  }                    ArrayList<Object>  savedConversation;                  if  (userInfo.size()  ==  4){                          savedConversation  =  new  ArrayList<Object>();                          savedConversation.add(info);                          contacts2.get(contactsId).add(savedConversation);                  }else{                          ((ArrayList<Object>)contacts2.get(contactsId).get(4)).add(info);                  }                  ConversationListTab  activeConv  =  (ConversationListTab)this.getSupportFragmentManager().findFragmentByTag("tab2");                    if  (contactsId  ==  activeConv.activeContact){                          activeConv.postNewMessage();                  }          }            public  byte[]  messageDecryption(byte[]  D){                  byte[]  msgToDecrypt  =  new  byte[D.length-­‐1];                  for  (int  i  =  0;  i<D.length-­‐1;  i++){                          msgToDecrypt[i]  =  D[i];                  }                  System.out.println(""+D[D.length-­‐1]);                  BigInteger  encryptedMsg  =  new  BigInteger(msgToDecrypt);                    encryptedMsg  =  encryptedMsg.modPow(d,  N);                    if  (D[D.length-­‐1]  ==  (byte)1){                          encryptedMsg  =  encryptedMsg.multiply(BigInteger.valueOf(-­‐1));                  }    

 

 vii  

               ConversationListTab  activeConv  =  (ConversationListTab)this.getSupportFragmentManager().findFragmentByTag("tab2");                    return  encryptedMsg.toByteArray();  

               //return  (new  BigInteger(D)).modPow(d,  N).toByteArray();          }  }  

 Ø ContactListTab.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.os.Bundle;  import  android.support.v4.app.Fragment;  import  android.view.LayoutInflater;  import  android.view.View;  import  android.view.ViewGroup;  import  android.widget.AdapterView;  import  android.widget.ListView;    import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/2/15.    */  public  class  ContactListTab  extends  Fragment  implements  AdapterView.OnItemClickListener{            ListView  contactList;            @Override          public  View  onCreateView(LayoutInflater  inflater,  ViewGroup  container,                                                            Bundle  savedInstanceState)  {  

               //  Inflate  the  layout  for  this  fragment                  View  V  =  inflater.inflate(R.layout.contact_list_tab,  container,  false);                    contactList  =  (ListView)V.findViewById(R.id.listView);                    ContactListAdapter  adapter  =  new  ContactListAdapter(this.getActivity(),  1,  ((ContactsTabActivity)this.getActivity()).contacts2.toArray());                  contactList.setAdapter(adapter);                  contactList.setOnItemClickListener(this);                  return  V;          }            @Override          public  void  onItemClick(AdapterView<?>  parent,  View  view,  int  position,  long  id)  {                  System.out.println(""+position);                  ((ContactsTabActivity)this.getActivity()).openConversation(position);          }  }  

 Ø ContactListAdapter.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.app.Fragment;  import  android.content.Context;  import  android.support.v4.app.FragmentActivity;  import  android.view.LayoutInflater;  import  android.view.View;  import  android.view.ViewGroup;  import  android.widget.ArrayAdapter;  import  android.widget.TextView;    import  java.util.ArrayList;  import  java.util.Objects;    /**    *  Created  by  ricardoviteri  on  7/19/15.    */  public  class  ContactListAdapter  extends  ArrayAdapter  {            Object[]  contacts;          Context  context;            public  ContactListAdapter(Context  ctx,  int  resource,  Object[]  objects)  {                  super(ctx,  resource,  objects);                  contacts  =  objects;  

               context  =  ctx;          }              @Override          public  View  getView(int  position,  View  convertView,  ViewGroup  parent)  {                    if(convertView==null){                          //  inflate  the  layout                          LayoutInflater  inflater  =  ((FragmentActivity)context).getLayoutInflater();                          convertView  =  inflater.inflate(R.layout.contact_cell,  parent,  false);                  }                    TextView  name  =  (TextView)convertView.findViewById(R.id.textView15);                  ArrayList  contact  =  (ArrayList)  contacts[position];                  name.setText(contact.get(1).toString());                      return  convertView;          }  }  

 

 

 8  

Ø ConversationListTab.java  package  com.example.ricardoviteri.safetimeapp;    import  android.content.Intent;  import  android.database.Cursor;  import  android.graphics.Bitmap;  import  android.graphics.drawable.BitmapDrawable;  import  android.graphics.drawable.Drawable;  import  android.net.Uri;  import  android.os.Bundle;  import  android.os.Parcelable;  import  android.provider.MediaStore;  import  android.support.v4.app.Fragment;  import  android.util.Log;  import  android.view.LayoutInflater;  import  android.view.View;  import  android.view.ViewGroup;  import  android.widget.Button;  import  android.widget.EditText;  import  android.widget.ImageView;  import  android.widget.ListView;  import  android.widget.RelativeLayout;  import  android.widget.TextView;  import  android.widget.Toast;    import  java.io.ByteArrayOutputStream;  import  java.io.IOException;  import  java.math.BigInteger;  import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/7/15.    */  public  class  ConversationListTab  extends  Fragment  implements  View.OnClickListener  {          int  activeContact  =  0;          TextView  txtUser;          EditText  message;          ListView  conversation;          Button  sendMessage,  loadImg,  sendImage;          ImageView  image;          RelativeLayout  layoutImage;          ArrayList<Object>  userInfo;          ArrayList<Object>  savedConversation;          String  key;            @Override          public  void  onCreate(Bundle  savedInstanceState)  {                  super.onCreate(savedInstanceState);                  System.out.println("Conversation  tab  "+activeContact);                  if  (((ContactsTabActivity)this.getActivity()).mTabHost  !=  null){                          ((ContactsTabActivity)this.getActivity()).switchTabTo(0);                  }          }            @Override          public  View  onCreateView(LayoutInflater  inflater,  ViewGroup  container,                                                            Bundle  savedInstanceState)  {                  //  Inflate  the  layout  for  this  fragment  

               View  V  =  inflater.inflate(R.layout.conversation_tab,  container,  false);                  txtUser  =  (TextView)V.findViewById(R.id.textView16);                  message  =  (EditText)V.findViewById(R.id.editText10);                  conversation  =  (ListView)V.findViewById(R.id.listView2);                  sendMessage  =  (Button)V.findViewById(R.id.button7);                  loadImg  =  (Button)V.findViewById(R.id.button8);                  sendImage  =  (Button)V.findViewById(R.id.button9);                  image  =  (ImageView)V.findViewById(R.id.imageView3);                  layoutImage  =  (RelativeLayout)V.findViewById(R.id.imageLayout);                    if((((ContactsTabActivity)this.getActivity()).contacts2).size()  !=  0){                          userInfo  =  ((ContactsTabActivity)this.getActivity()).contacts2.get(activeContact);                          key  =  (String)  userInfo.get(3);                          if  (userInfo.size()  ==  4){                                  savedConversation  =  new  ArrayList<Object>();                                  userInfo.add(savedConversation);                          }else{                                  savedConversation  =  (ArrayList<Object>)  userInfo.get(4);                          }                            txtUser.setText(userInfo.get(1).toString());                            sendMessage.setOnClickListener(this);                          loadImg.setOnClickListener(this);                          sendImage.setOnClickListener(this);                            ConversationAdapter  adapter  =  new  ConversationAdapter(this.getActivity(),  1,  savedConversation.toArray());                          conversation.setAdapter(adapter);                          conversation.setSelection(savedConversation.size()-­‐1);                  }else{                          txtUser.setText("No  contacts");                  }                          return  V;          }            @Override          public  void  onClick(View  v)  {                  switch  (v.getId()){                          case  R.id.button7:  

 

 ix  

                               if  (message.getText().toString().length()>0){                                          String[]  info  =  {"0",  message.getText().toString()};                                          ArrayList<Object>  task  =  new  ArrayList<Object>();                                          task.add("11");                                          task.add(userInfo.get(2));                                          task.add(messageEncryption((message.getText().toString()).getBytes()));                                          ((ContactsTabActivity)this.getActivity()).tasksToDo.add(task);                                          /*SOK_CLIENT_BASIC  cosa  =  new  SOK_CLIENT_BASIC((message.getText().toString()).getBytes());                                          try  {                                              cosa.run();                                          }  catch  (Exception  e)  {                                              e.printStackTrace();                                          }*/                                          savedConversation.add(info);                                          ConversationAdapter  adapter  =  new  ConversationAdapter(this.getActivity(),  1,  savedConversation.toArray());                                          conversation.setAdapter(adapter);                                          message.setText("");                                          conversation.setSelection(savedConversation.size()-­‐1);                                    }                                  break;                          case  R.id.button8:                                  Intent  intent  =  new  Intent();                                  intent.setType("image/*");                                  intent.setAction(Intent.ACTION_GET_CONTENT);                                  this.getActivity().startActivityForResult(Intent.createChooser(intent,"Select  Picture"),  101);                                  break;                          case  R.id.button9:                                  ArrayList<Object>  info  =  new  ArrayList<Object>();                                  info.add("0");                                  info.add(image.getDrawable());                                  savedConversation.add(info);                                  ConversationAdapter  adapter  =  new  ConversationAdapter(this.getActivity(),  1,  savedConversation.toArray());                                  conversation.setAdapter(adapter);                                  message.setText("");                                  conversation.setSelection(savedConversation.size()-­‐1);                                  layoutImage.setVisibility(View.INVISIBLE);                                    Bitmap  bitmap  =  ((BitmapDrawable)image.getDrawable()).getBitmap();                                  ByteArrayOutputStream  stream  =  new  ByteArrayOutputStream();  

                               bitmap.compress(Bitmap.CompressFormat.JPEG,  100,  stream);                                  byte[]  bitmapdata  =  stream.toByteArray();                                    new  EncryptPictureTask(this.getActivity(),  new  BigInteger(key.split("-­‐")[0]),  new  BigInteger(key.split("-­‐")[1]),  (String)userInfo.get(2)).execute(bitmapdata);                                  break;                  }            }            public  void  addPictureTask(ArrayList<Object>  task){                  ((ContactsTabActivity)this.getActivity()).tasksToDo.add(task);          }            public  String  getPath(Uri  uri)  {                    //  just  some  safety  built  in                  if(  uri  ==  null  )  {                          //  perform  some  logging  or  show  user  feedback                          Toast.makeText(this.getActivity(),  "Loading  picture  failed",  Toast.LENGTH_LONG).show();                          return  null;                  }                    //  try  to  retrieve  the  image  from  the  media  store  first                  //  this  will  only  work  for  images  selected  from  gallery                  String[]  projection  =  {  MediaStore.Images.Media.DATA  };                  Cursor  cursor  =  this.getActivity().managedQuery(uri,  projection,  null,  null,  null);                  if(  cursor  !=  null  ){                          int  column_index  =  cursor                                          .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);                          cursor.moveToFirst();                          return  cursor.getString(column_index);                  }                  //  this  is  our  fallback  here,  thanks  to  the  answer  from  @mad  indicating  this  is  needed  for                  //  working  code  based  on  images  selected  using  other  file  managers                  return  uri.getPath();          }            public  void  postNewMessage(){                  ConversationAdapter  adapter  =  new  ConversationAdapter(this.getActivity(),  1,  savedConversation.toArray());                  conversation.setAdapter(adapter);                  message.setText("");                  conversation.setSelection(savedConversation.size()-­‐1);  

 

 x  

       }            public  byte[]  messageEncryption(byte[]  M){                  BigInteger  N  =  new  BigInteger(key.split("-­‐")[0]);                  BigInteger  e  =  new  BigInteger(key.split("-­‐")[1]);                    BigInteger  encryptedMsg  =  new  BigInteger(M);                  if  (encryptedMsg.signum()  !=  1){                          encryptedMsg  =  encryptedMsg.multiply(BigInteger.valueOf(-­‐1));                          encryptedMsg  =  encryptedMsg.modPow(e,  N);                          byte[]  encMsgBytestemp  =  encryptedMsg.toByteArray();                          byte[]  encMsgBytes  =  new  byte[encMsgBytestemp.length+1];                          for  (int  i  =  0;  i<encMsgBytes.length;  i++){                                  if  (i  ==  encMsgBytes.length-­‐1){                                          encMsgBytes[i]  =  (byte)1;                                  }else{                                          encMsgBytes[i]  =  encMsgBytestemp[i];  

                               }                          }                          return  encMsgBytes;                  }else{                          encryptedMsg  =  encryptedMsg.modPow(e,  N);                          byte[]  encMsgBytestemp  =  encryptedMsg.toByteArray();                          byte[]  encMsgBytes  =  new  byte[encMsgBytestemp.length+1];                          for  (int  i  =  0;  i<encMsgBytes.length;  i++){                                  if  (i  ==  encMsgBytes.length-­‐1){                                          encMsgBytes[i]  =  (byte)2;                                  }else{                                          encMsgBytes[i]  =  encMsgBytestemp[i];                                  }                          }                          return  encMsgBytes;                  }                  //return  encryptedMsg.toByteArray();                  //return  (new  BigInteger(M)).modPow(e,  N).toByteArray();          }  }  

 Ø ConversationAdapter.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.graphics.drawable.Drawable;  import  android.support.v4.app.FragmentActivity;  import  android.view.Gravity;  import  android.view.LayoutInflater;  import  android.view.View;  import  android.view.ViewGroup;  import  android.widget.ArrayAdapter;  import  android.widget.ImageView;  import  android.widget.TextView;    import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/20/15.    */  public  class  ConversationAdapter  extends  ArrayAdapter  {            Object[]  conversation;          Context  context;            public  ConversationAdapter(Context  ctx,  int  resource,  Object[]  objects)  {                  super(ctx,  resource,  objects);                  conversation  =  objects;                  context  =  ctx;          }            @Override          public  View  getView(int  position,  View  convertView,  ViewGroup  parent)  {                    //  inflate  the  layout  

               LayoutInflater  inflater  =  ((FragmentActivity)context).getLayoutInflater();                  if  (conversation[position]  instanceof  String[]){                          convertView  =  inflater.inflate(R.layout.conversation_cell,  parent,  false);                            TextView  name;                            if  (Integer.parseInt(((String[])conversation[position])[0])  ==  0){                                  name  =  (TextView)convertView.findViewById(R.id.textView18);                          }else{                                  name  =  (TextView)convertView.findViewById(R.id.textView17);                          }                          name.setText(((String[])conversation[position])[1]);                  }else{                          convertView  =  inflater.inflate(R.layout.conversation_image_cell,  parent,  false);                          ImageView  image;                            if  (Integer.parseInt((String)  ((ArrayList<Object>)conversation[position]).get(0))  ==  0){                                  image  =  (ImageView)convertView.findViewById(R.id.imageView5);                          }else{  

 

 xi  

                               image  =  (ImageView)convertView.findViewById(R.id.imageView4);                          }                          image.setImageDrawable((Drawable)  ((ArrayList<Object>)conversation[position]).get(1));  

                 }                      return  convertView;          }  }  

 Ø AddContactTab.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.DialogInterface;  import  android.database.Cursor;  import  android.os.Bundle;  import  android.support.v4.app.Fragment;  import  android.view.LayoutInflater;  import  android.view.View;  import  android.view.ViewGroup;  import  android.widget.Button;  import  android.widget.EditText;  import  android.widget.RelativeLayout;  import  android.widget.Toast;    import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/7/15.    */  public  class  AddContactTab  extends  Fragment  implements  View.OnClickListener  {            public  EditText  userEdt;          public  Button  btnAdd;          public  RelativeLayout  loadingLayout;            @Override          public  View  onCreateView(LayoutInflater  inflater,  ViewGroup  container,                                                            Bundle  savedInstanceState)  {                  //  Inflate  the  layout  for  this  fragment                  View  V  =  inflater.inflate(R.layout.add_contact_tab,  container,  false);                  userEdt  =  (EditText)  V.findViewById(R.id.editText9);                  btnAdd  =  (Button)  V.findViewById(R.id.button6);                  loadingLayout  =  (RelativeLayout)  V.findViewById(R.id.loadingLayout);                    btnAdd.setOnClickListener(this);                    return  V;          }            @Override          public  void  onClick(View  v)  {                  if  (userEdt.getText().toString().length()  >  0){                          DBHelper  db  =  new  DBHelper(this.getActivity());                          ArrayList<String>  contacts  =  db.getAllCotacts();                          boolean  userExists  =  false;                          if  (contacts.size()  >  0){  

                               String  mail  =  userEdt.getText().toString();                                  for  (int  i  =  0;  i  <  contacts.size();  i++){                                          if  (contacts.get(i).equals(mail)){                                                  userExists  =  true;                                                  break;                                          }                                  }                                  if  (userExists){                                          Toast  toast  =  Toast.makeText(this.getActivity(),  "Contact  already  added",  Toast.LENGTH_SHORT);                                          toast.show();                                  }else{                                          //new  AddContactTask(this,  userEdt.getText().toString()).execute();                                          ArrayList<Object>  addUser  =  new  ArrayList<Object>();                                          addUser.add("10");                                          addUser.add(userEdt.getText().toString());                                          ((ContactsTabActivity)  this.getActivity()).tasksToDo.add(addUser);                                  }                          }else{                                  //new  AddContactTask(this,  userEdt.getText().toString()).execute();                                  ArrayList<Object>  addUser  =  new  ArrayList<Object>();                                  addUser.add("10");                                  addUser.add(userEdt.getText().toString());                                  ((ContactsTabActivity)  this.getActivity()).tasksToDo.add(addUser);                          }                      }          }            public  void  addContact(String[]  newContact){                  System.out.println(newContact[0]);                  System.out.println(newContact[1]);                  System.out.println(newContact[2]);                  DBHelper  db  =  new  DBHelper(this.getActivity());                  db.insertContact(newContact[0],  newContact[1],  newContact[2]);                  ((ContactsTabActivity)this.getActivity()).refreshContacts();          }            public  void  contactNotFound(){                  Toast  toast  =  Toast.makeText(this.getActivity(),  "User  not  found",  Toast.LENGTH_SHORT);  

 

 xii  

               toast.show();          }  

}  

 Ø LoginActivity.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.app.Activity;  import  android.content.Intent;  import  android.os.Bundle;  import  android.view.View;  import  android.widget.Button;  import  android.widget.EditText;  import  android.widget.RelativeLayout;  import  android.widget.Switch;  import  android.widget.Toast;    import  java.math.BigInteger;  import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  6/28/15.    */  public  class  LoginActivity  extends  Activity  implements  View.OnClickListener{          EditText  txtUsername,  txtPassword;          Button  btnRegister,  btnLogin;          BigInteger  N,  e,  d;          String[]  userInfo  =  new  String[3];          RelativeLayout  loadingView;            @Override          protected  void  onCreate(Bundle  savedInstanceState)  {                  super.onCreate(savedInstanceState);                  setContentView(R.layout.activity_login);                    txtUsername  =  (EditText)  findViewById(R.id.editText5);                  txtPassword  =  (EditText)  findViewById(R.id.editText6);                    loadingView  =  (RelativeLayout)  findViewById(R.id.loadingLayout);                    btnLogin  =  (Button)  findViewById(R.id.button2);                  btnRegister  =  (Button)  findViewById(R.id.button3);                    btnLogin.setOnClickListener(this);                  btnRegister.setOnClickListener(this);              }            @Override          public  void  onClick(View  v)  {                  switch  (v.getId()){                          case  R.id.button2:                                  boolean  isComplete  =  true;                                  if  (txtUsername.getText().toString().length()  ==  0  ||  txtPassword.getText().toString().length()  ==  0){                                          isComplete  =  false;                                  }  

                               if  (isComplete){                                          loadingView.setVisibility(View.VISIBLE);                                          new  LoginTask(this,  txtUsername.getText().toString(),  txtPassword.getText().toString()).execute();                                  }else{                                          Toast  toast  =  Toast.makeText(this,  "Fields  are  not  complete",  Toast.LENGTH_SHORT);                                          toast.show();                                  }                                  break;                          case  R.id.button3:                                  Intent  intent  =  new  Intent(this,  RegisterActivity.class);                                  startActivity(intent);                                  //this.finish();                                  break;                  }          }            public  void  loginAction(int  code,  String[]  user){                  /**                    *  1:  User  not  found                    *  2:  Correct  password                    *  3:  Incorrect  password                    *  4:  Info  not  received                  **/                    switch  (code){                          case  1:                                  executeToast("User  not  registered");                                  break;                          case  2:                                  System.out.println(user[0]);                                  System.out.println(user[1]);                                  System.out.println(user[2]);                                  System.out.println(user[3]);                                  userInfo  =  user;                                  new  KeyGenerationTask(this).execute();                                  break;                          case  3:                                  executeToast("Incorrect  password");                                  break;                          default:                                  executeToast("Connection  error");                  }            }            public  void  keysGenerated(BigInteger[]  keys){                  N  =  keys[0];                  e  =  keys[1];                  d  =  keys[2];                    new  UpdateKeyTask(this,  ""+N+"-­‐"+e,  userInfo[2]).execute();          }    

 

 xiii  

       public  void    keysUpdated(String  str){                  DBHelper  db  =  new  DBHelper(this);                  db.insertUser(userInfo[0],  userInfo[1],  userInfo[2],  ""+N+"-­‐"+d,  ""+N+"-­‐"+e,  userInfo[3]);                  System.out.println("User  saved  in  DB");                  ArrayList<String>  userSaved  =  db.getUser();                  System.out.println(""+userSaved.get(0)+"\n"+userSaved.get(1)+"\n"+userSaved.get(2)+"\n"+userSaved.get(3)+"\n"+userSaved.get(4)+"\n"+userSaved.get(5)+"\n"+userSaved.get(6)+"\n");    

               executeToast(str);                    Intent  intent  =  new  Intent(this,  ContactsTabActivity.class);                  startActivity(intent);                  this.finish();          }            public  void  executeToast(String  msg){                  Toast  toast  =  Toast.makeText(this,  msg,  Toast.LENGTH_SHORT);                  toast.show();          }  }  

 Ø RegisterActivity.java  

package  com.example.ricardoviteri.safetimeapp;    import  java.io.ByteArrayInputStream;  import  java.io.ByteArrayOutputStream;  import  java.lang.reflect.Array;  import  java.math.BigInteger;  import  java.util.ArrayList;  import  java.util.List;  import  java.util.Random;  import  android.app.Activity;  import  android.content.Intent;  import  android.graphics.Bitmap;  import  android.graphics.drawable.BitmapDrawable;  import  android.graphics.drawable.Drawable;  import  android.os.Bundle;  import  android.view.View;  import  android.widget.Button;  import  android.widget.EditText;  import  android.widget.ImageView;  import  android.widget.ProgressBar;  import  android.widget.RelativeLayout;  import  android.widget.TextView;  import  android.widget.Toast;  import  java.util.Arrays;    /**    *  Created  by  ricardoviteri  on  6/18/15.    */  public  class  RegisterActivity  extends  Activity  implements  View.OnClickListener{            EditText  txtName,  txtEmail,  txtPass,  txtRepPass,  txtPhone;          ImageView  imgTest;          TextView  txtProgress;          ProgressBar  progBar;          RelativeLayout  loadingView;          Button  btnRegister;          BigInteger  firstPrime,  secondPrime,  N,  e,  d;          String  name,  email,  password,  phone;          byte[]  encrypted,  decrypted;          int  bitlength  =  1024;          Random  r;            @Override          protected  void  onCreate(Bundle  savedInstanceState)  {                  super.onCreate(savedInstanceState);  

               setContentView(R.layout.activity_register);                    txtName  =  (EditText)  findViewById(R.id.editText);                  txtPhone  =  (EditText)  findViewById(R.id.editText7);                  txtEmail  =  (EditText)  findViewById(R.id.editText2);                  txtPass  =  (EditText)  findViewById(R.id.editText3);                  txtRepPass  =  (EditText)  findViewById(R.id.editText4);                  btnRegister  =  (Button)  findViewById(R.id.button);                  imgTest  =  (ImageView)  findViewById(R.id.imageView);                  txtProgress  =  (TextView)  findViewById(R.id.textView13);                  progBar  =  (ProgressBar)  findViewById(R.id.progressBar2);                  loadingView  =  (RelativeLayout)  findViewById(R.id.loadingLayout);                    btnRegister.setOnClickListener(this);          }            @Override          public  void  onClick(View  v)  {                  loadingView.setVisibility(View.VISIBLE);                  boolean  isComplete  =  true,  passMatch  =  true;                  System.out.println("Button  pushed!");                  if  (txtName.getText().toString().length()  >  0){                          name  =  txtName.getText().toString();                  }else{                          isComplete  =  false;                  }                    if  (txtPhone.getText().toString().length()  >  0){                          phone  =  txtPhone.getText().toString();                  }else{                          isComplete  =  false;                  }                    if  (txtEmail.getText().toString().length()  >  0){                          email  =  txtEmail.getText().toString();                  }else{  

 

 xiv  

                       isComplete  =  false;                  }                    if  (txtPass.getText().toString().length()  >  0){                          password  =  txtPass.getText().toString();                  }else{                          isComplete  =  false;                  }                    if  (txtRepPass.getText().toString().length()  >  0){                          if  (!txtRepPass.getText().toString().equals(password)){                                  passMatch  =  false;                          }                  }else{                          isComplete  =  false;                  }                    if  (isComplete){                          if  (passMatch){                                  System.out.println("Register  Successful");                                  //keyGeneration();                                    new  KeyGenerationTask(this).execute();                            }else{                                  Toast  toast  =  Toast.makeText(this,  "Passwords  does  not  match",  Toast.LENGTH_SHORT);                                  toast.show();                          }                  }else{                          Toast  toast  =  Toast.makeText(this,  "Fields  are  not  complete",  Toast.LENGTH_SHORT);                          toast.show();                  }                  //keyGeneration();          }            public  void  keyGeneration(){                  //Generate  a  random  number  and  look  for  two  prime  numbers  of  "bitlength"  size                  r  =  new  Random();                  firstPrime  =  BigInteger.probablePrime(bitlength,  r);                  secondPrime  =  BigInteger.probablePrime(bitlength,  r);                    //First  we  need  to  obtain  the  number  N  =  firstPrime*secondPrime                  N  =  firstPrime.multiply(secondPrime);                    //use  Euler  totient  function  to  obtain  phi  (phi(N))                  BigInteger  phi  =  N.subtract(firstPrime.add(secondPrime).subtract(BigInteger.ONE));                    //Obtain  a  prime  number  between  0  and  N  (should  be  coprime  with  phi)                  e  =  BigInteger.probablePrime(bitlength/2,  r);  

                 //Making  sure  that  e  is  coprime  with  N                  while  (phi.gcd(e).compareTo(BigInteger.ONE)  >  0  &&  e.compareTo(phi)  <  0  )  {                          e.add(BigInteger.ONE);                  }                    //Obtain  the  private  key  by  calculating  e  inverse  module  of  phi                  d  =  e.modInverse(phi);                    System.out.println("Finish  key  generation");                    /*                  Drawable  d  =  getResources().getDrawable(R.drawable.shefuni);                  Bitmap  bitmap  =  ((BitmapDrawable)d).getBitmap();                  ByteArrayOutputStream  stream  =  new  ByteArrayOutputStream();                  bitmap.compress(Bitmap.CompressFormat.JPEG,  100,  stream);                  byte[]  bitmapdata  =  stream.toByteArray();                    Drawable  d2  =  getResources().getDrawable(R.drawable.banana);                  Bitmap  bitmap2  =  ((BitmapDrawable)d2).getBitmap();                  ByteArrayOutputStream  stream2  =  new  ByteArrayOutputStream();                  bitmap2.compress(Bitmap.CompressFormat.JPEG,  100,  stream2);                  byte[]  bitmapdata2  =  stream2.toByteArray();                    int  counter  =  0;                  for  (int  i  =  0;  i  <  (bitmapdata.length  <  bitmapdata2.length  ?  bitmapdata.length  :  bitmapdata2.length);  i++){                          if  ((int)bitmapdata[i]  ==  (int)bitmapdata2[i]){                                  counter++;                          }else{                                  break;                          }                  }                    //163  header                    System.out.println("Size  of  picture  1  is:  "+bitmapdata.length+"  bytes");                  System.out.println("Size  of  picture  2  is:  "+bitmapdata2.length+"  bytes");                  System.out.println("Header  size  of  pictures  is:  "+counter+"  bytes");                        new  EncryptPictureTask(this).execute(bitmapdata);                  txtProgress.setText("Encrypting...");                  txtProgress.setVisibility(View.VISIBLE);  

 

 xv  

               progBar.setVisibility(View.VISIBLE);                  */          }            public  void  keysGenerated(BigInteger[]  keys){                  N  =  keys[0];                  e  =  keys[1];                  d  =  keys[2];                    new  RegisterUserTask(this,  name,  phone,  email,  password,  ""+N+"-­‐"+e).execute();          }            public  void  startApp(int  result,  String  port){                  loadingView.setVisibility(View.INVISIBLE);                  /**                    *  1:  Successfully  added                    *  2:  Email  already  registered                    *  3:  User  not  received                  **/                  switch(result){                          case  1:                                  DBHelper  db  =  new  DBHelper(this);                                  db.insertUser(name,  phone,  email,  ""+N+"-­‐"+d,  ""+N+"-­‐"+e,  port);                                  System.out.println("User  saved  in  DB");                                  ArrayList<String>  userSaved  =  db.getUser();                                  System.out.println(""+userSaved.get(0)+"\n"+userSaved.get(1)+"\n"+userSaved.get(2)+"\n"+userSaved.get(3)+"\n"+userSaved.get(4)+"\n"+userSaved.get(5)+"\n"+userSaved.get(6)+"\n");                                      Intent  intent  =  new  Intent(this,  ContactsTabActivity.class);                                  startActivity(intent);                                  this.finish();                                  break;                          case  2:                                  executeToast("Email  already  registered");                                  break;                          default:                                  executeToast("Connection  error");                  }            }            public  void  executeToast(String  msg){                  Toast  toast  =  Toast.makeText(this,  msg,  Toast.LENGTH_SHORT);                  toast.show();          }            /*          public  byte[]  messageEncryption(byte[]  M){                  BigInteger  encryptedMsg  =  new  BigInteger(M);                  if  (encryptedMsg.signum()  !=  1){                          encryptedMsg  =  encryptedMsg.multiply(BigInteger.valueOf(-­‐1));  

                       encryptedMsg  =  encryptedMsg.modPow(e,  N);                          byte[]  encMsgBytestemp  =  encryptedMsg.toByteArray();                          byte[]  encMsgBytes  =  new  byte[encMsgBytestemp.length+1];                          for  (int  i  =  0;  i<encMsgBytes.length;  i++){                                  if  (i  ==  encMsgBytes.length-­‐1){                                          encMsgBytes[i]  =  (byte)1;                                  }else{                                          encMsgBytes[i]  =  encMsgBytestemp[i];                                  }                          }                          return  encMsgBytes;                  }else{                          encryptedMsg  =  encryptedMsg.modPow(e,  N);                          byte[]  encMsgBytestemp  =  encryptedMsg.toByteArray();                          byte[]  encMsgBytes  =  new  byte[encMsgBytestemp.length+1];                          for  (int  i  =  0;  i<encMsgBytes.length;  i++){                                  if  (i  ==  encMsgBytes.length-­‐1){                                          encMsgBytes[i]  =  (byte)2;                                  }else{                                          encMsgBytes[i]  =  encMsgBytestemp[i];                                  }                          }                          return  encMsgBytes;                  }                  //return  encryptedMsg.toByteArray();                  //return  (new  BigInteger(M)).modPow(e,  N).toByteArray();          }            public  byte[]  messageDecryption(byte[]  D){                  byte[]  msgToDecrypt  =  new  byte[D.length-­‐1];                  for  (int  i  =  0;  i<D.length-­‐1;  i++){                          msgToDecrypt[i]  =  D[i];                  }                  System.out.println(""+D[D.length-­‐1]);                  BigInteger  encryptedMsg  =  new  BigInteger(msgToDecrypt);                    encryptedMsg  =  encryptedMsg.modPow(d,  N);                    if  (D[D.length-­‐1]  ==  (byte)1){                          encryptedMsg  =  encryptedMsg.multiply(BigInteger.valueOf(-­‐1));                  }                    return  encryptedMsg.toByteArray();                  //return  (new  BigInteger(D)).modPow(d,  N).toByteArray();          }            private  static  String  bytesToString(byte[]  encrypted)  {                  String  test  =  "";                  for  (byte  b  :  encrypted)  {                          test  +=  Byte.toString(b);                  }                  return  test;          }  

 

 xvi  

         public  static  boolean  isPrime(long  n)  {                  if  (n  <=  3)  {                          return  n  >  1;                  }  else  if  (n  %  2  ==  0  ||  n  %  3  ==  0)  {                          return  false;                  }  else  {                          for  (int  i  =  5;  i  *  i  <=  n;  i  +=  6)  {                                  if  (n  %  i  ==  0  ||  n  %  (i  +  2)  ==  0)  {                                          return  false;                                  }                          }                          return  true;                  }          }          */  

       public  void  imageWasEncrypted(ArrayList<byte[]>  encImg){                  new  DecryptPictureTask(this,  "").execute(encImg);                  txtProgress.setText("Decrypting...");          }            public  void  displayDecriptedImg(Drawable  img){                  imgTest.setImageDrawable(img);                  txtProgress.setText("Done!!");                  progBar.setVisibility(View.INVISIBLE);          }  }  

 Ø ServerThread.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.widget.Toast;    import  java.io.BufferedReader;  import  java.io.DataInputStream;  import  java.io.DataOutputStream;  import  java.io.IOException;  import  java.io.InputStream;  import  java.io.InputStreamReader;  import  java.io.OutputStream;  import  java.io.PrintStream;  import  java.net.ServerSocket;  import  java.net.Socket;  import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/20/15.    */  public  class  ServerThread  extends  Thread  {            ContactsTabActivity  parent;          String  thisUser;            public  ServerThread(ContactsTabActivity  context,  String  user)  {                  parent  =  context;                  thisUser  =  user;          }            public  void  run(){                    while(true){                            Socket  sock  =  null;                          try  {                                  sock  =  new  Socket("192.168.1.103",  parent.Port);                          }  catch  (IOException  e)  {                                  //System.out.println("No  connection");                          }                            if  (sock  !=  null){                                  PrintStream  PS  =  null;                                  try  {                                          PS  =  new  PrintStream(sock.getOutputStream());  

                               }  catch  (IOException  e)  {                                          e.printStackTrace();                                  }                                  //TODO:  sent  this  depending  on  if  there  is  something  to  send  or  not                                  if  (parent.tasksToDo.size()  >  0){                                          PS.println("1");                                  }else{                                          PS.println("0");                                  }                                        //initialize  reading                                  InputStreamReader  IR  =  null;                                  try  {                                          IR  =  new  InputStreamReader(sock.getInputStream());                                  }  catch  (IOException  e)  {                                          e.printStackTrace();                                  }                                  BufferedReader  BR  =  new  BufferedReader(IR);                                  //look  for  messages  that  might  be  received  by  the  server                                  String  MESSAGE  =  null;                                  try  {                                          MESSAGE  =  BR.readLine();                                          if  (MESSAGE  ==  null){                                                  MESSAGE  =  "20";                                          }                                          //System.out.println(MESSAGE);                                  }  catch  (Exception  e)  {                                          e.printStackTrace();                                          MESSAGE  =  "20";                                  }                                    /**                                    *  1:  Listen                                    *  2:  Send  data                                  **/                                  if  (Integer.parseInt(MESSAGE)  ==  1){                                          System.out.println("Recieving  something  from  server");                                          try  {                                                  MESSAGE  =  BR.readLine();                                                  //System.out.println(MESSAGE);                                          }  catch  (Exception  e)  {                                                  e.printStackTrace();  

 

 xvii  

                                               MESSAGE  =  "20";                                          }                                          int  idTask  =  Integer.parseInt(MESSAGE);                                            if  (idTask  ==  10){                                                  try  {                                                          String[]  userInfo  =  new  String[3];                                                          userInfo[0]  =  BR.readLine();                                                          userInfo[1]  =  BR.readLine();                                                          userInfo[2]  =  BR.readLine();                                                            parent.addContact(userInfo);                                                          //System.out.println(MESSAGE);                                                  }  catch  (Exception  e)  {                                                          e.printStackTrace();                                                          MESSAGE  =  "20";                                                  }                                          }                                            if  (idTask  ==  11){                                                  System.out.println("READING  MESSAGE");                                                  new  RecieveMessageTask(parent).execute();                                                  /*byte[]  encMessage  =  new  byte[257];                                                  try  {                                                          BR.read(encMessage);                                                          //System.out.println(MESSAGE);                                                  }  catch  (Exception  e)  {                                                          e.printStackTrace();                                                          MESSAGE  =  "20";                                                  }*/                                              }                                  }                                    if  (Integer.parseInt(MESSAGE)  ==  2){                                          final  ArrayList<Object>  task  =  parent.tasksToDo.get(0);                                            int  idTask  =  Integer.parseInt(task.get(0).toString());                                          /**                                            *  ***********  idTask  ****************                                            *            10:  Add  Contact                                            *            11:  Send  Message                                            */                                          if  (idTask  ==  10){                                                  PS  =  null;                                                  try  {                                                          PS  =  new  PrintStream(sock.getOutputStream());                                                  }  catch  (IOException  e)  {                                                          e.printStackTrace();                                                  }                                                  PS.println("1");                                                  PS.println(task.get(1).toString());                                                  System.out.println("Request  sent");                                                    //initialize  reading                                                  IR  =  null;  

                                               try  {                                                          IR  =  new  InputStreamReader(sock.getInputStream());                                                  }  catch  (IOException  e)  {                                                          e.printStackTrace();                                                  }                                                  BR  =  new  BufferedReader(IR);                                                  //look  for  messages  that  might  be  received  by  the  server                                                  MESSAGE  =  null;                                                  try  {                                                          MESSAGE  =  BR.readLine();                                                          System.out.println("command  received  "+MESSAGE);                                                  }  catch  (IOException  e)  {                                                          e.printStackTrace();                                                  }                                                    /**                                                    *  1:  User  found                                                    *  2:  User  not  found                                                    **/                                                  if  (Integer.parseInt(MESSAGE)  ==  1){                                                          System.out.println("Found  user");                                                          String[]  userInfo  =  new  String[3];                                                          try  {                                                                  userInfo[0]  =  BR.readLine();                                                                  userInfo[1]  =  BR.readLine();                                                                  userInfo[2]  =  BR.readLine();                                                                  parent.addContact(userInfo);                                                          }  catch  (IOException  e)  {                                                                  e.printStackTrace();                                                          }                                                          if  (parent.tasksToDo.size()  >  0){                                                                  parent.tasksToDo.remove(0);                                                          }                                                    }else{                                                          System.out.println("Not  found");                                                          parent.runOnUiThread(new  Runnable()  {                                                                  public  void  run()  {                                                                          //Toast.makeText(parent,  "Hello",  Toast.LENGTH_SHORT).show();                                                                          parent.contactNotFound(task.get(1).toString());                                                                    }                                                          });                                                          parent.tasksToDo.remove(0);                                                  }                                          }                                            if  (idTask  ==  11){                                                  PS  =  null;                                                  try  {                                                          PS  =  new  PrintStream(sock.getOutputStream());                                                  }  catch  (IOException  e)  {                                                          e.printStackTrace();                                                  }                                                  PS.println("2");                                                  //PS.println(task.get(1).toString());    

 

 xviii  

                                               SOK_CLIENT_BASIC  cosa  =  new  SOK_CLIENT_BASIC(task.get(2),  task.get(1).toString(),  thisUser);                                                  try  {                                                          cosa.run();                                                  }  catch  (Exception  e)  {                                                          e.printStackTrace();                                                  }                                                      /*                                                  //Send  de  message  byte[]                                                  byte[]  encMessage  =  (byte[])  task.get(2);                                                  System.out.println(new  String(encMessage));                                                  OutputStream  out  =  null;                                                  try  {                                                          out  =  sock.getOutputStream();                                                  }  catch  (IOException  e)  {                                                          e.printStackTrace();                                                  }                                                  DataOutputStream  dos  =  new  DataOutputStream(out);                                                    try  {                                                          dos.writeInt(encMessage.length);                                                  }  catch  (IOException  e)  {                                                          e.printStackTrace();                                                  }                                                  if  (encMessage.length  >  0)  {                                                          try  {                                                                  dos.write(encMessage,  0,  encMessage.length);                                                                  System.out.println("Sending...");                                                          }  catch  (IOException  e)  {  

                                                               e.printStackTrace();                                                          }                                                  }                                                    //initialize  reading                                                  IR  =  null;                                                  try  {                                                          IR  =  new  InputStreamReader(sock.getInputStream());                                                  }  catch  (IOException  e)  {                                                          e.printStackTrace();                                                  }                                                  BR  =  new  BufferedReader(IR);                                                  //look  for  messages  that  might  be  received  by  the  server                                                  MESSAGE  =  null;                                                  try  {                                                          MESSAGE  =  BR.readLine();                                                  }  catch  (IOException  e)  {                                                          e.printStackTrace();                                                  }                                                  System.out.println(MESSAGE);                                                  */                                                    parent.tasksToDo.remove(0);                                                  System.out.println("Erased");                                              }                                      }                          }                    }            }  }  

 Ø AddContactTask.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.os.AsyncTask;    import  java.io.BufferedReader;  import  java.io.IOException;  import  java.io.InputStreamReader;  import  java.io.PrintStream;  import  java.net.Socket;  import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/19/15.    */  public  class  AddContactTask  extends  AsyncTask<String,  Integer,  String[]>  {            AddContactTab  context;          String  usrToAdd;          String[]  userInfo  =  new  String[3];            public  AddContactTask(AddContactTab  ctx,  String  user)  {                  context  =  ctx;                  usrToAdd  =  user;  

       }            @Override          protected  String[]  doInBackground(String...  params)  {                    Socket  sock  =  null;                  try  {                          DBHelper  db  =  new  DBHelper(context.getActivity());                          ArrayList<String>  userSaved  =  db.getUser();                          sock  =  new  Socket("192.168.1.103",  9003);//Integer.parseInt(userSaved.get(6)));//userSaved.get(6)));                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                    PrintStream  PS  =  null;                  try  {                          PS  =  new  PrintStream(sock.getOutputStream());                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  PS.println("1");  

 

 xix  

               PS.println(usrToAdd);                    //initialize  reading                  InputStreamReader  IR  =  null;                  try  {                          IR  =  new  InputStreamReader(sock.getInputStream());                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  BufferedReader  BR  =  new  BufferedReader(IR);                  //look  for  messages  that  might  be  received  by  the  server                  String  MESSAGE  =  null;                  try  {                          MESSAGE  =  BR.readLine();                          System.out.println(MESSAGE);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                    /**                    *  1:  User  found                    *  2:  User  not  found                  **/                  if  (Integer.parseInt(MESSAGE)  ==  1){                            try  {                                  userInfo[0]  =  BR.readLine();                                  userInfo[1]  =  BR.readLine();  

                               userInfo[2]  =  BR.readLine();                          }  catch  (IOException  e)  {                                  e.printStackTrace();                          }                    }else{                          this.cancel(true);                  }                    return  userInfo;          }            @Override          protected  void  onPostExecute(String[]  strings)  {                  super.onPostExecute(strings);                  context.addContact(strings);          }            @Override          protected  void  onCancelled()  {                  super.onCancelled();                  context.contactNotFound();            }            @Override          protected  void  onPreExecute()  {                  super.onPreExecute();          }  }  

 Ø LoginTask.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.os.AsyncTask;    import  java.io.BufferedReader;  import  java.io.IOException;  import  java.io.InputStream;  import  java.io.InputStreamReader;  import  java.io.ObjectInputStream;  import  java.io.ObjectOutputStream;  import  java.io.PrintStream;  import  java.net.Socket;    /**    *  Created  by  ricardoviteri  on  7/16/15.    */  public  class  LoginTask  extends  AsyncTask<String,  Integer,  Integer>  {            Context  context;          String  usr,  pass;          String[]  userInfo  =  new  String[4];            public  LoginTask(Context  ctx,  String  user,  String  password)  {                  context  =  ctx;                  usr  =  user;                  pass  =  password;          }            @Override  

       protected  Integer  doInBackground(String...  params)  {                  String[]  user  =  new  String[2];                  user[0]  =  usr;                  user[1]  =  pass;                    Socket  sock  =  null;                  try  {                          sock  =  new  Socket("192.168.1.103",  9001);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                      ObjectOutputStream  out  =  null;                  try  {                          out  =  new  ObjectOutputStream(sock.getOutputStream());                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  try  {                          out.writeObject(user);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                      //initialize  reading                  InputStreamReader  IR  =  null;                  try  {                          IR  =  new  InputStreamReader(sock.getInputStream());  

 

 xx  

               }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  BufferedReader  BR  =  new  BufferedReader(IR);                  //look  for  messages  that  might  be  received  by  the  server                  String  MESSAGE  =  null;                  try  {                          MESSAGE  =  BR.readLine();                          System.out.println(MESSAGE);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                    if  (Integer.parseInt(MESSAGE)  ==  2){                            try  {                                  userInfo[0]  =  BR.readLine();                                  userInfo[1]  =  BR.readLine();                                  userInfo[2]  =  BR.readLine();                                  userInfo[3]  =  BR.readLine();                          }  catch  (IOException  e)  {                                  e.printStackTrace();                          }                            PrintStream  PS  =  null;                          try  {                                  PS  =  new  PrintStream(sock.getOutputStream());                                  PS.println("UserInfo  received");                          }  catch  (IOException  e)  {                                  e.printStackTrace();  

                       }                  }                      return  Integer.parseInt(MESSAGE);          }            @Override          protected  void  onPreExecute()  {                  super.onPreExecute();          }            @Override          protected  void  onPostExecute(Integer  integer)  {                  super.onPostExecute(integer);                  ((LoginActivity)context).loginAction(integer,  userInfo);          }            @Override          protected  void  onProgressUpdate(Integer...  values)  {                  super.onProgressUpdate(values);          }            @Override          protected  void  onCancelled(Integer  integer)  {                  super.onCancelled(integer);          }  }  

 Ø RegisterUserTask.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.os.AsyncTask;    import  java.io.BufferedReader;  import  java.io.DataOutputStream;  import  java.io.IOException;  import  java.io.InputStreamReader;  import  java.io.ObjectOutputStream;  import  java.io.OutputStream;  import  java.net.Socket;    /**    *  Created  by  ricardoviteri  on  7/14/15.    */  public  class  RegisterUserTask  extends  AsyncTask<String,  Integer,  Integer>{            String  usrName,  usrPhone,  usrEmail,  usrPass,  usrPKey,  port;          Context  context;            public  RegisterUserTask(Context  ctx,  String  name,  String  phone,  String  email,  String  pass,  String  pKey)  {                  usrName  =  name;                  usrPhone  =  phone;                  usrEmail  =  email;                  usrPass  =  pass;                  usrPKey  =  pKey;  

               context  =  ctx;          }            @Override          protected  Integer  doInBackground(String...  params)  {                    String[]  user  =  new  String[5];                  user[0]  =  usrName;                  user[1]  =  usrPhone;                  user[2]  =  usrEmail;                  user[3]  =  usrPass;                  user[4]  =  usrPKey;                    Socket  sock  =  null;                  try  {                          sock  =  new  Socket("192.168.1.103",  9000);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                      ObjectOutputStream  out  =  null;                  try  {                          out  =  new  ObjectOutputStream(sock.getOutputStream());                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  try  {                          out.writeObject(user);  

 

 xxi  

               }  catch  (IOException  e)  {                          e.printStackTrace();                  }                      //initialize  reading                  InputStreamReader  IR  =  null;                  try  {                          IR  =  new  InputStreamReader(sock.getInputStream());                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  BufferedReader  BR  =  new  BufferedReader(IR);                  //look  for  messages  that  might  be  received  by  the  server                  String  MESSAGE  =  null;                  try  {                          MESSAGE  =  BR.readLine();                          System.out.println(MESSAGE);                          if  (Integer.parseInt(MESSAGE)  ==  1){                                  port  =  BR.readLine();                          }                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }    

               return  Integer.parseInt(MESSAGE);          }            @Override          protected  void  onPreExecute()  {                  super.onPreExecute();          }            @Override          protected  void  onProgressUpdate(Integer...  values)  {                  super.onProgressUpdate(values);          }            @Override          protected  void  onPostExecute(Integer  code)  {                  super.onPostExecute(code);                  ((RegisterActivity)context).startApp(code,  port);          }            @Override          protected  void  onCancelled()  {                  super.onCancelled();          }  }  

 Ø KeyGenerationTask.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.os.AsyncTask;    import  java.math.BigInteger;  import  java.util.Random;    /**    *  Created  by  ricardoviteri  on  7/16/15.    */  public  class  KeyGenerationTask  extends  AsyncTask<String,  Integer,  BigInteger[]>  {            BigInteger  firstPrime,  secondPrime,  N,  e,  d;          Random  r;          int  bitlength  =  1024;          BigInteger[]  keys  =  new  BigInteger[3];          Context  context;            public  KeyGenerationTask(Context  ctx)  {                  context  =  ctx;          }            @Override          protected  BigInteger[]  doInBackground(String...  params)  {                  //Generate  a  random  number  and  look  for  two  prime  numbers  of  "bitlength"  size                  r  =  new  Random();                  firstPrime  =  BigInteger.probablePrime(bitlength,  r);                  secondPrime  =  BigInteger.probablePrime(bitlength,  r);    

               //First  we  need  to  obtain  the  number  N  =  firstPrime*secondPrime                  N  =  firstPrime.multiply(secondPrime);                    //use  Euler  totient  function  to  obtain  phi  (phi(N))                  BigInteger  phi  =  N.subtract(firstPrime.add(secondPrime).subtract(BigInteger.ONE));                    //Obtain  a  prime  number  between  0  and  N  (should  be  coprime  with  phi)                  e  =  BigInteger.probablePrime(bitlength/2,  r);                    //Making  sure  that  e  is  coprime  with  N                  while  (phi.gcd(e).compareTo(BigInteger.ONE)  >  0  &&  e.compareTo(phi)  <  0  )  {                          e.add(BigInteger.ONE);                  }                    //Obtain  the  private  key  by  calculating  e  inverse  module  of  phi                  d  =  e.modInverse(phi);                    System.out.println("Finish  key  generation");                  keys[0]  =  N;                  keys[1]  =  e;                  keys[2]  =  d;                    return  keys;          }            @Override  

 

 xxii  

       protected  void  onPostExecute(BigInteger[]  bigIntegers)  {                  super.onPostExecute(bigIntegers);                  if  (context  instanceof  RegisterActivity)  {                          ((RegisterActivity)  context).keysGenerated(bigIntegers);  

               }else{                          ((LoginActivity)  context).keysGenerated(bigIntegers);                  }          }  }  

 Ø EncryptionPictureTask.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.os.AsyncTask;    import  java.math.BigInteger;  import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/2/15.    */  public  class  EncryptPictureTask  extends  AsyncTask<byte[],  Integer,  ArrayList<byte[]>>  {            BigInteger  N,  e;          Context  context;          String  whoToSend;            public  EncryptPictureTask(Context  ctx,  BigInteger  iN,  BigInteger  ie,  String  user)  {                  context  =  ctx;                  N  =  iN;                  e  =  ie;                  whoToSend  =  user;          }            @Override          protected  ArrayList<byte[]>  doInBackground(byte[]...  params)  {                  //DBHelper  db  =  new  DBHelper(context);                  //ArrayList<String>  user  =  db.getUser();                  byte[]  bitmapdata  =  params[0];                    /*                  N  =  BigInteger.valueOf(0);                  e  =  BigInteger.valueOf(0);                    N  =  N.add(new  BigInteger((user.get(5).split("-­‐"))[0]));                  e  =  e.add(new  BigInteger((user.get(5).split("-­‐"))[1]));                  */                    int  rounds  =  (int)  Math.ceil((float)bitmapdata.length  /  255.0);                  ArrayList<byte[]>  cosa  =  new  ArrayList<byte[]>();                    for  (int  i  =  0;  i<rounds;  i++){                          byte[]  contents  =  new  byte[(bitmapdata.length-­‐(255*i)<255  ?  bitmapdata.length-­‐(255*i)  :  255)];                          for  (int  j  =  0;  j<(bitmapdata.length-­‐(255*i)<255  ?  bitmapdata.length-­‐(255*i)  :  255);  j++){                                  contents[j]  =  bitmapdata[i*255+j];                          }  

                       cosa.add(contents);                    }                  System.out.println("Finish  Padding  "+cosa.get(cosa.size()-­‐1).length);                    int  listSize  =  cosa.size();                  for  (int  i  =  0;  i<listSize;  i++){                          byte[]  temp  =  cosa.get(i);                          byte[]  temp2  =  messageEncryption(temp);                          cosa.remove(i);                          cosa.add(i,  temp2);                          //System.out.println("Encrypted  "+i);                  }                  return  cosa;          }            @Override          protected  void  onPreExecute()  {                  super.onPreExecute();          }            @Override          protected  void  onPostExecute(ArrayList<byte[]>  bytes)  {                  super.onPostExecute(bytes);                  System.out.println("Encryption  done!!");                  ArrayList<Object>  task  =  new  ArrayList<Object>();                  task.add("11");                  task.add(whoToSend);                  task.add(bytes);                    ((ContactsTabActivity)context).tasksToDo.add(task);          }            @Override          protected  void  onProgressUpdate(Integer...  values)  {                  super.onProgressUpdate(values);          }            @Override          protected  void  onCancelled()  {                  super.onCancelled();          }            public  byte[]  messageEncryption(byte[]  M){                  BigInteger  encryptedMsg  =  new  BigInteger(M);                  if  (encryptedMsg.signum()  !=  1){                          encryptedMsg  =  encryptedMsg.multiply(BigInteger.valueOf(-­‐1));                          encryptedMsg  =  encryptedMsg.modPow(e,  N);  

 

 xxiii  

                       byte[]  encMsgBytestemp  =  encryptedMsg.toByteArray();                          byte[]  encMsgBytes  =  new  byte[encMsgBytestemp.length+1];                          for  (int  i  =  0;  i<encMsgBytes.length;  i++){                                  if  (i  ==  encMsgBytes.length-­‐1){                                          encMsgBytes[i]  =  (byte)1;                                  }else{                                          encMsgBytes[i]  =  encMsgBytestemp[i];                                  }                          }                          return  encMsgBytes;                  }else{                          encryptedMsg  =  encryptedMsg.modPow(e,  N);                          byte[]  encMsgBytestemp  =  encryptedMsg.toByteArray();  

                       byte[]  encMsgBytes  =  new  byte[encMsgBytestemp.length+1];                          for  (int  i  =  0;  i<encMsgBytes.length;  i++){                                  if  (i  ==  encMsgBytes.length-­‐1){                                          encMsgBytes[i]  =  (byte)2;                                  }else{                                          encMsgBytes[i]  =  encMsgBytestemp[i];                                  }                          }                          return  encMsgBytes;                  }                  //return  encryptedMsg.toByteArray();                  //return  (new  BigInteger(M)).modPow(e,  N).toByteArray();          }  }  

 Ø DecryptPictureTask.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.graphics.drawable.Drawable;  import  android.os.AsyncTask;    import  java.io.ByteArrayInputStream;  import  java.math.BigInteger;  import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/2/15.    */  public  class  DecryptPictureTask  extends  AsyncTask<ArrayList<byte[]>,  Integer,  Drawable>  {            Context  context;          BigInteger  N,  d;          String  fromUser;            public  DecryptPictureTask(Context  context,  String  user)  {                  this.context  =  context;                  fromUser  =  user;          }            @Override          protected  Drawable  doInBackground(ArrayList<byte[]>...  params)  {                  DBHelper  db  =  new  DBHelper(context);                  ArrayList<String>  user  =  db.getUser();                    N  =  BigInteger.valueOf(0);                  d  =  BigInteger.valueOf(0);                    N  =  N.add(new  BigInteger((user.get(5).split("-­‐"))[0]));                  d  =  d.add(new  BigInteger((user.get(4).split("-­‐"))[1]));                    ArrayList<byte[]>  imgBytesEnc  =  params[0];                    int  listSize  =  imgBytesEnc.size();  

                 for  (int  i  =  0;  i<listSize;  i++){                          byte[]  temp  =  messageDecryption(imgBytesEnc.get(i));                          imgBytesEnc.remove(i);                          imgBytesEnc.add(i,  temp);                          //System.out.println("Decrypted  "+i);                  }                    System.out.println("Decrypted  ");                    int  counter  =  0;                  for(int  i  =  0;  i  <  imgBytesEnc.size();  i++){                          counter  +=  imgBytesEnc.get(i).length;                          if  (imgBytesEnc.get(i).length  <  255  &&  i  !=  imgBytesEnc.size()-­‐1){                                  counter++;                          }                  }                    byte[]  newBitmapData  =  new  byte[counter];                  int  newCounter  =  0;                  for  (int  i  =  0;  i  <  imgBytesEnc.size();  i++){                          for  (int  j  =  0;  j  <  imgBytesEnc.get(i).length;  j++){                                  if  (imgBytesEnc.get(i).length  <  255  &&  j==0  &&  i  !=  imgBytesEnc.size()-­‐1){                                          newBitmapData[newCounter]  =  (i  ==  0  ?  (byte)-­‐1  :  (byte)0);                                          newCounter++;                                  }                                  newBitmapData[newCounter]  =  imgBytesEnc.get(i)[j];                                  newCounter++;                          }                  }                    System.out.println("Reassembled  ");                  ByteArrayInputStream  is  =  new  ByteArrayInputStream(newBitmapData);                    Drawable  drw  =  Drawable.createFromStream(is,  "articleImage");      

 

 xxiv  

               return  drw;          }            @Override          protected  void  onPreExecute()  {                  super.onPreExecute();          }            @Override          protected  void  onPostExecute(Drawable  drawable)  {                  super.onPostExecute(drawable);                  ((ContactsTabActivity)context).addToConversation(fromUser,  drawable);            }            @Override          protected  void  onProgressUpdate(Integer...  values)  {                  super.onProgressUpdate(values);          }            @Override          protected  void  onCancelled(Drawable  drawable)  {  

               super.onCancelled(drawable);          }            public  byte[]  messageDecryption(byte[]  D){                  byte[]  msgToDecrypt  =  new  byte[D.length-­‐1];                  for  (int  i  =  0;  i<D.length-­‐1;  i++){                          msgToDecrypt[i]  =  D[i];                  }                  System.out.println(""+D[D.length-­‐1]);                  BigInteger  encryptedMsg  =  new  BigInteger(msgToDecrypt);                    encryptedMsg  =  encryptedMsg.modPow(d,  N);                    if  (D[D.length-­‐1]  ==  (byte)1){                          encryptedMsg  =  encryptedMsg.multiply(BigInteger.valueOf(-­‐1));                  }                    return  encryptedMsg.toByteArray();                  //return  (new  BigInteger(D)).modPow(d,  N).toByteArray();          }  }  

 Ø ReceiveMessageTask.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.os.AsyncTask;    import  java.io.BufferedReader;  import  java.io.DataInputStream;  import  java.io.DataOutputStream;  import  java.io.IOException;  import  java.io.InputStream;  import  java.io.InputStreamReader;  import  java.io.OutputStream;  import  java.net.Socket;  import  java.util.ArrayList;    /**    *  Created  by  ricardoviteri  on  7/22/15.    */  public  class  RecieveMessageTask  extends  AsyncTask<ArrayList<Object>,  Integer,  Integer>  {            Context  context;          String  fromUser;          Object  message;            public  RecieveMessageTask(Context  ctx){                  context  =  ctx;          }            @Override          protected  Integer  doInBackground(ArrayList<Object>...  params)  {                    Socket  sock  =  null;                  try  {  

                       sock  =  new  Socket("192.168.1.103",  8998);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                    OutputStream  out  =  null;                  try  {                          out  =  sock.getOutputStream();                          DataOutputStream  dos  =  new  DataOutputStream(out);                          dos.writeChar('E');                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                      InputStream  in  =  null;                  try  {                          in  =  sock.getInputStream();                          DataInputStream  dis  =  new  DataInputStream(in);                          //dis.wait(1000);                            char  type  =  dis.readChar();                          if  (type  ==  'M'){                                  int  len  =  dis.readInt();                                  System.out.println("size:  "+len);                                  byte[]  data  =  new  byte[len];                                  if  (len  >  0){                                          dis.readFully(data);                                  }                                  System.out.println("message:  "+new  String(data));                                  message  =  data;                          }else{                                  int  imgLen  =  dis.readInt();                                  System.out.println("size:  "+imgLen);  

 

 xxv  

                                 ArrayList<byte[]>  image  =  new  ArrayList<byte[]>();                                    for  (int  i  =  0;  i  <  imgLen;  i++){                                          System.out.println("Receiving");                                          int  len  =  dis.readInt();                                          byte[]  data  =  new  byte[len];                                          if  (len  >  0){                                                  dis.readFully(data);                                          }                                          image.add(data);                                          System.out.println("Received  #"+i);                                  }                                  System.out.println("Info  received:  "+image.size());                                  message  =  image;                          }                    }  catch  (IOException  e)  {                          e.printStackTrace();                  }                        //initialize  reading                  InputStreamReader  IR  =  null;                  try  {                          IR  =  new  InputStreamReader(sock.getInputStream());                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  BufferedReader  BR  =  new  BufferedReader(IR);  

               //look  for  messages  that  might  be  received  by  the  server                    try  {                          fromUser  =  BR.readLine();                          System.out.println("from:  "+fromUser);                          //System.out.println(MESSAGE);                  }  catch  (Exception  e)  {                          e.printStackTrace();                  }                  try  {                          sock.close();                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  return  null;          }            @Override          protected  void  onPostExecute(Integer  integer)  {                  super.onPostExecute(integer);                  if  (message  instanceof  byte[]){                          ((ContactsTabActivity)context).addToConversation(fromUser,  message);                  }else{                          new  DecryptPictureTask(context,  fromUser).execute((ArrayList<byte[]>)message);                  }            }  }  

 Ø UpdateKeyTask.java  

package  com.example.ricardoviteri.safetimeapp;    import  android.content.Context;  import  android.os.AsyncTask;    import  java.io.BufferedReader;  import  java.io.IOException;  import  java.io.InputStreamReader;  import  java.io.ObjectOutputStream;  import  java.io.PrintStream;  import  java.net.Socket;    /**    *  Created  by  ricardoviteri  on  7/16/15.    */  public  class  UpdateKeyTask  extends  AsyncTask<String,  Integer,  String>  {            Context  context;          String  key,  email;          String[]  userInfo  =  new  String[3];            public  UpdateKeyTask(Context  ctx,  String  publicKey,  String  mail)  {                  context  =  ctx;                  key  =  publicKey;                  email  =  mail;          }    

       @Override          protected  String  doInBackground(String...  params)  {                  String[]  user  =  new  String[2];                  user[0]  =  email;                  user[1]  =  key;                    Socket  sock  =  null;                  try  {                          sock  =  new  Socket("192.168.1.103",  9002);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                      ObjectOutputStream  out  =  null;                  try  {                          out  =  new  ObjectOutputStream(sock.getOutputStream());                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  try  {                          out.writeObject(user);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }      

 

 xxvi  

               //initialize  reading                  InputStreamReader  IR  =  null;                  try  {                          IR  =  new  InputStreamReader(sock.getInputStream());                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                  BufferedReader  BR  =  new  BufferedReader(IR);                  //look  for  messages  that  might  be  received  by  the  server                  String  MESSAGE  =  null;                  try  {                          MESSAGE  =  BR.readLine();                          System.out.println(MESSAGE);                  }  catch  (IOException  e)  {                          e.printStackTrace();                  }                    return  MESSAGE;          }  

         @Override          protected  void  onPreExecute()  {                  super.onPreExecute();          }            @Override          protected  void  onPostExecute(String  string)  {                  super.onPostExecute(string);                  ((LoginActivity)context).keysUpdated(string);          }            @Override          protected  void  onProgressUpdate(Integer...  values)  {                  super.onProgressUpdate(values);          }    }  

 Ø SOK_CLIENT.java  

package  com.example.ricardoviteri.safetimeapp;  import  android.os.AsyncTask;    import  java.io.*;  import  java.net.*;    /**    *  Created  by  ricardoviteri  on  7/7/15.    */  public  class  SOK_CLIENT  {          byte[]  encMessage;          String  key;            public  SOK_CLIENT(byte[]  msg,  String  key)  {                  encMessage  =  msg;                  this.key  =  key;          }            public  void  run()  throws  Exception{                  new  MyAsyncTask().execute();          }            private  class  MyAsyncTask  extends  AsyncTask<Void,  Void,  Void>          {                  @Override                  protected  void  onPostExecute(Void  result)  {                          //Task  you  want  to  do  on  UIThread  after  completing  Network  operation                          //onPostExecute  is  called  after  doInBackground  finishes  its  task.                  }                    @Override                  protected  Void  doInBackground(Void...  params)  {                          //Do  your  network  operation  here                          //create  a  socket  for  port  1500  at  the  Localhost                          Socket  sock  =  null;                          try  {  

                               sock  =  new  Socket("192.168.1.103",  9000);                          }  catch  (IOException  e)  {                                  e.printStackTrace();                          }                          //print  a  message  to  be  sent  to  the  server                          PrintStream  PS  =  null;                          try  {                                  PS  =  new  PrintStream(sock.getOutputStream());                          }  catch  (IOException  e)  {                                  e.printStackTrace();                          }                          PS.println(key);                              OutputStream  out  =  null;                          try  {                                  out  =  sock.getOutputStream();                          }  catch  (IOException  e)  {                                  e.printStackTrace();                          }                          DataOutputStream  dos  =  new  DataOutputStream(out);                            try  {                                  dos.writeInt(encMessage.length);                          }  catch  (IOException  e)  {                                  e.printStackTrace();                          }                          if  (encMessage.length  >  0)  {                                  try  {                                          dos.write(encMessage,  0,  encMessage.length);                                  }  catch  (IOException  e)  {                                          e.printStackTrace();                                  }                          }                              //initialize  reading                          InputStreamReader  IR  =  null;  

 

 xxvii  

                       try  {                                  IR  =  new  InputStreamReader(sock.getInputStream());                          }  catch  (IOException  e)  {                                  e.printStackTrace();                          }                          BufferedReader  BR  =  new  BufferedReader(IR);                          //look  for  messages  that  might  be  received  by  the  server                          String  MESSAGE  =  null;                          try  {                                  MESSAGE  =  BR.readLine();                          }  catch  (IOException  e)  {                                  e.printStackTrace();                          }                          System.out.println(MESSAGE);                          return  null;                  }          }    }  

 

 

 xxviii  

Appendix  B:  Server  codes  Ø socketServer.java  

package  saveTimeServer;  import  java.io.*;  import  java.net.*;  import  java.util.ArrayList;  import  java.util.Date;  import  java.util.List;    import  com.mongodb.BasicDBObject;  import  com.mongodb.DB;  import  com.mongodb.DBCollection;  import  com.mongodb.DBCursor;  import  com.mongodb.DBObject;  import  com.mongodb.MongoClient;    import  socketThreads.LoginUserThread;  import  socketThreads.NewUserThread;  import  socketThreads.SendMessageThread;  import  socketThreads.TestThread;  import  socketThreads.TimerThread;  import  socketThreads.UpdateKeyThread;    import  java.math.BigInteger;    public  class  socketServer  {       static  BigInteger  d;     static  BigInteger  N;     static  boolean  keepLoop  =  true;     static  boolean  receivingMsg  =  true;     static  int  actualPort;     static  ArrayList<ArrayList<Object>>  tasksToDo  =  new  ArrayList<ArrayList<Object>>();     static  ArrayList<ArrayList<Object>>  tasksForCycle  =  new  ArrayList<ArrayList<Object>>();         public  static  void  main(String[]  args)  throws  Exception{       socketServer  SERVER  =  new  socketServer();       N  =  BigInteger.valueOf(0);                  d  =  BigInteger.valueOf(0);                  NewUserThread  newUserThread  =  new  NewUserThread();                  newUserThread.start();                  UpdateKeyThread  updateKeyThread  =  new  UpdateKeyThread();                  updateKeyThread.start();                  LoginUserThread  loginUserThread  =  new  LoginUserThread();                  loginUserThread.start();                  TestThread  test  =  new  TestThread(SERVER);                  test.start();                         //SERVER.runKeyDecryption();                                    MongoClient  mongo  =  new  MongoClient("localhost",  27017);               /****  Get  database  ****/       //  if  database  doesn't  

exists,  MongoDB  will  create  it  for  you       DB  db  =  mongo.getDB("safetimedb");             actualPort  =  9003;                              while(true){                     //System.out.println("TaskPending:  "+tasksToDo.size());                     //System.out.println("TaskForCycle:  "+tasksForCycle.size());                     while(tasksForCycle.size()  >  0){                       tasksToDo.add(tasksForCycle.get(0));                       tasksForCycle.remove(0);                     }                     for(int  i  =  0;  i  <  tasksToDo.size();  i++){                       if(Integer.parseInt((String)  tasksToDo.get(i).get(0))  ==  actualPort){                         tasksForCycle.add(tasksToDo.get(i));                         tasksToDo.remove(i);                         i-­‐-­‐;                       }                     }                     //System.out.println("TaskPending:  "+tasksToDo.size());                     //System.out.println("TaskForCycle:  "+tasksForCycle.size());                                         keepLoop  =  true;                     TimerThread  timer  =  new  TimerThread(SERVER);                     timer.start();                     ServerSocket  srvrSocket  =  new  ServerSocket();;                     try{                       SERVER.mainUsersCycle(actualPort,  srvrSocket,  timer);                     }catch(Exception  e){                       //e.printStackTrace();                       timer.stop();                       srvrSocket.close();                     }                     //srvrSocket.close();                                         DBCollection  table  =  db.getCollection("users");                     int  numUsers  =  (int)  table.count();                                         actualPort  =  (actualPort  ==  9003+numUsers-­‐1  ?  9003  :  actualPort+1);                     //System.out.println("yo  ya  estoy!  -­‐-­‐-­‐>  "+actualPort);                     timer  =  null;                  }                   }  

 

 xxix  

          public  void  mainUsersCycle(int  Port,  ServerSocket  srvrSocket,  TimerThread  timer)  throws  Exception{             //System.out.println("MainUsersCycle:  "+"Main  socket  open");             //create  a  ServerSocket  for  Port       srvrSocket.setReuseAddress(true);       srvrSocket.bind(new  InetSocketAddress(Port));             srvrSocket.setSoTimeout(21000);       Socket  sock;             while(keepLoop){         //open  socket  connection                         sock  =  srvrSocket.accept();         sock.setSoTimeout(21000);         //sock.setKeepAlive(true);         InputStreamReader  ir  =  new  InputStreamReader(sock.getInputStream());                 BufferedReader  br  =  new  BufferedReader(ir);                 String  MESSAGE  =  br.readLine();                 PrintStream  Ps  =  new  PrintStream(sock.getOutputStream());                 /**          *  0:  Nothing  to  do          *  1:  Make  app  listen          *  2:  Make  app  send  data         **/         if(Integer.parseInt(MESSAGE)  ==  0  &&  tasksForCycle.size()  ==  0){           //System.out.println("Nothing  to  do  with  "+Port);           keepLoop  =  false;           timer.stop();                       srvrSocket.close();           Ps.println("0");         }else  

if(tasksForCycle.size()  !=  0){           Ps.println("1");           System.out.println("Send  stuff  to  app");           /**            *  10:  SOMEONE  ADDED  AS  CONTACT            *  11:  SOMEONE  SENT  A  MESSAGE            */                     ArrayList<Object>  task  =  tasksForCycle.get(0);                     if(Integer.parseInt((String)  task.get(1))  ==  10){             /**              *  ***********  Add  contact  task  list  **************              *       0:  Port              *       1:  taskId              *       2:  name              *       3:  email              *       4:  key              */                         Ps.println("10");                         System.out.println("Sending  contact!!!");             Ps.println(task.get(2));             Ps.println(task.get(3));             Ps.println(task.get(4));           }                     if(Integer.parseInt((String)  task.get(1))  ==  11){             /**              *  ***********  Send  message  task  list  **************              *       0:  Port              *       1:  taskId              *       2:  from  who          

 

 xxx  

   *       3:  message              */             SendMessageThread  loginUserThread  =  new  SendMessageThread(this,  task.get(3),  (String)  task.get(2));                        loginUserThread.start();                         Ps.println("11");                         System.out.println("Sending  message!!!");                         /*byte[]  encMessage  =  (byte[])  task.get(3);             //Ps.println(""+encMessage.length);                         Ps.println(encMessage);                         OutputStream  out  =  sock.getOutputStream();             DataOutputStream  dos  =  new  DataOutputStream(out);                         dos.write(encMessage);                         if(encMessage.length  >  0){               dos.write(encMessage,  0,  encMessage.length);             }             */           }                     tasksForCycle.remove(0);           //TODO:  Send  stuff  to  app!         }else{           Ps.println("2");                     MESSAGE  =  br.readLine();                     /**            *  1:  

ADD  CONTACT            *  2:  MESSAGE           **/           //ADD  CONTACT  PROCESS           if(Integer.parseInt(MESSAGE)  ==  1){             String  user  =  br.readLine();                         MongoClient  mongo  =  new  MongoClient("localhost",  27017);                           /****  Get  database  ****/             //  if  database  doesn't  exists,  MongoDB  will  create  it  for  you             DB  db  =  mongo.getDB("safetimedb");                         /****  Get  collection  /  table  from  'testdb'  ****/             //  if  collection  doesn't  exists,  MongoDB  will  create  it  for  you             DBCollection  table  =  db.getCollection("users");                         /****  Find  and  display  ****/             BasicDBObject  searchQuery  =  new  BasicDBObject();             searchQuery.put("email",  user);                         DBCursor  cursor  =  table.find(searchQuery);                         /**                *  1:  User  found              *  2:  User  not  found             **/             List<DBObject>  csrList  =  cursor.toArray();             PrintStream  PS  =  new  PrintStream(sock.getOutputStream());             if  (csrList.size()  >  0)  {               System.out.println("MainUsersCycle

 

 xxxi  

/AddContact:  User  found");                             PS.println("1");               PS.println(csrList.get(0).get("name").toString());               PS.println(csrList.get(0).get("email").toString());               PS.println(csrList.get(0).get("key").toString());                             /**                *  ***********  Add  contact  task  list  **************                *       0:  Port                *       1:  taskId                *       2:  name                *       3:  email                *       4:  key                */               BasicDBObject  searchQuery2  =  new  BasicDBObject();               searchQuery.put("port",  Port);                             DBCursor  cursor2  =  table.find(searchQuery2);               List<DBObject>  csrList2  =  cursor2.toArray();               ArrayList<Object>  task  =  new  ArrayList<Object>();               task.add(csrList.get(0).get("port").toString());               task.add("10");               task.add(csrList2.get(0).get("name").toString());          

    task.add(csrList2.get(0).get("email").toString());               task.add(csrList2.get(0).get("key").toString());                             tasksToDo.add(task);                                         }else{               System.out.println("MainUsersCycle/AddContact:  User  not  found");               PS.println("2");             }                       }                     if(Integer.parseInt(MESSAGE)  ==  2){                         while(receivingMsg){               //System.out.println("waiting");             }             System.out.println("finished  waiting");             receivingMsg  =  true;             }                             }                                            sock.close();               }       srvrSocket.close();           }         public  void  changeStopLoop(){       keepLoop  =  false;     }         public  void  stopReceiving(){       receivingMsg  =  false;     }         public  void  stopReceivingMsg(Object  msg,  String  toUser,  

 

 xxxii  

String  fromUser){       //int  thisPort  =  actualPort;       receivingMsg  =  false;       if(msg  instanceof  byte[]){         System.out.println(new  String((byte[])msg));       }else{         System.out.println("Is  an  image");       }       System.out.println(toUser);       ArrayList<Object>  task  =  new  ArrayList<Object>();       /**        *  ***********  Send  message  task  list  **************        *       0:  Port        *       1:  taskId        *       2:  from  who        *       3:  message        */             MongoClient  mongo  =  null;       try  {         mongo  =  new  MongoClient("localhost",  27017);       }  catch  (UnknownHostException  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }               /****  Get  database  ****/       //  if  database  doesn't  exists,  MongoDB  will  create  it  for  you       DB  db  =  mongo.getDB("safetimedb");             /****  Get  collection  /  table  from  'testdb'  ****/       //  if  collection  doesn't  exists,  MongoDB  will  create  it  for  you       DBCollection  table  =  db.getCollection("users");             /****  Find  and  display  ****/       BasicDBObject  searchQuery  =  new  BasicDBObject();       searchQuery.put("email",  toUser);             DBCursor  cursor  =  table.find(searchQuery);       List<DBObject>  csrList  =  cursor.toArray();       String  endUserPort  =  csrList.get(0).get("port").toString();  

    System.out.println("Send  message  task  list  port:  "+endUserPort);             /*BasicDBObject  searchQuery2  =  new  BasicDBObject();       System.out.println("thisPort"+thisPort);       searchQuery2.put("port",  thisPort);             DBCursor  cursor2  =  table.find(searchQuery);       List<DBObject>  csrList2  =  cursor2.toArray();       String  thisUser  =  csrList2.get(0).get("email").toString();       */       System.out.println("Send  message  task  list  user:  "+fromUser);             task.add(endUserPort);       task.add("11");       task.add(fromUser);       task.add(msg);             tasksToDo.add(task);     }         public  void  runKeyDecryption()  throws  Exception{             //create  a  ServerSocket  for  port  8080       ServerSocket  srvrSocket  =  new  ServerSocket(9003);       srvrSocket.setReuseAddress(true);       Socket  sock;             while(true){         //open  socket  connection         sock  =  srvrSocket.accept();         //sock.setKeepAlive(true);         System.out.println("Checkpoint  1");             InputStreamReader  IR  =  new  InputStreamReader(sock.getInputStream());         BufferedReader  BR  =  new  BufferedReader(IR);               //check  for  messages  received  from  the  socket         String  MESSAGE  =  BR.readLine();               N  =  N.add(new  BigInteger((MESSAGE.split("-­‐"))[0]));         d  =  d.add(new  BigInteger((MESSAGE.split("-­‐"))[1]));                           System.out.println(""+N);  

 

 xxxiii  

      System.out.println(""+d);                 System.out.println("Checkpoint  2");               MESSAGE  =  "now  the  message...";                 InputStream  in  =  sock.getInputStream();         DataInputStream  dis  =  new  DataInputStream(in);           int  len  =  dis.readInt();         System.out.println("size:  "+len);                 System.out.println("Checkpoint  3");                 byte[]  data  =  new  byte[len];         if  (len  >  0)  {           dis.readFully(data);         }                     System.out.println("Checkpoint  4");         System.out.println(new  String(data));                     if(data.length  !=  0){           //if  a  message  is  received,  print  in  console  

        PrintStream  PS  =  new  PrintStream(sock.getOutputStream());           PS.println("MESSAGE  recieved");         }                 System.out.println("Checkpoint  5");                 /*byte[]  decMessage  =  messageDecryption(data);         System.out.println(new  String(decMessage));         N  =  BigInteger.valueOf(0);                    d  =  BigInteger.valueOf(0);                    */                    data  =  null;                    sock.close();       }           }             public  byte[]  messageDecryption(byte[]  D){                  BigInteger  encryptedMsg  =  new  BigInteger(D);                  encryptedMsg  =  encryptedMsg.modPow(d,  N);                  return  encryptedMsg.toByteArray();                  //return  (new  BigInteger(D)).modPow(d,  N).toByteArray();          }        }  

 Ø LoginUserThread.java  

package  socketThreads;    import  java.io.BufferedReader;  import  java.io.InputStream;  import  java.io.InputStreamReader;  import  java.io.ObjectInputStream;  import  java.io.PrintStream;  import  java.net.ServerSocket;  import  java.net.Socket;  import  java.util.List;    import  com.mongodb.BasicDBObject;  import  com.mongodb.DB;  import  com.mongodb.DBCollection;  import  com.mongodb.DBCursor;  import  com.mongodb.DBObject;  import  com.mongodb.MongoClient;    public  class  LoginUserThread    extends  Thread  {       public  void  run(){       try  {         loginUserTask();  

    }  catch  (Exception  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }     }         public  void  loginUserTask()  throws  Exception{             //create  a  ServerSocket  for  port  8080       ServerSocket  srvrSocket  =  new  ServerSocket(9001);       srvrSocket.setReuseAddress(true);       Socket  sock;             System.out.println("LoginUserThread:  "+"Login  socket  open");             while(true){         //open  socket  

 

 xxxiv  

connection         sock  =  srvrSocket.accept();                 InputStream  in  =  sock.getInputStream();         ObjectInputStream  dis  =  new  ObjectInputStream(in);                 String[]  user  =  new  String[2];               user  =  (String[])  dis.readObject();                     if(user.length  !=  0){           //if  a  message  is  received,  print  in  console           System.out.println("LoginUserThread:  "+""+user[0]);           System.out.println("LoginUserThread:  "+""+user[1]);                     //TODO:  Add  user  to  DataBase!  send  a  unique  port  number  to  user.                     MongoClient  mongo  =  new  MongoClient("localhost",  27017);                       /****  Get  database  ****/           //  if  database  doesn't  exists,  MongoDB  will  create  it  for  you           DB  db  =  mongo.getDB("safetimedb");                     /****  Get  collection  /  table  from  'testdb'  ****/           //  if  collection  doesn't  exists,  MongoDB  will  create  it  for  you           DBCollection  table  =  db.getCollection("users");                     /****  Find  and  display  ****/           BasicDBObject  searchQuery  =  new  BasicDBObject();           searchQuery.put("email",  user[0]);                     DBCursor  cursor  =  table.find(searchQuery);                     /**              *  1:  User  not  found            *  2:  Correct  password  

         *  3:  Incorrect  password            *  4:  Info  not  received           **/           List<DBObject>  csrList  =  cursor.toArray();                     if  (csrList.size()  >  0)  {             String  pass  =  csrList.get(0).get("password").toString();             System.out.println(pass);             if(pass.equals(user[1])){               PrintStream  PS  =  new  PrintStream(sock.getOutputStream());               PS.println("2");               PS.println(csrList.get(0).get("name").toString());               PS.println(csrList.get(0).get("phone").toString());               PS.println(csrList.get(0).get("email").toString());               PS.println(csrList.get(0).get("port").toString());                             InputStreamReader  IR  =  new  InputStreamReader(sock.getInputStream());               BufferedReader  BR  =  new  BufferedReader(IR);                           //check  for  messages  received  from  the  socket               String  MESSAGE  =  BR.readLine();               System.out.println(MESSAGE);                           }else{               PrintStream  PS  =  new  PrintStream(sock.getOutputStream());               PS.println("3");          

 

 xxxv  

  }                       }else{             PrintStream  PS  =  new  PrintStream(sock.getOutputStream());             PS.println("1");           }           }else{  

        PrintStream  PS  =  new  PrintStream(sock.getOutputStream());           PS.println("4");         }                       sock.close();       }     }  }  

   

Ø NewUserThread.java  package  socketThreads;    import  java.io.InputStream;  import  java.io.ObjectInputStream;  import  java.io.PrintStream;  import  java.net.ServerSocket;  import  java.net.Socket;    import  com.mongodb.BasicDBObject;  import  com.mongodb.DB;  import  com.mongodb.DBCollection;  import  com.mongodb.DBCursor;  import  com.mongodb.MongoClient;    public  class  NewUserThread  extends  Thread  {         public  void  run(){       try  {         runNewUserTask();       }  catch  (Exception  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }     }         public  void  runNewUserTask()  throws  Exception{             //create  a  ServerSocket  for  port  8080       ServerSocket  srvrSocket  =  new  ServerSocket(9000);       srvrSocket.setReuseAddress(true);       Socket  sock;       System.out.println("NewUserThread:  "+"Registration  socket  open");             while(true){         //open  socket  connection         sock  =  srvrSocket.accept();                 InputStream  in  =  sock.getInputStream();      

  ObjectInputStream  dis  =  new  ObjectInputStream(in);                 String[]  user  =  new  String[5];               user  =  (String[])  dis.readObject();                     if(user.length  !=  0){           //if  a  message  is  received,  print  in  console           System.out.println("NewUserThread:  "+""+user[0]);           System.out.println("NewUserThread:  "+""+user[1]);           System.out.println("NewUserThread:  "+""+user[2]);           System.out.println("NewUserThread:  "+""+user[3]);           System.out.println("NewUserThread:  "+""+user[4]);                     //TODO:  Add  user  to  DataBase!  send  a  unique  port  number  to  user.                     MongoClient  mongo  =  new  MongoClient("localhost",  27017);                       /****  Get  database  ****/           //  if  database  doesn't  exists,  MongoDB  will  create  it  for  you           DB  db  =  mongo.getDB("safetimedb");                     /****  Get  collection  /  table  from  'testdb'  ****/           //  if  collection  doesn't  exists,  MongoDB  will  create  it  for  you        

 

 xxxvi  

  DBCollection  table  =  db.getCollection("users");                     /****  Find  and  display  ****/           BasicDBObject  searchQuery  =  new  BasicDBObject();           searchQuery.put("email",  user[2]);                     DBCursor  cursor  =  table.find(searchQuery);                     /**              *  1:  Sucessfully  added            *  2:  Email  already  registered            *  3:  User  not  received           **/           if  (cursor.length()  >  0)  {             PrintStream  PS  =  new  PrintStream(sock.getOutputStream());             PS.println("2");           }else{             long  port  =  9003  +  table.count();             /****  Insert  ****/             //  create  a  document  to  store  key  and  value             BasicDBObject  document  =  new  

BasicDBObject();             document.put("name",  user[0]);             document.put("phone",  user[1]);             document.put("email",  user[2]);             document.put("password",  user[3]);             document.put("key",  user[4]);             document.put("port",  ""+port);             table.insert(document);                                 PrintStream  PS  =  new  PrintStream(sock.getOutputStream());             PS.println("1");             PS.println(""+port);           }                   }else{           PrintStream  PS  =  new  PrintStream(sock.getOutputStream());           PS.println("3");         }                       sock.close();       }     }      }  

   

Ø SendMessageThread.java  package  socketThreads;    import  java.io.BufferedReader;  import  java.io.DataInputStream;  import  java.io.DataOutputStream;  import  java.io.IOException;  import  java.io.InputStream;  import  java.io.InputStreamReader;  import  java.io.OutputStream;  import  java.io.PrintStream;  import  java.net.ServerSocket;  import  java.net.Socket;  import  java.util.ArrayList;    import  saveTimeServer.socketServer;    public  class  SendMessageThread  extends  Thread{         socketServer  parent;     Object  encMessage;     String  user;      

  public  SendMessageThread(socketServer  context,  Object  msg,  String  usrToSend){       parent  =  context;       encMessage  =  msg;       user  =  usrToSend;     }         public  void  run(){       try  {         sendMessage();       }  catch  (Exception  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }     }         public  void  sendMessage()  throws  Exception{       try  {      

 

 xxxvii  

  System.out.println("SendMessage  running");         ServerSocket  srvrSocket  =  new  ServerSocket(8998);         srvrSocket.setReuseAddress(true);         Socket  sock;         sock  =  srvrSocket.accept();                 InputStream  in  =  sock.getInputStream();         DataInputStream  dis  =  new  DataInputStream(in);                 char  cosa  =  dis.readChar();         OutputStream  out  =  sock.getOutputStream();         DataOutputStream  dos  =  new  DataOutputStream(out);                 if(encMessage  instanceof  byte[]){           System.out.println(new  String((byte[])encMessage));                     dos.writeChar('M');                     dos.writeInt(((byte[])encMessage).length);                     if(((byte[])encMessage).length  >  0){             dos.write(((byte[])encMessage),  0,  ((byte[])encMessage).length);           }  

      }else{           dos.writeChar('I');                     dos.writeInt(((ArrayList)encMessage).size());                     for(int  i  =  0;  i  <  ((ArrayList)encMessage).size();  i++){             dos.writeInt(((byte[])((ArrayList)encMessage).get(i)).length);             if(((byte[])((ArrayList)encMessage).get(i)).length  >  0){               dos.write(((byte[])((ArrayList)encMessage).get(i)),  0,  ((byte[])((ArrayList)encMessage).get(i)).length);             }           }         }                         PrintStream  Ps  =  new  PrintStream(sock.getOutputStream());         Ps.println(user);               }  catch  (IOException  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }     }  }  

   

Ø TestThread.java  package  socketThreads;    import  java.io.BufferedReader;  import  java.io.DataInputStream;  import  java.io.IOException;  import  java.io.InputStream;  import  java.io.InputStreamReader;  import  java.net.ServerSocket;  import  java.net.Socket;  import  java.util.ArrayList;    import  saveTimeServer.socketServer;    public  class  TestThread  extends  Thread{         socketServer  parent;         public  TestThread(socketServer  context){       parent  =  context;     }  

      public  void  run(){       try  {         receiveMessage();       }  catch  (Exception  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }     }         public  void  receiveMessage()  throws  Exception{       try  {         System.out.println("TestThread  running");         ServerSocket  srvrSocket  =  new  ServerSocket(8999);  

 

 xxxviii  

      srvrSocket.setReuseAddress(true);         Socket  sock;                 while(true){           sock  =  srvrSocket.accept();                     InputStream  in  =  sock.getInputStream();           DataInputStream  dis  =  new  DataInputStream(in);                     char  type  =  dis.readChar();                     if(type  ==  'M'){             int  len  =  dis.readInt();                         System.out.println("size:  "+len);                         byte[]  data  =  new  byte[len];             if  (len  >  0)  {               dis.readFully(data);             }             InputStreamReader  ir  =  new  InputStreamReader(sock.getInputStream());             BufferedReader  br  =  new  BufferedReader(ir);             String  toUser  =  br.readLine();             String  fromUser  =  br.readLine();             parent.stopReceivingMsg(data,  toUser,  fromUser);           }else{                         int  imgLen  =  dis.readInt();             System.out.println("size  of  image:  "+imgLen);                         ArrayList<Object>  image  =  new  ArrayList<Object>();          

              for(int  i  =  0;  i  <  imgLen;  i++){               System.out.println("Receiving...");               int  len  =  dis.readInt();               byte[]  data  =  new  byte[len];               if  (len  >  0)  {                 dis.readFully(data);               }               image.add(data);               System.out.println("Received  #"+i);             }             System.out.println("info  received:  "+image.size());                         InputStreamReader  ir  =  new  InputStreamReader(sock.getInputStream());             BufferedReader  br  =  new  BufferedReader(ir);             String  toUser  =  br.readLine();             String  fromUser  =  br.readLine();             System.out.println("To  user:  "+toUser);             System.out.println("from  user:    "+fromUser);                         parent.stopReceivingMsg(image,  toUser,  fromUser);           }                             }               }  catch  (IOException  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }     }  }  

     

 

 xxxix  

Ø TimerThread.java  package  socketThreads;    import  saveTimeServer.socketServer;    public  class  TimerThread  extends  Thread{         socketServer  parent;         public  TimerThread(socketServer  context){       parent  =  context;     }         public  void  run(){       try  {         Thread.sleep(20000);       }  catch  (InterruptedException  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }       System.out.println("Timer  finished");       parent.changeStopLoop();     }  }      UpdateKeyThread.java    package  socketThreads;    import  java.io.InputStream;  import  java.io.ObjectInputStream;  import  java.io.PrintStream;  import  java.net.ServerSocket;  import  java.net.Socket;  import  java.util.List;    import  com.mongodb.BasicDBObject;  import  com.mongodb.DB;  import  com.mongodb.DBCollection;  import  com.mongodb.DBCursor;  import  com.mongodb.DBObject;  import  com.mongodb.MongoClient;    public  class  UpdateKeyThread  extends  Thread  {       public  void  run(){       try  {         updateKeyTask();       }  catch  (Exception  e)  {         //  TODO  Auto-­‐generated  catch  block         e.printStackTrace();       }     }         public  void  updateKeyTask()  throws  Exception{  

          //create  a  ServerSocket  for  port  8080       ServerSocket  srvrSocket  =  new  ServerSocket(9002);       srvrSocket.setReuseAddress(true);       Socket  sock;       System.out.println("UpdateKeyThread:  "+"Key  update  socket  open");             while(true){         //open  socket  connection         sock  =  srvrSocket.accept();                 InputStream  in  =  sock.getInputStream();         ObjectInputStream  dis  =  new  ObjectInputStream(in);                 String[]  user  =  new  String[2];               user  =  (String[])  dis.readObject();                     if(user.length  !=  0){           //if  a  message  is  received,  print  in  console           System.out.println("UpdateKeyThread:  "+""+user[0]);           System.out.println("UpdateKeyThread:  "+""+user[1]);                     //TODO:  Add  user  to  DataBase!  send  a  unique  port  number  to  user.                     MongoClient  mongo  =  new  MongoClient("localhost",  27017);                       /****  Get  database  ****/           //  if  database  doesn't  exists,  MongoDB  will  create  it  for  you           DB  db  =  mongo.getDB("safetimedb");                     /****  Get  collection  /  table  from  'testdb'  ****/           //  if  collection  doesn't  exists,  MongoDB  will  create  it  for  you           DBCollection  table  =  db.getCollection("users");                     /****  

 

 xl  

Update  ****/           //  search  document  where  name="mkyong"  and  update  it  with  new  values           BasicDBObject  query  =  new  BasicDBObject();           query.put("email",  user[0]);                               DBCursor  cursor  =  table.find(query);           List<DBObject>  csrList  =  cursor.toArray();           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("name").toString());           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("phone").toString());           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("email").toString());           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("password").toString());           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("key").toString());                               BasicDBObject  newDocument  =  new  BasicDBObject();           newDocument.put("key",  user[1]);                     BasicDBObject  updateObj  =  new  BasicDBObject();           updateObj.put("$set",  newDocument);                     table.update(query,  updateObj);                               BasicDBObject  query2  =  new  BasicDBObject();           query2.put("email",  user[0]);                     cursor  =  table.find(query2);           csrList  =  cursor.toArray();           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("name").toString());           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("phone").toString());           System.out.println("UpdateKeyThre

ad:  "+csrList.get(0).get("email").toString());           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("password").toString());           System.out.println("UpdateKeyThread:  "+csrList.get(0).get("key").toString());                               PrintStream  PS  =  new  PrintStream(sock.getOutputStream());           PS.println("Key  successfully  updated");                   }else{           PrintStream  PS  =  new  PrintStream(sock.getOutputStream());           PS.println("3");         }                       sock.close();       }     }  }  

 

 xli  

Appendix  C:  Test  RSA  keys  Public   key  

A  

N:  287973047397959966459171224813899804924489958240150171144632418612750012436289393

883489292547390478094515661452003404487648891297123185156001603931868101709758060

854839949352859800329224059177127529381738895709481327666740673015294901850034061

159008879133776767576897374331617835968282645031245013734438071430841271859036038

605069182960019317903533872073443874743942934512007359451933780032525716970355007

790263263221016535946736999155442475443611530939510186499607481645389483498274609

515078604074322961514399829579480338601370882132440005276219970272407684466237794

73484759682939168263552990438933236448270783096179  

e:  160939886914470350804474172516213429150273668023601232814645095900670025459200230

304644355172135209280127427290074919281076382688927964778360546919274923613177775

654684802629395792000808537872208888755637137297454336251887414392965423713293041

433037548117073451047132571445088585937354286000656687823149582353153283925830167

883667036666620201187344847795225043011272129079516363716182327319675375254314722

448951792554800672650372287768303941950670829458914643309904386843878828987538610

749396912855124401308615602176079823373962777640789622131528358328099466615218788

89061341341366543520090211856990469300451442976351  

Private   key  

A  

N:  287973047397959966459171224813899804924489958240150171144632418612750012436289393

883489292547390478094515661452003404487648891297123185156001603931868101709758060

854839949352859800329224059177127529381738895709481327666740673015294901850034061

159008879133776767576897374331617835968282645031245013734438071430841271859036038

605069182960019317903533872073443874743942934512007359451933780032525716970355007

790263263221016535946736999155442475443611530939510186499607481645389483498274609

515078604074322961514399829579480338601370882132440005276219970272407684466237794

73484759682939168263552990438933236448270783096179  

d:  130286134905903296878809904273909809219128868288854870690284843330319188758403650

92602163120321437241568892607436032444708019114394600985225325345978141119  

Public   key  

B  

N:  250375816420717654230341390083618198845133857389865187895448181623536720175215737

298162301587416790236753914696792070740168691581277755465981892844665279344032079

125976212548841750698664552841081756451944696489379954094399833574426518895389395

845245661651847121302424064982201516300295530730638594427374756038627538772481163

212583661719376529251612978716399036673963771202535312831189461306724400313299612

148899906147437344328591580095237534896231635413830237266245708588133793967697039

926803474180916493859329352055220340986127416405819953677016209476062898208613556

40874707113754994144032009208031199649556323224773  

e:  160043651603909917991739363542657835352920347005814770669336486989694895266587929

316756426693143361273006937259401116945071669413197601790686825488357671930766433

592384957319696945946716984171843986738705652178961505176933725616075821307250323

230924754483957395151720464793300597866219411321393552930202629652278982658200187

093909761956584267608965637558793753398136709445294001102087043886572237622644790

 

 xlii  

581219866854957968076163032820298263445062213411078395088387552002975117527220656

368452276982213433947994297756918784702763953298638278115079740571615973875815210

5989976397068557238550551265514937312957717154885  

Private   key  

B  

N:  250375816420717654230341390083618198845133857389865187895448181623536720175215737

298162301587416790236753914696792070740168691581277755465981892844665279344032079

125976212548841750698664552841081756451944696489379954094399833574426518895389395

845245661651847121302424064982201516300295530730638594427374756038627538772481163

212583661719376529251612978716399036673963771202535312831189461306724400313299612

148899906147437344328591580095237534896231635413830237266245708588133793967697039

926803474180916493859329352055220340986127416405819953677016209476062898208613556

40874707113754994144032009208031199649556323224773  

d:  125154922989015516313948357087251477948476674921424729140171055347407444329693363

76038257673079408354329994964643989080807755408570576427974105419136074769  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 xliii  

Appendix  D:  Encryption  algorithm  C  code  tests  Ø AES  algorithm:  

// // main.c // AESalgorithm // // Created by Ricardo Viteri on 5/10/15. // Copyright (c) 2015 Ricardo Viteri. All rights reserved. // #include <stdio.h> int cipherKey[4][4] = {{0x2b, 0x28, 0xab, 0x09}, {0x7e, 0xae, 0xf7, 0xcf}, {0x15, 0xd2, 0x15, 0x4f}, {0x16, 0xa6, 0x88, 0x3c}}; int roundKey[4][44] = {{0x2b, 0x28, 0xab, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x7e, 0xae, 0xf7, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x15, 0xd2, 0x15, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x16, 0xa6, 0x88, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; int rCon[4][10] = {{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; int mixColumnMatrix[4][4] = {{2, 3, 1, 1}, {1, 2, 3, 1}, {1, 1, 2, 3}, {3, 1, 1, 2}}; int encLookupTbl[16][16] = {{0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76}, {0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0}, {0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15}, {0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75}, {0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84}, {0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF}, {0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8}, {0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2}, {0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73}, {0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE,

0x5E, 0x0B, 0xDB}, {0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79}, {0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08}, {0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A}, {0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E}, {0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF}, {0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}}; int decLookupTbl[16][16] = {{0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB}, {0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB}, {0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E}, {0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25}, {0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92}, {0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84}, {0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06}, {0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B}, {0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73}, {0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E}, {0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B}, {0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4}, {0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F}, {0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF}, {0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61}, {0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D}}; int twoTable[16][16] = {{0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e}, {0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e}, {0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e}, {0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e}, {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x9

 

 xliv  

4,0x96,0x98,0x9a,0x9c,0x9e}, {0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe}, {0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde}, {0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe}, {0x1b,0x19,0x1f,0x1d,0x13,0x11,0x17,0x15,0x0b,0x09,0x0f,0x0d,0x03,0x01,0x07,0x05}, {0x3b,0x39,0x3f,0x3d,0x33,0x31,0x37,0x35,0x2b,0x29,0x2f,0x2d,0x23,0x21,0x27,0x25}, {0x5b,0x59,0x5f,0x5d,0x53,0x51,0x57,0x55,0x4b,0x49,0x4f,0x4d,0x43,0x41,0x47,0x45}, {0x7b,0x79,0x7f,0x7d,0x73,0x71,0x77,0x75,0x6b,0x69,0x6f,0x6d,0x63,0x61,0x67,0x65}, {0x9b,0x99,0x9f,0x9d,0x93,0x91,0x97,0x95,0x8b,0x89,0x8f,0x8d,0x83,0x81,0x87,0x85}, {0xbb,0xb9,0xbf,0xbd,0xb3,0xb1,0xb7,0xb5,0xab,0xa9,0xaf,0xad,0xa3,0xa1,0xa7,0xa5}, {0xdb,0xd9,0xdf,0xdd,0xd3,0xd1,0xd7,0xd5,0xcb,0xc9,0xcf,0xcd,0xc3,0xc1,0xc7,0xc5}, {0xfb,0xf9,0xff,0xfd,0xf3,0xf1,0xf7,0xf5,0xeb,0xe9,0xef,0xed,0xe3,0xe1,0xe7,0xe5}}; int threeTable[16][16] = {{0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09,0x18,0x1b,0x1e,0x1d,0x14,0x17,0x12,0x11}, {0x30,0x33,0x36,0x35,0x3c,0x3f,0x3a,0x39,0x28,0x2b,0x2e,0x2d,0x24,0x27,0x22,0x21}, {0x60,0x63,0x66,0x65,0x6c,0x6f,0x6a,0x69,0x78,0x7b,0x7e,0x7d,0x74,0x77,0x72,0x71}, {0x50,0x53,0x56,0x55,0x5c,0x5f,0x5a,0x59,0x48,0x4b,0x4e,0x4d,0x44,0x47,0x42,0x41}, {0xc0,0xc3,0xc6,0xc5,0xcc,0xcf,0xca,0xc9,0xd8,0xdb,0xde,0xdd,0xd4,0xd7,0xd2,0xd1}, {0xf0,0xf3,0xf6,0xf5,0xfc,0xff,0xfa,0xf9,0xe8,0xeb,0xee,0xed,0xe4,0xe7,0xe2,0xe1}, {0xa0,0xa3,0xa6,0xa5,0xac,0xaf,0xaa,0xa9,0xb8,0xbb,0xbe,0xbd,0xb4,0xb7,0xb2,0xb1}, {0x90,0x93,0x96,0x95,0x9c,0x9f,0x9a,0x99,0x88,0x8b,0x8e,0x8d,0x84,0x87,0x82,0x81}, {0x9b,0x98,0x9d,0x9e,0x97,0x94,0x91,0x92,0x83,0x80,0x85,0x86,0x8f,0x8c,0x89,0x8a}, {0xab,0xa8,0xad,0xae,0xa7,0xa4,0xa1,0xa2,0xb3,0xb0,0xb5,0xb6,0xbf,0xbc,0xb9,0xba}, {0xfb,0xf8,0xfd,0xfe,0xf7,0xf4,0xf1,0xf2,0xe3,0xe0,0xe5,0xe6,0xef,0xec,0xe9,0xea}, {0xcb,0xc8,0xcd,0xce,0xc7,0xc4,0xc1,0xc2,0xd3,0xd0,0xd5,0xd6,0xdf,0xdc,0xd9,0xda}, {0x5b,0x58,0x5d,0x5e,0x57,0x54,0x51,0x52,0x43,0x40,0x45,0x46,0x4f,0x4c,0x49,0x4a}, {0x6b,0x68,0x6d,0x6e,0x67,0x64,0x61,0x62,0x73,0x70,0x75,0x76,0x7f,0x7c,0x79,0x7a}, {0x3b,0x38,0x3d,0x3e,0x37,0x34,0x31,0x32,0x23,0x20,0x25,0x26,0x2f,0x2c,0x29,0x2a}, {0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,0x13,0x10,0x15,0x16,0x1f,0x1c,0x19,0x1a}}; void keySchedulingProcess(int rotConNum){ int keySchCol[4] = {roundKey[1][3+(rotConNum*4)], roundKey[2][3+(rotConNum*4)], roundKey[3][3+(rotConNum*4)], roundKey[0][3+(rotConNum*4)]}; int lutXaxis, lutYaxis;

for (int i = 0; i < 4; i++) { lutYaxis = (keySchCol[i]&0xf0)>>4; lutXaxis = keySchCol[i]&0x0f; keySchCol[i] = encLookupTbl[lutYaxis][lutXaxis]; } for (int j = 0; j < 4; j++) { roundKey[j][((rotConNum+1)*4)] = roundKey[j][(rotConNum*4)] ^ rCon[j][rotConNum] ^ keySchCol[j]; } for (int i = 1; i < 4; i++) { for (int j = 0; j < 4; j++) { roundKey[j][i+((rotConNum+1)*4)] = roundKey[j][i-1+((rotConNum+1)*4)] ^ roundKey[j][i+(rotConNum*4)]; } } printf("Round Key:\n"); printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n\n", roundKey[0][0], roundKey[0][1], roundKey[0][2], roundKey[0][3], roundKey[0][4], roundKey[0][5], roundKey[0][6], roundKey[0][7], roundKey[0][8], roundKey[0][9], roundKey[0][10], roundKey[0][11], roundKey[0][12], roundKey[0][13], roundKey[0][14], roundKey[0][15], roundKey[0][16], roundKey[0][17], roundKey[0][18], roundKey[0][19], roundKey[0][20], roundKey[0][21], roundKey[0][22], roundKey[0][23], roundKey[0][24], roundKey[0][25], roundKey[0][26], roundKey[0][27], roundKey[0][28], roundKey[0][29], roundKey[0][30], roundKey[0][31], roundKey[0][32], roundKey[0][33], roundKey[0][34], roundKey[0][35], roundKey[0][36], roundKey[0][37], roundKey[0][38], roundKey[0][39], roundKey[0][40], roundKey[0][41], roundKey[0][42], roundKey[0][43], roundKey[1][0], roundKey[1][1], roundKey[1][2], roundKey[1][3], roundKey[1][4], roundKey[1][5], roundKey[1][6], roundKey[1][7], roundKey[1][8], roundKey[1][9], roundKey[1][10], roundKey[1][11], roundKey[1][12], roundKey[1][13], roundKey[1][14], roundKey[1][15], roundKey[1][16], roundKey[1][17], roundKey[1][18], roundKey[1][19], roundKey[1][20], roundKey[1][21], roundKey[1][22], roundKey[1][23], roundKey[1][24], roundKey[1][25], roundKey[1][26], roundKey[1][27], roundKey[1][28], roundKey[1][29], roundKey[1][30], roundKey[1][31], roundKey[1][32], roundKey[1][33], roundKey[1][34], roundKey[1][35], roundKey[1][36], roundKey[1][37], roundKey[1][38], roundKey[1][39], roundKey[1][40], roundKey[1][41], roundKey[1][42], roundKey[1][43], roundKey[2][0], roundKey[2][1], roundKey[2][2], roundKey[2][3], roundKey[2][4], roundKey[2][5], roundKey[2][6], roundKey[2][7], roundKey[2][8], roundKey[2][9], roundKey[2][10], roundKey[2][11], roundKey[2][12], roundKey[2][13], roundKey[2][14], roundKey[2][15], roundKey[2][16], roundKey[2][17], roundKey[2][18], roundKey[2][19], roundKey[2][20], roundKey[2][21], roundKey[2][22], roundKey[2][23], roundKey[2][24], roundKey[2][25], roundKey[2][26], roundKey[2][27], roundKey[2][28], roundKey[2][29], roundKey[2][30], roundKey[2][31], roundKey[2][32], roundKey[2][33], roundKey[2][34], roundKey[2][35], roundKey[2][36], roundKey[2][37], roundKey[2][38], roundKey[2][39], roundKey[2][40], roundKey[2][41], roundKey[2][42], roundKey[2][43], roundKey[3][0], roundKey[3][1], roundKey[3][2], roundKey[3][3], roundKey[3][4], roundKey[3][5], roundKey[3][6], roundKey[3][7], roundKey[3][8], roundKey[3][9], roundKey[3][10], roundKey[3][11], roundKey[3][12], roundKey[3][13], roundKey[3][14], roundKey[3][15], roundKey[3][16], roundKey[3][17], roundKey[3][18], roundKey[3][19], roundKey[3][20], roundKey[3][21], roundKey[3][22], roundKey[3][23], roundKey[3][24],

 

 xlv  

roundKey[3][25], roundKey[3][26], roundKey[3][27], roundKey[3][28], roundKey[3][29], roundKey[3][30], roundKey[3][31], roundKey[3][32], roundKey[3][33], roundKey[3][34], roundKey[3][35], roundKey[3][36], roundKey[3][37], roundKey[3][38], roundKey[3][39], roundKey[3][40], roundKey[3][41], roundKey[3][42], roundKey[3][43]); } int main(int argc, const char * argv[]) { // insert code here... int dataIn[4][4] = {{0x32, 0x88, 0x31, 0xe0}, {0x43, 0x5a, 0x31, 0x37}, {0xf6, 0x30, 0x98, 0x07}, {0xa8, 0x8d, 0xa2, 0x34}}; int rotConNum = 0; //Initial ADDROUNDKEY for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { dataIn[j][i] = dataIn[j][i] ^ roundKey[j][i]; } } keySchedulingProcess(rotConNum); rotConNum++; for (int k = 0; k < 9; k++) { //SUBBYTES state int lutXaxis, lutYaxis; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { lutYaxis = (dataIn[j][i]&0xf0)>>4; lutXaxis = dataIn[j][i]&0x0f; dataIn[j][i] = encLookupTbl[lutYaxis][lutXaxis]; } } printf("Data after SUBBYTES Round %d\n", k+1); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //SHIFTROWS state for (int i = 1; i < 4; i++) { int shiftTemp[4] = {dataIn[i][0], dataIn[i][1], dataIn[i][2], dataIn[i][3]}; dataIn[i][0] = shiftTemp[i]; dataIn[i][1] = shiftTemp[(i+1 < 4 ? i+1 : i+1-4)]; dataIn[i][2] = shiftTemp[(i+2 < 4 ? i+2 : i+2-4)]; dataIn[i][3] = shiftTemp[(i+3 < 4 ? i+3 : i+3-4)]; } printf("Data after SHIFTROWS Round %d\n", k+1); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //MIXCOLUMNS step for (int i = 0; i < 4; i++) { int mixTemp[4] = {dataIn[0][i], dataIn[1][i], dataIn[2][i], dataIn[3][i]}; int mixResult[4]; for (int j = 0; j < 4; j++) { mixResult[j] = mixColumnMatrix[j][0]*mixTemp[0] + mixColumnMatrix[j][1]*mixTemp[1] + mixColumnMatrix[j][2]*mixTemp[2] + mixColumnMatrix[j][3]*mixTemp[3]; int lutXaxis, lutYaxis; lutYaxis = (mixTemp[0]&0xf0)>>4; lutXaxis = mixTemp[0]&0x0f; if (mixColumnMatrix[j][0] == 2) {

mixResult[j] = twoTable[lutYaxis][lutXaxis]; }else if (mixColumnMatrix[j][0] == 3){ mixResult[j] = threeTable[lutYaxis][lutXaxis]; }else{ mixResult[j] = mixTemp[0]; } lutYaxis = (mixTemp[1]&0xf0)>>4; lutXaxis = mixTemp[1]&0x0f; if (mixColumnMatrix[j][1] == 2) { mixResult[j] = mixResult[j] ^ twoTable[lutYaxis][lutXaxis]; }else if (mixColumnMatrix[j][1] == 3){ mixResult[j] = mixResult[j] ^ threeTable[lutYaxis][lutXaxis]; }else{ mixResult[j] = mixResult[j] ^ mixTemp[1]; } lutYaxis = (mixTemp[2]&0xf0)>>4; lutXaxis = mixTemp[2]&0x0f; if (mixColumnMatrix[j][2] == 2) { mixResult[j] = mixResult[j] ^ twoTable[lutYaxis][lutXaxis]; }else if (mixColumnMatrix[j][2] == 3){ mixResult[j] = mixResult[j] ^ threeTable[lutYaxis][lutXaxis]; }else{ mixResult[j] = mixResult[j] ^ mixTemp[2]; } lutYaxis = (mixTemp[3]&0xf0)>>4; lutXaxis = mixTemp[3]&0x0f; if (mixColumnMatrix[j][3] == 2) { mixResult[j] = mixResult[j] ^ twoTable[lutYaxis][lutXaxis]; }else if (mixColumnMatrix[j][3] == 3){ mixResult[j] = mixResult[j] ^ threeTable[lutYaxis][lutXaxis]; }else{ mixResult[j] = mixResult[j] ^ mixTemp[3]; } } dataIn[0][i] = mixResult[0]; dataIn[1][i] = mixResult[1]; dataIn[2][i] = mixResult[2]; dataIn[3][i] = mixResult[3]; } printf("Data after MIXCOLUMNS Round %d\n", k+1); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //ADDROUNDKEY step for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { dataIn[j][i] = dataIn[j][i] ^ roundKey[j][i]; } } printf("Data after ADDROUNDKEY Round %d\n", k+1); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); keySchedulingProcess(rotConNum);

 

 xlvi  

rotConNum++; } //final SUBBYTES state int lutXaxis, lutYaxis; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { lutYaxis = (dataIn[j][i]&0xf0)>>4; lutXaxis = dataIn[j][i]&0x0f; dataIn[j][i] = encLookupTbl[lutYaxis][lutXaxis]; } } printf("Data after SUBBYTES Round 10\n"); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //final SHIFTROWS state for (int i = 1; i < 4; i++) { int shiftTemp[4] = {dataIn[i][0], dataIn[i][1], dataIn[i][2], dataIn[i][3]}; dataIn[i][0] = shiftTemp[i]; dataIn[i][1] = shiftTemp[(i+1 < 4 ? i+1 : i+1-4)]; dataIn[i][2] = shiftTemp[(i+2 < 4 ? i+2 : i+2-4)]; dataIn[i][3] = shiftTemp[(i+3 < 4 ? i+3 : i+3-

4)]; } printf("Data after SHIFTROWS Round 10\n"); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); //final ADDROUNDKEY step for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { dataIn[j][i] = dataIn[j][i] ^ roundKey[j][i]; } } printf("Data after ADDROUNDKEY Round 10\n**************CIPHERETEXT****************\n"); printf("%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n%02x %02x %02x %02x\n\n", dataIn[0][0], dataIn[0][1], dataIn[0][2], dataIn[0][3], dataIn[1][0], dataIn[1][1], dataIn[1][2], dataIn[1][3], dataIn[2][0], dataIn[2][1], dataIn[2][2], dataIn[2][3], dataIn[3][0], dataIn[3][1], dataIn[3][2], dataIn[3][3]); return 0; }

 

 

Ø RSA  algorithm:  // // main.c // RSAalgorithm // // Created by Ricardo Viteri on 5/7/15. // Copyright (c) 2015 Ricardo Viteri. All rights reserved. // #include <stdio.h> #include <math.h> #include <stdlib.h> int main(int argc, const char * argv[]) { // insert code here... /******************************** KEY GENERATION *******************************/ int p = 3, q = 13; //Obtain n int n = p*q; //use Euler totient function to obtain phi (phi(n)) int phi = n - (p + q - 1); //choose an integer e such as (1 < e < phi) and is coprime with n int e = 0; int array[100], a = 0, coprimes[100], cCounter = 0; for (int i = 2; i < phi; i++) { if (phi%i == 0) { array[a] = i; a++; } } for (int i = 2; i<phi; i++) { int temp = 0; for (int j = 0; j<a-1; j++) { if (i%array[j] == 0) { temp++; }

} if (temp == 0) { coprimes[cCounter] = i; cCounter++; } } e = coprimes[rand()%(cCounter < 5 ? cCounter : 5)]; //calculate d such as (d*e)%n = 1 int d = 0; for (int i = 0; i<n; i++) { int temp = (i*e)%phi; if (temp == 1) { d=i; break; } } printf("We have keys!!\n"); printf("Public key = (%d, %d)\n", n, e); printf("Private key = (%d, %d)\n", n, d); /******************************** ENCRYPTION *******************************/ //Message must be changed into an integer number m such that (0 <= m <= n) int m = n/8; printf("The message is: %d\n",m); //Encryption is done by encMessage = (m^e)mod(n) long encMessage = pow(m, e); encMessage = encMessage%n; printf("The encoded message is: %ld\n", encMessage); /******************************** DECRYPTION *******************************/ //Decryption is done by decMessage = (encMessage^d)mod(n)

 

 xlvi  

long decMessage = pow(encMessage, d); decMessage = decMessage%n; //decMessage and m should be the same printf("The decoded message is: %ld\n",

decMessage); return 0; }