web-dev-qa-db-fra.com

Quel est le moyen le plus simple de chiffrer un mot de passe lorsque je l’enregistre dans le registre?

Actuellement, je l'écris en texte clair oups!, c'est un programme interne, donc ce n'est pas si grave, mais j'aimerais le faire correctement. Comment dois-je procéder pour le chiffrer lors de l'écriture dans le registre et comment le déchiffrer?

OurKey.SetValue("Password", textBoxPassword.Text);
57
Lisa

Vous ne déchiffrez pas les mots de passe d'authentification!

Hachez-les en utilisant quelque chose comme le fournisseur SHA256 et quand vous devez contester, hachez l'entrée de l'utilisateur et voyez si les deux hachages correspondent.

byte[] data = System.Text.Encoding.ASCII.GetBytes(inputString);
data = new System.Security.Cryptography.SHA256Managed().ComputeHash(data);
String hash = System.Text.Encoding.ASCII.GetString(data);

Laisser les mots de passe réversibles est un modèle vraiment horrible.

Edit2: Je pensais que nous ne parlions que de l'authentification de première ligne. Bien sûr, il existe des cas dans lesquels vous souhaitez chiffrer les mots de passe pour d’autres éléments devant être réversibles, mais il devrait y avoir un verrou à sens unique par-dessus tout cela (à de très rares exceptions près).

J'ai mis à jour l'algorithme de hachage mais vous souhaitez conserver la meilleure puissance possible n sel privé et ajoutez-le à votre entrée avant le hachage il . Vous feriez cela à nouveau lorsque vous comparez. Cela ajoute une couche supplémentaire, ce qui rend encore plus difficile l'inversion.

123
Oli

Pensez également à "saler" votre hasch (pas un concept culinaire!). Fondamentalement, cela signifie ajouter du texte aléatoire au mot de passe avant de le hacher.

" La valeur du sel contribue à ralentir l'attaque par un attaquant lors d'une attaque par dictionnaire si votre banque d'informations d'identification est compromise, ce qui vous laisse un délai supplémentaire pour la détection et la réaction. "

Pour stocker les hachages de mots de passe:

a) Générer une valeur de sel aléatoire:

byte[] salt = new byte[32];
System.Security.Cryptography.RNGCryptoServiceProvider.Create().GetBytes(salt);

b) Ajoutez le sel au mot de passe.

// Convert the plain string pwd into bytes
byte[] plainTextBytes = System.Text UnicodeEncoding.Unicode.GetBytes(plainText);
// Append salt to pwd before hashing
byte[] combinedBytes = new byte[plainTextBytes.Length + salt.Length];
System.Buffer.BlockCopy(plainTextBytes, 0, combinedBytes, 0, plainTextBytes.Length);
System.Buffer.BlockCopy(salt, 0, combinedBytes, plainTextBytes.Length, salt.Length);

c) Hachez le mot de passe et le sel combinés:

// Create hash for the pwd+salt
System.Security.Cryptography.HashAlgorithm hashAlgo = new System.Security.Cryptography.SHA256Managed();
byte[] hash = hashAlgo.ComputeHash(combinedBytes);

d) Ajoutez le sel au hash résultant.

// Append the salt to the hash
byte[] hashPlusSalt = new byte[hash.Length + salt.Length];
System.Buffer.BlockCopy(hash, 0, hashPlusSalt, 0, hash.Length);
System.Buffer.BlockCopy(salt, 0, hashPlusSalt, hash.Length, salt.Length);

e) Stockez le résultat dans la base de données de votre magasin utilisateur.

Cette approche signifie que vous n'avez pas besoin de stocker le sel séparément, puis de recalculer le hachage à l'aide de la valeur du sel et du mot de passe en texte brut obtenu de l'utilisateur.

Modifier : La puissance de calcul brute devenant de moins en moins chère et plus rapide, la valeur du hachage - ou du hachage en salaison - a diminué. Jeff Atwood a une excellente mise à jour 2012 trop long à répéter dans son intégralité ici qui dit:

Cela (en utilisant du sel salé) donnera l'illusion de sécurité plus que toute sécurité réelle. Étant donné que vous avez besoin du sel et du choix de l'algorithme de hachage pour générer le hachage, et pour vérifier le hachage, il est peu probable qu'un attaquant en ait un mais pas l'autre. Si vous avez été compromis au point qu’un attaquant dispose de votre base de données de mots de passe, il est raisonnable de supposer qu’ils possèdent ou peuvent obtenir votre secret, votre sel caché.

La première règle de sécurité est de toujours assumer et de planifier pour le pire. Devez-vous utiliser un sel, idéalement un sel aléatoire pour chaque utilisateur? Bien sûr, c’est certainement une bonne pratique, et à tout le moins, cela vous permet de ne pas faire l’ambiguïté de deux utilisateurs qui ont le même mot de passe. Mais ces jours-ci, les sels à eux seuls ne peuvent plus vous sauver d'une personne disposée à dépenser quelques milliers de dollars en matériel de carte vidéo, et si vous pensez qu'ils le peuvent, vous êtes en difficulté.

23
DOK

Tom Scott a bien compris comment il ne stockait pas les mots de passe, sur Computerphile.

https://www.youtube.com/watch?v=8ZtInClXe1Q

  1. Si vous pouvez l'éviter, n'essayez pas de stocker les mots de passe vous-même. Utilisez une plate-forme d'authentification d'utilisateur distincte, pré-établie et digne de confiance (par exemple: = OAuth, domaine Active Directory de votre société, etc.) à la place.

  2. Si vous devez stocker des mots de passe, ne suivez pas les instructions ici. Du moins, sans consulter également des publications plus récentes et réputées, applicables à votre langue. de choix.

Il y a certainement beaucoup de gens intelligents ici, et probablement même de bons conseils. Mais il y a de fortes chances que, au moment où vous lisez ceci, toutes les réponses ici (y compris celle-ci) soient déjà obsolètes.


La bonne façon de stocker les mots de passe change avec le temps.

Probablement plus souvent que certaines personnes changent de sous-vêtements.


Cela étant dit, voici quelques conseils généraux qui, espérons-le, resteront utiles pendant un certain temps.

  1. Ne chiffrez pas les mots de passe. Toute méthode de stockage permettant de récupérer les données stockées est intrinsèquement non sécurisée aux fins de détenir des mots de passe - toutes les formes de cryptage incluses.
  2. Traite les mots de passe exactement tels qu'ils ont été entrés par l'utilisateur au cours du processus de création. Tout ce que vous faites avec le mot de passe avant de l'envoyer au module de cryptographie va probablement juste l'affaiblir. Effectuer l'une des opérations suivantes ne fait qu'ajouter de la complexité au processus de stockage et de vérification des mots de passe, ce qui pourrait poser d'autres problèmes (voire même introduire des vulnérabilités).

    • Ne convertissez pas en toutes lettres majuscules/minuscules.
    • Ne supprimez pas les espaces.
    • Ne supprimez pas les caractères ou les chaînes inacceptables.
    • Ne changez pas l'encodage du texte.
    • Ne faites aucune substitution de caractère ou de chaîne.
    • Ne tronquez pas les mots de passe de quelque longueur que ce soit.
  3. Refuser la création de mots de passe qui ne peuvent pas être stockés sans modification. Renforcer ce qui précède. S'il y a une raison pour laquelle votre mécanisme de stockage de mot de passe ne peut pas gérer correctement certains caractères, espaces, chaînes ou longueurs de mot de passe, retournez une erreur et informez l'utilisateur des limitations du système afin qu'il puisse réessayer avec un mot de passe qui y correspond. Pour une meilleure expérience utilisateur, faites une liste de ces limitations accessibles à l'utilisateur dès le départ. Ne vous inquiétez même pas, ne vous inquiétez pas, cachez la liste aux attaquants - ils la comprendront assez facilement quand même.

  4. Utilisez un sel long, aléatoire et unique pour chaque compte. Aucun mot de passe de deux comptes ne doit être identique. en stockage, même si les mots de passe sont en réalité identiques.
  5. Utilisez des algorithmes de hachage lents et cryptographiquement puissants conçus pour être utilisés avec des mots de passe. MD5 est certainement sorti. SHA-1/SHA-2 sont interdits. Mais je ne vais pas vous dire ce que vous utilisez devrait ici. (Voir la première balle n ° 2 dans ce post.)
  6. Itérer autant que vous pouvez tolérer. Alors que votre système pourrait avoir de meilleures choses à faire avec ses cycles de traitement que le hachage mots de passe toute la journée, les personnes qui vont craquer vos mots de passe ont des systèmes qui ne le font pas. Faites-le aussi dur que possible, sans trop le rendre "trop ​​dur".

Le plus important ...

N'écoutez pas qui que ce soit ici.

Allez chercher une publication réputée et très récente sur les méthodes de stockage de mots de passe correspondant à la langue de votre choix. En fait, vous devriez trouver plusieurs publications récentes provenant de plusieurs sources distinctes qui sont en accord avant de choisir une méthode.

Il est extrêmement possible que tout ce que tout le monde ici (y compris moi-même) a dit ait déjà été remplacé par de meilleures technologies ou rendu non sécurisé par de nouvelles méthodes d'attaque. Allez trouver quelque chose qui n'est probablement pas.

14
Iszi

Voici ce que vous aimeriez faire:

OurKey.SetValue("Password", StringEncryptor.EncryptString(textBoxPassword.Text));
OurKey.GetValue("Password", StringEncryptor.DecryptString(textBoxPassword.Text));

Vous pouvez le faire avec les classes suivantes. Cette classe est une classe générique est le point de terminaison du client. Il active IOC de divers algorithmes de cryptage utilisant Ninject .

public class StringEncryptor
{
    private static IKernel _kernel;

    static StringEncryptor()
    {
        _kernel = new StandardKernel(new EncryptionModule());
    }

    public static string EncryptString(string plainText)
    {
        return _kernel.Get<IStringEncryptor>().EncryptString(plainText);
    }

    public static string DecryptString(string encryptedText)
    {
        return _kernel.Get<IStringEncryptor>().DecryptString(encryptedText);
    }
}

Cette classe suivante est la classe ninject qui vous permet d’injecter différents algorithmes:

public class EncryptionModule : StandardModule
{
    public override void Load()
    {
        Bind<IStringEncryptor>().To<TripleDESStringEncryptor>();
    }
}

C'est l'interface que tout algorithme doit implémenter pour chiffrer/déchiffrer des chaînes:

public interface IStringEncryptor
{
    string EncryptString(string plainText);
    string DecryptString(string encryptedText);
}

Ceci est une implémentation utilisant l'algorithme TripleDES:

public class TripleDESStringEncryptor : IStringEncryptor
{
    private byte[] _key;
    private byte[] _iv;
    private TripleDESCryptoServiceProvider _provider;

    public TripleDESStringEncryptor()
    {
        _key = System.Text.ASCIIEncoding.ASCII.GetBytes("GSYAHAGCBDUUADIADKOPAAAW");
        _iv = System.Text.ASCIIEncoding.ASCII.GetBytes("USAZBGAW");
        _provider = new TripleDESCryptoServiceProvider();
    }

    #region IStringEncryptor Members

    public string EncryptString(string plainText)
    {
        return Transform(plainText, _provider.CreateEncryptor(_key, _iv));
    }

    public string DecryptString(string encryptedText)
    {
        return Transform(encryptedText, _provider.CreateDecryptor(_key, _iv));
    }

    #endregion

    private string Transform(string text, ICryptoTransform transform)
    {
        if (text == null)
        {
            return null;
        }
        using (MemoryStream stream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            {
                byte[] input = Encoding.Default.GetBytes(text);
                cryptoStream.Write(input, 0, input.Length);
                cryptoStream.FlushFinalBlock();

                return Encoding.Default.GetString(stream.ToArray());
            }
        }
    }
}

Vous pouvez regarder ma vidéo et télécharger le code correspondant à l'adresse suivante: http://www.wrightin.gs/2008/11/how-to-encryptdecrypt-sensitive-column-contents-in- nhibernateactive-record-video.html

11
Jamie Wright

Une option serait de stocker le hachage (SHA1, MD5) du mot de passe au lieu du mot de passe en texte clair, et chaque fois que vous voulez voir si le mot de passe est bon, comparez-le simplement à ce hachage.

Si vous avez besoin d'un stockage sécurisé (par exemple pour un mot de passe que vous utiliserez pour vous connecter à un service), le problème est plus complexe.

Si c'est juste pour l'authentification, alors il suffirait d'utiliser le hachage.

10
Bogdan Maxim

Si vous voulez pouvoir déchiffrer le mot de passe, je pense que le moyen le plus simple serait d'utiliser DPAPI (mode de magasin utilisateur) pour chiffrer/déchiffrer. Ainsi, vous n'avez pas besoin de manipuler les clés de cryptage, de les stocker quelque part ou de les coder en dur dans votre code - dans les deux cas, quelqu'un peut les découvrir en consultant le registre, les paramètres utilisateur ou en utilisant Reflector.

Sinon, utilisez les hachages SHA1 ou MD5 comme d'autres l'ont dit ici.

9
liggett78

Comme dit ligget78, DPAPI serait un bon moyen de stocker des mots de passe. Consultez la classe ProtectedData sur MSDN pour un exemple d'utilisation.

6
Beau

J'ai cherché partout un bon exemple de processus de cryptage et de décryptage, mais la plupart étaient excessivement complexes.

Quoi qu'il en soit, il existe de nombreuses raisons pour lesquelles une personne peut vouloir déchiffrer certaines valeurs de texte, y compris les mots de passe. La raison pour laquelle j'ai besoin de déchiffrer le mot de passe sur le site sur lequel je travaille actuellement, c'est parce qu'ils veulent s'assurer que lorsqu'une personne est forcée de changer son mot de passe à l'expiration, nous ne la laissons pas changer avec une variante proche du même mot de passe. ils ont utilisé au cours des x derniers mois.

J'ai donc écrit un processus qui le fera de manière simplifiée. J'espère que ce code est bénéfique pour quelqu'un. Pour autant que je sache, je pourrais finir par l'utiliser à un autre moment pour une autre société/un autre site.

public string GenerateAPassKey(string passphrase)
    {
        // Pass Phrase can be any string
        string passPhrase = passphrase;
        // Salt Value can be any string(for simplicity use the same value as used for the pass phrase)
        string saltValue = passphrase;
        // Hash Algorithm can be "SHA1 or MD5"
        string hashAlgorithm = "SHA1";
        // Password Iterations can be any number
        int passwordIterations = 2;
        // Key Size can be 128,192 or 256
        int keySize = 256;
        // Convert Salt passphrase string to a Byte Array
        byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
        // Using System.Security.Cryptography.PasswordDeriveBytes to create the Key
        PasswordDeriveBytes pdb = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
        //When creating a Key Byte array from the base64 string the Key must have 32 dimensions.
        byte[] Key = pdb.GetBytes(keySize / 11);
        String KeyString = Convert.ToBase64String(Key);

        return KeyString;
    }

 //Save the keystring some place like your database and use it to decrypt and encrypt
//any text string or text file etc. Make sure you dont lose it though.

 private static string Encrypt(string plainStr, string KeyString)        
    {            
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = 256;
        aesEncryption.BlockSize = 128;
        aesEncryption.Mode = CipherMode.ECB;
        aesEncryption.Padding = PaddingMode.ISO10126;
        byte[] KeyInBytes = Encoding.UTF8.GetBytes(KeyString);
        aesEncryption.Key = KeyInBytes;
        byte[] plainText = ASCIIEncoding.UTF8.GetBytes(plainStr);
        ICryptoTransform crypto = aesEncryption.CreateEncryptor();
        byte[] cipherText = crypto.TransformFinalBlock(plainText, 0, plainText.Length);
        return Convert.ToBase64String(cipherText);
    }

 private static string Decrypt(string encryptedText, string KeyString) 
    {
        RijndaelManaged aesEncryption = new RijndaelManaged(); 
        aesEncryption.KeySize = 256;
        aesEncryption.BlockSize = 128; 
        aesEncryption.Mode = CipherMode.ECB;
        aesEncryption.Padding = PaddingMode.ISO10126;
        byte[] KeyInBytes = Encoding.UTF8.GetBytes(KeyString);
        aesEncryption.Key = KeyInBytes;
        ICryptoTransform decrypto = aesEncryption.CreateDecryptor(); 
        byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length); 
        return ASCIIEncoding.UTF8.GetString(decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length)); 
    }

 String KeyString = GenerateAPassKey("PassKey");
 String EncryptedPassword = Encrypt("25Characterlengthpassword!", KeyString);
 String DecryptedPassword = Decrypt(EncryptedPassword, KeyString);
6
Deathstalker

S'il s'agit d'un mot de passe utilisé pour l'authentification par votre application, hachez le mot de passe comme le suggèrent d'autres personnes.

Si vous stockez des mots de passe pour une ressource externe, vous voudrez souvent pouvoir demander à l'utilisateur ces informations d'identification et lui donner la possibilité de les sauvegarder de manière sécurisée. Windows fournit à cet effet l'interface utilisateur de Credentials (CredUI). Plusieurs exemples montrent comment l'utiliser dans .NET, notamment celui-ci sur MSDN .

5
Joe

Si vous avez besoin de plus que cela, par exemple, la sécurisation d'une chaîne de connexion (pour la connexion à une base de données), cochez ceci article , car il fournit la meilleure "option" pour cela.

La réponse de Oli est également bonne, car elle montre comment créer un hachage pour une chaîne.

1
Bogdan Maxim

..NET fournit des services de chiffrement dans la classe contenue dans l'espace de noms System.Security.Cryptography.

0
osp70