<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Cryptographie on Guillaume Delré</title><link>https://guillaumedelre.github.io/fr/tags/cryptographie/</link><description>Recent content in Cryptographie on Guillaume Delré</description><generator>Hugo</generator><language>fr-FR</language><lastBuildDate>Sun, 14 Jan 2018 00:00:00 +0000</lastBuildDate><atom:link href="https://guillaumedelre.github.io/fr/tags/cryptographie/index.xml" rel="self" type="application/rss+xml"/><item><title>PHP 7.2 : adieu mcrypt, bonjour sodium</title><link>https://guillaumedelre.github.io/fr/2018/01/14/php-7.2-adieu-mcrypt-bonjour-sodium/</link><pubDate>Sun, 14 Jan 2018 00:00:00 +0000</pubDate><guid>https://guillaumedelre.github.io/fr/2018/01/14/php-7.2-adieu-mcrypt-bonjour-sodium/</guid><description>Part 3 of 11 in &amp;quot;Sorties PHP&amp;quot;: PHP 7.2 supprime l&amp;#39;extension mcrypt, abandonnée depuis des années, et intègre libsodium — la cryptographie PHP entre enfin dans le XXIe siècle.</description><category>php-releases</category><content:encoded><![CDATA[<p>PHP 7.2 est sorti le 30 novembre. La grande nouvelle n&rsquo;est pas une nouvelle fonctionnalité, c&rsquo;est une suppression. <code>mcrypt</code> disparaît.</p>
<p>C&rsquo;est une bonne chose, même si ça ne le semble pas quand c&rsquo;est vous qui devez faire la migration.</p>
<h2 id="le-problème-mcrypt">Le problème mcrypt</h2>
<p><code>mcrypt</code> n&rsquo;est plus maintenu depuis 2007. Plus d&rsquo;une décennie de stagnation dans une bibliothèque cryptographique. Dépréciée en 7.1, elle est retirée définitivement en 7.2. Son remplaçant : <code>sodium</code>, désormais intégré comme extension core.</p>
<p>Sodium est le binding PHP pour <a href="https://libsodium.org" target="_blank" rel="noopener noreferrer">libsodium</a>, une bibliothèque cryptographique moderne conçue autour de valeurs par défaut sûres. Là où mcrypt vous demandait de choisir le bon algorithme, le bon mode et le bon padding (et vous laissait vous planter silencieusement), l&rsquo;API de sodium rend les choix dangereux structurellement difficiles. <code>sodium_crypto_secretbox()</code> pour le chiffrement symétrique, <code>sodium_crypto_box()</code> pour l&rsquo;asymétrique, <code>sodium_crypto_sign()</code> pour les signatures. Les noms disent ce qu&rsquo;on fait.</p>
<p>Si vous avez du code mcrypt en production, la migration est inévitable. Et ça vaut le coup de le faire soigneusement : du code cryptographique qui &ldquo;fonctionne encore&rdquo; peut être silencieusement cassé d&rsquo;une façon que vous ne remarquerez qu&rsquo;il sera trop tard.</p>
<h2 id="le-type-hint-object">Le type hint <code>object</code></h2>
<p>7.2 ajoute <code>object</code> comme type de paramètre et de retour :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">serialize</span>(<span style="color:#a6e22e">object</span> $data)<span style="color:#f92672">:</span> <span style="color:#a6e22e">string</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// accepte n&#39;importe quel objet
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>C&rsquo;est large — n&rsquo;importe quel objet le satisfait — mais c&rsquo;est mieux qu&rsquo;aucun type du tout quand vous ne vous souciez vraiment pas de la classe spécifique. Complète les types existants <code>array</code>, <code>callable</code> et les hints par classe concrète.</p>
<h2 id="argon2-dans-password_hash">Argon2 dans password_hash</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span>$hash <span style="color:#f92672">=</span> <span style="color:#a6e22e">password_hash</span>($password, <span style="color:#a6e22e">PASSWORD_ARGON2I</span>);
</span></span></code></pre></div><p><code>PASSWORD_BCRYPT</code> était la valeur par défaut et reste raisonnable, mais Argon2 a remporté le Password Hashing Competition pour une bonne raison : il est memory-hard, ce qui rend le craquage par GPU significativement plus coûteux. Vaut la peine de basculer pour les nouvelles apps.</p>
<p>7.2 est davantage une version sécurité qu&rsquo;une version langage. Supprimez mcrypt, ajoutez sodium, et vous placez la plateforme dans un état où on peut lui faire confiance avec des données sensibles. Les fonctionnalités du langage sont incrémentales. Le changement d&rsquo;infrastructure, lui, ne l&rsquo;est pas.</p>
<h2 id="des-types-de-paramètres-quon-peut-désormais-omettre-intentionnellement">Des types de paramètres qu&rsquo;on peut désormais omettre intentionnellement</h2>
<p>7.2 formalise quelque chose qui était jusqu&rsquo;ici juste une odeur de code : quand vous implémentez une interface ou surchargez une méthode, vous pouvez maintenant omettre complètement le type du paramètre. C&rsquo;est de la contravariance valide au sens du principe de substitution de Liskov.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">Serializable</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">serialize</span>(<span style="color:#66d9ef">array</span> $data)<span style="color:#f92672">:</span> <span style="color:#a6e22e">string</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">JsonSerializer</span> <span style="color:#66d9ef">implements</span> <span style="color:#a6e22e">Serializable</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">serialize</span>($data)<span style="color:#f92672">:</span> <span style="color:#a6e22e">string</span> { <span style="color:#75715e">// pas de type — accepte plus, toujours valide
</span></span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">json_encode</span>($data);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Ça paraît bizarre au premier abord. Mais c&rsquo;est logiquement correct : une méthode qui accepte tout est strictement plus permissive qu&rsquo;une qui n&rsquo;accepte que des tableaux. Le système de types est d&rsquo;accord, même si votre relecteur de code lève un sourcil.</p>
<h2 id="des-méthodes-abstraites-qui-évoluent">Des méthodes abstraites qui évoluent</h2>
<p>Quand une classe abstraite étend une autre classe abstraite, elle peut désormais surcharger la méthode abstraite avec une signature différente. La contrainte est directionnelle : les paramètres peuvent être élargis (contravariants), les types de retour peuvent être resserrés (covariants).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">BaseProcessor</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">process</span>(<span style="color:#a6e22e">string</span> $input);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TypedProcessor</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">BaseProcessor</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">process</span>($input)<span style="color:#f92672">:</span> <span style="color:#a6e22e">int</span>; <span style="color:#75715e">// paramètre élargi, type de retour ajouté
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>C&rsquo;était refusé avant 7.2. Ça débloque des abstractions intermédiaires sans forcer chaque classe feuille à répéter la même signature.</p>
<h2 id="virgule-finale-dans-les-imports-groupés">Virgule finale dans les imports groupés</h2>
<p>Petit, mais je remarque son absence quand elle manque. Les imports de namespaces groupés peuvent désormais avoir une virgule finale après le dernier élément :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#66d9ef">use</span> <span style="color:#a6e22e">App\Services\</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">UserService</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">OrderService</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">NotificationService</span>, <span style="color:#75715e">// virgule ici — enfin
</span></span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>Ça signifie qu&rsquo;on peut réordonner ou ajouter des lignes sans toucher à la ligne précédente. Les diffs git deviennent plus propres, les conflits de merge plus rares.</p>
<h2 id="count-a-développé-une-conscience"><code>count()</code> a développé une conscience</h2>
<p>Avant 7.2, <code>count(null)</code> retournait 0. Silencieusement. Sans warning. C&rsquo;est exactement le genre de chose qui enterre un bug pendant des mois. Maintenant, ça émet un <code>E_WARNING</code> quand vous passez quelque chose qui n&rsquo;est ni un tableau ni un objet <code>Countable</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#a6e22e">count</span>(<span style="color:#66d9ef">null</span>);  <span style="color:#75715e">// Warning: count(): Parameter must be an array or an object that implements Countable
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">count</span>(<span style="color:#ae81ff">42</span>);    <span style="color:#75715e">// pareil
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">count</span>(<span style="color:#e6db74">&#34;hi&#34;</span>);  <span style="color:#75715e">// pareil
</span></span></span></code></pre></div><p>Le comportement n&rsquo;a pas changé pour les entrées valides. Seul le silence a été brisé. C&rsquo;est la bonne direction.</p>
<h2 id="spl_object_id--ce-que-vous-émuliez-avec-splobjectstorage"><code>spl_object_id()</code> — ce que vous émuliez avec SplObjectStorage</h2>
<p>Si vous avez déjà construit une map indexée par identité d&rsquo;objet, vous avez écrit quelque chose comme ça :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span>$storage <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">SplObjectStorage</span>();
</span></span><span style="display:flex;"><span>$storage[$obj] <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span></code></pre></div><p>7.2 ajoute <code>spl_object_id()</code>, qui retourne un entier unique pour la durée de vie d&rsquo;un objet. C&rsquo;est le même handle interne qu&rsquo;utilise <code>SplObjectStorage</code>, rendu directement accessible :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span>$id <span style="color:#f92672">=</span> <span style="color:#a6e22e">spl_object_id</span>($obj); <span style="color:#75715e">// ex. 42
</span></span></span><span style="display:flex;"><span>$map[$id] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;something&#39;</span>;
</span></span></code></pre></div><p>L&rsquo;entier est réutilisé après la destruction de l&rsquo;objet, donc ne le conservez pas au-delà de la durée de vie de l&rsquo;objet. Dans un contexte bien délimité cependant, c&rsquo;est une clé d&rsquo;identité peu coûteuse.</p>
<h2 id="pdo--les-chaînes-de-caractères-nationales">PDO : les chaînes de caractères nationales</h2>
<p>Quand on travaille avec des bases de données qui distinguent les types de chaînes régulières et nationales (Oracle, SQL Server), 7.2 ajoute les flags nécessaires :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span>$stmt <span style="color:#f92672">=</span> $pdo<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">prepare</span>(<span style="color:#e6db74">&#34;SELECT * FROM users WHERE name = ?&#34;</span>);
</span></span><span style="display:flex;"><span>$stmt<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">bindValue</span>(<span style="color:#ae81ff">1</span>, <span style="color:#e6db74">&#39;Ångström&#39;</span>, <span style="color:#a6e22e">PDO</span><span style="color:#f92672">::</span><span style="color:#a6e22e">PARAM_STR</span> <span style="color:#f92672">|</span> <span style="color:#a6e22e">PDO</span><span style="color:#f92672">::</span><span style="color:#a6e22e">PARAM_STR_NATL</span>);
</span></span></code></pre></div><p>Ou définir une valeur par défaut au niveau de la connexion :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span>$pdo<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">setAttribute</span>(<span style="color:#a6e22e">PDO</span><span style="color:#f92672">::</span><span style="color:#a6e22e">ATTR_DEFAULT_STR_PARAM</span>, <span style="color:#a6e22e">PDO</span><span style="color:#f92672">::</span><span style="color:#a6e22e">PARAM_STR_NATL</span>);
</span></span></code></pre></div><p><code>PDO::PARAM_STR_NATL</code> indique que la chaîne est un type caractère national (NCHAR/NVARCHAR). Obscur, certes. Indispensable si vous avez déjà vu vos données Unicode ressortir déformées parce que le driver ne faisait pas la différence.</p>
<h2 id="gd-supporte-les-bmp-et-les-rectangles-de-clipping">GD supporte les BMP et les rectangles de clipping</h2>
<p>Deux choses à connaître. D&rsquo;abord, les fichiers BMP sont désormais des citoyens de première classe dans l&rsquo;extension GD :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span>$image <span style="color:#f92672">=</span> <span style="color:#a6e22e">imagecreatefrombmp</span>(<span style="color:#e6db74">&#39;photo.bmp&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">imagebmp</span>($image, <span style="color:#e6db74">&#39;output.bmp&#39;</span>);
</span></span></code></pre></div><p>Ensuite, on peut maintenant définir un rectangle de clipping pour que les opérations de dessin n&rsquo;affectent qu&rsquo;une portion de l&rsquo;image :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#a6e22e">imagesetclip</span>($image, <span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">200</span>, <span style="color:#ae81ff">150</span>); <span style="color:#75715e">// x1, y1, x2, y2
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// tout ce qui est dessiné en dehors de ce rectangle est silencieusement ignoré
</span></span></span></code></pre></div><p>Aucune de ces fonctionnalités ne transforme la façon dont la plupart des apps fonctionnent, mais les deux remplacent &ldquo;installer une bibliothèque supplémentaire&rdquo; par &ldquo;c&rsquo;est juste dans le core maintenant.&rdquo;</p>
<h2 id="mb_chr-et-mb_ord--le-chr-et-ord-dunicode"><code>mb_chr()</code> et <code>mb_ord()</code> — le <code>chr()</code> et <code>ord()</code> d&rsquo;Unicode</h2>
<p>PHP a <code>chr()</code> et <code>ord()</code> depuis toujours. Ils travaillent sur des octets. Pour les points de code Unicode, vous étiez livré à vous-même. 7.2 ajoute les équivalents multibyte :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span>$char <span style="color:#f92672">=</span> <span style="color:#a6e22e">mb_chr</span>(<span style="color:#ae81ff">0x1F600</span>); <span style="color:#75715e">// retourne l&#39;emoji 😀
</span></span></span><span style="display:flex;"><span>$code <span style="color:#f92672">=</span> <span style="color:#a6e22e">mb_ord</span>(<span style="color:#e6db74">&#39;é&#39;</span>);     <span style="color:#75715e">// retourne 233
</span></span></span></code></pre></div><p>Et <code>mb_scrub()</code>, qui supprime les séquences d&rsquo;octets invalides d&rsquo;une chaîne plutôt que d&rsquo;échouer silencieusement ou de lancer une exception :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span>$clean <span style="color:#f92672">=</span> <span style="color:#a6e22e">mb_scrub</span>($untrustedInput, <span style="color:#e6db74">&#39;UTF-8&#39;</span>);
</span></span></code></pre></div><p>Pratique à toute frontière externe : réponses API, uploads de fichiers, lectures en base depuis des systèmes legacy.</p>
<h2 id="dépréciations-à-connaître-avant-larrivée-de-74">Dépréciations à connaître avant l&rsquo;arrivée de 7.4</h2>
<p>Plusieurs choses ont été mollement dépréciées en 7.2 et deviendront des erreurs dans les versions ultérieures. Celles qui risquent le plus de piquer :</p>
<p><code>__autoload()</code> est déprécié. Si vous enregistrez encore une fonction d&rsquo;autoload globale au lieu d&rsquo;utiliser <code>spl_autoload_register()</code>, corrigez ça avant que ça devienne fatal.</p>
<p><code>create_function()</code> est déprécié. C&rsquo;est un wrapper autour de <code>eval()</code> et ça a toujours été dangereux. Utilisez une closure :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#75715e">// avant
</span></span></span><span style="display:flex;"><span>$fn <span style="color:#f92672">=</span> <span style="color:#a6e22e">create_function</span>(<span style="color:#e6db74">&#39;$x&#39;</span>, <span style="color:#e6db74">&#39;return $x * 2;&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// après
</span></span></span><span style="display:flex;"><span>$fn <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($x) <span style="color:#f92672">=&gt;</span> $x <span style="color:#f92672">*</span> <span style="color:#ae81ff">2</span>;
</span></span></code></pre></div><p><code>each()</code> est déprécié. Le pattern de boucle qu&rsquo;il permettait s&rsquo;écrit mieux avec <code>foreach</code>. Aucune perte ici.</p>
<p><code>parse_str()</code> sans second argument déverse les valeurs parsées dans la table des symboles locale — un problème de sécurité qui n&rsquo;aurait jamais dû être autorisé. Passez toujours la variable de sortie :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#a6e22e">parse_str</span>($queryString, $params); <span style="color:#75715e">// correct
</span></span></span></code></pre></div><p>Le cast <code>(unset)</code> est déprécié parce qu&rsquo;il retourne toujours <code>null</code>, que vous pouvez simplement écrire <code>null</code>. Une syntaxe complètement inutile qui n&rsquo;aurait jamais dû exister.</p>
]]></content:encoded></item></channel></rss>