/******************************************************************************* * Copyright © 2017-2020 Znyc.Admin.Framework 版权所有 * Author: Znyc * Description: Znyc快速开发平台 * Website:http://www.Znyc.Admin.com *********************************************************************************/ using System; using System.Collections.Generic; using System.Text; namespace Znyc.Admin.Commons { /// <summary> /// 基于Base64的加密编码辅助类, /// 可以设置不同的密码表来获取不同的编码与解码 /// </summary> public class Base64Util { /// <summary> /// 构造函数,初始化编码表 /// </summary> public Base64Util() { InitDict(); } /// <summary> /// /// </summary> protected static Base64Util s_b64 = new Base64Util(); /// <summary> /// 使用默认的密码表加密字符串 /// </summary> /// <param name="input">待加密字符串</param> /// <returns></returns> public static string Encrypt(string input) { return s_b64.Encode(input); } /// <summary> /// 使用默认的密码表解密字符串 /// </summary> /// <param name="input">待解密字符串</param> /// <returns></returns> public static string Decrypt(string input) { return s_b64.Decode(input); } /// <summary> /// 获取具有标准的Base64密码表的加密类 /// </summary> /// <returns></returns> public static Base64Util GetStandardBase64() { Base64Util b64 = new Base64Util { Pad = "=", CodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" }; return b64; } /// <summary> /// 密码表 /// </summary> protected string m_codeTable = @"ABCDEFGHIJKLMNOPQRSTUVWXYZbacdefghijklmnopqrstu_wxyz0123456789*-"; /// <summary> /// 补码 /// </summary> protected string m_pad = "v"; /// <summary> /// /// </summary> protected Dictionary<int, char> m_t1 = new Dictionary<int, char>(); /// <summary> /// /// </summary> protected Dictionary<char, int> m_t2 = new Dictionary<char, int>(); /// <summary> /// 密码表 /// </summary> public string CodeTable { get => m_codeTable; set { if (value == null) { throw new Exception("密码表不能为null"); } else if (value.Length < 64) { throw new Exception("密码表长度必须至少为64"); } else { ValidateRepeat(value); ValidateEqualPad(value, m_pad); m_codeTable = value; InitDict(); } } } /// <summary> /// 补码 /// </summary> public string Pad { get => m_pad; set { if (value == null) { throw new Exception("密码表的补码不能为null"); } else if (value.Length != 1) { throw new Exception("密码表的补码长度必须为1"); } else { ValidateEqualPad(m_codeTable, value); m_pad = value; InitDict(); } } } /// <summary> /// 返回编码后的字符串 /// </summary> /// <param name="source">原字符串</param> /// <returns></returns> public string Encode(string source) { if (source == null || source == "") { return ""; } else { StringBuilder sb = new StringBuilder(); byte[] tmp = Encoding.UTF8.GetBytes(source); int remain = tmp.Length % 3; int patch = 3 - remain; if (remain != 0) { Array.Resize(ref tmp, tmp.Length + patch); } int cnt = (int)Math.Ceiling(tmp.Length * 1.0 / 3); for (int i = 0; i < cnt; i++) { sb.Append(EncodeUnit(tmp[i * 3], tmp[i * 3 + 1], tmp[i * 3 + 2])); } if (remain != 0) { sb.Remove(sb.Length - patch, patch); for (int i = 0; i < patch; i++) { sb.Append(m_pad); } } return sb.ToString(); } } /// <summary> /// /// </summary> /// <param name="unit"></param> /// <returns></returns> protected string EncodeUnit(params byte[] unit) { int[] obj = new int[4]; obj[0] = (unit[0] & 0xfc) >> 2; obj[1] = ((unit[0] & 0x03) << 4) + ((unit[1] & 0xf0) >> 4); obj[2] = ((unit[1] & 0x0f) << 2) + ((unit[2] & 0xc0) >> 6); obj[3] = unit[2] & 0x3f; StringBuilder sb = new StringBuilder(); for (int i = 0; i < obj.Length; i++) { sb.Append(GetEC(obj[i])); } return sb.ToString(); } /// <summary> /// /// </summary> /// <param name="code"></param> /// <returns></returns> protected char GetEC(int code) { return m_t1[code]; //m_codeTable[code]; } /// <summary> /// 获得解码字符串 /// </summary> /// <param name="source">原字符串</param> /// <returns></returns> public string Decode(string source) { if (source == null || source == "") { return ""; } else { List<byte> list = new List<byte>(); char[] tmp = source.ToCharArray(); int remain = tmp.Length % 4; if (remain != 0) { Array.Resize(ref tmp, tmp.Length - remain); } int patch = source.IndexOf(m_pad); if (patch != -1) { patch = source.Length - patch; } int cnt = tmp.Length / 4; for (int i = 0; i < cnt; i++) { DecodeUnit(list, tmp[i * 4], tmp[i * 4 + 1], tmp[i * 4 + 2], tmp[i * 4 + 3]); } for (int i = 0; i < patch; i++) { list.RemoveAt(list.Count - 1); } return Encoding.UTF8.GetString(list.ToArray()); } } /// <summary> /// 获得解码字符串 /// </summary> /// <param name="byteArr"></param> /// <param name="chArray"></param> protected void DecodeUnit(List<byte> byteArr, params char[] chArray) { int[] res = new int[3]; byte[] unit = new byte[chArray.Length]; for (int i = 0; i < chArray.Length; i++) { unit[i] = FindChar(chArray[i]); } res[0] = (unit[0] << 2) + ((unit[1] & 0x30) >> 4); res[1] = ((unit[1] & 0xf) << 4) + ((unit[2] & 0x3c) >> 2); res[2] = ((unit[2] & 0x3) << 6) + unit[3]; for (int i = 0; i < res.Length; i++) { byteArr.Add((byte)res[i]); } } /// <summary> /// /// </summary> /// <param name="ch"></param> /// <returns></returns> protected byte FindChar(char ch) { int pos = m_t2[ch]; //m_codeTable.IndexOf(ch); return (byte)pos; } /// <summary> /// 初始化双向哈希字典 /// </summary> protected void InitDict() { m_t1.Clear(); m_t2.Clear(); m_t2.Add(m_pad[0], -1); for (int i = 0; i < m_codeTable.Length; i++) { m_t1.Add(i, m_codeTable[i]); m_t2.Add(m_codeTable[i], i); } } /// <summary> /// 检查字符串中的字符是否有重复 /// </summary> /// <param name="input">待检查字符串</param> /// <returns></returns> protected void ValidateRepeat(string input) { for (int i = 0; i < input.Length; i++) { if (input.LastIndexOf(input[i]) > i) { throw new Exception("密码表中含有重复字符:" + input[i]); } } } /// <summary> /// 检查字符串是否包含补码字符 /// </summary> /// <param name="input">待检查字符串</param> /// <param name="pad"></param> protected void ValidateEqualPad(string input, string pad) { if (input.IndexOf(pad) > -1) { throw new Exception("密码表中包含了补码字符:" + pad); } } } }