Comment stocker ses mots de passe en .Net

icon Tags de l'article : , ,

Novembre 24, 2014
Il existe de nombreuses façons de stocker les mots de passe pour une application ou un site web. La triste nouvelle, c'est que la majorité des sites et des applications n'utilisent pas les bonnes.

Aujourd'hui nous allons voir comment bien faire les choses.

Déjà, voici les différentes façons de faire, de la plus ridicule à la plus paranoïaque :

  • Niveau 0 : tout en clair. Rien de bien compliqué, aucune sécurité, la moindre fuite de données et on doit demander à nos utilisateurs de changer de mots de passe... Vraiment pas top pour l'image. Sécurité : 0%

  • Niveau 1 : mots de passe hashés avec une clef en dur. Pourquoi pas, sauf que... ça ne sert à rien. Le hacker n'aura qu'à générer des rainbow tables à partir de votre clef, et il aura les correspondances en clair pour tous les mots de passe hashés en base. Sécurité : 1%

  • Niveau 2 : on hashe les mots de passe avec un sel, généré aléatoirement pour chaque utilisateur. Un petit peu mieux. Seul bémol : il suffit de régénérer des Rainbow Tables, une par utilisateur, et ... on a tous les mots de passe. Sécurité : 5%

  • Niveau 3 : on hashe les mots de passe avec un sel, généré aléatoirement pour chaque utilisateur, à l'aide d'un algorithme lent : BlowFish. Ici on corrige le principal problème du niveau 2 : générer des Rainbow Tables pour chaque utilisateur peut prendre des jours, voire des mois... Sécurité : 80%

  • Niveau 4 : on utilise un module physique pour hasher les mots de passe. Si quelqu'un essaye de le déplacer ou d'y accéder, il effacera automatiquement toutes les données. Vous l'avez compris, il s'agit du mode paranoïaque ! Sécurité : 99%

Vous l'aurez compris, on va surtout s'intéresser au niveau 3, facilement réalisable et ne demandant pas, lui, d'investissements financiers. La clef repose sur le fait d'avoir un sel généré unique par utilisateur, et d'utiliser l'algorithme lent BlowFish. A l'échelle d'un site web, le temps de hash de l'algorithme est court. Mais lorsqu'on fait du bruteforce, le temps pour générer un dictionnaire entier de mots de passe est gigantesque !

La mise en place est plutôt simple :

Il faut d'abord créer deux entrées dans notre base, une pour le mot de passe hashé, et une pour le sel. Il ne faut jamais stocker ni déplacer le mot de passe non hashé. Si vous voulez bien faire les choses, utilisez HTTPS et stockez le sel ailleurs.



Ensuite, il faut ajouter BCrypt.Net à notre projet (via NuGet) :



Cette implémentation de l'algorithme BlowFish offre 2 méthodes : GenerateSalt et HashPassword, à utiliser comme suit :



Maintenant vous n'avez plus qu'à implémenter la bonne logique dans votre code :
  • Lorsque l'utilisateur s'inscrit, on génère et stocke un salt aléatoire pour lui, puis on se sert de ce salt pour hasher son mot de passe.
  • Lorsqu'il se connecte, on récupère le salt, et on hashe le mot de passe saisi à l'aide du salt pour ensuite comparer les deux hashs générés.
  • Lorsqu'il a perdu son mot de passe, on génère un mot de passe et un salt aléatoires, pour ensuite lui envoyer un mail avec son nouveau mot de passe.

Voilà, j'espère que ce petit article vous a plu,

Bonne soirée à tous !

Un petit outil pour gérer ses fichiers de traduction en PHP

icon Tags de l'article : , ,

Septembre 17, 2014
Hello,

Juste pour ceux que ça intéresse, voici un petit outil très simple que j'ai développé pour moi afin de gérer les traductions dans mes applications en PHP.

Resmanager (sur Github)

Le fonctionnement est très simple :
  • on remplit le fichier resources.lng avec nos traductions
  • on lance le petit exécutable ResourcesSplitter.exe
  • ce dernier va générer automatiquement des fichiers PHP avec nos traductions, un fichier par langue
  • on n'a plus qu'à inclure/utiliser ces fichiers dans nos applications

Le petit exe est fait en .Net, il est très simple et son code source est également présent sur le repository (fichier ResourcesSplitter.cs).

Voilà, on ne sait jamais, ça vous servira peut-être ! Si vous avez des questions n'hésitez pas !

Bon développement à tous !

(Et oui, pour ceux qui se demandent, je m'en sert pour la nouvelle version à venir de MyCryptoChat :)

Tests unitaires, présentation

icon Tags de l'article : , ,

Mars 25, 2014
Aujourd'hui, je vais vous parler de tests unitaires.

On teste tous nos développements. Que ce soit en compilant et regardant rapidement si ça marche, en déroulant un cahier de tests, en faisant n'importe quoi pour voir si on arrive à planter l'application, etc.

Sauf qu'assez peu de gens font des tests unitaires.

C'est triste, car il s'agit du meilleur moyen d'améliorer considérablement la qualité de vos développements, mais aussi d'anticiper sur les différents bugs à venir.

En effet, beaucoup de développeurs auront tendance à considérer les tests unitaires comme une perte de temps, voire un truc plutôt gadget qui coute toujours plus que ce qu'il apporte.

Ce n'est pas vrai.

De vrais bons tests unitaires auront effectivement un cout assez lourd au départ, mais ce cout sera vite amorti si vous passez du temps sur votre application.

Ca peut sembler idiot, mais c'est vrai.

A chaque développement, il y a un risque de coder un ou plusieurs bug. Voire même de faire réapparaître un ancien bug. Les tests unitaires permettent d'éliminer 90% des bugs.

Le vrai problème qui se pose est donc : comment bien faire mes tests unitaires ?

Nous verrons cela très bientôt, dans de futurs articles :
  • Quand faire des tests unitaires ?
  • Les tests de connectivité
  • Présentation des tests unitaires pour la couche d'accès aux données
  • Présentation des tests unitaires pour la couche métier

Bonne soirée !

Faut-il créer sa variable dans la boucle, ou en dehors ?

icon Tags de l'article :

Mars 24, 2014
Il s'agit d'une question qu'on a tous, je pense, entendu au moins une fois. Il existe trois types de réponses :

  • Il faut créer ta variable dans ton for, comme ceci :

for(int i = 0 ; i < maListe.Count ; i++) 
{
	int monI = maListe[i];
}

  • Pas du tout, il faut la créer avant :

int monI;
for(int i = 0 ; i < maListe.Count ; i++) 
{
	monI = maListe[i];
}

  • Et la bonne réponse : ça ne change rien.

Il faut savoir que les "variables" éphémères (monI dans ce cas) n'existent que pour le développeur.

En effet, le compilateur est capable d'identifier les variables qui ont une utilisation très spécifique, dans un scope réduit. Il remplacera alors l'utilisation de la variable par un accès direct à cette dernière.

Sur notre exemple :

for(int i = 0 ; i < maListe.Count ; i++) 
{
	int monI = maListe[i];
}

// génèrera strictement le même code MSIL que :

int monI;
for(int i = 0 ; i < maListe.Count ; i++) 
{
	monI = maListe[i];
}
// je n'utilise plus monI à partir d'ici

L'endroit où nous créerons notre variable monI n'a donc aucun impact sur le code MSIL généré.

Néanmoins, il est plutôt conseillé de la créer à l'intérieur du for, et ce pour plusieurs raisons :
  • L'optimiseur comprendra directement que la variable ne sera utilisée que dans la boucle et pas en dehors,
  • On ne transportera pas, à chaque itération, la valeur précédente,
  • On ne risque pas, par inadvertance, de la réutiliser en dehors de la boucle.

Mais il s'agit plus d'une bonne pratique que d'une optimisation.

Bonne soirée et bon dev à tous !

Méthodes d'extensions C# - 2

icon Tags de l'article :

Mars 24, 2014
Bonjour à tous !

Prêts pour une nouvelle fournée de méthodes d'extensions C# super-méga-ultra utiles ?

C'est parti !

Déjà, une méthode d'extension pour la classe string afin de faire bien plus rapidement nos String.Format (et non pas string.Format) :

public static string Format(this string s, params object[] args)
{
    return String.Format(s, args);
}

// et son appel

string myString = "{0} {1}";
myString.Format("Hello", "World");

Ensuite, une autre petite méthode qui va nous servir de raccourci : créer notre propre méthode d'extension Log sur la classe Exception pour unifier le logging de nos erreurs :

public static void Log(this Exception obj)
{
    // votre logique de logging ici
}

// et son utilisation

try
{
    // votre code
}
catch(Exception ex)
{
    ex.Log();
}

Ces deux petites méthodes vous feront gagner un temps fou, croyez-moi ;)

Bon dev à tous !

Méthodes d'extensions C# - 1

icon Tags de l'article :

Mars 21, 2014
Hello à tous,

J'ai décidé de commencer une petite série d'articles sur les méthodes d'extensions vraiment utiles.

A force de développer en C# sur différents projets, je me suis rendu compte que je m'étais constitué un joli petit pool de méthodes d'extensions... que je vais partager avec vous. Merci qui ? :)

Pour commencer, voici une méthode d'extension qui sert à faire un .Contains() case-insensitive sur une collection. Ca peut sembler simple et idiot, mais le faire à la main plusieurs fois est encore plus embêtant :

public static bool Contains(this string source, string toCheck, StringComparison comp)
{
    return source.IndexOf(toCheck, comp) >= 0;
}

// et son appel

bool contains = myString.Contains("hello", StringComparison.OrdinalIgnoreCase);

Et pour continuer sur cette lancée, voici une petite méthode d'extension pour vérifier si notre objet est présent dans une liste d'objets passés en paramètres, bien plus utile que ça en a l'air :

public static bool IsIn<T>(this T source, params T[] list)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    return list.Contains(source);
}

// et son appel

if (myString.IsIn("string1", "string2", "string3", "string4"))
{
    // do something
}

Bon weekend et bon dev à tous !

DateTime.Now ou DateTime.UtcNow

icon Tags de l'article :

Mars 20, 2014
Et vous, comment vous faites avec les dates ? - Doc Emmet Brown, ou pas.

Aujourd'hui on utilise tous les dates dans nos applications : récupération de la date courante, stockage d'une date précise, calculs sur des dates, etc.

Sauf qu'il existe deux façons de récupérer et de manipuler la date courante :

DateTime.Now
// ou
DateTime.UtcNow

Maintenant la question : laquelle utiliser ?

La réponse est simple : DateTime.UtcNow.

Pourquoi ?

Déjà DateTime.UtcNow est bien plus performant que DateTime.Now (du fait de ne pas avoir à gérer le fuseau horaires et les changements d'heure).

Ensuite, stocker des dates au format UTC permet d'éviter les nombreux problèmes d'incohérences sur les dates. En effet, utiliser DateTime.Now vous posera problème dès que vous hébergerez votre application dans un autre fuseau horaire (merci le Cloud !), dès que vous migrerez vos données, dès que vous effectuerez des calculs sur les dates, ...

Après vous pouvez toujours convertir la date pour l'afficher ou la manipuler, mais pour le stockage et à la récupération, il faut privilégier DateTime.UtcNow.

Vous ne direz pas qu'on ne vous a pas prévenu !

EDIT : Attention, il existe une exception : la réutilisation de dates. Lorsqu'on veut stocker une donnée au format date la réutiliser (par exemple planifier un rendez-vous récurrent tous les vendredis à 9h00), il ne faut pas la stocker au format UTC. Pourquoi ? Si on la stocke au format UTC et qu'on la convertie à chaque fois, le jour où on changera d'heure... Notre rendez-vous aussi changera d'heure ! Dans ce genre de situations (assez rares, il faut bien l'admettre), la solution est d'utiliser le DateTimeOffset.

string ou String ?

icon Tags de l'article :

Mars 20, 2014
Savez vous quelle est la différence entre string et String ? Et bien... Il n'y en a pas. Enfin...

Il faut savoir que string n'est qu'un alias de System.String.

Techniquement, il n'y a donc aucune différence. C'est la même chose pour int et Int32 par exemple.

Après, lorsqu'on code, il y a quelques bonnes pratiques conseillées vis-à-vis de l'utilisation de string & String.

Il est généralement conseillé d'utiliser string lorsqu'on se réfère à une instance de string :

string myString = "Hello World!";

Mais il est plutôt conseillé d'utiliser String lorsqu'on se réfère à la classe, par exemple pour appeler ses méthodes statiques :

string myString = String.Format("{0} {1}!", "Hello", "World");

Voilà, c'était le petit conseil C# du jour.

Bonne journée et bon dev à tous !

Voir le type d'une variable initialisée avec var

icon Tags de l'article :

Mars 19, 2014
"I've been so wrong these years!" - moi

J'ai découvert quelque chose il y a quelques jours... Quelque chose qui a changé ma vie de développeur .Net...

Quelque chose que la majorité des gens connaissent depuis longtemps et que j'aurais dû connaître depuis longtemps également...

J'ai découvert qu'on pouvait savoir le type d'une variable initialisée avec var en passant la souris sur le var.

Pas besoin d'aller regarder ce qu'il y a à droite du =, il suffit juste de passer la souris sur le "var" et le type de notre variable apparait sous nos yeux ébahis :



J'en ai les larme aux yeux...
Dire que je viens de découvrir ça après 5 ans de .Net...

Voir une requête générée par Linq To SQL

icon Tags de l'article : , ,

Mars 19, 2014
Une question qui revient assez souvent lorsqu'on travaille avec Linq To Sql : comment peut-on faire pour voir une requête SQL générée ?

Certains vous recommenderont d'utiliser Linqpad, ce qui est effectivement une solution...

Mais il y a bien plus simple : utiliser la méthode .ToString() sur notre objet IQueryable.
Cette méthode (qui surcharge en fait ObjectQuery.ToTraceString()) renverra tout simplement la requête SQL générée par Linq To Sql !

Exemple :

using (var dc = new DataClassesVideoGameDataContext())
{
    var result = dc.VideoGames.Where(e => e.Price < 70).OrderBy(e => e.Name);

    var query = result.ToString();

    // query : 
    // SELECT [t0].[IdVideoGame], [t0].[Name], [t0].[Description], [t0].[Price]
    // FROM [dbo].[VideoGame] AS [t0]
    // WHERE [t0].[Price] < @p0
    // ORDER BY [t0].[Name]
}

Bon dev à tous !