|
|
@ -767,6 +767,17 @@ namespace Apewer |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region PKCS #5
|
|
|
|
|
|
|
|
/// <summary>使用密码生成密钥。</summary>
|
|
|
|
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<RijndaelManaged, ICryptoTransform> create, Stream input, Stream output) |
|
|
@ -842,6 +853,130 @@ namespace Apewer |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
private static readonly byte[] AesDefaultIV = new byte[16]; |
|
|
|
|
|
|
|
static T UseAes<T>(byte[] key, byte[] iv, CipherMode cipherMode, PaddingMode paddingMode, Func<RijndaelManaged, T> 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<RijndaelManaged, ICryptoTransform> create) |
|
|
|
{ |
|
|
|
if (input == null) throw new ArgumentNullException(nameof(input)); |
|
|
|
if (output == null) throw new ArgumentNullException(nameof(output)); |
|
|
|
|
|
|
|
UseAes<object>(key, iv, cipherMode, paddingMode, rijndael => |
|
|
|
{ |
|
|
|
using (var transformer = create.Invoke(rijndael)) |
|
|
|
{ |
|
|
|
|
|
|
|
using (var stream = new CryptoStream(output, transformer, CryptoStreamMode.Write)) |
|
|
|
{ |
|
|
|
Read(input, stream); |
|
|
|
stream.Close(); |
|
|
|
} |
|
|
|
} |
|
|
|
return null; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
static byte[] UseAes(byte[] input, byte[] key, byte[] iv, CipherMode cipherMode, PaddingMode paddingMode, Func<RijndaelManaged, ICryptoTransform> create) |
|
|
|
{ |
|
|
|
if (input == null) input = new byte[0]; |
|
|
|
|
|
|
|
var result = null as byte[]; |
|
|
|
return UseAes<byte[]>(key, iv, cipherMode, paddingMode, rijndael => |
|
|
|
{ |
|
|
|
using (var transformer = create.Invoke(rijndael)) |
|
|
|
{ |
|
|
|
var result = transformer.TransformFinalBlock(input, 0, input.Length); |
|
|
|
return result; |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>执行 AES 128/192/256 加密。</summary>
|
|
|
|
/// <param name="plain">明文。</param>
|
|
|
|
/// <param name="key">密钥。</param>
|
|
|
|
/// <param name="cipherMode">块密码模式。</param>
|
|
|
|
/// <param name="paddingMode">填充模式。</param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="ArgumentNullException" />
|
|
|
|
/// <exception cref="ArgumentException" />
|
|
|
|
/// <exception cref="CryptographicException" />
|
|
|
|
public static byte[] AesEncrypt(byte[] plain, byte[] key, CipherMode cipherMode = CipherMode.ECB, PaddingMode paddingMode = PaddingMode.PKCS7) |
|
|
|
{ |
|
|
|
return UseAes(plain, key, null, cipherMode, paddingMode, (rijndael) => rijndael.CreateEncryptor(rijndael.Key, rijndael.IV)); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>执行 AES 128/192/256 加密。</summary>
|
|
|
|
/// <param name="plain">明文。</param>
|
|
|
|
/// <param name="key">密钥,长度必须是 128 位(16 字节)、192 位(24 字节)或 256 位(32 字节)。</param>
|
|
|
|
/// <param name="iv">初始化向量,必须是 128 位(16 字节)。</param>
|
|
|
|
/// <param name="cipherMode">块密码模式。</param>
|
|
|
|
/// <param name="paddingMode">填充模式。</param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="ArgumentNullException" />
|
|
|
|
/// <exception cref="ArgumentException" />
|
|
|
|
/// <exception cref="CryptographicException" />
|
|
|
|
public static byte[] AesEncrypt(byte[] plain, byte[] key, byte[] iv, CipherMode cipherMode = CipherMode.ECB, PaddingMode paddingMode = PaddingMode.PKCS7) |
|
|
|
{ |
|
|
|
return UseAes(plain, key, iv, cipherMode, paddingMode, (rijndael) => rijndael.CreateEncryptor(rijndael.Key, rijndael.IV)); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>执行 AES 128/192/256 解密。</summary>
|
|
|
|
/// <param name="cipher">密文。</param>
|
|
|
|
/// <param name="key">密钥,长度必须是 128 位(16 字节)、192 位(24 字节)或 256 位(32 字节)。</param>
|
|
|
|
/// <param name="cipherMode">块密码模式。</param>
|
|
|
|
/// <param name="paddingMode">填充模式。</param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="ArgumentNullException" />
|
|
|
|
/// <exception cref="ArgumentException" />
|
|
|
|
/// <exception cref="CryptographicException" />
|
|
|
|
public static byte[] AesDecrypt(byte[] cipher, byte[] key, CipherMode cipherMode = CipherMode.ECB, PaddingMode paddingMode = PaddingMode.PKCS7) |
|
|
|
{ |
|
|
|
return UseAes(cipher, key, null, cipherMode, paddingMode, (rijndael) => rijndael.CreateEncryptor(rijndael.Key, rijndael.IV)); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>执行 AES 128/192/256 解密。</summary>
|
|
|
|
/// <param name="cipher">密文。</param>
|
|
|
|
/// <param name="key">密钥,长度必须是 128 位(16 字节)、192 位(24 字节)或 256 位(32 字节)。</param>
|
|
|
|
/// <param name="iv">初始化向量,必须是 128 位(16 字节)。</param>
|
|
|
|
/// <param name="cipherMode">块密码模式。</param>
|
|
|
|
/// <param name="paddingMode">填充模式。</param>
|
|
|
|
/// <returns></returns>
|
|
|
|
/// <exception cref="ArgumentNullException" />
|
|
|
|
/// <exception cref="ArgumentException" />
|
|
|
|
/// <exception cref="CryptographicException" />
|
|
|
|
public static byte[] AesDecrypt(byte[] cipher, byte[] key, byte[] iv, CipherMode cipherMode = CipherMode.ECB, PaddingMode paddingMode = PaddingMode.PKCS7) |
|
|
|
{ |
|
|
|
return UseAes(cipher, key, iv, cipherMode, paddingMode, (rijndael) => rijndael.CreateEncryptor(rijndael.Key, rijndael.IV)); |
|
|
|
} |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Hash
|
|
|
|