Dévérouiller son pc avec son téléphone portable grâce à un qrcode (sisi)

Oui c’est un gros billet avec pleins de phrases compliquées. Pour ceux qui veulent lire en travers sautez à la partie Principe de fonctionnement directement ;)

Avertissements

Tout le système que je vais décrire par après c’est de la bidouille. Si vous voulez faire fonctionner ça sur votre machine il vous faudra forcément trifouiller dans le code (surtout si vous voulez un truc qui soit sécurisé vu que les exécutables ont tous le même ‘mot de passe’). De plus ce système n’est peut-être pas inviolable (on ne peut pas penser à tout ;) ), mais en tout cas (à mon avis) c’est quand même sûr.

Faire les manipulations décrites dans ce billet peut donc ouvrir des failles de sécurité, causer divers problèmes sur votre pc, donc suivez les instructions / jouez avec les programmes que si vous savez ce que vous faites ! Vous êtes prévenus. Na.

Tout le système ainsi que le billet n’est pas vraiment user-firendly. Je sais mais c’est un peu dur de faire simple ;) .

Le système marche sous linux, n’importe quelle distribution. Les paquets requis sont au moins disponibles sous ubuntu, au pire vous pouvez installer les dépendances à la main, sans utiliser votre gestionnaire de paquets.

S’authentifier sur son pc

Il existe pleins de manières différentes de s’authentifier sur son pc, notamment la plus basique, le mot de passe. Mais ce n’est pas très rigolo ! J’ai donc cherché un moyen plus sympa de m’authentifier sur mon pc.

Déjà, il y a la solution que l’on trouve sur bon nombre de portable, le lecteur d’empreintes digitales. Mais j’en ai pas sur le mien (de lecteur).

On peut aussi s’authentifier avec une clé usb (pam_usb). Mais bon je ne trouve pas ça super sécurisé, sachant qu’il suffit de pas beaucoup de temps pour juste lire les données de la clé et savoir quelles sont les informations à fournir pour faire une ‘fausse clé’. Surtout que c’est fait pour aller se brancher partout ces bébêtes et on n’est pas toujours sûr du pc sur lequel on va se brancher…

Il y a aussi l’authentification par bluetooth (pam_blue). Alors, non seulement ce système utilise inutilement de la batterie (faut bien laisser le bluetooth allumé sur le périphérique qui sert à s’authentifier), mais ensuite c’est aussi sécurisé que d’avoir son mot de passe avec un postit à côté de l’écran (et écrit en gros caractères).  Tout ce qui est radio c’est le mal, c’est interceptable aussi facilement que bonjour !

Il y a toutes les techniques d’identification avec la voix et la reconnaissance du visage. Le problème c’est que c’est très dépendant de l’environnement (des gens qui hurlent autour de vous / un fond pas normal et hop ça ne marche plus) et je n’ai pas envie de sourire à ma webcam pendant 15 minutes ou hurler une phrase aléatoire à mon pc pendant le même laps de temps.

Il y a aussi la technique de l’interrupteur à clé dans une boite de biscuit que je vous avais déjà présenté. Malheureusement j’ai plus de port imprimante sur mon pc et c’est aussi sécurisé qu’un mot de passe à une lettre (suffit de cour-circuiter les fils…).

Toutes ces techniques ont un élément commun : on essaie d’authentifier quelque chose d’unique et de personnel dont on remarque généralement vite la perte (un périphérique bluetooth (généralement un téléphone portable), une clé usb, un doigt ou encore son cerveau qui connais le mot de passe). Le truc serait d’arriver à un système permettant d’identifier à coup sûr un objet sans pouvoir le falsifier.

J’ai une webcam sur mon pc. Il existe un moyen de transiter des informations par l’image, les qrcodes. J’ai donc eu l’idée de m’en servir pour faire ‘transiter’ une information unique, permettant à coup sur d’identifier mon téléphone portable :]

Les qrcodes

L\'url de mon blog qrencodéeDéjà un qrcode c’est quoi ? La wikipedia nous dit ceci :

Le code QR ou QR Code (en anglais) est un code-barres en 2 dimensions (code matrice) pouvant stocker jusqu’à 7089 caractères numériques, 4296 caractères alphanumériques (contrairement au code-barre « traditionnel » qui lui ne peut stocker que de 10 à 13 caractères) ou 2953 octets . Il a l’avantage de pouvoir stocker beaucoup d’informations tout en étant petit et rapide à scanner. Ainsi, le sigle « QR » dérive de « Quick Response » car le contenu peut être décodé rapidement.

Le code QR a été crée par l’entreprise japonaise Denso-Wave en 1994. Le code QR est très utilisé au Japon ; c’est actuellement le code à deux dimensions le plus populaire au Japon.

Le standard japonais pour les codes QR, JIS X 0510, a été publié en 1999, et la norme ISO correspondante, ISO/IEC 18004, a été approuvée en juin 2000.

Un article sympa sur Clubic aussi si ça vous intéresse de voir comment les gens s’en servent : Live Japon : du QR Code aux publicités subliminales.

Si vous aussi vous avez envie de les lires avec votre portable je vous conseille ce lecteur (en plus c’est une société suisse alors bon ^^).

Principe de fonctionnement

Le but est de se servir de qrcodes pour faire passer un mot de passe unique, généré par un objet que l’on garde généralement toujours sur soi, un téléphone portable dans notre cas. Le téléphone affiche le qrcode et le pc prend une photo à l’aide de sa webcam. Il décode le qrcode et si celui-ci est valide il déverrouille le pc.

Évidemment, il ne faut pas que les données transitées par le qrcode soient toujours les mêmes, parque sinon il suffirait d’obtenir une fois les données (qui serait une simple chaine de texte) pour s’authentifier sur votre pc…
J’ai donc utilisé une technique consistant à obtenir un code d’authentification qui varie avec le temps. De cette manière, obtenir les données du qrcode à un instant T ne permet pas de se logger à un instant T+1, ce qui augmente le niveau de sécurité.

Le code d’authentification est créé ainsi :

  • On prend la date et l’heure actuelle (heure GMT)
  • On rajoute une chaine commue (une sorte de mot de passe)
  • On fait la somme md5 des deux éléments précédents

Exemple : Il est minuit 28, le 30 aout 2008 et ma chaine commue est mysupersecrectstring. On crée le code d’authentification comme suit : 200808292228mysupersecrectstring (notez que l’on recule de deux heures pour être à l’heure GMT (deux car c’est l’heure d’été)) et on calcule le md5 de cette chaine qui est bd76299ff48d23743b8c4a7cb85a2c74. C’est notre code d’identification, une sorte de mot de passe qui change toutes les minutes et qu’on n’a pas besoin de retenir.
Il est impossible (normalement) de revenir à la chaine commune depuis le md5, même en sachant l’heure qu’il est !

Du côté du pc, il faut lire le code et regarder qu’il corresponde. Mais il y a un problème : il faudrait que le téléphone portable et le pc soient synchronisés à la seconde près, de plus se trouver aux alentours de 00:00:59 quand on génère le code et à 00:01:12 quand on lit le code pose un problème, car la minute aura changé et donc le code d’authentification aura changé. Pour résoudre ces problèmes, le pc va accepter 5 codes d’authentification : celui pour la minute en cours, ceux des deux minutes précédentes et deux des deux minutes suivantes. Ainsi, même avec une minute de décalage entre le téléphone portable et le pc, on parviendra toujours à s’identifier !

Réalisation pratique

Il y avait trois choses à faire fonctionner : Capturer une image de ma webcam en ligne de commande (figurez vous que c’est compliqué…), être capable de lire un éventuel qrcode dans cette image et savoir générer un qrcode sur mon téléphone portable.

Déjà pour capturer une image c’est très compliqué. Il existe bon nombre de programmes avec une interface graphique qui savent le faire, mais là le but était de faire ça de manière automatique. Après de longues recherches, j’ai fini par trouvé uvccapture qui parvenait enfin à faire ce que je voulais. Je me suis servi de son code source et je l’ai modifié de manière à être capable de prendre une image quand mon téléphone portable est visible, mais pas encore surexposé (uvccapture est normalement capable de demander à la webcam une exposition particulière, mais avec la mienne ça ne marche pas, elle se règle toute seule…), après un temps X (dépendant aussi de l’initialisation de la webcam, etc.). J’ai fait le ménage dans le code pour garder que le nécessaire et on a notre exécutable qui prend une photo et la sauve sous 2snap.jpg (et aussi une image plus sombre sous 1snap.jpg, mais pour l’instant je ne l’utilise pas).

Ensuite, décoder un qrcode dans cette image. Le problème a été de trouver une libraire avec une licence libre et facilement réutilisable. La seule que j’ai fini par trouver est PyQrCodec, qui fait appel à une autre en C qui utilise OpenCV (cf les liens plus bas). Le truc plante de temps en temps au décodage et n’est pas capable de reconnaitre tous les qrcodes, mais ce n’est pas un problème vu que l’on va s’occuper aussi de la génération du dit qrcode il suffira de faire quelque chose de compatible.
J’ai implémenté toute la logique du système (génération des md5, déverrouillage de l’écran de veille) dans le script en python (vu que c’est le plus facilement modifiable).

Enfin il faut générer un qrcode. Ça à l’aire vachement sympa ces images en noir et blanc avec des carrés partout, mais en fait c’est super compliqué à faire (c’est pleins de maths compliqués). Après beaucoup de recherche j’ai fini par tomber sur une source en php capable d’en générer et qui sont lisibles par le décodeur (voir dans les liens plus bas). J’ai donc profité de cette source pour la réadapter en java (meilleure manière faire tourner quelque chose sur un téléphone portable à mon avis), ça prend du temps et j’ai sauté quelques parties mais ça a fini par fonctionner (en tout cas je n’ai pas rencontré de problèmes jusqu’à maintenant…). Le programme est un peut lent (~5 pour se lancer) (hors java) et il faudrait peut-être faire un peu d’optimisation (je n’ai pas tout récrit à la manière java et certaines parties ne sont pas très intelligentes, par exemple bosser avec des strings au lieu de faire tout avec des tableaux d’int (chose que j’ai faite quand j’étais obligé)) mais ça marche.

Et donc on a trois programmes qui font ce qu’ils doivent faire (c’est quand même sympa tous ces langages, du C, du python, du php et du java pour 3 programme pour ce système…) et il faut juste les mettre ensemble !

Et ça marche ?

Oui. (Ba tiens x]) Il faut en moyenne 5s pour que le code soit lu et reconnu si je tiens mon téléphone portable à 15cm de la webcam. Qu’il fasse nuit ou jour cela fonctionne, le système n’est donc pas perturbé par l’environnement !

Il faut encore que je trouve un moyen de le lancer automatiquement avant que l’écran de veille s’active (parce qu’à l’heure actuelle il désactive l’écran de veille) en évitant de changer toutes les entrées dans mes raccourcis :p

Les sources & exécutables

Bon, il y a pleins de langages différents et de licences différentes vu que j’ai récupéré du code de pleins d’endroits différentes, mais c’est normal. J’ai gardé les licences d’où le code provenais, j’ai mit la partie en java que j’ai réécrite en MPL/GPL/LGPL.

Alors oui ce n’est pas du très beau code et ce n’est pas commenté, mais c’est juste pour faire mumuse, si j’ai le temps je ferais quelque chose de clean.

Les exécutables (le mot de passe utilisé est  : mysupersecrectstring )

Notez qu’il vous faudra PyQrCodec (voir les liens) d’installé pour le décodeur. Suivez les instructions sur le site dans les liens, toutes les dépendances requises sont dans les dépôts d’ubuntu.

Pour le programme de capture de la webcam aussi, il vous faudra v4l2 d’installé, mais normalement c’est le cas.

Les sources :

À l’heure actuelle (programme et source), cela ne devrait fonctionner que si vous avez un matériel parfaitement compatible (taille de la webcam, même taille d’écran pour le téléphone portable (il faut une ’surface utile’ de 235×235 au moins)), mais rien de vous empêche de jouer avec le code source ;)

Pour lancer le programme mettez captureimage dans le même dossier. Faites un touch data.tmp et lancez python QrAuth.py. PyQrcodec doit être dans le path (si il est installé correctement normalement c’est bon, au pire copiez son dossier dans le dossier avec QrAuth.py (après compilation bien évidemment)). Attention ! Pour arrêter le programme il faut soit arriver à vous authentifier, soit appuyer sur ctrl-c jusqu’à ce qu’il s’arrête (ce qu’il ne fait pas tout le temps..). Ou fermer le terminal. Effectivement faudrait faire quelque chose de plus mieux bien sur ce point mais bon ;) . Normalement ça marche. Normalement.

Si vous avez une webcam qui fonctionne autrement vous pouvez modifier le code python pour capturer une image autrement et faire fonctionner le système quand même !

Les choses qu’il faudrait améliorer

L’ensemble n’est évidemment pas parfait et terminé, ça reste de la bidouille. Il faudrait exemple faire un peu de ménage dans le programme qui génère des qrcodes, il y a beaucoup de fichiers de définition qui ne servent probablement à rien. De plus, il serait beaucoup plus pratique d’arriver à prendre et analyser la présence d’un qrcode devant la webcam en permanence, mais pour cela il faudrait résoudre le problème de la luminosité. Notez aussi que le décodeur sur le pc est en deux parties et les informations entre les deux scripts sont échangés à l’aide d’un fichier… Ce n’est pas très intelligent, mais le problème est que la demande de décodage d’un qrcode fait de temps en temps planter le programme python qui s’arrête, d’où la séparation entre les deux programmes. Et l’information est passé à l’aide d’un fichier parque je n’avais pas envie de m’embêter à récupérer la sortie standard du deuxième processus, mais normalement il faudrait faire comme ça.

Un autre point serait aussi de pouvoir utiliser des fichiers de configuration ou des paramètres pour éviter par exemple de devoir recompiler le programme lorsque la webcam change de ‘fichier’ (c’est pas un fichier mais c’est comme tel) /dev, ou lorsque l’on veut changer le mot de passe.

De plus il faudrait arriver à utiliser la librairie qui décode les qrcode non pas en python,  mais directement en c, lors de la capture de la webcam, pour éviter d’avoir à utiliser un langage de plus, malheureusement je n’ai pas réussi à compiler la dite libraire directement en C.

Liens


Tout ça pour ça, effectivement… Il m’a quand même fallu 3 jours pour arriver à quelque chose qui marche x].

Sinon pour conclure une image qui n’a rien à voir, mais que j’aime vachement bien et que je peux m’empêcher de vous monter : C’est par ici.

Vus : 829
Publié par TheGlu : 20