Catégories
Développement web Sécurité informatique

Déve­lop­peurs, vous devriez avoir honte — Règles de mots de passe

Je rage à chaque fois que je saisis un mot de passe fort et que le site m’en­voie bouler parce que je n’ai pas de carac­tère autre qu’al­pha­nu­mé­rique.

Essayons quelque chose d’un peu plus smart pour évaluer la robus­tesse d’un mot de passe

Déve­lop­peurs, vous savez proba­ble­ment tout ça, mais conti­nuez à lire parce que la fin vous est adres­sée

Si j’en crois Hacker­noon on peut calcu­ler envi­ron 800 millions de SHA256 par seconde sur un maté­riel qui coûte 0,82 € par heure sur AWS. Ça fait 3,5 10^12 combi­nai­sons par euro.

Traduit autre­ment, voici le nombre de combi­nai­sons qu’on peut tester, et le même chiffre écrit en puis­sance de deux (arrondi à la déci­male infé­rieure) :

1 €3,5 × 10^122^41,6
10 €3,5 × 10^132^44,9
100 €3,5 × 10^142^48,3
1 000 €3,5 × 10^152^51,6
10 000 €3,5 × 10^162^54,9
100 000 €3,5 × 10^172^58,2

Quand on vous parle ailleurs de bits d’en­tro­pie, ça corres­pond à ces puis­sances de 2. Avec 1 000 € on peut tester toutes les combi­nai­sons de SHA 256 d’une chaîne aléa­toire de 51 bits.

Ok, mais ça me dit quoi ? Une lettre c’est 26 combi­nai­sons, envi­ron 4,7 bits. Si vous ajou­tez les majus­cules vous doublez le nombre de combi­nai­sons et vous ajou­tez 1 bit. Si vous ajou­tez les chiffres et quelques carac­tères spéciaux on arrive à à peine plus de 6 bits.

Petit calcul, en utili­sant juste les 26 lettres de l’al­pha­bet, on peut tester toutes les combi­nai­sons de 8 carac­tères pour moins de 1 €. Vu qu’on aura de bonnes chances de tomber dessus avant d’avoir testé toutes les combi­nai­sons, autant dire que même avec 9 carac­tères, votre mot de passe ne vaut pas plus de 1 €.

Combien faut-il de carac­tères pour se trou­ver rela­ti­ve­ment à l’abri (c’est à dire que la somme inves­tie ne peut pas tester plus de 1% des combi­nai­sons) ? Ça va dépendre de ce que vous y mettez comme types de carac­tères. J’ai fait les calculs pour vous :

a-za-z
A-Z
a-z
A-Z
0–9
a-z
A-Z
0–9
+-%
1 €11998
10 €111099
100 €12101010
1 000 €13111010
10 000 €14111111
100 000 €14121111

Et là magie : 8 carac­tères, même avec des chiffres, des majus­cules et des symboles, ça résiste tout juste à 1 €. Et encore, là c’est en partant du prin­cipe que vous choi­sis­sez réel­le­ment les carac­tères de façon aléa­toire, pas que vous ajou­tez juste un symbole à la fin ou que vous trans­for­mez un E en 3.

Vous voulez que votre mot de passe résiste à un voisin malveillant prêt à mettre plus de 10 € sur la table ? Prévoyez au moins 10 carac­tères.

Et là, seconde magie : Si vous mettez 10 carac­tères on se moque de savoir si vous y avez mis des chiffres ou symboles. La longueur a bien plus d’im­por­tance que l’éven­tail de carac­tères utilisé.


Main­te­nant que vous savez ça, tous les sites qui vous imposent au moins une majus­cule et un symbole mais qui vous laissent ne mettre que 8 carac­tères : Poubelle.

Je ne suis pas en train de vous apprendre à faire un mot de passe fort. Vous devriez utili­ser un gestion­naire de mots de passe et le géné­ra­teur auto­ma­tique qui y est inclus.

Je suis en train d’es­sayer de rendre honteux tous les déve­lop­peurs qui acceptent de mettre ces règles à la con sur les sites web dont ils ont la charge : Vous impo­sez des mots de passe qui sont à la fois imbi­tables et peu robustes.


Vous voulez faire mieux ?

Regar­dez dans quelle colonne est l’uti­li­sa­teur en fonc­tion des carac­tères qu’il a déjà tapé et donnez-lui un indi­ca­teur en fonc­tion de la longueur de son mot de passe.

  • Mot de passe refusé s’il est sur « Have I Been Pwned? »
  • Moins de 10 € ? mot de passe insuf­fi­sant, refusé
  • Moins de 100 € ? mot de passe faible, couleur rouge
  • Moins de 1 000 € ? mot de passe moyen, couleur orange
  • Mot de passe sûr, couleur verte, à partir de 10 000 €

Si vous gérez un site central, par exemple un réseau social public, vous pouvez proba­ble­ment rele­ver tout ça d’un cran.

Si ça donne accès à des données sensibles, à des possi­bi­li­tés d’achat, à la boite e-mail ou à l’opé­ra­teur télé­pho­nique, mieux vaux rele­ver tout ça de deux crans.

Le tout prend proba­ble­ment moins de 10 lignes en javas­cript. C’est une honte que vous accep­tiez encore d’im­plé­men­ter des règles à la con « au moins une majus­cule, un chiffre et un symbole, voici les symboles auto­ri­sés […] ».

Déve­lop­peurs, vous devriez avoir honte.

Catégories
CSS javascript React

Où je dis du bien du CSS-in-JS

Il n’y a que les imbé­ciles qui ne changent pas d’avis et c’est mon avis depuis toujours

Coluche

J’ai toujours regardé avec dédain les tenta­tives des dev JS pour contour­ner l’écri­ture de CSS mais je commence à consi­dé­rer que les outils de CSS-in-JS type Emotion sont la bonne solu­tion pour les webapp React.


J’ai été inté­gra­teur, à faire de la belle CSS sépa­rée du code HTML. On finit quand même vite par construire des monstres ou se prendre les pieds dans le tapis dès qu’on fait plus de quelques pages types.

Pour résoudre le problème, élimi­nons le. C’est ce que proposent les conven­tions comme BEM. Si je cari­ca­ture, il s’agit prin­ci­pa­le­ment de reti­rer les sélec­teurs CSS un attri­buant une ou plusieurs classes spéci­fiques à chaque contexte. C’est fran­che­ment moche mais ça fonc­tionne.

CSS-Modules va un peu plus loin. Le prin­cipe est le même mais on permet au déve­lop­peur d’uti­li­ser un nommage plus agréable. C’est l’ou­til de géné­ra­tion qui gère la complexité au lieu du déve­lop­peur.


J’avoue que j’aime bien CSS-modules. C’était mon favori jusqu’à présent.

Ça revient à juste gérer un fichier par compo­sant en se limi­tant à des sélec­teurs très simples pour ne pas créer de conflits de spéci­fi­cité. On reste sur du CSS stan­dard et sur une approche proche de mes habi­tudes histo­riques. Mieux : L’in­té­gra­tion peut se faire indé­pen­dam­ment du langage de déve­lop­pe­ment de l’ap­pli­ca­tif.

C’est top mais ça se base sur des compo­sants qui ne bougent pas beau­coup, dont on connait à l’avance tous les états.

Dès qu’il s’agit de cumu­ler plusieurs états, le résul­tat dépend de l’ordre d’écri­ture dans la CSS. Parfois c’est bien prévu, parfois non.

Dès qu’il s’agit de rendre des choses très dyna­miques, il faut de toutes façons sortir des CSS modules. Vous voulez que dans la vue large les items de navi­ga­tion se colorent au survol en fonc­tion de la caté­go­rie desti­na­tion déter­mi­née dyna­mique­ment mais qu’ils utilisent la couleur neutre dans la vue réduite desti­née aux mobiles ? Vous êtes à poil et il va falloir compo­ser avec d’autres façons d’injec­ter des CSS, peut-être même tâton­ner sur les prio­ri­tés entre classes.


Les classes utili­taires et CSS atomiques à la Tachyon sont là pour indus­tria­li­ser en pous­sant encore plus loin.

J’ai une classe par valeur à appliquer : .ms7-ns applique la septième valeur du cata­logue (7) comme taille hori­zon­tale maxi­mum (ms pour max-width) si la fenêtre a une taille supé­rieure au point de rupture « small » (ns pour non-small).

Ça n’offre quasi­ment aucune abstrac­tion utile (unifor­mi­ser les valeurs on a déjà plein d’ou­tils plus effi­caces). C’est vite cryp­tique, lourd, et mons­trueux dès qu’on multi­plie les valeurs et les points de rupture possibles.

Le seul inté­rêt par rapport à écrire direc­te­ment les attri­buts style c’est que ça permet d’ac­cé­der aux media query et aux pseudo-sélec­teurs.

Malheu­reu­se­ment non seule­ment ça ne résout pas les conflits de prio­ri­tés mais ça les empire. Si je spécia­lise un compo­sant exis­tant en y ajou­tant une classe liée à une direc­tive déjà présente, je joue à la roulette russe. Il faut abso­lu­ment que mon compo­sant initial prévoit lui-même tous les cas possibles pour savoir quelle classe injec­ter et ou ne pas injec­ter. Pas d’al­ter­na­tive.

J’ai vrai­ment l’im­pres­sion d’un retour en arrière mons­trueux avec ces CSS atomiques, cumu­ler les défauts sans aucun avan­tage, et c’est proba­ble­ment ce qui m’a fait reje­ter par prin­cipe les CSS-in-JS jusqu’a­lors.


Les CSS-in-JS c’est fina­le­ment pous­ser la logique de Tachyons un cran plus loin. Quitte à déci­der de tout dans le code HTML, autant écrire direc­te­ment les styles à cet endroit là en utili­sant la vraie syntaxe CSS et en y ajou­tant la possi­bi­lité d’ac­cé­der aux media query et aux pseudo-sélec­teurs.

Emotion c’est ça. On est à la croi­sée entre le « j’écris tout dans un attri­but style » et le « j’at­tache un module CSS ».

En fonc­tion­ne­ment basique c’est comme un CSS module sans le sélec­teur. Je donne les direc­tives en CSS on ne peut plus clas­siques et j’ai accès aux media query, aux pseudo-sélec­teurs et aux anima­tions avec une syntaxe proche de ce que font les prépro­ces­seurs habi­tuels (et en phase avec la direc­tion que prend la syntaxe CSS elle-même).

const style = css`
padding: 32px;
background-color: hotpink;
font-size: 24px;
border-radius: 4px;
&:hover {
color: blue;
}
`

Je peux direc­te­ment ajou­ter le résul­tat aux classes CSS de mon compo­sant. Il se char­gera de géné­rer un nom de classe, de créer la CSS corres­pon­dante dans le docu­ment, et de lier les deux, comme avec CSS-Modules.

L’exemple est peu parlant. On a juste l’im­pres­sion d’un CSS-Modules écrit dans le fichier JS.

L’avan­tage c’est que je ne suis pas limité aux valeurs en dur. Je peux avoir des valeurs dyna­miques venant de mon Javas­cript ou de mon thème, et je n’en limite pas les effets à ce que me permettent les variables CSS.

Je peux aussi réuti­li­ser, compo­ser ou surchar­ger un élément ou un bloc de styles avec un autre sans risque de conflit de prio­rité.


Tachyons me donnait l’im­pres­sion de cumu­ler les incon­vé­nients, ici j’ai vrai­ment l’im­pres­sion de cumu­ler les avan­tages.

La seule contrainte c’est que mon code CSS se retrouve dans mes fichiers JS. C’est moche quand c’est dit ainsi mais pour une app en React, on a de toutes façons un fichier par compo­sant HTML et ça a du sens de grou­per HTML, JS et CSS lié au compo­sant ensemble quand ils sont forte­ment liés. C’est d’ailleurs le choix de VueJS.

Ce n’est forcé­ment pas adapté à tout, et si vous voulez rester géné­riques les CSS-Modules sont à mon avis l’op­tion la plus saine, mais pour un code React je crois que c’est là que je commen­ce­rai par défaut désor­mais.

Catégories
Développement informatique javascript Sécurité informatique

Une histoire de dépen­dances

Le main­te­neur d’un paquet NPM n’a plus eu envie et a donné la main à un tiers. Ce tiers a injecté un code mali­cieux dans une version publique et poten­tiel­le­ment infecté pas mal de monde. Ça n’a été détecté qu’au bout de deux mois et demi alors que le paquet est utilisé un peu partout.


J’en vois qui lancent des blâmes ou qui se moquent sur l’ac­tua­lité du paquet NPM mali­cieux. Ça défoule mais : Faites-vous mieux ? Permet­tez-moi d’en douter très très forte­ment.

Le moindre projet React, Symfony ou Rails, c’est une centaine de dépen­dances directes et indi­rectes, certaines proviennent de sources dont vous n’avez jamais entendu parler. J’ai listé trois frame­works mais c’est bien la même chose sur les autres langages/tech­nos.

C’est bien le sujet : Sauf si vous avez la taille d’un Face­book/Google ou la criti­cité d’un Thalès ou d’un état, vous n’avez ni les moyens de passer des années-homme à tout reco­der en interne, ni les moyens d’au­di­ter chaque source à chaque mise à jour (si tant est que ça suffise).

Même ceux que j’ai nommé, je ne suis pas certains qu’ils le fassent toujours, sur tous les types de projet. Je suis même assez convaincu du contraire. Le ratio béné­fice/risque n’est juste pas assez impor­tant pour ça. Les moyens et les délais ne sont pas dimen­sion­nés pour.


Alors moquez-vous, de ceux qui utilisent NPM, de ceux qui ne contrôlent pas l’en­semble des dépen­dances, mais vous ne faites proba­ble­ment pas mieux. Il y a pas mal d’hy­po­cri­sie dans les réac­tions que je vois passer.

Ne blâmez pas non plus le main­te­neur d’ori­gine. Lui ne vous a jamais rien promis. C’est même dit expli­ci­te­ment dans la licence « aucune garan­tie d’au­cune sorte ». Ce n’est pas parce que d’autres utilisent son code gratui­te­ment qu’il aurait magique­ment des comptes à rendre. En fait avoir passé la main est plutôt quelque chose d’en­cou­ragé dans l’open source. S’il n’y avait pas eu cette issue, il aurait plutôt fallu le remer­cier.


Alors quoi ? Alors rien.

Le problème a été résolu. Si ça arrive trop souvent alors ça chan­gera le ratio béné­fice/risque et la commu­nauté évaluera le fait d’avoir trop de dépen­dances tierces un (tout petit) peu plus néga­ti­ve­ment, et ainsi de suite.

La ques­tion inté­res­sante que personne ne semble poser c’est celle de l’hon­nê­teté du main­te­neur d’ori­gine. A-t-il vrai­ment passé la main ? et s’il l’a fait, est-ce qu’il en a tiré un béné­fice tout en soupçon­nant ce qui pouvait se passer ? C’est à peu près la seule chose qui pour­rait à mon sens lui faire porter une quel­conque respon­sa­bi­lité.

Catégories
Droit d'auteur Livre PHP Vie personnelle

« PHP 5 avancé » en chiffres

Je vois les auteurs racon­ter leur histoire, leurs rému­né­ra­tions. Je n’ai pas trop envie de m’y mélan­ger vu que je n’ai jamais été auteur profes­sion­nel ni n’ai jamais cher­ché à l’être. Mes enjeux d’au­teur du dimanche sont bien diffé­rents. Ajou­tez y que j’ai écrit dans à propos de tech­nique infor­ma­tique, très loin des auteurs de romans et de bande dessi­née.

Pour autant, c’est aussi l’oc­ca­sion parce que je ne crois pas avoir déjà fait un tel bilan. Peut-être que ça inté­res­sera certain d’entre vous. Dites-moi s’il y a des ques­tions auxquelles je ne réponds pas.

Atten­tion, ce n’est repré­sen­ta­tif de rien d’autre que de mon cas person­nel. J’ai même tendance à penser que mon histoire entre dans l’ex­cep­tion à plus d’un titre. Le fait qu’il y ait des gros chiffres dans la suite ne doit certai­ne­ment pas vous amener à penser que les auteurs roulent habi­tuel­le­ment sur l’or.

Six éditions et quatre colla­bo­ra­teurs

Travail à quatre mains avec Cyril Pierre de Geyer. Le premier chapitre a été fait en février 2003 pour une publi­ca­tion de 700 pages en juin 2004.

PHP a pas mal évolué et le livre serait rapi­de­ment devenu obso­lète. Nous avons du mettre à jour le livre régu­liè­re­ment. Il y a eu une édition par an jusqu’en 2008 puis une sixième de 870 pages en 2012.

La troi­sième édition a été reti­rée sur un format « best-of » en 2007, en paral­lèle de la vente de la quatrième dans son format d’ori­gine. J’avoue que ça me semble toujours étrange, d’au­tant que si nous en avons fait une quatrième édition plutôt qu’un reti­rage c’est que l’évo­lu­tion de PHP rendait l’an­cienne version moins perti­nente.

Nous avons été épaulé par Hugo Hamon pour les relec­tures et l’in­dexa­tion de la cinquième édition. La sixième édition a été parta­gée avec un troi­sième auteur, Frédé­ric Hardy. Il est en petit sur la couver­ture, je le regrette aujourd’­hui.

Les tirages et les ventes

Le premier tirage était prévu à 3000 exem­plaires. Vus les chiffres de vente je suppose qu’il en a plutôt été tiré 3200 (ou alors on a vendu des livres qui n’exis­taient pas). Les chiffres des éditions suivantes ne tombant même pas proches de multiples de 250, j’ima­gine qu’on en imprime toujours un peu plus au cas où et que le chiffre final n’est pas tota­le­ment maitri­sable.

La seconde édition a été tirée à envi­ron 3700 exem­plaires, la troi­sième et la quatrième ont toutes les deux fait entre 3200 et 3300 exem­plaires, plus envi­ron 4000 exem­plaires pour la best-off. La cinquième a béné­fi­cié de deux tirages, proba­ble­ment respec­ti­ve­ment 3400 et 2000 exem­plaires. La dernière a été tirée à quelque chose comme 3800 exem­plaires, proba­ble­ment en deux fois.

Au total j’ai quelque chose comme 26 500 ventes sur les 12 ans de vie du livre.

Le travail d’écri­ture

Diffi­cile d’es­ti­mer le temps passé en écri­ture tant il était très frac­tionné, d’au­tant que ce n’était pas mon acti­vité prin­ci­pale. Sur les 16 mois de travail de l’édi­tion initiale, j’ai quand même du y passer une bonne majo­rité des soirs et week-end, et quelques mois quasi­ment à temps plein. À cela il faut bien entendu ajou­ter le travail de mon co-éditeur.

Chose éton­nante pour moi, nous n’avons pas utilisé de logi­ciel ou de format de fichier spéci­fique à l’édi­tion, juste du Micro­soft Word avec une feuille de styles interne : un fichier par version et par chapitre nommé d’après l’au­teur a avoir créé la version, le tout dans un FTP.

Les autres éditions ont été un effort variable, plus fort pour les premières que pour les dernières. On parle quand même géné­ra­le­ment de plusieurs mois pendant des soirs et des week-ends.

Je n’ai aucune idée du travail total en équi­valent temps plein 35h sala­rié. Si je devais donner un chiffre je dirais proba­ble­ment un an équi­valent temps plein sala­rié, mais en réalité ça peut faci­le­ment être la moitié moins ou moitié plus.

Malgré la moti­va­tion des premiers temps, faire ça en paral­lèle d’un job très prenant n’est pas aisé, surtout au moment des relec­tures. La colla­bo­ra­tion entre auteurs n’a pas toujours été évidente non plus. Ça parait évident après coup mais écrire à deux quand on ne se connait pas vrai­ment et qu’on ne se voit jamais en face à face, c’est forcé­ment un peu diffi­cile.

La rému­né­ra­tion

La rému­né­ra­tion est de 10% du hors taxe pour les ventes françaises grand format (4% sur les ventes à l’étran­ger, 5% sur le format poche — l’édi­teur a souhaité en sortir un une année, nous avons refusé), à parta­ger entre les auteurs initiaux, sans aucune avance, sur des livres qui ont varié de 35 à 45 € pour la collec­tion prin­ci­pale, 25 € pour le best-of.

Même en allant cher­cher dans les archives, je suis encore aujourd’­hui inca­pable de dire combien j’ai gagné que ce soit en net ou en brut. J’ai des comptes de vente, des détails de coti­sa­tions, des avis de paie­ment et des résu­més de sommes à décla­rer au fisc. Rien ne se recoupe vrai­ment, quand je n’ai pas deux docu­ments d’un même type tota­le­ment diffé­rents pour une même année.

Disons que la somme encais­sée avant impôts sur le revenu doit être entre 40 et 47 000 euros nets depuis le premier verse­ment en 2005. Précis hein ?

Ramené à un an de travail c’est effec­ti­ve­ment très bien payé, surtout par rapport à ce que je lis à propos de auteurs en litté­ra­ture, en jeunesse ou en bande dessi­née. Même dans la four­chette haute, en comp­tant deux ans de travail en équi­valent temps plein, ça reste bien au dessus du SMIC. Cela dit il était loin d’être dit que ça rému­nè­re­rait autant, et ce que ça m’a apporté a large­ment dépassé le finan­cier. Je ne pensais pas à l’argent. Je ne m’étais en fait même pas fait de prévi­sion quand j’ai dit oui, et je n’au­rais pas su dire si je m’at­ten­dais à 1 000 ou 10 000 euros.

Cette somme est après paie­ment de la TVA, de la CSG et CRDS, ainsi que d’une coti­sa­tion de 1% à l’Agessa. Tout ça est prelevé pour moi en amont par l’édi­teur. Pas de retraite, pas de prévoyance, et avec dans les 4000€ par an en moyenne je n’au­rais proba­ble­ment eu aucune couver­ture sociale si je n’avais pas eu un emploi sala­rié en paral­lèle.

Pour l’im­pôt sur le revenu je déclare ce que l’édi­teur me dit en trai­te­ments et salaires. C’est peut-être idiot ou anor­mal, je n’ai jamais su (on m’a donné des réponses diffé­rentes à chaque fois que je deman­dais ce que devait faire un auteur de loisir) mais du coup c’est imposé sur le barème progres­sif.

Autant Hugo (en relec­teur) que Frédé­ric (en co-auteur sur la dernière mise à jour) ont été rému­né­rés sur une base fixe, payée par l’édi­teur en plus de nos droits d’au­teur.

L’édi­teur

J’en­tends beau­coup de choses sur les éditeurs. Person­nel­le­ment moi j’ai plutôt eu une très bonne expé­rience d’Ey­rolles. Muriel, tu as été vrai­ment super, Karine aussi, et j’ou­blie certai­ne­ment des gens. Je n’ai eu à me plaindre de personne, au contraire.

Si je devais repro­cher quelque chose, c’est le refus total de consi­dé­rer une durée limi­tée pour la version numé­rique du livre. Je crains cepen­dant qu’il en soit de même pour l’es­sen­tiel des éditeurs et mon co-auteur a de toutes façons refusé toute vente numé­rique par peur du pira­tage (qui a tout de même eu lieu, visi­ble­ment par des fuites des PDF internes desti­nés à l’im­pri­meur, avec les marques de découpe). Oh si, si je devais pinailler, il y a briè­ve­ment eu une mise en vente de la quatrième édition sous forme numé­rique malgré le refus expli­cite au contrat, mais ils y ont mis un terme quand on l’a fait remarquer.

Je ne m’éten­drai pas sur ce point mais on a même eu une diffi­culté de répar­ti­tion des droits entre co-auteurs à un moment. Non seule­ment l’édi­teur a aidé à sa réso­lu­tion mais il a aussi pris le diffé­ren­tiel à sa charge pour solder le passé. Ok, vu les ventes ils pouvaient se le permettre, mais rien ne les y obli­geait non plus.

PHP 7 avancé

Aujoud’­hui PHP 5 avancé n’existe plus. Il y a eu réécri­ture partielle pour construire PHP 7 avancé mais consi­dé­rant les diffi­cul­tés de colla­bo­ra­tion, on a décidé de ne pas forcé­ment le refaire ensemble. Je suis toujours sur la couver­ture en grisé mais j’ai passé la main aux excel­lents Pascal Martin et Julien Pauli, au moins pour les deux premières éditions (la seconde arrive parait-il sous peu).

Catégories
javascript navigateurs et API Sécurité informatique

Comment on fait de la crypto dans le navi­ga­teur ?

Faire de la cryp­to­gra­phie dans le navi­ga­teur se révèle bien plus simple que prévu.

Lais­sez tomber les portages de libso­dium & co. Quasi­ment tous les navi­ga­teurs supportent désor­mais une API native dédiée. Seul IE11 ne le fait pas tota­le­ment mais il a au moins le mini­mum qu’est la géné­ra­tion de nombres réel­le­ment aléa­toires. Ceux qui veulent vrai­ment pour­ront complé­ter l’im­plé­men­ta­tion d’IE11 avec un poly­fill sans risquer de problème de sécu­rité.

Il y a plein de jolis exemples sur qnimate mais certaines choses datent un peu. J’ai tenté de résu­mer ici pour ceux que ça inté­resse. Ici pour du déchif­fre­ment à partir d’une clef secrète.

Avant-propos

Je ne suis pas un expert en chif­fre­ment et ce genre de choses est toujours à manier avec précau­tion. Si vous faites quelque chose de sérieux, ne vous conten­tez pas d’exemples et embau­chez quelqu’un qui sait.

Rien que choi­sir l’al­go­rithme perti­nent demande de savoir ce qu’on fait. AES-CTR semble perti­nent pour mon cas d’usage où n’ai pas besoin de véri­fier l’au­then­ti­cité du message, où je n’ai pas envie de me colti­ner les ques­tions de padding, et où je serai heureux de profi­ter des multiples cœurs des smart­phones.

Si l’al­go­rithme choisi ou autre chose vous dérange et que vous en savez plus que moi, n’hé­si­tez pas à commen­ter.

Récu­pé­rer une clef

Le plus simple est de récu­pé­rer direc­te­ment une clef au format JSON Web Key (en gros la clef en base64url plus un peu de méta­don­nées). Dans ce cas il suffit de passer par importKey :

const crypto = window.crypto.subtle;

const jwk = {
  "kty": "oct",
  "use": "enc",
  "k": "SDRSTgdOpUGfgn3iAwiC1cpzsevLM98r_6ehMXlK1Gk",
  "alg": "A256CTR"
};
const algo = {name: "AES-CTR"};
const exportable = false;
const usage = ["decrypt"];

const key = await crypto.importKey("jwk", jwk, algo, exportable, usage);
Déri­ver une clef

Si on veut partir d’une phrase secrète mémo­ri­sable et non d’une clef complète, on commence par créer une clef tempo­raire et on utilise un algo­rithme de déri­va­tion comme PBKDF2.

Malheu­reu­se­ment pour créer cette première clef il faut passer par un TextEn­co­der et ArrayBuf­fer. peut toujours déri­ver la clef à partir de là. TextEn­co­der n’existe pas sous Edge et IE11, il vous faudra utili­ser une fonc­tion comme uniba­bel qui fait ça pour vous.

const crypto = window.crypto.subtle;
const encoder = TextEncoder();

const passphrase = "l'eau ça mouille, le feu ça brûle";
const buffer = encoder.encode( passphrase );
const d_algo =  {name: 'PBKDF2'};
const d_exportable = false;
const d_usage = ['deriveBits', 'deriveKey'];
const d_key = await crypto.importKey('raw', buffer, d_algo, d_exportable, d_usage);

const deriv = { 
  name: 'PBKDF2',
  salt: encoder.encode( "c'est le week-end !" ),
  iterations = 25,
  hash: 'SHA-256',
};
const algo = {name: "AES-CTR", length: 256}; 
const exportable = false; 
const usage = ["decrypt"];

const key = await crypto.deriveKey(deriv, d_key, algo, exportable, usage);

La sécu­rité de tout ça dépend de la longueur et de l’uni­cité de votre phrase secrète initiale. À vous de trou­ver le bon compro­mis entre la sécu­rité et la puis­sance des smart­phones qui risquent d’uti­li­ser votre code. Le 25 ici est pure­ment arbi­traire et le temps de calcul néces­saire est propor­tion­nel.

Déchif­frer

Déchif­frer n’est pas plus diffi­cile.

Le vecteur d’ini­tia­li­sa­tion (iv) et la donnée chif­frée (encryp­ted) sont atten­dus sous forme d’Ar­rayBuf­fer. Il faudra de nouveau passer par uniba­bel ou une autre solu­tion si vous avez ça sous forme de chaîne binaire ou codé en base64.

Le résul­tat de decrypt() vous est retourné sous la même forme. S’il est petit le plus simple est d’uti­li­ser TextDe­co­der ou uniba­bel. Si vous avez quelque chose de plus volu­mi­neux vous pouvez aussi passer par un Blob et un FileRea­der.

const crypto = window.crypto.subtle;
const decoder = TextDecoder

const key = ...
const iv = ...
const encrypted = ...

const algo = { name: 'AES-CTR', iv: iv }
const buffer = await crypto.decrypt(alg, key, encryted);
Catégories
Développement web javascript Sécurité informatique

Donnée confi­den­tielle dans une session de navi­ga­tion.

Je partage, ça peut servir à d’autres. Je cher­chais à garder confi­den­tiel une infor­ma­tion confi­den­tielle le temps d’une session de navi­ga­tion. En gros je cher­chais un genre de cookie de session mais qui reste côté client sans jamais tran­si­ter sur le réseau.

Le localS­to­rage est top mais il persiste au delà de la session de navi­ga­tion. Le sessionS­to­rage est top mais il n’est pas partagé entre les onglets.

Visi­ble­ment certains se sont penchés sur la ques­tion il y a quelques années et sont reve­nus avec une solu­tion toute bête mais effi­cace : Faire dialo­guer les diffé­rents sessionS­to­rage en surveillant les écri­tures dans le localS­to­rage.

C’est tout con, ça prend juste 20 lignes, mais il fallait y penser.

Merci Rik

Catégories
Développement informatique Développement web Geek Sécurité informatique Web

Un espace de publi­ca­tion chif­fré côté client

Je ne veux plus gérer de serveur en ligne. Je me sens de moins en moins capable d’as­su­rer la sécu­rité d’un tel envi­ron­ne­ment 24/7 seul et sur mon temps person­nel. Je n’en ai pas la moti­va­tion, ne souhaite pas y inves­tir le temps néces­saire. Ne parlons même pas de la possi­bi­lité de prendre des congés deux semaines hors de France sans connexion Inter­net ni veille sécu­rité. Rien qu’a­voir ce blog sous word­press me gêne.

Je vais dépla­cer mes services sur un envi­ron­ne­ment mutua­lisé, géré par des profes­sion­nels qui ont les moyens, le temps et les compé­tences. Je vais en profi­ter pour passer à peu près tout en fichiers HTML statiques. Publier des fichiers html, css et images sur un espace à 2€, ça limite pas mal la main­te­nance.

* * *

Mon problème c’est que j’ai aussi des parties de site à accès restreint, avec des docu­ments qui ne doivent pas sortir n’im­porte où.

Je peux faci­le­ment trou­ver un héber­ge­ment mutua­lisé qui me permet de faire des accès restreints par authen­ti­fi­ca­tion HTTP ou avec un bout de PHP en façade, mais j’ai une confiance limi­tée dans la confi­den­tia­lité des fichiers que je peux poser sur un héber­geur mutua­lisé.

Du coup j’ima­gine utili­ser du chif­fre­ment côté client, avec un croi­se­ment entre Jekyll/Peli­can et 0bin/cryp­to­pad. Je chiffre les conte­nus lors de la géné­ra­tion et je les envoie chif­frés sur l’hé­ber­ge­ment. Les conte­nus sont déchif­frés dans le navi­ga­teur du client avec un gros bout de JS, en utili­sant un dérivé de mot de passe ou une clef cachée dans l’URL.

Le seul défaut que je vois c’est inter­dire l’ac­cès à ceux qui désac­tivent volon­tai­re­ment Javas­cript, et impo­ser un peu d’at­tente aux autres pour déver­rouiller les conte­nus : Pas idéal, pas perti­nent pour tous les usages, mais ici ça me semble accep­table.

* * *

Il y a 0bin et Cryp­to­pad (ainsi que d’autres) qui fonc­tionnent un peu sur ce prin­cipe, mais bran­cher ça dans Jekyll ou Peli­can me semble néces­si­ter un peu de travail, surtout si je veux avoir plus que du texte et que je veux présen­ter à l’uti­li­sa­teur unique­ment les liens auxquels il a accès.

Si vous connais­sez un CMS à publi­ca­tion statique qui a envi­sagé quelque chose du genre, je suis preneur.

Catégories
Développement web javascript

[Aide] Commu­ni­ca­tion entre une page et une exten­sion navi­ga­teur

J’ai une page qui fait des trai­te­ments javas­cripts basés sur des appels XHR authen­ti­fiés vers son origine et sur des commu­ni­ca­tions en window.postMes­sage avec des <iframe>. Elle n’a besoin d’au­cune permis­sion privi­lé­giée, c’est juste une page web avec une origine normale.

J’ai­me­rais pouvoir inter­ro­ger cette page depuis une exten­sion Fire­fox et qu’elle me commu­nique le résul­tat de ses trai­te­ments, mais sans que ça n’af­fiche la page à l’uti­li­sa­teur.

Au départ j’ima­gi­nais que l’ex­ten­sion pouvait lancer une <iframe> cachée et discu­ter avec elle en postMes­sage. On me dit que ce n’est pas possible.

Embarquer direc­te­ment le code de la page dans l’ex­ten­sion n’est pas envi­sa­geable pour des raisons de sécu­rité (et on ne ferait que repor­ter le problème vu que cette page lance elle-même des iframes pour commu­niquer avec elles).

Dis, public, est-ce que tu aurais une sugges­tion ou une piste à explo­rer ?

Catégories
Développement web Geek Vie professionnelle

La base de travail pour 2018

Une progres­sive web app prévue d’abord pour mobile, fonc­tion­nant tota­le­ment hors ligne avec une synchro à la prochaine recon­nexion et des données chif­frées côté client.

Oui, votre besoin a peut-être des usages ou des contraintes qui ne cadrent pas avec ce stéréo­type mais ça mérite proba­ble­ment d’y réflé­chir deux fois avant d’écar­ter un des éléments.

Quand je vois nombre de projets sans chif­fre­ment des données ou quasi­ment inutiles une fois hors ligne, j’ai l’im­pres­sion de retrou­ver les projets d’il y a quelques années qui consi­dé­raient le mobile comme acces­soire.

Catégories
Développement web Photo

Et si on agençait des photos sur une page web mobile ?

J’ai commencé à vouloir mettre en pratique mes études sur l’agen­ce­ment de photos dans une page web et… j’ai tout repris à zéro.

Quand je donne un lien vers mes photos, il est quasi­ment toujours ouvert en premier sur mobile. Sauf à y faire des minia­tures illi­sibles, on peut y mettre une ou deux photos maxi­mum en largeur. La vue à la Flickr n’a aucun sens.

Du coup je suis reparti d’une vue mobile, avec des agen­ce­ments prédé­ter­mi­nés. J’ai en trouvé quatre, même si bien évidem­ment certains peuvent s’in­ver­ser :

Tech­nique­ment les calculs pour que les agen­ce­ments avec plusieurs images tombent « juste » sont les mêmes que dans la vue Flickr décrite au précé­dent billet.

* * *

La vraie ques­tion c’est le choix de l’agen­ce­ment en fonc­tion du format des diffé­rentes photos et de leur ordre d’ap­pa­ri­tion.

La mauvaise idée de départ c’était tenter de faire des règles complexes pour choi­sir l’agen­ce­ment en fonc­tion des prochaines images et de leur format. L’ap­proche naïve était simple mais le résul­tat assez mauvais visuel­le­ment. Il aurait fallu faire plus complexe que verti­cal / carré / hori­zon­tal mais si je commence à distin­guer sept caté­go­ries, les combi­nai­sons explosent.

Autant calcu­ler les quatre agen­ce­ments possibles et voir lequel est le plus perti­nent. J’ai pris deux axiomes :

1– L’im­por­tant visuel­le­ment c’est la surface affi­chée de chaque image plutôt que sa taille en largeur ou hauteur.  Trop gros est aussi mauvais que trop petit. Je compare donc la surface de l’image à évaluer à celle d’une image de réfé­rence (une hori­zon­tale au format 3/2 affi­chée en pleine largeur).

2– Il suffit d’une seule image illi­sible pour tout gâcher. Je calcule donc le score de chaque image indi­vi­duel­le­ment et le score d’un agen­ce­ment de plusieurs images corres­pond au plus mauvais score des images concer­nées.

Le résul­tat est plutôt réussi. J’ai tenté de bidouiller et ajou­ter d’autres règles complexes mais ça n’a pas donné des amélio­ra­tions visuelles signi­fi­ca­tives.

* * *

Je calcule la gale­rie au fur et à mesure. Parfois il me reste une image verti­cale à la fin et je n’ai plus qu’à l’af­fi­cher en grand, même si c’est déme­suré. Une solu­tion pour­rait être de calcu­ler réel­le­ment toutes les combi­nai­sons pour toute la gale­rie avant de faire mon choix. Ça risque d’être un peu lourd pour ce seul défaut, surtout pour des gale­ries assez longues, donc pour l’ins­tant je ne suis pas allé sur ce chemin.

Aujourd’­hui je garde l’ordre des photos. Je pour­rais aussi éven­tuel­le­ment iden­ti­fier les cas où tous les agen­ce­ments testés sont mauvais, et tenter de modi­fier un peu l’ordre des images avec celles juste après, pour voir si c’est mieux.

Tant que je ne repère pas de cas vrai­ment moche, je vais toute­fois rester sur du simple.

* * *

Le choix assumé c’est de faire du mobile-first. Si j’ai plus d’es­pace hori­zon­tal je peux tenter de faire deux colonnes avec ce même algo­rithme.

Si je trouve un point pivot et que je découpe la gale­rie en deux sections, je pour­rai choi­sir de les enchaî­ner verti­ca­le­ment ou hori­zon­ta­le­ment sans avoir besoin de calcu­ler quoi que ce soit en javas­cript.

Si j’ai vrai­ment une grande surface en hauteur et en largeur, un mur d’images à la Flickr est peut-être plus perti­nent mais je ne m’in­ter­dis pas de simple­ment garder deux colonnes de grande largeur. Je vais attendre de voir ce que ça donne avant de faire mon choix.