■詳しい仕組みについては下記サイト
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;
}
}
}