Security & Privacy
Creare un'app Android crittografata end-to-end conforme al GDPR
52 min
come creare un'app di chat conforme al gdpr introduzione ahoy comunitĂ di back4app! questo è un tutorial ospite del team di virgil security, inc https //virgilsecurity com/?utm source=back4app\&utm medium=blog\&utm campaign=e2eechat siamo la tecnologia crittografica dietro la messaggistica crittografata end to end di twilio https //www twilio com/blog/2016/05/introducing end to end encryption for twilio ip messaging with virgil security html i nostri amici di back4app ci hanno chiesto di mostrarti come costruire un'app di chat crittografata end to end su back4app in questo post, ti guideremo attraverso i passaggi per rendere un'app di messaggistica android back4app crittografata end to end! sei pronto? ps se non ti interessano i dettagli, salta semplicemente alla fine del post e scarica il prodotto finale che cos'è la crittografia end to end? innanzitutto, iniziamo con un rapido ripasso di cosa sia l'e2ee (crittografia end to end) e come funzioni l'e2ee è semplice quando digiti un messaggio in chat, viene crittografato sul tuo dispositivo mobile (o nel tuo browser) e viene decrittografato solo quando il tuo partner di chat lo riceve e desidera visualizzarlo nella finestra della chat il messaggio rimane crittografato mentre viaggia su wi fi e internet, attraverso il cloud / server web, in un database e sulla strada di ritorno al tuo partner di chat in altre parole, nessuna delle reti o dei server ha idea di cosa stiate chiacchierando ciò che è difficile nella crittografia end to end è il compito di gestire le chiavi di crittografia in modo che solo gli utenti coinvolti nella chat possano accedervi e nessun altro e quando scrivo ânessun altroâ, intendo davvero anche gli insider del tuo fornitore di cloud o anche tu, lo sviluppatore, sono esclusi; nessun errore accidentale https //techcrunch com/2017/11/29/meet the man who deactivated trumps twitter account/ o sguardi legalmente imposti sono possibili scrivere crittografia, specialmente per piĂš piattaforme, è difficile generare numeri casuali veri, scegliere gli algoritmi giusti e scegliere le modalitĂ di crittografia corrette sono solo alcuni esempi che fanno alzare le mani nella disperazione alla maggior parte degli sviluppatori, che alla fine non lo fanno questo post del blog ti mostrerĂ come ignorare tutti questi dettagli fastidiosi e crittografare rapidamente e semplicemente end to end utilizzando il sdk di virgil per un'introduzione, ecco come aggiorneremo l'app di messaggistica di back4app per essere end to end crittografata durante la registrazione genereremo le chiavi private e pubbliche individuali per i nuovi utenti (ricorda la chiave pubblica del destinatario crittografa i messaggi e la corrispondente chiave privata del destinatario li decrittografa) prima di inviare messaggi, crittograferai i messaggi di chat con la chiave pubblica del destinatario dopo aver ricevuto i messaggi, decrittograferai i messaggi di chat con la chiave privata del destinatario pubblicheremo le chiavi pubbliche degli utenti nel servizio di carte di virgil in modo che gli utenti della chat possano cercarsi a vicenda e crittografare messaggi l'uno per l'altro le chiavi private rimarranno sui dispositivi degli utenti mantienilo semplice questa è l'implementazione piĂš semplice possibile di una chat e2ee e funziona perfettamente per semplici app di chat tra 2 utenti dove le conversazioni sono di breve durata ed è accettabile perdere la cronologia dei messaggi se un dispositivo viene perso con la chiave privata ok, basta parlare! passiamo al codice inizieremo guidandoti attraverso la configurazione dell'app android, poi, aggiungeremo del codice per rendere l'app crittografata end to end requisiti per completare questo tutorial, hai bisogno di android studio un'app creata su back4app segui il tutorial crea nuova app per imparare come creare un'app su back4app registrati per un account virgil security (creeremo l'app piĂš tardi) impostiamo l'app messenger âpulitaâ di back4app 1 imposta il tuo app server iniziamo con il deploy della funzione cloud per questo, avrai bisogno di trova main js main js e package json package json nella directory scripts directory scripts ; apri main js main js con il tuo editor preferito 1 1) ottieni le credenziali di back4app apri dashboard dashboard della tua app > impostazioni app impostazioni app > sicurezza e chiavi sicurezza e chiavi in main js main js , sostituisci parse app id parse app id con il tuo id dell'applicazione id dell'applicazione e parse rest api key parse rest api key con il tuo chiave api rest chiave api rest 1 2) ottieni le credenziali di virgil crea un'applicazione su virgil dashboard https //dashboard virgilsecurity com/ apri la tua nuova applicazione virgil, vai alla sezione e3kit e genera un env env file sotto la sezione e3kit nella barra laterale sinistra copia i valori di app id app id , app key app key , e app key id app key id dal env env file sostituisci i valori copiati nel tuo main js main js file nei campi corrispondenti ( main js main js di scripts scripts directory) 1 3) distribuisci la funzione di codice cloud apri il âdashboardâ di back4app della tua app > âcoreâ > funzioni di codice cloud; clicca +aggiungi e seleziona il tuo main js e package json (dalla directory scripts), dopo di che sposta entrambi nella cartella cloud; clicca distribuisci 2 avvia l'app demo kotlin back4app non dimenticare di configurare prima la funzione di codice cloud di back4app è una parte obbligatoria di questa demo dopo di ciò, segui i seguenti passaggi 2 1) importa il progetto in android studio apri android studio > file file > nuovo nuovo > progetto da controllo versione progetto da controllo versione > git git url del repository git https //github com/virgilsecurity/chat back4app android controlla il clean chat kt clean chat kt branch importante! seleziona il tipo di file âprogettoâ dell'albero dei file sarĂ utilizzato per tutto il tutorial 2 2) configura le credenziali di back4app nel progetto apri il âdashboardâ di back4app della tua app > âimpostazioni appâ > âsicurezza e chiaviâ; vai al /app/src/main/res/values/strings xml /app/src/main/res/values/strings xml file nel tuo progetto android e sostituisci your back4app app id your back4app app id con il tuo application id application id e your back4app client key your back4app client key con il tuo client key client key 2 3) configura db apri back4app âdashboardâ > âcoreâ > âdatabase browserâ > âcrea una classeâ e crea classi di custom custom di tipo chiamato message message e chatthread chatthread ; 2 4) configura la query live torna al tuo account back4app https //dashboard back4app com/apps/#!/admin premi il pannello di controllo del server pannello di controllo del server pulsante sulla tua applicazione trova il blocco âweb hosting e live queryâ apri le impostazioni della live query e controlla l' attiva hosting attiva hosting opzione scegli un nome per il tuo sottodominio per attivare la live query per le 2 classi che hai creato messaggio messaggio e chatthread chatthread copia il tuo nuovo nome di sottodominio e clicca sul pulsante salva torna a /app/src/main/res/values/strings xml /app/src/main/res/values/strings xml e incolla ânome del sottodominioâ che hai inserito sopra nel back4app live query url back4app live query url invece di âyoursubdomainnameâ dopo questi passaggi sarai in grado di premere il pulsante esegui in android studio e far funzionare il campione usa un emulatore o un dispositivo reale per testarlo 3 esegui la demo pulita per vedere il risultato dell'esecuzione della versione pulita della demo, dovrai registrare 2 utenti; avviare una conversazione tra di loro e inviare un paio di messaggi; 3\ apri back4app âdashboardâ > âcoreâ > âdatabase browserâ > âmessageâ se tutto ha funzionato, dovresti vedere l'app di messaggistica chat apparire registrati due utenti e invia alcuni messaggi l'uno all'altro dovresti vedere nuovi dati apparire nella message message classe nota che puoi vedere sul server di cosa stanno chiacchierando i tuoi utenti prossimo chiudi la tua interfaccia di chat e passa al passaggio successivo â aggiungere la crittografia e2ee ora, crittografiamo end to end quei messaggi! entro la fine di questa parte, i tuoi messaggi di chat appariranno cosĂŹ sul server riesci a notare la differenza? come ci arriviamo? ovviamente, dobbiamo implementare la crittografia end to end, il che significa che la nostra app deve generare la coppia di chiavi private e pubbliche come parte della registrazione memorizzare la chiave privata nello storage delle chiavi sul dispositivo dell'utente pubblicare la chiave pubblica nel servizio card di virgil come una âvirgil cardâ per altri utenti da scaricare e crittografare messaggi con essa crittografare i messaggi con la chiave pubblica e firmare con la chiave privata; decrittografare i messaggi con la chiave privata e verificare con la chiave pubblica per questo, dovremo aggiungere e3kit alla nostra applicazione demo pulita e un po' di codice in piĂš per implementare tutto ciò che è stato descritto sopra ma prima di iniziare, chiariremo due termini importanti per te cos'è una virgil card e una chiave privata? virgil card le virgil cards contengono le chiavi private degli utenti le virgil cards sono pubblicate nel servizio card di virgil (immagina che questo servizio sia come un elenco telefonico) affinchĂŠ altri utenti possano recuperarle alice deve recuperare la chiave pubblica di bob per crittografare un messaggio per bob utilizzando quella chiave chiave privata una parte privata della chiave di crittografia ricorda, le chiavi private possono decrittografare i dati che sono stati crittografati utilizzando la chiave pubblica corrispondente 1 aggiungi e3kit alla pulita demo kotlin di e3kit back4app nell'app level ( modulo app modulo app ) gradle a /app/build gradle /app/build gradle aggiungi (ma non sincronizzare ancora gli script gradle) aggiungi quanto segue alla fine del tuo progetto level /build gradle /build gradle ( progetto chat back4app android progetto chat back4app android ) ora puoi sincronizzare gli script gradle; aggiorna la tua appvirgil appvirgil classe aggiungendo nuovi campi premi alt+ enter alt+ enter per importare le librerie necessarie nella classe 2 autenticare gli utenti con back4app cloud code nella /virgilsecurity/virgilback4app/model/ /virgilsecurity/virgilback4app/model/ directory, crea le classi dati authenticateresponse authenticateresponse e virgiljwtresponse virgiljwtresponse che rappresentano le risposte dalle funzioni cloud code nella /virgilsecurity/virgilback4app/util/ /virgilsecurity/virgilback4app/util/ crea un authrx authrx oggetto che implementa le chiamate alle funzioni cloud code (non dimenticare di importare tutte le librerie necessarie dopo) 1 object authrx { 2 3 / 4 you can call it only after successful \[authenticate] 5 / 6 fun virgiljwt(sessiontoken string) = single create\<string> { emitter > 7 val requestparams = mutablemapof\<string, string>() apply { 8 put("sessiontoken", sessiontoken) 9 } 10 11 parsecloud callfunctioninbackground\<map\<string, any>>( 12 key virgil jwt, 13 requestparams 14 ) { virgiljwt, exception > 15 if (exception == null) 16 emitter onsuccess(virgiljwt\[key token] tostring()) 17 else 18 emitter onerror(exception) 19 20 } 21 } 22 23 private const val key virgil jwt = "virgil jwt" 24 private const val key token = "token" 25 } 3 memorizza il virgil jwt localmente il token virgil ricevuto dalle funzioni cloud code deve essere memorizzato localmente aggiorniamo la preferences preferences classe in /virgilsecurity/virgilback4app/util/ /virgilsecurity/virgilback4app/util/ definisci la costante aggiungi le funzioni setvirgiltoken setvirgiltoken , virgiltoken virgiltoken e clearvirgiltoken clearvirgiltoken kotlin fun setvirgiltoken(virgiltoken string) { with(sharedpreferences edit()) { putstring(key virgil token, virgiltoken) apply() } } fun virgiltoken() string? { with(sharedpreferences) { return getstring(key virgil token, null) } } fun clearvirgiltoken() { with(sharedpreferences edit()) { remove(key virgil token) apply() } } 1 virgil token should be reset on logout let's add `preferences instance(this) clearvirgiltoken()` line into `initdrawer` function of `threadslistactivity` class (in ` /virgilsecurity/virgilback4app/chat/contactslist/`) 2 kotlin 3 private fun initdrawer() { 4 5 nvnavigation setnavigationitemselectedlistener { item > 6 r id itemlogout > { 7 dldrawer closedrawer(gravitycompat start) 8 presenter disposeall() 9 showbaseloading(true) 10 // new code >> 11 preferences instance(this) clearvirgiltoken() 12 // << new code 13 14 } 15 } 16 } 4 modifica della registrazione dell'utente e3kit si occupa delle tue chiavi private e pubbliche per generarle durante il processo di registrazione, dovremo fare quanto segue in /virgilsecurity/virgilback4app/util/ /virgilsecurity/virgilback4app/util/ crea rxethree rxethree classe ora, aggiungi initethree initethree funzione che inizializza l'istanza di e3kit in rxethree rxethree classe 1 import com virgilsecurity android common model ethreeparams 2 import com virgilsecurity android ethree interaction ethree 3 4 5 fun initethree(identity string, verifyprivatekey boolean = false) 6single\<ethree> = single create { e > 6 val params = ethreeparams(identity, {preferences virgiltoken()!!}, context) 7 val ethree = ethree(params) 8 if (verifyprivatekey) { 9 if (ethree haslocalprivatekey()) { 10 e onsuccess(ethree) 11 } else { 12 e onerror(keyentrynotfoundexception()) 13 } 14 } else { 15 e onsuccess(ethree) 16 } 17 } aggiungi registerethree registerethree funzione che registra un nuovo utente in rxethree rxethree classe e3kit genera una coppia di chiavi durante la registrazione la chiave privata generata viene quindi memorizzata nello storage locale, e la chiave pubblica viene pubblicata ai servizi virgil come una virgil card 1 import com android virgilsecurity virgilback4app appvirgil 2 import com virgilsecurity common callback oncompletelistener 3 import io reactivex completable 4 5 6 fun registerethree() completable = completable create { e > 7 appvirgil ethree register() addcallback(object oncompletelistener { 8 override fun onerror(throwable throwable) { 9 e onerror(throwable) 10 } 11 12 override fun onsuccess() { 13 e oncomplete() 14 } 15 16 }) 17 } facciamo alcune modifiche a loginpresenter loginpresenter classe (in /virgilsecurity/virgilback4app/auth/) /virgilsecurity/virgilback4app/auth/) aggiungi rxethree rxethree campo 1 private val rxethree = rxethree(context) aggiorna il requestsignup requestsignup funzione per eseguire la registrazione con e3kit 1 fun requestsignup(identity string, onsuccess () > unit, onerror (throwable) > unit) { 2 val password = generatepassword(identity tobytearray()) 3 4 val disposable = rxparse signup(identity, password) 5 subscribeon(schedulers io()) 6 observeon(schedulers io()) 7 // new code >> 8 tosingle { parseuser getcurrentuser() } 9 flatmap { authrx virgiljwt(it sessiontoken) } 10 map { preferences setvirgiltoken(it) } 11 flatmap { rxethree initethree(identity) } 12 map { appvirgil ethree = it } 13 flatmap { rxethree registerethree() tosingle { unit } } 14 // << new code 15 observeon(androidschedulers mainthread()) 16 // updated code >> 17 subscribeby( 18 onsuccess = { 19 onsuccess() 20 }, 21 onerror = { 22 onerror(it) 23 } 24 ) 25 // << updated code 26 27 compositedisposable += disposable 28 } 5 modifica le funzioni di accesso ora, apportiamo modifiche al requestsignin requestsignin metodo di loginpresenter loginpresenter classe (in /virgilsecurity/virgilback4app/auth/) /virgilsecurity/virgilback4app/auth/) 1 fun requestsignin(identity string, 2 onsuccess () > unit, 3 onerror (throwable) > unit) { 4 5 val password = generatepassword(identity tobytearray()) 6 7 val disposable = rxparse login(identity, password) 8 subscribeon(schedulers io()) 9 observeon(schedulers io()) 10 // new code >> 11 flatmap { authrx virgiljwt(it sessiontoken) } 12 map { preferences setvirgiltoken(it) } 13 flatmap { rxethree initethree(identity, true) } 14 map { appvirgil ethree = it } 15 // << new code 16 observeon(androidschedulers mainthread()) 17 // updated code >> 18 subscribeby( 19 onsuccess = { 20 onsuccess() 21 }, 22 onerror = { 23 onerror(it) 24 } 25 ) 26 // << updated code 27 28 compositedisposable += disposable 29 } 6 ottieni l'elenco delle chat esistenti successivamente, aggiungi funzioni che gestiscono l'inizializzazione di e3kit nella threadslistfragment threadslistfragment classe (in /virgilsecurity/virgilback4app/chat/contactslist/) /virgilsecurity/virgilback4app/chat/contactslist/) 1 private fun oninitethreesuccess() { 2 presenter requestthreads(parseuser getcurrentuser(), 3 20, 4 page, 5 const tablenames created at criteria, 6 ongetthreadssuccess, 7 ongetthreadserror) 8 } 9 10 private fun oninitethreeerror(throwable throwable) { 11 showprogress(false) 12 if (adapter itemcount == 0) 13 tverror visibility = view\ visible 14 15 utils toast(activity, utils resolveerror(throwable)) 16 } aggiorna postcreateinit postcreateinit funzione per inizializzare e3kit 1 override fun postcreateinit() { 2 3 presenter = threadslistfragmentpresenter(activity) 4 5 showprogress(true) 6 // updated code >> 7 if (appvirgil isethreeinitialized()) { 8 presenter requestthreads(parseuser getcurrentuser(), 9 20, 10 page, 11 const tablenames created at criteria, 12 ongetthreadssuccess, 13 ongetthreadserror) 14 } else { 15 presenter requestethreeinit(parseuser getcurrentuser(), oninitethreesuccess, oninitethreeerror) 16 } 17 // << updated code 18 } e aggiungi il seguente codice nella threadslistfragmentpresenter threadslistfragmentpresenter classe in virgilsecurity virgilback4app chat contactslist/ virgilsecurity virgilback4app chat contactslist/ aggiungi campo 1 private val rxethree = rxethree(context) e funzione 1 fun requestethreeinit(currentuser parseuser, onsuccess () > unit, onerror (throwable) > unit) { 2 val disposable = rxethree initethree(currentuser username) 3 subscribeon(schedulers io()) 4 observeon(androidschedulers mainthread()) 5 subscribeby( 6 onsuccess = { 7 appvirgil ethree = it 8 onsuccess() 9 }, 10 onerror = { 11 onerror(it) 12 } 13 ) 14 15 compositedisposable += disposable 16 } a questo punto siamo in grado di registrare/accesso a un utente e creare una nuova chat con un altro utente ora aggiungiamo la crittografia per i nostri messaggi 7 crittografia e decrittografia dei messaggi aggiungiamo findcard findcard funzione a rxethree rxethree classe (in /virgilsecurity/virgilback4app/util/ /virgilsecurity/virgilback4app/util/ ) che ci aiuterĂ a ottenere l'ultima virgil card per nome utente 1 fun findcard(identity string) single\<card> = single create { e > 2 appvirgil ethree finduser(identity) addcallback(object onresultlistener\<card> { 3 override fun onerror(throwable throwable) { 4 e onerror(throwable) 5 } 6 7 override fun onsuccess(result card) { 8 e onsuccess(result) 9 } 10 11 }) 12 } quando viene aperta una chat, dovremmo ottenere la virgil card del destinatario modifica postcreateinit postcreateinit di chatthreadfragment chatthreadfragment classe (in /virgilsecurity/virgilback4app/chat/thread/ /virgilsecurity/virgilback4app/chat/thread/ ) sostituendo 1 presenter requestmessages(thread, 2 50, 3 page, 4 const tablenames created at criteria, 5 ongetmessagessuccess, 6 ongetmessageserror) codice con uno nuovo 1 presenter requestcard(recipientid, 2 ongetcardsuccess, 3 ongetcarderror) e aggiungi due funzioni 1 private fun ongetcardsuccess(card card) { 2 showprogress(false) 3 adapter interlocutorcard = card 4 presenter requestmessages(thread, 5 50, 6 page, 7 const tablenames created at criteria, 8 ongetmessagessuccess, 9 ongetmessageserror) 10 } 11 12 private fun ongetcarderror(t throwable) { 13 if (t is virgilcardisnotfoundexception || t is virgilcardserviceexception) { 14 utils toast(this, 15 "virgil card is not found \nyou can not chat with user without virgil card") 16 activity onbackpressed() 17 } 18 showprogress(false) 19 srlrefresh isrefreshing = false 20 locksendui(lock = false, lockinput = false) 21 22 utils toast(this, utils resolveerror(t)) 23 } ora cambiamo chatthreadpresenter chatthreadpresenter aggiungi campi 1 private val ethree = appvirgil ethree 2 private lateinit var usercard card 3 private val rxethree = rxethree(context) aggiungi una funzione che ottiene una virgil card del destinatario 1 fun requestcard(identity string, 2 onsuccess (card) > unit, 3 onerror (throwable) > unit) { 4 5 val disposable = rxethree findcard(identity) 6 subscribeon(schedulers io()) 7 observeon(androidschedulers mainthread()) 8 subscribeby( 9 onsuccess = { 10 usercard = it 11 onsuccess(it) 12 }, 13 onerror = { 14 onerror(it) 15 } 16 ) 17 18 compositedisposable += disposable 19 } aggiungi la crittografia dei messaggi in uscita in requestsendmessage requestsendmessage funzione 1 fun requestsendmessage(text string, 2 thread chatthread, 3 onsuccess () > unit, 4 onerror (throwable) > unit) { 5 6 val encryptedtext = ethree authencrypt(text, usercard) 7 val disposable = rxparse sendmessage(encryptedtext, thread) 8 9 } aggiungi la decrittografia di tutti i messaggi in arrivo in chatthreadrvadapter chatthreadrvadapter classe (in /virgilsecurity/virgilback4app/chat/thread/) /virgilsecurity/virgilback4app/chat/thread/) aggiungi campi 1 private var ethree ethree = appvirgil ethree 2 lateinit var interlocutorcard card implementa la decrittazione dei messaggi in onbindviewholder onbindviewholder funzione 1 override fun onbindviewholder(viewholder recyclerview\ viewholder, position int) { 2 when (viewholder) { 3 is holdermessageme > { 4 val decryptedtext = ethree authdecrypt(items\[position] body) 5 viewholder bind(decryptedtext) 6 } 7 is holdermessageyou > { 8 val decryptedtext = ethree authdecrypt(items\[position] body, interlocutorcard) 9 viewholder bind(decryptedtext) 10 } 11 } 12 } 8 esegui la demo completa end to end crittografata ora per vedere il risultato della nostra demo completamente crittografata end to end, segui di nuovo questi passaggi disconnetti l'utente precedente registrati 2 nuovi utenti; inizia una conversazione tra di loro e invia un paio di messaggi; apri back4app âdashboardâ > âcoreâ > âdatabase browserâ > âmessageâ importante! devi disconnettere l'utente attuale e registrare due nuovi utenti, dopodichĂŠ puoi iniziare una chat e2ee con questi due nuovi utenti il motivo è che i tuoi primi due utenti non hanno virgil card virgil card âs, quindi non puoi usare crittografia\decrittografia per loro { blockquote tip} fatto! ora puoi vedere che i messaggi degli utenti sono crittografati e possono essere accessibili solo nell'app dagli utenti stessi conformitĂ a hipaa e gdpr la crittografia end to end è un modo per soddisfare i requisiti tecnici per hipaa (l'atto di portabilitĂ e responsabilitĂ dell'assicurazione sanitaria degli stati uniti del 1996) e gdpr (il regolamento generale sulla protezione dei dati dell'unione europea) se hai bisogno di ulteriori dettagli, registrati per un account virgil https //developer virgilsecurity com/account/signup?utm source=back4app\&utm medium=blog\&utm campaign=e2eechat , unisciti alla nostra comunitĂ slack e contattaci lĂŹ siamo felici di discutere le tue circostanze di privacy e aiutarti a capire cosa è necessario per soddisfare i requisiti tecnici di hipaa e gdpr dove andare da qui? progetto finale https //github com/virgilsecurity/chat back4app android/ se ti sei perso pezzi del puzzle, apri il ramo del progetto e2ee puoi inserire le credenziali della tua applicazione in questo codice (come hai fatto durante l'articolo) e costruire il progetto puoi trovare ulteriori informazioni su cosa puoi costruire con virgil security qui https //virgilsecurity com/?utm source=back4app\&utm medium=blog\&utm campaign=e2eechat