Dev Web - L©S ßlog - CyberSDF

L©S ßlog - CyberSDF

jeudi 23 novembre 2006

Authenfication forte pour pas un rond (ou presque)

Si vous êtes comme moi, vous ne faites qu'une confiance partielle aux différents couples de login et mot de passe.
En effet, sans même entrer dans le détail du nombre de petits programmes espions que pourrait contenir votre ordinateur ou de quelqu'un qui écoute votre réseau, n'importe qui peut regarder derrière votre épaule et voir vos identifiants.

Pour pallier à tout ça, il a été inventé le principe d'authentification forte[1] que j'ai déjà introduit dans ce blog.

Pour mémoire, le concept de l'authentification forte repose sur l'utilisation d'au moins deux facteurs parmi les suivants :
- Ce que l'utilisateur connaît (login, un mot de passe, un code PIN),
- Ce que l'utilisateur détient (une carte magnétique, une carte à puce, un « authentifieur »),
- Ce que l'utilisateur est (empreinte digitale, empreinte rétinienne, structure de la main, structure osseuse du visage ou tout autre élément biométrique)

On voit donc des solutions arriver, que ce soit en biométrie ou des secureID à mettre autour du cou, etc.
Le hic, c'est que toutes ces technologies coûtent de l'argent (et pas qu'un peu pour certaines d'entre elles), et moi de l'argent, je vous avoue que je n'en ai pas beaucoup...
Pourtant, pour certaines applications (quelles qu'elles soient) j'aimerais bien leur proposer une authentification forte quand même. Comment faire ?

Et bien je vais vous donner une méthode simplissime qui ne vous coûtera pas un rond !

Le principe général

Bon déjà on oublie la biométrie, donc ce que l'utilisateur est on met de côté.
On se concentre donc sur ce que l'utilisateur connaît et ce que l'utilisateur détient.

L'idée est de fournir à votre utilisateur (en plus d'un nom d'utilisateur et d'un mot de passe) une carte du style bataille navale de n colonnes sur n lignes (tout dépend de ce que vous voulez faire).

Votre utilisateur entre donc son login (CyberSDF) et son password (12345678), l'application le reconnaît (elle peut même lui dire bonjour) et, pour confirmer que c'est bien CyberSDF himself qui veut se connecter, lui demande la valeur de la case D7 de SA carte. Il cherche partout sa carte, la trouve, cherche la case D7, entre la valeur 2e68 et envoie.
Si la réponse est correcte, le serveur lui donne l'accès, sinon l'envoie bouler.

La réalisation (en php)

Créer la carte

Là vous me dites, t'es bien gentil mais comment je fais pour lui créer ta carte de bataille navale ?
Rien de plus simple ! Tout ce dont vous avez besoin c'est de son login (normalement ça devrait être bon) et d'un grain de sel[2], qui est associé à l'utilisateur qui sera stocké quelque part.

Aller, le bout de code et on explique après :

[php]
<?php
function gencard($login='CyberSDF',$salt18 = 'voilàmongraindesel') {  

 $temp = md5($login.$salt18);
 $alphabet = 'ABCDE';

 for($i=1; $i<=5; $i++) {
  for($j=0; $j<5; $j++) { 
   $foo[$i][$alphabet[$j]] = dechex( (ord($temp[$i])*ord($temp[$j])) );
  }
 }
 return $foo;
}
?>

Voilà une fonction qui nous génère notre carte de 5 colonnes sur 5 lignes dans un tableau à deux dimensions.

  1. Je fais un MD5 du login et du grain de sel histoire d'avoir quelque chose sur 32 caractères ;
  2. Mon tableau aura 10 colonnes, donc 10 lettres de l'alphabet ;
  3. Je commence une boucle de 1 à 5 inclus ;
  4. Je met une seconde boucle de 0 à 5 exclu ;
  5. Je crée mon tableau multidimensionnel déjà indexé avec les bons chiffres et lettres ;
  6. Je renvoie le tableau.

Pour le remplissage du tableau, je me suis inventé un petit truc où je multiple les valeurs ASCCI de deux lettres et je transforme le résultat en hexadécimal. Pourquoi de l'hexa ? Tout simplement pour avoir de temps en temps des lettres, je trouve juste que c'est plus sympathique :-)

Deux mises en garde tout de même [3] :
- Mon modèle mathématique est horrible !!! En effet, si vous comptez bien, je ne peux créer qu'une carte de 32 cases (mon MD5) donc pour une carte d'au-delà de 5*5 il y a forcement des répétitions. Le but ici n'est pas de vous donner le meilleur modèle mathématique mais de vous présenter le principe, charge à vous de faire votre propre machin.
- Le grain de sel ne doit pas être transmis en clair (pour le login on s'en fiche)

Afficher la carte

Là, rien de plus simple, c'est un simple parcours de tableau :

[php]
<?php $bar = gencard(); ?>
<table border="1" cellpadding="5">
 <tr>
  <th>&nbsp;</th>
  <?php
  $alpha = 'ABCDE';
  for($j=0; $j<strlen($alpha); $j++) {
  echo "  <th>".$alpha[$j]."</th>\r\n";
  }
  ?>
 </tr>
  <?php
    for($i=1; $i<=10; $i++) {
       echo " <tr>\r\n  <th>".$i."</th>\r\n";
       for($j=1; $j<=strlen($alpha); $j++) {
          echo "  <td>".$bar[$i][$alpha[$j-1]]."</td>\r\n";
       }
       echo "</tr>\r\n";
     }
 ?>
</table>

Demander une case

On a généré la carte qui va bien, notre utilisateur l'a imprimée, il ne reste plus qu'à l'utiliser.

On lui demande une case au pif :

[php]
<?php
$ltr = 'ABCDE';
echo $case = $ltr[mt_rand(0,4)].mt_rand(1,5);
?>

Notre utilisateur envoie à l'application le contenu de la case, et pour vérifier le résultat il n'y a plus qu'à recréer la carte (sans l'afficher bien sûr) et de comparer la valeur trouvée avec la valeur envoyée.

[php]
<form method="post" id="monform" name="monform" action="<?php echo $_SERVER['PHP_SELF'] ?>">
 <input type="text" id="val" name="val" /> 
 <input type="hidden" id="case" name="case" value="<?php echo $case ?>" />
 <input type="submit" />
</form>
[php]
<?php
function verifcase() {
 if($_REQUEST['val']!='') {
  $plop = gencard();
  if($plop[substr($_REQUEST['case'],1,2)][substr($_REQUEST['case'],0,1)] == $_REQUEST['val'])
   return true;
  else
   return false
 }
}
?>

Et voilà ! Simple comme tout non ?

Si jamais vous voulez voir ça en action, j'ai fait une démo

Notes

[1] Faudra que quelqu'un pense à compléter ça http://fr.wikipedia.org/wiki/Authentification_forte

[2] Une explication de la technique du grain de sel très claire

[3] Si vous utilisez mon code tel quel, c'est à vos risques et périls hein

jeudi 8 septembre 2005

La recherche d'erreur en programmation : debug

Vous avez tous entendu dire « il y a un bug dans le programme » oui mais c'est quoi exactement un bug ? Un bug est tout simplement une erreur quelque par dans un programme, erreur qu'il faut bien sur identifier et corriger.

Il existe trois familles d'erreurs :

Erreur de syntaxe : « syntax error »

C'est le type d'erreur la plus répandue, tout programmeur quel que soit son niveau se heurte à ce genre d'erreur. Cette erreur est généralement bloquante et le programme refuse soit de s'exécuter soit d'aller au delà d'où le bug se trouve.

Petit rappel sur ce qu'est la syntaxe :
Tout comme une langue parlée un langage de programmation suit un certain nombre de règles grammaticales et orthographiques arbitraires établis à sa conception.
Exemple de règle grammaticale : Chaque appel à une fonction doit commencer par une majuscule et qu'une instruction se termine par un point-virgule.
Exemple de règle orthographique : Print(‘coucou le monde') ;
Si vous vous manquez quelque part (oubli du point-virgule, au lieu d'écrire Print vous écrivez Pint, etc.) vous aurez un superbe message d'erreur.

Ce sont généralement les erreurs les plus fréquentes lorsque l'on débute dans un langage de programmation ou tout bêtement une erreur de frappe qui se glisse dans une instruction car on est allé un peu vite.
Heureusement, certains éditeurs proposent une colorisation syntaxique qui reconnaissent le langage que vous utilisez et qui aide grandement à voir ou on s'est trompé et surtout de le remarquer bien avant de se lancer dans l'exécution du programme.

Erreur à l'exécution : « Run-time error »

Une erreur d'exécution, également appelée exception apparaît lorsque le programme est déjà en cours d'exécution mais qu'il s'est passé quelque chose d'anormal du genre une ressource introuvable (lecture d'un ficher qui n'existe plus ou base de donnée injoignable, etc.). Ce genre d'erreur est totalement imprévisible mais on peu tout de même se prémunir de leurs effets néfastes en déterminant les plus probables et en programmant « un retour sur erreur »
(Exemple : base de donnée injoignable => message mes plus plates excuses, on répare ça ASAP).

Erreur sémantique (erreur de logique)

C'est l'erreur la plus difficile à détecter. En effet elle n'a aucune incidence sur l'exécution elle-même du programme, aucun message d'erreur mais le résultat obtenu n'est pas celui attendu.
Ce genre d'erreur renvoi souvent à la relecture complète du code voir à repartir à l'étape papier crayon (étape que tout bon programmeur se doit de respecter).

Recherche d'erreur

Même si c'est souvent fastidieux c'est à mon avis un aspect de la programmation qui est très passionnant car il apporte beaucoup plus que l'on pense en premier lieu. En effet vous devez emmètre des hypothèses pour déterminer le ou les processus qui ont conduits au résultat constaté, bref une véritable enquête digne de colombo :-) , relire les documentations pour être sur de ce que vous avez écrit, reprendre votre code, procéder par petite touches et voir le comportement, etc. Il existe bien sur des méthodes d'analyse ainsi que des programmes spécifique aux débugage mais franchement rien ne m'a vraiment convaincu si ce n'est de jouer moi-même les fouineurs de code et d'utiliser mes méthodes à moi que j'ai :-)

samedi 25 juin 2005

Sécurité PHP - Web Dynamique

Il y a quelques mois, John Gallet avait lancé un fil de discussion dans les groupes <news:fr.comp.lang.php> et <news:fr.comp.securite> Pratiques de codage php et webapps. Il nous avait promis à l'époque de nous faire une petite synthèse des réponses et débats que ce fil engendrait.

Voila qui est fait ! Ca a mis presque 7 mois et il y en aura bien fallu 3 pour l'écrire, mais connaissant le bonhomme ils s'est documenté à foison, fouillé partout, fait des tests sur ses propres machines.
Il nous affuble donc de 24 pages passionantes au format PDF écrite avec sa verve habituelle qui nous détaille les choses à ne pas faire et comment mieux protéger.

Un document indispensable à lire et à garder dans un coin et ce quelque soit son niveau en développement web dynamique.

samedi 7 mai 2005

PHP/SQL : Les sessions 'à la PHP3'

Si vous avez touché un peu à PHP, vous vous êtes peut être penché sur les sessions. La documentation vous propose une gestion des sessions en interne (dites à la PHP4) ce qui, pour moi, n'est pas vraiment très souple ni très fiable au niveau maintenance du code et auxquelles je ne donne (peut être à tord) qu'une confiance toute relative.

Lire la suite

samedi 30 avril 2005

OVH et MySQL

En développant une petite application en PHP/MySQL pour quelqu'un, je me suis rendu compte que le MySQL proposé dans les offres GP de OVH n'était pas compilé avec le support de table en innoDB.
Pour mémoire en MySQL seul le format de table innoDB comprend les clés étrangères ce qui est indispensable à mes yeux lorsque l'on essaye d'avoir une base de donnée cohérente. Et bien sur, cela n'est mentionné nulle part par OVH dans le descriptif de l'offre.

Bref, retour à la case départ, on reprend le schéma de la BdD et on dé-normalise le tout.

Pff... Vivement que PostgreSQL se généralise dans les offres des hébergeurs. Remarque, vu que je dois revoir mes ambitions en matière de BbD et au vu de ce qui est proposé avec le MySQL d'OVH, c'est peut être l'occasion de se pencher vers SQLite qui est intégré à PHP5.

Edit : Même l'utilisation de PHP5 est chiante chez OVH car on doit nommer les fichiers en .php5 :-(

samedi 2 avril 2005

PHP : de MySQL à MySQLi

Il y a quelques temps, je devais migrer quelques sites qui avaient été écrit pour fonctionner avec le SGBD/R MySQL4.0 sur une machine ne disposant que de MySQL4.1, seulement cela entraîne quelques complications.

Lire la suite

jeudi 31 mars 2005

Blog et graphisme

Graphisme web, cela est-il bien nécessaire ? Peut-être pas dans tous les cas...

Si je prends l'exemple de ce blog, les statistiques, certes très modestes, me montrent que les gens touchent la page d'accueil puis s'abonnent au flux RSS (ou Atom pour ceux qui le proposent). De plus, personnellement, je ne vais que rarement sur les quelques 30 blogs que je surveille quotidiennement; preuve que les gens (dont je fais partie) s'attachent plus au contenu qu'au site lui-même et ce, même s'il est beau à voir.
Je me pose donc la question, pour un site dont pratiquement tout le contenu est syndiqué (d'autres sites ne syndiquent qu'une partie de contenu, ce qui est super énervant au passage :-/ ), les efforts déployés dans le graphisme et le design sont-ils vraiment nécessaires ?

Donc à terme, je pense que les blogs ne seront qu'un (ou plusieurs) fichier XML syndiquant le contenu avec une légère feuille de style pour y mettre un peu de couleurs (à moins que les blogs disparaissent ?).
Tiens, ça peut même être une bonne idée de plate-forme d'hébergement de blog ça. Faudrait que je pense à déposer un brevet avant qu'un entrepreneur français me pique l'idée.

mercredi 30 mars 2005

24 millions d'internautes et moi

Si on en crois mediametrie nous serions près de 24 millions d'internautes en France : 23 723 000 d'internautes.
A partir de ce chiffre, on peu avancer que si 12,2% de Français utilisent Firefox ça nous fait 2 894 206 d'utilisateurs soit près de 3 millions ! Donc a ceux qui pensent encore que limiter un site à un navigateur hyper présent n'impacte pas beaucoup de monde car cela ne correspond qu'à seulement 12,2% des gens, gardez en tête qu'ils sont quand même 3 millions.

Edit : Une petite précision : je dis 3 millions en ne comptant que les utilisateurs de Firefox (qui est le second navigateur en terme d'utilisation en France), mais à ces 3 millions, il faut également compter tout ceux qui ont choisis un autre navigateurs et la non plus le nombre réel de personne que cela donne n'est pas négligeable (1% de 24 millions ça fait quand même 240 000, et comme on estime la part de marché de tous les "navigateurs alternatifs" à plus de 20%...).

vendredi 25 mars 2005

Webagency et standards du web

Le web est un gamin, il est en perpétuelle évolution et amélioration. Comme dans beaucoup de domaines de l'informatique qui évolue très rapidement, ce qui était vrai hier peut devenir une bêtise éhonté aujourd'huit.
A ce titre, j'ai du mal à comprendre que les professionnels ne se remettent pas en question concernant leurs méthodes de travail ni face aux technologies qu'ils utilisent.

Lire la suite

mercredi 16 mars 2005

XHTML : on "name" les "id" !

En relisant une page web en XHTML 1.0 Strict écrite par quelqu'un d'autre, j'ai remarqué qu'il utilisait l'attribut name de l'élément A pour ses ancres. Ses ancres étant des références (genre notes de fin de documents) il a choisi de donner en valeur un numéro à chacun.

On se retrouvait donc avec quelque chose du style :

<a href="#1">Lien 1</a>
<a href="#2">Lien 2</a>
<a href="#3">Lien 3</a>

<a name="1"></a>(1) Blabla
<a name="2"></a>(2) Blabla
<a name="3"></a>(3) Blabla

Jusque la, aucun problème, tout est complètement conforme à ce qu'on peu lire dans la doc de HTML 4.01 vu que les identificateurs partiels que sont name et id sont complètement prévus.

Seulement en XHTML il en est tout autrement. En effet XHTML est un langage XML et en XML, le seul identificateur partiel possible est de type ID, et la franchement ça tombe super bien vu que l'attribut id est aussi défini de type ID [1]. La ou a déconné, c'est qu'il ne respectait pas la règle qui dit que les documents XHTML 1.0 DOIVENT utiliser l'attribut id quand l'identificateur partiel est défini, même sur les éléments qui historiquement ont également un attribut name [2]

La ou ça pêche le plus c'est que le validateur du W3C n'avait rien vu et nous disait que la page était valide, et bien sur, cela fonctionnait correctement dans les divers navigateurs.

Donc la vous vous dites, ok, pas bien grave on fait un rechercher de name qu'on remplace par id ce qui nous donnerait cette fois ci :

<a href="#1">Lien 1</a>
<a href="#2">Lien 2</a>
<a href="#3">Lien 3</a>

<a id="1"></a>(1) Blabla
<a id="2"></a>(2) Blabla
<a id="3"></a>(3) Blabla

Oui mais non !

La encore, on introduit une erreur dans notre document ; En effet, la personne à utilisé des chiffres comme identificateur partiel (ancres) et la, cela ne fonctionne plus (du moins pour le langage, le navigateur lui...). Tout simplement parce que si on peu donner la valeur que l'on désire à name, vu que la spécification de HTML4 dit que la valeur de name est de type CDATA, il n'en est pas de même pour l'attribut id qui lui n'accepte que les valeurs de type nom qui doivent commencer par une lettre ([A-Za-z]).

Donc en résumé et pour éviter toutes erreurs futur et chercher pendant des heures la ou ça coince :

  • N'utilisez pas l'attribut name pour vos ancres (d'ailleurs ne l'utilisez carrément plus ça sera mieux) et ce même si vous faites du HTML 4.01 Strcit ou du XHTML 1.0 Strict.
  • Utilisez des valeurs d'identificateur parlantes (ex : annexe1, annexe2, etc.)
  • Ne faites qu'une confiance partielle au validateur, il n'est pas omnicient ;-) .

Notes

[1] Bon, comme je vois que ceux du fond commencent à lacher avec tous ces id et ID, je détaille un peu plus. Un attribut en XHTML est toujours en minuscule, donc lorsque j'écris id, on parle bien de l'attribut en (X)HTML et lorsque j'écris 'ID'' je parle du type de donnée que cela inclue en XML, donc un attribut qui identifie de manière unique un élément

[2] http://www.la-grange.net/w3c/xhtml1/#h-4.10

Toutes les fautes d'orthographes présentes sur ce site sont protégées par la licence Logo Creative common Creative common

 |  Valid XHTML  |  Valid CSS  |  Dotclear  |  Design décliné de [ON]Simple par [ NikO ]
Hébergé par Typhon.Network