using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace Top.Api.Util
{
    /// 
    /// 安全工具类
    /// 
    public abstract class SecurityUtil
    {
        private static readonly char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".ToCharArray();
        private static readonly int[] IA = InitIA();
        private static readonly int KeySize = 128;
        private static readonly int BlockSize = 128;
        private static readonly byte[] IvBytes = Encoding.UTF8.GetBytes("0102030405060708");//初始向量
        private static int[] InitIA()
        {
            int len = 256;
            int[] a = new int[len];
            for (int i = 0; i < len; i++)
            {
                a[i] = -1;
            }
            for (int i = 0, iS = CA.Length; i < iS; i++)
            {
                a[CA[i]] = i;
            }
            a['='] = 0;
            return a;
        }
        /// 
        /// 判断是否base64值
        /// 
        /// 
        /// 
        public static bool IsBase64Value(string str)
        {
            // Check special case
            int sLen = str != null ? str.Length : 0;
            if (sLen == 0)
                return false;
            // Count illegal characters (including '\r', '\n') to know what size the returned array will be,
            // so we don't have to reallocate & copy it later.
            int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
            for (int i = 0; i < sLen; i++)  // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
            {
                char currentChar = str[i];
                if (currentChar >= IA.Length) {
                    return false;
                }
                if (IA[currentChar] < 0) {
                    sepCnt++;
                }
            }  
            // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045.
            if ((sLen - sepCnt) % 4 != 0)
            {
                return false;
            }
            return true;
        }
        /// 
        /// 生成滑动窗口
        /// 
        /// 数据
        /// 分词大小
        /// 分词元素
        public static List GetSlideWindows(string input, int slideSize)
        {
            List windows = new List();
            int startIndex = 0;
            int endIndex = 0;
            int currentWindowSize = 0;
            string currentWindow = null;
            while (endIndex < input.Length || currentWindowSize > slideSize)
            {
                bool startsWithLetterOrDigit;
                if (currentWindow == null)
                {
                    startsWithLetterOrDigit = false;
                }
                else
                {
                    startsWithLetterOrDigit = IsLetterOrDigit(currentWindow[0]);
                }
                if (endIndex == input.Length && !startsWithLetterOrDigit)
                {
                    break;
                }
                if (currentWindowSize == slideSize && !startsWithLetterOrDigit && IsLetterOrDigit(input[endIndex]))
                {
                    endIndex++;
                    currentWindow = input.Substring(startIndex, endIndex - startIndex);
                    currentWindowSize = 5;
                }
                else
                {
                    if (endIndex != 0)
                    {
                        if (startsWithLetterOrDigit)
                        {
                            currentWindowSize -= 1;
                        }
                        else
                        {
                            currentWindowSize -= 2;
                        }
                        startIndex++;
                    }
                    while (currentWindowSize < slideSize && endIndex < input.Length)
                    {
                        char currentChar = input[endIndex];
                        if (IsLetterOrDigit(currentChar))
                        {
                            currentWindowSize += 1;
                        }
                        else
                        {
                            currentWindowSize += 2;
                        }
                        endIndex++;
                    }
                    currentWindow = input.Substring(startIndex, endIndex - startIndex);
                }
                windows.Add(currentWindow);
            }
            return windows;
        }
        /// 
        /// 判断是否小写字母
        /// 
        /// 
        /// 
        private static bool IsLetterOrDigit(char x)
        {
            if (0 <= x && x <= 127)
            {
                return true;
            }
            return false;
        }
        /// 
        /// 压缩
        /// 
        /// 
        /// 
        /// 
        private static byte[] Compress(byte[] input, int toLength)
        {
            if (toLength < 0)
            {
                return null;
            }
            byte[] output = new byte[toLength];
            for (int i = 0; i < output.Length; i++)
            {
                output[i] = 0;
            }
            for (int i = 0; i < input.Length; i++)
            {
                int index_output = i % toLength;
                output[index_output] ^= input[i];
            }
            return output;
        }
        /// 
        /// Base64加密
        /// 
        /// 待加密的明文
        /// 编码方式
        /// 
        public static string EncodeBase64(string source, Encoding encode)
        {
            byte[] bytes = encode.GetBytes(source);
            return Convert.ToBase64String(bytes);
        }
        /// 
        /// Base64加密
        /// 
        /// 待加密的明文
        /// 
        /// 
        ///   
        /// 参看SecurityUtil.EncodeBase64(string,Encoding)方法的说明   
        public static string EncodeBase64(string source)
        {
            return EncodeBase64(source, Encoding.UTF8);
        }
        /// 
        /// AES加密 
        /// 
        /// 待加密的内容
        /// 加密密钥
        /// 
        public static string AESEncrypt(string context, byte[] keyBytes)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;
            rijndaelCipher.KeySize = KeySize;
            rijndaelCipher.BlockSize = KeySize;
            // 加密密钥
            rijndaelCipher.Key = keyBytes;
            rijndaelCipher.IV = IvBytes;
            ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
            byte[] plainText = Encoding.UTF8.GetBytes(context);
            byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length);
            return Convert.ToBase64String(cipherBytes);
        }
        /// 
        /// AES解密
        /// 
        /// 
        /// 
        /// 
        public static string AESDecrypt(string context, byte[] keyBytes)
        {
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;
            rijndaelCipher.KeySize = KeySize;
            rijndaelCipher.BlockSize = BlockSize;
            byte[] encryptedData = Convert.FromBase64String(context);
            rijndaelCipher.Key = keyBytes;
            rijndaelCipher.IV = IvBytes;
            ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
            byte[] plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
            return Encoding.UTF8.GetString(plainText);
        }
        public static byte[] HmacMD5Encrypt(String encryptText, byte[] encryptKey)
        {
            HMACMD5 hmac = new HMACMD5(encryptKey);
            byte[] bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(encryptText));
            return bytes;
        }
        /// 
        /// 生成BASE64(H_MAC)
        /// 
        /// 被签名的字符串
        /// 秘钥
        /// 
        public static string HmacMD5EncryptToBase64(string encryptText, byte[] encryptKey)
        {
            return Convert.ToBase64String(HmacMD5Encrypt(encryptText, encryptKey));
        }
        /// 
        /// 生成BASE64(H_MAC),压缩H_MAC值
        /// 
        /// 
        /// 
        /// 
        /// 
        public static String HmacMD5EncryptToBase64(string encryptText, byte[] encryptKey, int compressLen)
        {
            return Convert.ToBase64String(Compress(HmacMD5Encrypt(encryptText, encryptKey), compressLen));
        }
    }
}