В този урок ще създадем криптирано примерно приложение за чат/съобщения за Android. За да направим това, ние ще комбинираме двете платформи Stream Chat и Virgil Security. Stream и Virgil улесняват изграждането на решение с отлична сигурност, като комбинират всички функции, които бихте очаквали като разработчик, когато създавате приложение за съобщения.

Тези две услуги позволяват на разработчиците да интегрират чат, който е нулево знание, към вашия бекенд или поток. Примерното приложение вгражда „eThree Kit“ на Virgil Security — защитена платформа за криптирани съобщения — с компонентите на Stream Chat за „Android“.

Имайте предвид, че целият изходен код за този пример, приложението за Android е наличен в GitHub. Освен това, преди да преминете към този урок, препоръчвам да разгледате Урока за поточно чат за Android, който ще ви преведе как да внедрите поточно чат от общ преглед на високо ниво.

Какво е шифровано съобщение от край до край?

Криптираните съобщения от край до край означават, че потребителите в този конкретен чат могат да четат само съобщения, изпратени между двама души. За да активирате това, съобщенията, които се изпращат, се криптират, преди да напуснат устройството на потребителя, и могат да бъдат декриптирани само от предвидения получател (краен потребител).

Virgil Security е доставчик, който позволява на разработчиците да създават криптиране от край до край чрез технология за публичен/частен ключ чрез използването на тяхната стабилна и сигурна услуга за криптирани съобщения. С Android SDK на Virgil разработчиците могат сигурно да създават, съхраняват и предоставят стабилно криптиране от край до край.

По време на този урок ще научим как да създадем приложение за поточен чат, което използва платформата за криптиране/декриптиране на Virgil, за да попречи на никого, освен на предвидените страни, да чете съобщения. Никой във вашата компания, нито някой доставчик на облак, който използвате, не може да прочете тези съобщения. По същество, дори ако злонамерен човек получи достъп до базата данни, съдържаща съобщенията, този човек ще види само криптиран текст, наречен шифрован текст.

Изграждане на криптирано приложение за чат съобщения

За да създадем това приложение, ще разчитаме най-вече на две библиотеки, Stream Chat Android и Virgil Security за Kotlin. Нашият резултат ще шифрова текст на устройството, преди да изпрати съобщение. И дешифрирането, и проверката ще се извършват в устройството на получателя. API за съобщения на Stream ще вижда само шифрован текст, като гарантира, че данните на нашия потребител никога няма да бъдат видени от никой друг, включително от нас.

За да постигне това, приложението изпълнява следните стъпки:

  1. Потребителят се удостоверява с вашия бекенд.
  2. Приложението на потребителя изисква токен за удостоверяване на поток и API ключ от бекенда. Приложението за Android създава „клиент за поточен чат“ за този потребител.
  3. Приложението на потребителя изисква токен за удостоверяване на Virgil от бекенда и се регистрира във Virgil. Това генерира техния частен и публичен ключ. Частният ключ се съхранява локално, а публичният ключ се съхранява във Virgil.
  4. След като потребителят реши с кого иска да разговаря, приложението създава и се присъединява към „Канал за поточен чат“.
  5. Приложението пита Virgil за публичния ключ на приемника.
  6. Потребителят въвежда съобщение и го изпраща на Stream. Преди да изпрати, приложението предава публичния ключ на получателя на Virgil, за да шифрова съобщението. Съобщението се предава чрез Stream Chat към получателя. Stream получава шифрован текст, което означава, че никога не могат да видят оригиналното съобщение.
  7. Получаващият потребител дешифрира изпратеното съобщение с помощта на Virgil. Когато съобщението бъде получено, приложението дешифрира съобщението с помощта на Virgil и това се предава на компонентите на потребителския интерфейс на Stream. Virgil проверява дали съобщението е автентично, като използва публичния ключ на подателя.

Въпреки че това изглежда сложно, Stream и Virgil вършат по-голямата част от работата вместо нас. Ще използваме готовите компоненти на потребителския интерфейс на Stream, за да визуализираме потребителския интерфейс за чат, а Virgil да извърши цялата криптография и управление на ключове. Ние просто комбинираме тези услуги.

Кодът е разделен между интерфейса на Android, съдържащ се в директорията android, и бекенда Express (Node.js) се намира в директорията backend. Вижте README.md във всяка директория, за да видите инструкции за инсталиране и стартиране. Ако искате да следвате заедно с изпълнявания код, уверете се, че и backend, и android работят, преди да продължите.

Нека преминем и разгледаме важния код, необходим за всяка стъпка.

Предпоставки

Необходими са основни познания за Android (Kotlin) и Node.js, за да следвате този урок с инструкции.

Обърнете внимание, че това защитено приложение за съобщения е предназначено само за локално изпълнение на вашата машина и ние няма да покриваме как да внедрите примерното приложение в магазини за приложения за iOS или Android.

Ние използваме Anko, за да опростим нашия асинхронен код. Моля, имайте предвид, че тази библиотека наскоро беше „отхвърлена“. Вероятни грешки има и в нашата асинхронна реализация. Ние обаче избрахме да сведем шума до минимум в този урок, като използваме Anko и поддържаме async прост. Моля, използвайте най-добрите практики за асинхронен код.

Ще ви трябва акаунт с Stream и Virgil. След като създадете вашите акаунти, можете да поставите идентификационните си данни в backend/.env, ако искате да стартирате кода. Можете да използвате backend/.env.example като справка за това какви идентификационни данни са необходими. Трябва също така да поставите своя API ключ за поток в MainActivity.kt:60.

Стъпка 0. Настройте бекенда

За да може нашият интерфейс на Android да взаимодейства със Stream и Virgil, приложението предоставя три крайни точки:

  • POST /v1/authenticate: Тази крайна точка генерира токен за удостоверяване, който позволява на приложението за Android да комуникира с /v1/stream-credentials и /v1/virgil-credentials. За да опростим нещата, тази крайна точка позволява клиентът да бъде всеки потребител. Предният интерфейс казва на бекенда в кого иска да се удостовери. Във вашето приложение това трябва да бъде заменено с крайната точка за удостоверяване на вашия API.
  • POST /v1/stream-credentials: Това връща данните, необходими на приложението за Android, за да комуникира с Stream. За да върнем тази информация, трябва да кажем на Stream, че този потребител съществува и да го помолим да създаде валиден токен за удостоверяване:

Полезният товар на отговора има следната форма:

  • apiKey е идентификаторът на акаунта за поток за вашето копие на потока. Необходим е, за да идентифицирате с кой акаунт се опитва да се свърже вашият интерфейс.
  • token JWT токен за упълномощаване на интерфейса с поток.
  • user: Този обект съдържа данните, от които интерфейсът се нуждае, за да се свърже и изобрази изгледа на потребителя.
  • POST /v1/virgil-credentials: Това връща токена за удостоверяване, използван за свързване на интерфейса към Virgil. Използваме Virgil Crypto SDK, за да генерираме валиден токен за удостоверяване за нас:

В този случай интерфейсът се нуждае само от маркера за удостоверяване.

Стъпка 1. Потребителят се удостоверява с Backend

Първо влизаме в потребител. За да опростим нещата, ще имаме само празен формуляр, който ви позволява да влизате с произволно име:

Това е проста форма, която приема всяко произволно име, което на практика ни позволява да влизаме като всеки. Настроихме това в нашия MainActivity:

И оформлението:

Когато изпратим формуляра, ние влизаме в нашия бекенд, получаваме токен за удостоверяване на интерфейса на Stream и Virgil, генерираме нашия частен ключ и се регистрираме във Virgil, след което започваме следващата си дейност. Ще разгледаме всеки от тях на свой ред.

Нека да видим нашето влизане и генериране на токени:

Тъй като нашият backend (вижте Стъпка 1) генерира токен, това са прости REST извиквания. Върнатите токени са токени за удостоверяване на интерфейса, които позволяват на нашия клиент да говори директно със Stream и Virgil. Освен връщането на списък с потребители, вече не се нуждаем от нашия бекенд, за да вършим каквато и да е работа.

Сега, след като имаме нашите токени за преден интерфейс, нека генерираме нашите частни ключове и регистрираме нашите публични ключове с Virgil:

Клиентът на Върджил се казва eThree. Инициализираме екземпляр EThree и се регистрираме. Това обаждане генерира частен ключ и го съхранява на устройството и изпраща нашия публичен ключ на Virgil. Ако получим RegistrationException, вече сме регистрирали този потребител. Имайте предвид, че не можете да влезете в същия потребител на друго устройство, тъй като ние не споделяме личния ключ с другото устройство! Това е възможно, но извън обхвата на този урок. Ако искате да постигнете това, вижте документацията на Virgil.

Сега, след като имаме нашите токени и регистрация, нека намерим потребител, с когото да разговаряме!

Стъпка 2: Избройте потребители

За да опростим нещата, ще вземем всички регистрирани потребители от нашия бекенд и ще ги покажем в прост изглед на списък:

Ето дейността:

И оформлението:

Извършваме извикване на API чрез BackendService.getUsers и филтрираме влезлия потребител. Добавяме отговора към обикновен ArrayAdapter и показваме нашите резултати в ListView. Когато потребител щракне върху елемент от списъка, стартираме ChannelActivity, което е канал за чат 1:1.

Стъпка 3: Създайте частен 1:1 канал

Първо, трябва да създадем наш канал за нашия личен чат. Нека да разгледаме нашата дейност и оформление:

И оформлението:

Ние използваме готови компоненти на Stream UI с две леки вариации. Първо, закачаме персонализиран EncryptedMessageInputView, който ни позволява да шифроваме съобщение, преди да го изпратим. Ние също така закачаме персонализиран EncryptedMessageViewHolderFactory, който позволява дешифриране на съобщения (ще разгледаме това след малко). Основните битове започват вътре в doAsync. Първо търсим публичния ключ на другия потребител. Това нека да използваме шифроването на нашите съобщения и да проверим дали техните съобщения са автентични. След това създаваме канал в Stream via .query. След като каналът бъде създаден, ние зареждаме съобщения. Преди да разгледаме как зареждаме съобщения, първо трябва да изпратим съобщение.

Стъпка 4: Изпращане на криптирано съобщение

Нека да разгледаме EncryptedMessageInputView, който е обвързан в оформлението и конфигуриран в нашата дейност. Ето кода:

Ние отменяме MessageInputView на Stream и просто дешифрираме съобщението, преди да го изпратим. MessageInputView извиква prepareMessage преди да го изпрати до API, така че ние отменяме това и шифроваме, преди да изпратим съобщението.

Моля, имайте предвид, че актуализирането на съобщение не използва този метод, така че имайте предвид, ако искате да поддържате функционалност за редактиране. Можете да обмислите изграждането на свой собствен MessageInputView. За краткост няма да отидем там в този урок.

Стъпка 5: Преглед на съобщения

Тъй като всичките ни съобщения в Stream нашият сега шифрован текст, трябва да ги дешифрираме, преди да ги покажем. За да се свържем с компонентите на потребителския интерфейс на Stream, ние се свързваме чрез binding.messageList.setViewHolderFactory(EncryptedMessageViewHolderFactory(eThree)). С нашата персонализирана фабрика можем да инициализираме персонализиран декриптиращ обект за всяко съобщение:

Тази фабрика проверява дали имаме тип съобщение (срещу друг тип като разделител за дата) и инициализира нашия EncryptedMessageViewHolder. Да погледнем да разгледаме:

Първо проверяваме дали имаме редовно съобщение и ако имаме, го дешифрираме. Копираме нашия обект на съобщение, за да избегнем мутирането на оригиналната версия (Потокът кешира това и ще объркаме нещата, ако го манипулираме). С това копие проверяваме дали съобщението е наше или тяхно. В нашия случай знаем как да дешифрираме директно, тъй като го създадохме. Ако е тяхно, трябва да потърсим техния публичен ключ, за да проверим съобщението. Предаваме това на Върджил и правим нашето дешифриране.

Събирайки тези последни стъпки заедно, ще видим нашия краен продукт:

Последни мисли

И това е. Вече разполагаме с частно и изключително сигурно приложение за съобщения от край до край, създадено за Android с Поточен чат и Virgil Security. Трябва да имате пълно разбиране на основите на криптирането от край до край с помощта на Stream Chat и Virgil Security, заедно с фундаментално разбиране за това как работи процесът E2EE, когато се прилага с Android, Virgil и Stream Chat.

Ако искате да направите още една крачка напред, Stream Chat предлага няколко ресурса, които да ви помогнат да стигнете до следващото ниво с вашите Android котлети. Вижте връзките по-долу:

Приятно кодиране и както винаги, моля, не се колебайте да оставите всякакви мисли или въпроси в коментарите по-долу.

Първоначално публикувано в The Stream Blog наhttps://getstream.io/blog/encrypted-messaging-app-android/.