いちばん簡単なやつ。
とりあえず。
– 暗号にしたい文字列を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