diff --git a/Apewer/BytesUtility.cs b/Apewer/BytesUtility.cs
index 4b76127..e81fd1a 100644
--- a/Apewer/BytesUtility.cs
+++ b/Apewer/BytesUtility.cs
@@ -767,6 +767,17 @@ namespace Apewer
#endregion
+ #region PKCS #5
+
+ /// 使用密码生成密钥。
+ static byte[] PKCS5(byte[] password, byte[] salt = null, int iterations = 1000, int bits = 32)
+ {
+ var rfc2898 = new Rfc2898DeriveBytes(password, salt, 1);
+ return rfc2898.GetBytes(32);
+ }
+
+ #endregion
+
#region AES
private static void Aes256(byte[] key, byte[] salt, Func create, Stream input, Stream output)
@@ -842,6 +853,130 @@ namespace Apewer
return result;
}
+ private static readonly byte[] AesDefaultIV = new byte[16];
+
+ static T UseAes(byte[] key, byte[] iv, CipherMode cipherMode, PaddingMode paddingMode, Func callback)
+ {
+ if (key == null) throw new ArgumentNullException(nameof(key));
+ var keySize = key.Length * 8;
+ switch (keySize)
+ {
+ case 128:
+ case 192:
+ case 256:
+ break;
+ default:
+ throw new ArgumentException($"密钥大小【{keySize}】bits 无效。");
+ }
+
+ if (iv == null) iv = AesDefaultIV;
+ var ivSize = iv.Length * 8;
+ if (ivSize != 128) throw new ArgumentException($"初始化向量【{ivSize}】bits 无效。");
+
+ using (var rijndael = new RijndaelManaged())
+ {
+ rijndael.Key = key;
+ rijndael.IV = iv;
+ rijndael.Mode = cipherMode;
+ rijndael.Padding = paddingMode;
+
+ return callback.Invoke(rijndael);
+ }
+ }
+
+ static void UseAes(Stream input, Stream output, byte[] key, byte[] iv, CipherMode cipherMode, PaddingMode paddingMode, Func create)
+ {
+ if (input == null) throw new ArgumentNullException(nameof(input));
+ if (output == null) throw new ArgumentNullException(nameof(output));
+
+ UseAes