C#でのハッシュおよびソルトパスワード


178

ユーザーパスワードのハッシュに関するDavidHaydenの記事の1つを読んでいました。

本当に私は彼が達成しようとしていることを得ることができません。

これが彼のコードです:

private static string CreateSalt(int size)
{
    //Generate a cryptographic random number.
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    byte[] buff = new byte[size];
    rng.GetBytes(buff);

    // Return a Base64 string representation of the random number.
    return Convert.ToBase64String(buff);
}

private static string CreatePasswordHash(string pwd, string salt)
{
    string saltAndPwd = String.Concat(pwd, salt);
    string hashedPwd =
        FormsAuthentication.HashPasswordForStoringInConfigFile(
        saltAndPwd, "sha1");
    return hashedPwd;
}

パスワードをハッシュしてソルトを追加する他のC#メソッドはありますか?


これは、salt encrypto.codeplex.comで
Omu

6
塩を生成する最初のメソッドのサイズには何を渡すべきですか?
シェーンルブラン

6
リンクが壊れています。
osmanraifgunes 14

@ShaneLeBlanc少なくとも関数の出力と同じ数のビットが必要です。SHA1は暗号グレードではないため、少なくともSHA256256ビットまたは32バイトを出力するを使用する必要があります。ただし、256ビットはbase 64に簡単に変換できません。これは、各base64 charは6ビットをエンコードし、256は完全に6で割り切れないためです。 256ビット以上、つまり264バイトまたは33バイト。TLDR:使用33.
VSO

回答:


248

実際、これは一種の奇妙なことであり、メンバーシッププロバイダーが文字列変換を使用して、構成ファイルに変換します。ハッシュとソルトはバイナリBLOBであり、テキストファイルに入れたい場合を除き、文字列に変換する必要はありません。

私の著書 『Beginning ASP.NET Security』(最後に、本をひっくり返すための言い訳)で、私は次のことを行います

static byte[] GenerateSaltedHash(byte[] plainText, byte[] salt)
{
  HashAlgorithm algorithm = new SHA256Managed();

  byte[] plainTextWithSaltBytes = 
    new byte[plainText.Length + salt.Length];

  for (int i = 0; i < plainText.Length; i++)
  {
    plainTextWithSaltBytes[i] = plainText[i];
  }
  for (int i = 0; i < salt.Length; i++)
  {
    plainTextWithSaltBytes[plainText.Length + i] = salt[i];
  }

  return algorithm.ComputeHash(plainTextWithSaltBytes);            
}

問題の例として、塩の生成があります。を使用して、テキストをバイト配列に変換できますEncoding.UTF8.GetBytes(string)。ハッシュを文字列表現に変換する必要がある場合はConvert.ToBase64StringConvert.FromBase64Stringに変換するを使用して元に戻す。

バイト配列では等号演算子を使用できないことに注意してください。これは参照をチェックするため、両方の配列をループして、各バイトをチェックするだけです。

public static bool CompareByteArrays(byte[] array1, byte[] array2)
{
  if (array1.Length != array2.Length)
  {
    return false;
  }

  for (int i = 0; i < array1.Length; i++)
  {
    if (array1[i] != array2[i])
    {
      return false;
    }
  }

  return true;
}

パスワードごとに常に新しいソルトを使用します。ソルトは秘密にしておく必要はなく、ハッシュ自体と一緒に保存できます。


3
このアドバイスに感謝します-私を始めるのに本当に役立ちました。また、私は、このリンク<出くわしたdijksterhuis.org/creating-salted-hash-values-in-c私はずっとこの記事の中で述べたものの良い実用的なアドバイスや鏡がわかった>
アレックスP

18
CompareByteArraysのnifty LINQステートメントのリファクタリング return array1.Length == array2.Length && !array1.Where((t, i) => t != array2[i]).Any();
ハンター

6
@Brettski技術的にはそうですが、ユーザーごとに固有のソルトがあると、Rainbow Table(ハッシュされたパスワードをクラックする最も効率的な方法として一般に受け入れられています)が実質的に役に立たなくなります。これは簡単なoveviewであり、パスワードを安全に保存する方法と、なぜ/どのように機能するかについて、詳細ではありますが、圧倒的ではありません。
レンジャー

3
@hunter:.ToList()を追加して一定の時間にする必要があります。例:return array1.Length == array2.Length &&!array1.Where((t、i)=> t!= array2 [i])。ToList()。Any(); そうでない場合、LINQは、等しくない1バイトを見つけるとすぐに戻ります。
Alex Rouillard、2012年

17
高速ハッシュ関数を使用する場合は-1。PBKDF2、bcrypt、scryptなどの遅い構成を使用します。
CodesInChaos 2013

48

blowdartが言ったことですが、コードは少し少なくなっています。LinqまたはCopyToを使用して配列を連結します。

public static byte[] Hash(string value, byte[] salt)
{
    return Hash(Encoding.UTF8.GetBytes(value), salt);
}

public static byte[] Hash(byte[] value, byte[] salt)
{
    byte[] saltedValue = value.Concat(salt).ToArray();
    // Alternatively use CopyTo.
    //var saltedValue = new byte[value.Length + salt.Length];
    //value.CopyTo(saltedValue, 0);
    //salt.CopyTo(saltedValue, value.Length);

    return new SHA256Managed().ComputeHash(saltedValue);
}

Linqには、バイト配列を比較する簡単な方法もあります。

public bool ConfirmPassword(string password)
{
    byte[] passwordHash = Hash(password, _passwordSalt);

    return _passwordHash.SequenceEqual(passwordHash);
}

ただし、これを実装する前に、この投稿を確認してください。パスワードハッシュでは、高速なアルゴリズムではなく、低速なハッシュアルゴリズムが必要になる場合があります。

そのために、Rfc2898DeriveBytes遅い(そして遅くすることができる)クラスがあり、パスワードとソルトを取得してハッシュを返すことができるという点で、元の質問の2番目の部分に答えることがあります。詳細については、この質問を参照してください。Stack ExchangeがRfc2898DeriveBytesパスワードハッシュに使用していることに注意してください(ソースコードはこちら)。


6
@MushinNoShin SHA256は高速ハッシュです。パスワードハッシュには、PBKDF2、bcrypt、scryptなどの低速ハッシュが必要です。パスワードを安全にハッシュする方法を参照してください詳細については、security.seを参照してください。
CodesInChaos 2015

32

私は、SHA256のようなハッシュ関数が実際にパスワードの保存での使用を意図していないことを読んでいます:https ://patrickmn.com/security/storing-passwords-securely/#notpasswordhashes

代わりに、PBKDF2、bcrypt、scryptなどのアダプティブキー導出関数がありました。以下は、MicrosoftがMicrosoft.AspNet.IdentityライブラリでPasswordHasher用に作成したPBKDF2ベースのコードです。

/* =======================
 * HASHED PASSWORD FORMATS
 * =======================
 * 
 * Version 3:
 * PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations.
 * Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
 * (All UInt32s are stored big-endian.)
 */

public string HashPassword(string password)
{
    var prf = KeyDerivationPrf.HMACSHA256;
    var rng = RandomNumberGenerator.Create();
    const int iterCount = 10000;
    const int saltSize = 128 / 8;
    const int numBytesRequested = 256 / 8;

    // Produce a version 3 (see comment above) text hash.
    var salt = new byte[saltSize];
    rng.GetBytes(salt);
    var subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);

    var outputBytes = new byte[13 + salt.Length + subkey.Length];
    outputBytes[0] = 0x01; // format marker
    WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
    WriteNetworkByteOrder(outputBytes, 5, iterCount);
    WriteNetworkByteOrder(outputBytes, 9, saltSize);
    Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
    Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
    return Convert.ToBase64String(outputBytes);
}

public bool VerifyHashedPassword(string hashedPassword, string providedPassword)
{
    var decodedHashedPassword = Convert.FromBase64String(hashedPassword);

    // Wrong version
    if (decodedHashedPassword[0] != 0x01)
        return false;

    // Read header information
    var prf = (KeyDerivationPrf)ReadNetworkByteOrder(decodedHashedPassword, 1);
    var iterCount = (int)ReadNetworkByteOrder(decodedHashedPassword, 5);
    var saltLength = (int)ReadNetworkByteOrder(decodedHashedPassword, 9);

    // Read the salt: must be >= 128 bits
    if (saltLength < 128 / 8)
    {
        return false;
    }
    var salt = new byte[saltLength];
    Buffer.BlockCopy(decodedHashedPassword, 13, salt, 0, salt.Length);

    // Read the subkey (the rest of the payload): must be >= 128 bits
    var subkeyLength = decodedHashedPassword.Length - 13 - salt.Length;
    if (subkeyLength < 128 / 8)
    {
        return false;
    }
    var expectedSubkey = new byte[subkeyLength];
    Buffer.BlockCopy(decodedHashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);

    // Hash the incoming password and verify it
    var actualSubkey = KeyDerivation.Pbkdf2(providedPassword, salt, prf, iterCount, subkeyLength);
    return actualSubkey.SequenceEqual(expectedSubkey);
}

private static void WriteNetworkByteOrder(byte[] buffer, int offset, uint value)
{
    buffer[offset + 0] = (byte)(value >> 24);
    buffer[offset + 1] = (byte)(value >> 16);
    buffer[offset + 2] = (byte)(value >> 8);
    buffer[offset + 3] = (byte)(value >> 0);
}

private static uint ReadNetworkByteOrder(byte[] buffer, int offset)
{
    return ((uint)(buffer[offset + 0]) << 24)
        | ((uint)(buffer[offset + 1]) << 16)
        | ((uint)(buffer[offset + 2]) << 8)
        | ((uint)(buffer[offset + 3]));
}

これには、.NET Standard 2.0(.NET 4.6.1以降)を必要とするMicrosoft.AspNetCore.Cryptography.KeyDerivation nugetパッケージがインストールされている必要があります。以前のバージョンの.NETについては、MicrosoftのSystem.Web.HelpersライブラリのCryptoクラスを参照してください。

2015年11月
更新PBKDF2-HMAC-SHA1の代わりにPBKDF2-HMAC-SHA256ハッシュを使用する別のMicrosoftライブラリの実装を使用するように回答を更新しました(iterCountが十分に高い場合、PBKDF2 -HMAC-SHA1はまだ安全です)。以前の回答から実装されたハッシュの検証とアップグレードを実際に処理するため、簡略化されたコードがコピーされたソースをチェックアウトできます。将来的にiterCountを増やす必要がある場合に役立ちます。


1
PBKDF2IterCountをより大きな値に増やす価値があることに注意してください。詳細については、security.stackexchange.com / q / 3959を参照してください。
Michael

2
1)PBKDF2SubkeyLength20バイトに減らします。これはSHA1の自然なサイズであり、それを超えると、攻撃者を遅くすることなく、防御側を遅くします。2)反復回数を増やすことをお勧めします。パフォーマンスの予算に応じて、1万から10万をお勧めします。3)一定時間の比較でも害はありませんが、実際的な影響はあまりありません。
CodesInChaos 2015年

KeyDerivationPrf、KeyDerivation、BlockCopyは未定義ですが、それらのクラスは何ですか?
mrbengi 2016年

@mrbengi前述のMicrosoft.AspNet.Cryptography.KeyDerivation nugetパッケージをインストールしましたか?これが適切ない場合は、nugetパッケージを必要としないバージョンです。Buffer.BlockCopyは、システムの一部として存在する必要があります。
マイケル

1
nugetパッケージはMicrosoft.AspNetCore.Cryptography.KeyDerivationになりました。
James Blake、

25

ソルトは、ハッシュに複雑さを追加するために使用され、ブルートフォースによるクラックを困難にします。

Sitepointの記事から:

ハッカーは依然として辞書攻撃と呼ばれるものを実行できます。悪意のある当事者は、たとえば、人々が頻繁に使用していることがわかっている100,000個のパスワード(都市名、スポーツチームなど)を使って辞書攻撃を行い、ハッシュして、辞書の各エントリをデータベースの各行と比較します。テーブル。ハッカーが一致を見つけたら、ビンゴ!彼らはあなたのパスワードを持っています。ただし、この問題を解決するには、ハッシュをソルトするだけです。

ハッシュをソルトするには、ランダムに見えるテキストの文字列を考え出し、それをユーザーが指定したパスワードと連結し、ランダムに生成された文字列とパスワードの両方を1つの値としてハッシュします。次に、ハッシュとソルトの両方をUsersテーブル内の個別のフィールドとして保存します。

このシナリオでは、ハッカーはパスワードを推測する必要があるだけでなく、ソルトも推測する必要があります。クリアテキストにソルトを追加すると、セキュリティが向上します。ハッカーが辞書攻撃を試みた場合、ハッカーは100,000エントリをすべてのユーザー行のソルトでハッシュする必要があります。それはまだ可能ですが、ハッキングの成功の可能性は根本的に減少します。

.NETでこれを自動的に行う方法はないため、上記のソリューションを使用する必要があります。


塩は、レインボーテーブルなどの防御に使用されます。:辞書攻撃を防御するために(また、キーストレッチとして知られている)仕事率は、任意の良いKDFのように必要とされるen.wikipedia.org/wiki/Key_stretching
エルワン・ルグラン

11

次のメソッドを持つクラスを作成しました。

  1. 塩を作る
  2. ハッシュ入力
  3. 入力を検証

    public class CryptographyProcessor
    {
        public string CreateSalt(int size)
        {
            //Generate a cryptographic random number.
              RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
             byte[] buff = new byte[size];
             rng.GetBytes(buff);
             return Convert.ToBase64String(buff);
        }
    
    
          public string GenerateHash(string input, string salt)
          { 
             byte[] bytes = Encoding.UTF8.GetBytes(input + salt);
             SHA256Managed sHA256ManagedString = new SHA256Managed();
             byte[] hash = sHA256ManagedString.ComputeHash(bytes);
             return Convert.ToBase64String(hash);
          }
    
          public bool AreEqual(string plainTextInput, string hashedInput, string salt)
          {
               string newHashedPin = GenerateHash(plainTextInput, salt);
               return newHashedPin.Equals(hashedInput); 
          }
     }

    `



3

Microsoftが提供する基本的なクラスでハッシュのプロセスを簡単にするために、ライブラリSimpleHashing.Netを作成しました。通常のSHAでは、パスワードを安全に保存するのに十分ではありません。

ライブラリはBcryptのハッシュ形式のアイデアを使用しますが、公式のMS実装がないため、フレームワークで使用可能なもの(つまりPBKDF2)を使用することを好みますが、箱から出すのは少し難しいです。

これは、ライブラリの使用方法の簡単な例です。

ISimpleHash simpleHash = new SimpleHash();

// Creating a user hash, hashedPassword can be stored in a database
// hashedPassword contains the number of iterations and salt inside it similar to bcrypt format
string hashedPassword = simpleHash.Compute("Password123");

// Validating user's password by first loading it from database by username
string storedHash = _repository.GetUserPasswordHash(username);
isPasswordValid = simpleHash.Verify("Password123", storedHash);

2

これは私がそれをする方法です。私はハッシュを作成し、ProtectedDataapi を使用してそれを保存します:

    public static string GenerateKeyHash(string Password)
    {
        if (string.IsNullOrEmpty(Password)) return null;
        if (Password.Length < 1) return null;

        byte[] salt = new byte[20];
        byte[] key = new byte[20];
        byte[] ret = new byte[40];

        try
        {
            using (RNGCryptoServiceProvider randomBytes = new RNGCryptoServiceProvider())
            {
                randomBytes.GetBytes(salt);

                using (var hashBytes = new Rfc2898DeriveBytes(Password, salt, 10000))
                {
                    key = hashBytes.GetBytes(20);
                    Buffer.BlockCopy(salt, 0, ret, 0, 20);
                    Buffer.BlockCopy(key, 0, ret, 20, 20);
                }
            }
            // returns salt/key pair
            return Convert.ToBase64String(ret);
        }
        finally
        {
            if (salt != null)
                Array.Clear(salt, 0, salt.Length);
            if (key != null)
                Array.Clear(key, 0, key.Length);
            if (ret != null)
                Array.Clear(ret, 0, ret.Length);
        } 
    }

    public static bool ComparePasswords(string PasswordHash, string Password)
    {
        if (string.IsNullOrEmpty(PasswordHash) || string.IsNullOrEmpty(Password)) return false;
        if (PasswordHash.Length < 40 || Password.Length < 1) return false;

        byte[] salt = new byte[20];
        byte[] key = new byte[20];
        byte[] hash = Convert.FromBase64String(PasswordHash);

        try
        {
            Buffer.BlockCopy(hash, 0, salt, 0, 20);
            Buffer.BlockCopy(hash, 20, key, 0, 20);

            using (var hashBytes = new Rfc2898DeriveBytes(Password, salt, 10000))
            {
                byte[] newKey = hashBytes.GetBytes(20);

                if (newKey != null)
                    if (newKey.SequenceEqual(key))
                        return true;
            }
            return false;
        }
        finally
        {
            if (salt != null)
                Array.Clear(salt, 0, salt.Length);
            if (key != null)
                Array.Clear(key, 0, key.Length);
            if (hash != null)
                Array.Clear(hash, 0, hash.Length);
        }
    }

    public static byte[] DecryptData(string Data, byte[] Salt)
    {
        if (string.IsNullOrEmpty(Data)) return null;

        byte[] btData = Convert.FromBase64String(Data);

        try
        {
            return ProtectedData.Unprotect(btData, Salt, DataProtectionScope.CurrentUser);
        }
        finally
        {
            if (btData != null)
                Array.Clear(btData, 0, btData.Length);
        }
    }

    public static string EncryptData(byte[] Data, byte[] Salt)
    {
        if (Data == null) return null;
        if (Data.Length < 1) return null;

        byte[] buffer = new byte[Data.Length];

        try
        {
            Buffer.BlockCopy(Data, 0, buffer, 0, Data.Length);
            return System.Convert.ToBase64String(ProtectedData.Protect(buffer, Salt, DataProtectionScope.CurrentUser));
        }
        finally
        {
            if (buffer != null)
                Array.Clear(buffer, 0, buffer.Length);
        }
    }

保存時と後で比較するときに呼び出す方法を教えてください。
SearchForKnowledge

2

私はすべての回答を読みましたが、特にハッシュが遅い@Michaelの記事と@CodesInChaosの良いコメントで十分だと思いますが、役立つ可能性があるハッシュ/検証のためのコードスニペットを共有することにしました。 .KeyDerivation ]。

    private static bool SlowEquals(byte[] a, byte[] b)
            {
                uint diff = (uint)a.Length ^ (uint)b.Length;
                for (int i = 0; i < a.Length && i < b.Length; i++)
                    diff |= (uint)(a[i] ^ b[i]);
                return diff == 0;
            }

    private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
            {
                Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
                pbkdf2.IterationCount = iterations;
                return pbkdf2.GetBytes(outputBytes);
            }

    private static string CreateHash(string value, int salt_bytes, int hash_bytes, int pbkdf2_iterations)
            {
                // Generate a random salt
                RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
                byte[] salt = new byte[salt_bytes];
                csprng.GetBytes(salt);

                // Hash the value and encode the parameters
                byte[] hash = PBKDF2(value, salt, pbkdf2_iterations, hash_bytes);

                //You need to return the salt value too for the validation process
                return Convert.ToBase64String(hash) + ":" + 
                       Convert.ToBase64String(hash);
            }

    private static bool ValidateHash(string pureVal, string saltVal, string hashVal, int pbkdf2_iterations)
            {
                try
                {
                    byte[] salt = Convert.FromBase64String(saltVal);
                    byte[] hash = Convert.FromBase64String(hashVal);

                    byte[] testHash = PBKDF2(pureVal, salt, pbkdf2_iterations, hash.Length);
                    return SlowEquals(hash, testHash);
                }
                catch (Exception ex)
                {
                    return false;
                }
            }

非常に重要なSlowEquals関数に注意してください。最後に、この助けを願っています。


ビジーループを作成するのではなく、人為的な非ビジー遅延を設定してみませんか。たとえばTask.Delayを使用します。これはブルートフォースの試行を遅らせますが、アクティブなスレッドをブロックしません。
gburton

@gburtonアドバイスありがとうございます。私はそれをチェックします。
QMaster、

CreateHashにはタイプミスがあります。Convert.ToBase64String(hash)をソルトではなくそれ自体に連結しています。それ以外は、これは他の回答に関するコメントで提起されたほとんどすべての問題に対処する素晴らしい回答です。
ZeRemz

2

System.Web.Helpers.CryptoMicrosoft のNuGetパッケージを使用します。ハッシュに自動的にソルトを追加します。

次のようにパスワードをハッシュします。 var hash = Crypto.HashPassword("foo");

次のようなパスワードを確認します。 var verified = Crypto.VerifyHashedPassword(hash, "foo");


1

asp.netまたは.netコアを使用しない場合は、> = .Net Standard 2.0プロジェクトで簡単な方法もあります。

まず、希望するハッシュのサイズ、ソルト、およびハッシュ生成の期間に関連する反復回数を設定できます。

private const int SaltSize = 32;
private const int HashSize = 32;
private const int IterationCount = 10000;

パスワードのハッシュとソルトを生成するには、次のようなものを使用できます。

public static string GeneratePasswordHash(string password, out string salt)
{
    using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
    {
        rfc2898DeriveBytes.IterationCount = IterationCount;
        byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
        byte[] saltData = rfc2898DeriveBytes.Salt;
        salt = Convert.ToBase64String(saltData);
        return Convert.ToBase64String(hashData);
    }
}

ユーザーが入力したパスワードが有効かどうかを確認するには、データベースの値を確認します。

public static bool VerifyPassword(string password, string passwordHash, string salt)
{
    using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
    {
        rfc2898DeriveBytes.IterationCount = IterationCount;
        rfc2898DeriveBytes.Salt = Convert.FromBase64String(salt);
        byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
        return Convert.ToBase64String(hashData) == passwordHash;
    }
}

次の単体テストは、使用方法を示しています。

string password = "MySecret";

string passwordHash = PasswordHasher.GeneratePasswordHash(password, out string salt);

Assert.True(PasswordHasher.VerifyPassword(password, passwordHash, salt));
Assert.False(PasswordHasher.VerifyPassword(password.ToUpper(), passwordHash, salt));

Microsoft Rfc2898DeriveBytesソース


-1

元の質問の「パスワードをハッシュするための他のC#メソッドはありますか?」のこの部分に答えて、ASP.NET Identity v3.0 https://www.nuget.org/packages/Microsoft.AspNet.Identityを使用してこれを実現できます。 EntityFramework / 3.0.0-rc1-final

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using System.Security.Principal;

namespace HashTest{


    class Program
    {
        static void Main(string[] args)
        {

            WindowsIdentity wi = WindowsIdentity.GetCurrent();

            var ph = new PasswordHasher<WindowsIdentity>();

            Console.WriteLine(ph.HashPassword(wi,"test"));

            Console.WriteLine(ph.VerifyHashedPassword(wi,"AQAAAAEAACcQAAAAEA5S5X7dmbx/NzTk6ixCX+bi8zbKqBUjBhID3Dg1teh+TRZMkAy3CZC5yIfbLqwk2A==","test"));

        }
    }


}

-1
 protected void m_GenerateSHA256_Button1_Click(objectSender, EventArgs e)
{
string salt =createSalt(10);
string hashedPassword=GenerateSHA256Hash(m_UserInput_TextBox.Text,Salt);
m_SaltHash_TextBox.Text=Salt;
 m_SaltSHA256Hash_TextBox.Text=hashedPassword;

}
 public string createSalt(int size)
{
 var rng= new System.Security.Cyptography.RNGCyptoServiceProvider();
 var buff= new byte[size];
rng.GetBytes(buff);
 return Convert.ToBase64String(buff);
}


 public string GenerateSHA256Hash(string input,string salt)
{
 byte[]bytes=System.Text.Encoding.UTF8.GetBytes(input+salt);
 new System.Security.Cyptography.SHA256Managed();
 byte[]hash=sha256hashString.ComputedHash(bytes);
 return bytesArrayToHexString(hash);
  }

他のメソッドは文字列ですpassword = HashPasswordForStoringInConfigFile(TextBox1.Text、SHA1)
ankush shukla

-6
create proc [dbo].[hash_pass] @family nvarchar(50), @username nvarchar(50), @pass nvarchar(Max),``` @semat nvarchar(50), @tell nvarchar(50)

as insert into tbl_karbar values (@family,@username,(select HASHBYTES('SHA1' ,@pass)),@semat,@tell)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.