いちばん簡単なやつ。
とりあえず。
– 暗号にしたい文字列をSHA-1文字列化する
– 比較する
-暗号化して格納する
– 格納したのを復号化する。
SHA-1文字列化
String^ result = System::Web::Security::FormsAuthentication::HashPasswordForStoringInConfigFile(keydata, "sha1")->ToLower();
これだけ。
パスワード暗号化・復号化
まだ完全には原理が分かってないんだよなぁ。
まぁとりあえず、ここではパスワードをSHA-1化文字列にしている。
ソルト(salt)は分からなかったのでそのまま8バイトのままにしてみた。
参考。
-http://blogs.msdn.com/shawnfa/archive/2005/11/10/491431.aspx
ソース
#using <mscorlib.dll> #using <System.Web.dll> #using <System.Security.dll> #using <mscorlib.dll> using namespace System; using namespace System::Security::Cryptography; using namespace System::Text; using namespace System::IO; #define RESOURCEDATA L"89ede2f410ac0613d4b655bbfacfc81428c52f24" /** * パスワード暗号化(AES用)(AES 128bit) * 入力 暗号対象文字列 * パスワード文字列 * 出力 暗号後文字列(Base64) **/ String^ Encrypt(String^ encryptstr,String^ password) { String^ encryptedstr = nullptr; //8は8バイトのような気がする。 Rfc2898DeriveBytes^ keyGenerator = gcnew Rfc2898DeriveBytes(password,8); Rijndael^ aes = Rijndael::Create(); aes->IV = keyGenerator->GetBytes(aes->BlockSize / 8); aes->Key = keyGenerator->GetBytes(aes->KeySize / 8); /* Unicodeが微妙 */ array<Byte>^ rawData = Encoding::Unicode->GetBytes(encryptstr); MemoryStream^ memoryStream = gcnew MemoryStream(); CryptoStream^ cryptoStream = gcnew CryptoStream(memoryStream, aes->CreateEncryptor(), CryptoStreamMode::Write); /* ソルトをデータとして書き込む */ memoryStream->Write(keyGenerator->Salt, 0, keyGenerator->Salt->Length); cryptoStream->Write(rawData, 0, rawData->Length); cryptoStream->Close(); array<Byte>^ encrypted = memoryStream->ToArray(); encryptedstr = Convert::ToBase64String(encrypted); Console::WriteLine("OK " + encryptstr); return encryptedstr; } /** * パスワード復号化 * 入力 暗号対象文字列 * パスワード文字列 * 出力 暗号後文字列(Base64) **/ String^ Decrypt(String^ encryptstr,String^ password) { String^ decryptstr = nullptr; array<Byte>^ rawData = Convert::FromBase64String(encryptstr); //ソルト(暗号するための種)を設定している。バイナリデータの最初に指定したから。 array<Byte>^ salt = gcnew array<Byte>(8); for(int i = 0; i < salt->Length; i++) { salt[i] = rawData[i]; } Rfc2898DeriveBytes^ keyGenerator = gcnew Rfc2898DeriveBytes(password,salt); Rijndael^ aes = Rijndael::Create(); aes->IV = keyGenerator->GetBytes(aes->BlockSize / 8); aes->Key = keyGenerator->GetBytes(aes->KeySize / 8); MemoryStream^ memoryStream = gcnew MemoryStream(); CryptoStream^ cryptoStream = gcnew CryptoStream(memoryStream, aes->CreateDecryptor(), CryptoStreamMode::Write); //ソルトの後からデータを取得している。 cryptoStream->Write(rawData, 8, rawData->Length-8); cryptoStream->Close(); array<Byte>^ decrypted = memoryStream->ToArray(); decryptstr = Encoding::Unicode->GetString(decrypted); Console::WriteLine("OK " + decryptstr); return decryptstr; } int main(array<System::String ^> ^args) { String^ keydata = "12345-xxxxx-xxxxx-xxxxx-6789x"; //文字列からSHA1してBase64に String^ result = System::Web::Security::FormsAuthentication::HashPasswordForStoringInConfigFile(keydata, "sha1")->ToLower(); Console::WriteLine(result); //次は比較。 String^ results = gcnew String(RESOURCEDATA); if ( result->CompareTo(results) == 0 ) { Console::WriteLine("比較OK"); } //あとはライセンスの格納。面倒だからRESOURCEDATAで暗号化しとくか。 //関数を想定。 String^ encryptstr = Encrypt(keydata,results); Console::WriteLine("暗号前データ=A " + keydata); Console::WriteLine("パスワード " + results); Console::WriteLine("暗号後データ " + encryptstr); String^ decryptstr = Decrypt(encryptstr,results); Console::WriteLine("暗号前データ " + encryptstr); Console::WriteLine("パスワード " + results); Console::WriteLine("暗号後データ(=Aと一緒) " + decryptstr); return 0; }
出力結果
89ede2f410ac0613d4b655bbfacfc81428c52f24 比較OK OK 12345-xxxxx-xxxxx-xxxxx-6789x 暗号前データ=A 12345-xxxxx-xxxxx-xxxxx-6789x パスワード 89ede2f410ac0613d4b655bbfacfc81428c52f24 暗号後データ OPrE7kiNeKvguGvjmmvy9kTsV33jStSz9Jrhya+I3yOQ7JAjBghc0RQPoHijlxj6xaR cI6RLbxkS5y6SKNX91rksG4FZ6Se5 OK 12345-xxxxx-xxxxx-xxxxx-6789x 暗号前データ OPrE7kiNeKvguGvjmmvy9kTsV33jStSz9Jrhya+I3yOQ7JAjBghc0RQPoHijlxj6xaR cI6RLbxkS5y6SKNX91rksG4FZ6Se5 パスワード 89ede2f410ac0613d4b655bbfacfc81428c52f24 暗号後データ(=Aと一緒) 12345-xxxxx-xxxxx-xxxxx-6789x