😊
【C#】共通鍵暗号での暗号化(DOBON.NET互換)
共通鍵暗号での暗号化
For: C# で共通鍵暗号を使いたい人
国内ではDOBON.NET の手法が用いられることも多いと思いますが、現在では System.Security.Cryptography.RijndaelManaged
が Obsolete
になっているので対処法を記述します。
DOBON.NET 互換の暗号化
実は System.Security.Cryptography.RijndaelManaged
を System.Security.Cryptography.Aes.Create()
に置き換えるだけで互換のある動作になります。
static class Crypt
{
static void Main()
{
const string input = "Input String 文字列";
const string password = "password";
var rijndael = new System.Security.Cryptography.RijndaelManaged();
var aes = System.Security.Cryptography.Aes.Create();
string encryptedRijndael = rijndael.EncryptString(input, password);
string encryptedAes = aes.EncryptString(input, password);
Console.WriteLine($"Rijndael: {encryptedRijndael}");
Console.WriteLine($" Aes: {encryptedAes}");
Console.WriteLine(rijndael.DecryptString(encryptedRijndael, password));
Console.WriteLine(aes.DecryptString(encryptedRijndael, password));
}
/// <summary>
/// 文字列を暗号化する
/// </summary>
/// <param name="sourceString">暗号化する文字列</param>
/// <param name="password">暗号化に使用するパスワード</param>
/// <returns>暗号化された文字列</returns>
public static string EncryptString(this SymmetricAlgorithm algorithm, string sourceString, string password)
{
//パスワードから共有キーと初期化ベクタを作成
byte[] key, iv;
GenerateKeyFromPassword(
password, algorithm.KeySize, out key, algorithm.BlockSize, out iv);
algorithm.Key = key;
algorithm.IV = iv;
//文字列をバイト型配列に変換する
byte[] strBytes = System.Text.Encoding.UTF8.GetBytes(sourceString);
//対称暗号化オブジェクトの作成
System.Security.Cryptography.ICryptoTransform encryptor =
algorithm.CreateEncryptor();
//バイト型配列を暗号化する
byte[] encBytes = encryptor.TransformFinalBlock(strBytes, 0, strBytes.Length);
//閉じる
encryptor.Dispose();
//バイト型配列を文字列に変換して返す
return System.Convert.ToBase64String(encBytes);
}
/// <summary>
/// 暗号化された文字列を復号化する
/// </summary>
/// <param name="sourceString">暗号化された文字列</param>
/// <param name="password">暗号化に使用したパスワード</param>
/// <returns>復号化された文字列</returns>
public static string DecryptString(this SymmetricAlgorithm algorithm, string sourceString, string password)
{
//パスワードから共有キーと初期化ベクタを作成
byte[] key, iv;
GenerateKeyFromPassword(
password, algorithm.KeySize, out key, algorithm.BlockSize, out iv);
algorithm.Key = key;
algorithm.IV = iv;
//文字列をバイト型配列に戻す
byte[] strBytes = System.Convert.FromBase64String(sourceString);
//対称暗号化オブジェクトの作成
System.Security.Cryptography.ICryptoTransform decryptor =
algorithm.CreateDecryptor();
//バイト型配列を復号化する
//復号化に失敗すると例外CryptographicExceptionが発生
byte[] decBytes = decryptor.TransformFinalBlock(strBytes, 0, strBytes.Length);
//閉じる
decryptor.Dispose();
//バイト型配列を文字列に戻して返す
return System.Text.Encoding.UTF8.GetString(decBytes);
}
/// <summary>
/// パスワードから共有キーと初期化ベクタを生成する
/// </summary>
/// <param name="password">基になるパスワード</param>
/// <param name="keySize">共有キーのサイズ(ビット)</param>
/// <param name="key">作成された共有キー</param>
/// <param name="blockSize">初期化ベクタのサイズ(ビット)</param>
/// <param name="iv">作成された初期化ベクタ</param>
static void GenerateKeyFromPassword(string password,
int keySize, out byte[] key, int blockSize, out byte[] iv)
{
//パスワードから共有キーと初期化ベクタを作成する
//saltを決める
byte[] salt = System.Text.Encoding.UTF8.GetBytes("saltは必ず8バイト以上");
//Rfc2898DeriveBytesオブジェクトを作成する
System.Security.Cryptography.Rfc2898DeriveBytes deriveBytes =
new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt);
//.NET Framework 1.1以下の時は、PasswordDeriveBytesを使用する
//System.Security.Cryptography.PasswordDeriveBytes deriveBytes =
// new System.Security.Cryptography.PasswordDeriveBytes(password, salt);
//反復処理回数を指定する デフォルトで1000回
deriveBytes.IterationCount = 1000;
//共有キーと初期化ベクタを生成する
key = deriveBytes.GetBytes(keySize / 8);
iv = deriveBytes.GetBytes(blockSize / 8);
}
}
Discussion