| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -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
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |