Appuyez sur Entrée pour voir vos résultats ou Echap pour annuler.

Code Review – L’application Alerte Covid

Encore une nouvelle sĂ©rie 😅 Je sais… ça fait plusieurs, mais il y a tellement de choses Ă  dire… Dans cette nouvelle sĂ©rie, j’aimerais regarder du code fait par d’autres, l’analyser et ressortir les points forts et les points faibles. Bref, faire un code review, mais sans prĂ©tention. Le but Ă©tant de s’amuser autour d’un morceau de code. Donc aujourd’hui, on commence par l’application Alerte Covid.

Qui en est l’auteur?

À la base, CovidShield est une application dĂ©veloppĂ©e des bĂ©nĂ©voles chez Shopify. Elle a Ă©tĂ© ensuite forkĂ©e et adaptĂ©e pour le Canada. L’application Alerte Covid qu’on utilise a Ă©tĂ© dĂ©veloppĂ©e par Service NumĂ©rique Canada (SNC). Cette compagnie dĂ©veloppe des solutions numĂ©riques avec le gouvernement fĂ©dĂ©ral. Les Ă©quipes sont mixtes, constituĂ©es de membres de l’entreprise et du ministĂšre avec lequel ils font affaires.

Vous pouvez consulter leur page GitHub sur laquelle ils publient leurs sources réguliÚrement.

Les technologies

L’application est constituĂ©e de 3 parties, du moins ce qu’on peut voir sur leur GitHub, soit :

Aujourd’hui, on se concentre sur la premiĂšre. Commençons par la base, depuis un dossier vide :

PremiĂšre Ă©tape, on constate qu’il y a un package.json à la racine. Un rapide coup d’Ɠil nous permet de voir que l’application s’appelle CovidShield et qu’ils ont choisi React Native comme cadre de dĂ©veloppement, qui permet d’Ă©crire un seul code en React pour obtenir un build pour iOS et Android.

Allons donc chercher les prĂ©cieuses dĂ©pendances de l’application :

Les tests unitaires

Bon… « juste » 500 mo de dĂ©pendances. On peut voir aussi qu’ils ont jest comme dĂ©pendance. Jest Ă©tant un framework de tests unitaires, voyons voir leur couverture :

13 suites de tests contenant 155 tests. Pour ceux qui ne seraient pas habituĂ© avec jest, aprĂšs l’exĂ©cution, il est possible de consulter un rapport d’exĂ©cution. Pour le voir, ouvrez le fichier  coverage\lcov-report\index.html :

Personnellement, la couverture des tests me semble assez intĂ©ressante. Bien sĂ»r, on vise 100 %, mais ce n’est pas toujours possible ou pertinent. Un exemple concret de ça serait le bout de code suivant du BackendService :

En utilisant une expression lambda, on crĂ©e une fonction anonyme qui n’est pas testable. Pour la rendre testable, il aurait fallu l’extraire dans une mĂ©thode de la classe, mais ça n’aurait pas Ă©tĂ© pertinent de le tester. Cette unique ligne non testĂ©e explique le presque 2 % manquant au niveau de la couverture de cette classe.

Un point qui me titille, c’est le seul test qui n’est pas exĂ©cutĂ©. Le voici :

Par curiositĂ©, je l’ai activĂ© et j’ai rĂ©exĂ©cutĂ© les tests pour voir le rĂ©sultat. Il passe 😅

Comment ça marche?

À partir d’ici, on va plonger dans le code. J’aimerais comprendre comment ils :

  • tracent les rencontres entre 2 personnes
  • communiquent avec le backend
  • annoncent qu’on doit se faire tester
  • valident qu’une personne a vraiment la covid

Le traçage via Bluetooth

Ce qu’on nous explique, c’est que l’application Ă©met un code alĂ©atoire via Bluetooth et que les autres tĂ©lĂ©phones gardent ce code pour une pĂ©riode de 14 jours. Commençons notre recherche dans le ExposureNotificationService.

On peut voir une mĂ©thode start() qui semble intĂ©ressante. Par contre, elle ne fait qu’appeler une fonction start() sur un objet injectĂ© via le constructeur :

Ceci m’indique que la partie Bluetooth a Ă©tĂ© relayĂ©e Ă  du code natif, et il y a effectivement un bout de code Kotlin qui dĂ©finit cette classe :

Puis, on se rend vite compte qu’ils dĂ©lĂšguent le tout Ă  une librairie tierce qui est injectĂ©e via le contexte applicatif :

On peut trouver cette librairie dans le rĂ©pertoire lib de l’application Android en Kotlin. Cette librairie est aussi open source. Elle a Ă©tĂ© dĂ©veloppĂ©e par Google.

On peut donc ici comprendre qu’ils n’ont pas voulu rĂ©inventer la roue au risque de faire des erreurs, ce qui est mature comme mentalitĂ©.

Communication avec le backend

Il y a quelques points intĂ©ressants Ă  valider au niveau de la sĂ©curitĂ© dans un appel entre une front et un backend. PremiĂšrement, on s’attend Ă  ce que cette communication soit chiffrĂ©e afin d’Ă©viter que quelqu’un puisse intercepter un message pour le lire. Ce qui est le cas ici.

D’ailleurs, si une personne a la possibilitĂ© d’intercepter un message, elle pourrait aussi potentiellement modifier la requĂȘte et / ou la rĂ©ponse afin de gĂ©nĂ©rer des comportements inattendus. Il faut donc une protection Ă  ce niveau.

Revenons au BackendService. Perso, le nom 😅 mais bon. En regardant son API, on peut voir qu’il y a plusieurs mĂ©thodes pour communiquer avec le backend.  Une premiĂšre mĂ©thode  retrieveDiagnosisKeys() permet d’obtenir la liste des codes positifs dans la rĂ©gion. Nous y reviendrons dans la prochaine section.

Une autre mĂ©thode attire mon attention. Elle permet d’obtenir les configurations d’exposition, qui sont disponibles ici. Ce qui donne :

Ces configurations servent à mesurer le risque associé à une rencontre avec une autre personne.

Si vous ĂȘtes infectĂ©s et que vous avez saisi le code de SantĂ© Canada dans l’application, vous recevrez une notification pour transmettre les codes que vous avez croisĂ©s, advenant le cas oĂč vous deviez sortir. Ceci est gĂ©rĂ© par la variable needsSubmission de ExposureStatus. On peut donc comprendre que l’application fonctionne aussi pour les rencontres post-diagnostique.

Avant de traiter la fonction de rĂ©cupĂ©ration des cas positifs, traitons la soumissions des numĂ©ros alĂ©atoires croisĂ©s dans le cas oĂč on serait positif. Encore une fois, ils font preuve d’extrĂȘme prudence en implĂ©mentant un HMAC sur le corps de la requĂȘte avant l’envoi. Ceci permet au serveur de valider que le contenu de la requĂȘte n’a pas changĂ© entre l’envoi depuis le tĂ©lĂ©phone de la personne infectĂ©e jusqu’aux serveurs de SantĂ© Canada. De plus, cet encodage du payload utilise un nonce, qui permet d’ajouter un facteur alĂ©atoire afin de complexifier encore plus le processus de dĂ©codage.

Annonce qu’on doit se faire tester

Au dĂ©part, je pensais Ă  un push du serveur vers notre appareil. J’Ă©tais un peu inquiet puisque ça signifierait que le serveur connait notre appareil. Mais ce n’est pas le cas 😛

Par soucis de performance, on rĂ©cupĂšre uniquement les nouvelles clĂ©s. On peut constater ici que l’application fait un GET au serveur, contrairement Ă  ce que je pensais initialement. Non seulement ça, mais ils ont aussi mis un HMAC Ă  la fin de l’URL en chiffrant les paramĂštres de l’URL. Vous ne pourriez donc pas appeler cette URL sans avoir la clĂ© HMAC qui est Ă©videmment tenue secrĂšte :

Et zut 😛

Validation qu’une personne a rĂ©ellement la covid

Pour Ă©viter que n’importe qui se dĂ©clare positif et sĂšme la zizanie, SantĂ© Canada va crĂ©er un code alĂ©atoire Ă  usage unique et vous le remettre. Vous avez la responsabilitĂ© de saisir ce code dans l’application, qui va faire un GET au serveur pour valider que ce code est valide.

Si le code est valide, le serveur va retourner des clĂ©s de soumission afin d’encrypter le payload. L’utilisation de clĂ©s spĂ©ciales provenant du serveur pour la soumission me fait penser que les clĂ©s sont Ă  usage unique et surtout alĂ©atoire, donc gĂ©nĂ©rĂ©es Ă  la demande. On pourra valider le tout quand on regardera le code du backend.

Une fois les clĂ©s reçues, un ExposureStatus de type ExposureStatusType.Diagnosed est transmis au backend, de la mĂȘme façon que les autres codes d’exposition sont envoyĂ©s (voir plus haut).

Conclusion

Est-ce qu’on peut dire que cette application est sĂ©curitaire? Well… je pense sincĂšrement qu’il n’y a pas moyen de faire mieux en terme de sĂ©curitĂ© pour ce cas d’utilisation prĂ©cis. Ils ont pris toutes les prĂ©cautions pour Ă©viter les faux positifs, le spoofing, le man-in-the-middle et probablement bien d’autres qui m’Ă©chappent.

Je l’ai installĂ©e. Et toi?

Si t’as aimĂ© cet article, je t’invite Ă  t’abonner au blogue pour recevoir les nouveaux articles par courriel. Je t’invite aussi Ă  le partager dans tes rĂ©seaux sociaux 🙂

 

Suivez-nous par courriel!

Saisissez votre adresse courriel pour vous abonner au blog d'Ezo et recevoir une notification de chaque nouvel article par email.

Rejoignez 30 autres abonnés