using System; using System.Collections.Generic; using Top.Api.Util; namespace Top.Api.Security { /// /// 加、解密客户端(单例使用,不要初始化多个) /// public class SecurityClient : SecurityConstants { // 秘钥管理核心类 private SecurityCore secretCore; private SecurityCounter securityCounter; /// /// 秘钥管理核心类 /// /// serverUrl必须是https协议 /// 伪随机码 public SecurityClient(DefaultTopClient topClient, string randomNum): this(topClient, randomNum, false) { } /// /// 秘钥管理核心类 /// /// serverUrl必须是https协议 /// 伪随机码 /// 是否全链路压测 public SecurityClient(DefaultTopClient topClient, string randomNum, bool streetest) { securityCounter = new SecurityCounter(topClient.appKey); secretCore = new SecurityCore(topClient, randomNum, streetest); } /// /// 初始化秘钥(如果半小时内会调用加、解密方法,建议先初始化秘钥)。所有用户共用秘钥 /// public void InitSecret() { secretCore.GetSecret(null, null); } public void SetRandomNum(string randomNum) { this.secretCore.SetRandomNum(randomNum); } /// /// 初始化秘钥(如果半小时内会调用加、解密方法,建议先初始化秘钥)。每个用户单独分配秘钥 /// /// public void InitSecret(string session) { secretCore.GetSecret(session, null); } /// /// 批量解密(所有用户共用秘钥) /// /// /// /// public IDictionary Decrypt(List dataList, string type) { return Decrypt(dataList, type, null); } /// /// 批量解密(每个用户单独分配秘钥) /// /// /// /// /// key=密文数据,value=明文数据 public IDictionary Decrypt(List dataList, string type, string session) { if (dataList == null || dataList.Count == 0) { throw new SecretException("dataList can`t be empty"); } IDictionary resultMap = new Dictionary(); foreach (string data in dataList) { if (!resultMap.ContainsKey(data)) { string decryptValue = Decrypt(data, type, session); resultMap.Add(data, decryptValue); } } return resultMap; } /// /// 解密(所有用户共用秘钥) /// /// /// /// public string Decrypt(string data, string type) { return Decrypt(data, type, null); } /// /// 解密(每个用户单独分配秘钥) /// /// /// 密文数据 手机号码格式:$手机号码前3位明文$base64(encrypt(phone后8位))$111$ /// simple格式:~base64(encrypt(nick))~111~ /// /// 解密字段类型(例如:simple\phone) /// 用户身份,用户级加密必填 /// public string Decrypt(string data, string type, string session) { if (string.IsNullOrEmpty(data) || data.Length < 4) { return data; } // 获取分隔符 Nullable charValue = null; SecurityBiz.GetSeparatorCharMap().TryGetValue(type, out charValue); if (charValue == null) { throw new SecretException("type error"); } // 校验 char separator = charValue.Value; if (!(data[0] == separator && data[data.Length - 1] == separator)) { return data; } SecretData secretDataDO = null; if (data[data.Length - 2] == separator) { secretDataDO = SecurityBiz.GetIndexSecretData(data, separator); } else { secretDataDO = SecurityBiz.GetSecretData(data, separator); } // 非法密文 if (secretDataDO == null) { return data; } // 如果密文数据的版本号小于0代表公共秘钥 if (secretDataDO.SecretVersion < 0) { secretDataDO.SecretVersion=Math.Abs(secretDataDO.SecretVersion.Value); session = null; } securityCounter.AddDecryptCount(type, session);// 计数器 SecretContext secretContextDO = secretCore.GetSecret(session, secretDataDO.SecretVersion); string decryptValue = SecurityUtil.AESDecrypt(secretDataDO.OriginalBase64Value, secretContextDO.Secret); if (PHONE.Equals(type) && !secretDataDO.Search) { // 加上手机号前3位,手机号只加密了后8位 return secretDataDO.OriginalValue + decryptValue; } return decryptValue; } /// /// 判断list元素是否全部为密文数据 /// /// /// 加密字段类型(例如:simple\phone) /// public static bool IsEncryptData(List dataList, string type) { if (dataList == null || dataList.Count == 0) { return false; } bool result = false; foreach (string data in dataList) { result = IsEncryptData(data, type); if (!result) { return false; } } return result; } /// /// 判断list元素是否存在密文数据。只要有一个是密文,则返回true /// /// /// 加密字段类型(例如:simple\phone) /// public static bool IsPartEncryptData(List dataList, String type) { if (dataList == null || dataList.Count == 0) { return false; } bool result = false; foreach (string data in dataList) { result = IsEncryptData(data, type); if (result) { return true; } } return result; } /// /// 判断是否密文数据 /// /// /// 加密字段类型(例如:simple\phone) /// public static bool IsEncryptData(string data, string type) { return SecurityBiz.IsEncryptData(data, type); } /// /// 加密(所有用户共用秘钥) /// /// /// /// public string Encrypt(string data, string type) { return Encrypt(data, type, null, null); } /// /// 用老秘钥加密,只在秘钥升级时使用(所有用户共用秘钥) /// /// /// /// public string EncryptPrevious(string data, string type) { return Encrypt(data, type, null, -1L); } /// /// 加密(每个用户单独分配秘钥) /// /// /// /// /// public string Encrypt(string data, string type, string session) { return Encrypt(data, type, session, null); } /// /// 用老秘钥加密,只在秘钥升级时使用(每个用户单独分配秘钥) /// /// /// /// /// public string EncryptPrevious(string data, string type, string session) { return Encrypt(data, type, session, -1L); } /// /// 密文检索(所有用户共用秘钥) /// /// /// /// public string Search(string data, string type) { return Search(data, type, null, null); } /// /// 密文检索,在秘钥升级场景下兼容查询(所有用户共用秘钥) /// /// /// /// public string SearchPrevious(string data, string type) { return Search(data, type, null, -1L); } /// /// 密文检索(每个用户单独分配秘钥) /// /// /// /// /// public string Search(string data, string type, string session) { return Search(data, type, session, null); } /// /// 密文检索,在秘钥升级场景下兼容查询(每个用户单独分配秘钥) /// /// /// /// /// public string SearchPrevious(string data, string type, string session) { return Search(data, type, session, -1L); } /// /// 密文检索。 手机号码格式:$base64(H-MAC(phone后4位))$ simple格式:base64(H-MAC(滑窗)) /// /// 明文数据 /// 加密字段类型(例如:simple\phone) /// 用户身份,用户级加密必填 /// 秘钥历史版本 /// private string Search(string data, string type, string session, Nullable version) { if (string.IsNullOrEmpty(data)) { return data; } SecretContext secretContext = secretCore.GetSecret(session, version); if (secretContext == null) { throw new SecretException("secretKey is null"); } if (secretContext.Secret == null) { return data; } string separator = null; SecurityBiz.GetSeparatorMap().TryGetValue(type, out separator); if (separator == null) { throw new SecretException("type error"); } // 公共秘钥版本号用负数区分 if (session == null) { SecretContext publicSecretContext = new SecretContext(); publicSecretContext.Secret = secretContext.Secret; publicSecretContext.SecretVersion = -secretContext.SecretVersion; secretContext = publicSecretContext; } securityCounter.AddSearchCount(type, session);// 计数器 if (PHONE.Equals(type)) { return SecurityBiz.SearchPhoneIndex(data, separator, secretContext); } else { int compressLen = secretCore.GetCompressLen(); int slideSize = secretCore.GetSlideSize(); return SecurityBiz.SearchNormalIndex(data, compressLen, slideSize, secretContext); } } /// /// 加密之后格式。 手机号码格式:$手机号码前3位明文$base64(encrypt(phone后8位))$111$ /// simple格式:~base64(encrypt(nick))~111~ /// /// 明文数据 /// 加密字段类型(例如:simple\phone) /// 用户身份,用户级加密必填 /// 秘钥历史版本 /// private string Encrypt(string data, string type, string session, Nullable version) { if (string.IsNullOrEmpty(data)) { return data; } SecretContext secretContext = secretCore.GetSecret(session, version); if (secretContext == null) { throw new SecretException("secretKey is null"); } if (secretContext.Secret == null) { return data; } string separator = null; SecurityBiz.GetSeparatorMap().TryGetValue(type, out separator); if (separator == null) { throw new SecretException("type error"); } // 公共秘钥版本号用负数区分 if (session == null) { SecretContext publicSecretContext = new SecretContext(); publicSecretContext.Secret = secretContext.Secret; publicSecretContext.SecretVersion = -secretContext.SecretVersion; secretContext = publicSecretContext; } securityCounter.AddEncryptCount(type, session);// 计数器 bool isEncryptIndex = secretCore.IsIndexEncrypt(type, version); // 支持密文检索 if (isEncryptIndex || SEARCH.Equals(type)) { if (PHONE.Equals(type)) { return SecurityBiz.EncryptPhoneIndex(data, separator, secretContext); } else { int compressLen = secretCore.GetCompressLen(); int slideSize = secretCore.GetSlideSize(); return SecurityBiz.EncryptNormalIndex(data, compressLen, slideSize, separator, secretContext); } } else { if (PHONE.Equals(type)) { return SecurityBiz.EncryptPhone(data, separator, secretContext); } else { return SecurityBiz.EncryptNormal(data, separator, secretContext); } } } /// /// 批量加密(所有用户共用秘钥) /// /// /// /// public IDictionary Encrypt(List dataList, string type) { return Encrypt(dataList, type, null); } /// /// 批量加密(每个用户单独分配秘钥) /// /// /// /// /// key=明文数据,value=密文数据 public IDictionary Encrypt(List dataList, string type, string session) { if (dataList == null || dataList.Count == 0) { throw new SecretException("dataList can`t be empty"); } IDictionary resultMap = new Dictionary(); foreach (string data in dataList) { if (!resultMap.ContainsKey(data)) { string encryptValue = Encrypt(data, type, session, null); resultMap.Add(data, encryptValue); } } return resultMap; } /// /// 生成自定义session,提供给自主账号使用 /// /// /// public static string GenerateCustomerSession(long userId) { return UNDERLINE + userId; } } }