9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Unity C#で Rfc2898 / PBKDF2 + SHA256 による暗号化

Last updated at Posted at 2016-02-10

■詳しい仕組みについては下記サイト
 https://www.sophos.com/ja-jp/press-office/press-releases/2013/11/ns-serious-security-how-to-store-your-users-passwords-safely.aspx

■参考サイト(めっちゃ助かった)
 https://gist.github.com/peteroupc/6986999#file-pbkdf2-cs

dklenは戻した後のバイト数っぽい
自分のプロジェクトは暗号化後のbyte配列の長さが256ビット(32バイト)なので32

自分のプロジェクトは暗号化後のbyte配列を文字列に変換する時に
base64する必要があるので入力側でConvert.ToBase64Stringする。

自分のプロジェクトはストレッチ回数が1000なのでiterationCountの引数は1000

■呼び出し元ソース

using System;

public void OnClickTest()
{
    System.DateTime times = System.DateTime.Now;

    string salt = "1234567890";
    string pwd = "testtesttest";

    byte[] returnvalue = PBKDF2Sha256GetBytes
        (
            System.Text.Encoding.UTF8.GetBytes(pwd + salt),
            System.Text.Encoding.UTF8.GetBytes(salt),
            1000
        );

    string result = Convert.ToBase64String(returnvalue);
    Debug.Log("result = " + result);
}

■ちょっと元ソース改造

// .NET: PBKDF2-SHA256
// http://upokecenter.dreamhosters.com/articles/2012/02/net-pbkdf2-sha256/
//As a followup to the Secure Password Storage article, 
// here is a .NET implementation of PBKDF2 using SHA256 
//(Rfc2898DerivedBytes uses PBKDF2-SHA1, where the 
// underlying hash algorithm unfortunately is not configurable. 
// It’s in the public domain under CC0 
// http://creativecommons.org/publicdomain/zero/1.0/.

    // NOTE: The iteration count should
    // be as high as possible without causing
    // unreasonable delay.  Note also that the password
    // and salt are byte arrays, not strings.  After use,
    // the password and salt should be cleared (with Array.Clear)
        public static byte[] PBKDF2Sha256GetBytes(byte[] password, byte[] salt, int iterationCount)
        {
            int dklen = 32; 
            using (var hmac = new System.Security.Cryptography.HMACSHA256(password))
            {
                int hashLength = hmac.HashSize / 8;
                if ((hmac.HashSize & 7) != 0)
                    hashLength++;
                int keyLength = dklen / hashLength;
                if ((long)dklen > (0xFFFFFFFFL * hashLength) || dklen < 0)
                    throw new ArgumentOutOfRangeException("dklen");
                if (dklen % hashLength != 0)
                    keyLength++;
                byte[] extendedkey = new byte[salt.Length + 4];
                Buffer.BlockCopy(salt, 0, extendedkey, 0, salt.Length);
                using (var ms = new System.IO.MemoryStream())
                {
                    for (int i = 0; i < keyLength; i++)
                    {
                        extendedkey[salt.Length] = (byte)(((i + 1) >> 24) & 0xFF);
                        extendedkey[salt.Length + 1] = (byte)(((i + 1) >> 16) & 0xFF);
                        extendedkey[salt.Length + 2] = (byte)(((i + 1) >> 8) & 0xFF);
                        extendedkey[salt.Length + 3] = (byte)(((i + 1)) & 0xFF);
                        byte[] u = hmac.ComputeHash(extendedkey);
                        Array.Clear(extendedkey, salt.Length, 4);
                        byte[] f = u;
                        for (int j = 1; j < iterationCount; j++)
                        {
                            u = hmac.ComputeHash(u);
                            for (int k = 0; k < f.Length; k++)
                            {
                                f[k] ^= u[k];
                            }
                        }
                        ms.Write(f, 0, f.Length);
                        Array.Clear(u, 0, u.Length);
                        Array.Clear(f, 0, f.Length);
                    }
                    byte[] dk = new byte[dklen];
                    ms.Position = 0;
                    ms.Read(dk, 0, dklen);
                    ms.Position = 0;
                    for (long i = 0; i < ms.Length; i++)
                    {
                        ms.WriteByte(0);
                    }
                    Array.Clear(extendedkey, 0, extendedkey.Length);
                    return dk;
                }
            }
        }
9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?