namespace WX.CRM.WEB.Controllers.Csvr { using System; using System.Linq; using System.Text; using System.Web.Mvc; using WX.CRM.BLL.Util; using WX.CRM.Common; using WX.CRM.IBLL.Base; using WX.CRM.IBLL.Csvr; using WX.CRM.IBLL.IPSC; using WX.CRM.IBLL.RedisBL; using WX.CRM.IBLL.Res; using WX.CRM.IBLL.Util; using WX.CRM.Model.Entity; using WX.CRM.WebHelper; public class CallController : BaseController { #region 呼叫枚举 /// /// 呼叫状态 /// public enum EnumCallState { 呼入 = 0, 呼出 = 1, 预览外呼 = 2 } /// /// 电话类型 /// public enum EnumPhoneType { 不确定 = 0, 手机 = 1, 座机 = 2, 小灵通 = 3 } public enum EnumCallType { 销售电话 = 1, 服务电话 = 2 } #endregion 呼叫枚举 [Ninject.Inject] public ICSVR_BLACKNUMBER_Q _CSVR_BLACKNUMBER { get; set; } [Ninject.Inject] public ICSVR_CALLINLOG _CSVR_CALLINLOG { get; set; } [Ninject.Inject] public IRES_CUSTOMER _RES_CUSTOMER { get; set; } [Ninject.Inject] public IRES_CUSTOMER_Q _RES_CUSTOMER_Q { get; set; } [Ninject.Inject] public IBAS_PARAMETER_Q _BAS_PARAMETER_Q { get; set; } [Ninject.Inject] public IRES_APPLY _RES_APPLY { get; set; } [Ninject.Inject] public IIPSC_Q _IIPSC_Q { get; set; } private ValidationErrors errors = new ValidationErrors(); private WebHelper.RedisFactory.RedisFactory redisFactory = new WebHelper.RedisFactory.RedisFactory(); //[Ninject.Inject] //public IRES_CUSTOMER_REDIS customerRedisBiz { get; set; } //[Ninject.Inject] //public IRES_CUSTOMERDETAIL_REDIS customerDetailRedisBiz { get; set; } [Ninject.Inject] public IRES_CUSTOMERDETAIL_Q _RES_CUSTOMER_DETAIL_Q { get; set; } [Ninject.Inject] public ICUSTOMER_REDIS customerRedisBL { get; set; } [Ninject.Inject] public ICSVR_FAVORITECUSTOMER_Q _favCustomer { get; set; } [Ninject.Inject] public ICACHE_Q _cache { get; set; } #region 拨号 /// /// 判断是否黑名单 /// /// public ActionResult JudgeNumberIsBlackNumber(string typeId, string resid, string zero) { //var _num_encypt = _BAS_PARAMETER_Q.GetModel_Patameter("SYS_CALLOUT_NUM_ENCYPTDES"); var _num_encypt = _cache.GetValue_Parameter("SYS_CALLOUT_NUM_ENCYPTDES"); var _bol_encypt = false; if (_num_encypt != null && _num_encypt.ToLower() == "true") { _bol_encypt = true; } string remark = ""; bool result = false; try { result = IsBlackNumber(resid, typeId, UserId, out remark); } catch (Exception ex) { LogHelper.Error(ex); } string strresult = ""; if (!string.IsNullOrEmpty(remark)) { try { if (_bol_encypt)//DES加密 { SecurityHelper sHelper = new SecurityHelper(); strresult = sHelper.encyptCtiNumStr(zero + remark.Trim()); } else strresult = encMe(remark.Trim(), "KKid228JD13"); } catch (Exception ex) { LogHelper.Error(ex); } } //黑名单 if (result == true) { if (string.IsNullOrEmpty(remark)) { return Json(new { isBN = "1", result = "1", encypydes = _bol_encypt }, JsonRequestBehavior.AllowGet); } else { return Json(new { isBN = "1", result = strresult, encypydes = _bol_encypt }, JsonRequestBehavior.AllowGet); } } else { //讲解外呼,不受收藏客户外呼限制 if (!userRoleCodes.Contains("[JSWH]")) { //是否启用收藏客户外呼 var favCustomerEnableCanCall = _cache.GetValue_Parameter("FavCustomerEnableCanCall"); if (favCustomerEnableCanCall == "false") { try { var msg = string.Empty; var list = _favCustomer.FavCallList(resid, UserId).Select(p => p.salesid); foreach (var item in list) { if (item.HasValue) { msg += "【" + InnerUserHelper.Instance.EidAndName(item) + "】"; } } if (!string.IsNullOrEmpty(msg)) { msg = "已经被" + msg + "收藏,您不能外呼"; return Json(new { isBN = "2", result = msg, encypydes = _bol_encypt }, JsonRequestBehavior.AllowGet); } } catch (Exception ex) { LogHelper.Error("检测收藏客户拨打:" + ex.ToString()); return Json(new { isBN = "2", result = "系统异常了,请稍后重试!", encypydes = _bol_encypt }, JsonRequestBehavior.AllowGet); } } } return Json(new { isBN = "0", result = strresult, encypydes = _bol_encypt }, JsonRequestBehavior.AllowGet); } } /// /// 十六进制换算为十进制 /// /// /// private int GetHexadecimalValue(String strColorValue) { char[] nums = strColorValue.ToCharArray(); int total = 0; try { for (int i = 0; i < nums.Length; i++) { String strNum = nums[i].ToString().ToUpper(); switch (strNum) { case "A": strNum = "10"; break; case "B": strNum = "11"; break; case "C": strNum = "12"; break; case "D": strNum = "13"; break; case "E": strNum = "14"; break; case "F": strNum = "15"; break; default: break; } double power = Math.Pow(16, Convert.ToDouble(nums.Length - i - 1)); total += Convert.ToInt32(strNum) * Convert.ToInt32(power); } } catch (System.Exception ex) { String strErorr = ex.ToString(); return 0; } return total; } private string confusionMobile(string mobile) { var rst = ""; rst = mobile.Substring(mobile.Length - 3) + mobile.Substring(0, mobile.Length - 3); return bianma(rst.PadLeft(15, '0')); } /// /// 将字符串转成二进制 /// /// /// public static string bianma(string s) { byte[] data = Encoding.Unicode.GetBytes(s); StringBuilder result = new StringBuilder(data.Length * 8); foreach (byte b in data) { result.Append(Convert.ToString(b, 2).PadLeft(8, '0')); } return result.ToString(); } private bool IsBlackNumber(string resid, string type, decimal userid, out string remark) { bool result = false; remark = ""; //解密后的手机号,如果是黑名单用户,那么就是黑名单理由 var list = _CSVR_BLACKNUMBER.GetBlackNumberByRESID(resid, userid, out remark); if (list.Count() > 0 && list.Where(p => p.BLACKTYPE == "H").Count() > 0) { var roles = DataCacheHelper.GetCache().Get_RoleCodes(userRoleId); if (!(roles.Contains("[CKHT]") || roles.Contains("[SH]") || roles.Contains("[bsh]") || roles.Contains("[TNBHG]"))) { remark = list.Where(p => p.BLACKTYPE == "H").Select(p => p.REASON).FirstOrDefault(); result = true; } LogHelper.Info("eid:" + Eid + ",roles:" + roles + ",remark:" + remark); } else if (list.Count() > 0 && list.Where(p => p.BLACKTYPE == type.ToString()).Count() > 0) { remark = list.Where(p => p.BLACKTYPE == type.ToString()).Select(p => p.REASON).FirstOrDefault(); result = true; } return result; } public ActionResult GetUserAgent(string usereid) { var agentlist = _IIPSC_Q.Get_IVR_Moniter(); var agent = agentlist.Tables[0].Select("userid='" + usereid + "'"); if (null != agent && agent.Length > 0) { return Content(agent[0]["agentid"].ToString()); } return Content(""); } #endregion 拨号 #region 弹屏 /// /// /// /// 呼出呼入状态 State参数必须传入 三种状态 呼入=0,呼出=1,预览呼出=2 /// 呼叫类型:销售=1,服务=2 /// 被叫号码 /// 主叫号码 /// http://192.168.1.86:807/Call/CallLog?State=0&CallType=1&DNIS=31039699&Tel=15635054711&SRID=14373546465113418319&SRN=31039699&AGENTID=6363 /// http://192.168.1.86:807/Call/CallLog?State=0&CallType=1&DNIS=31039699&Tel=18816013940&SRID=14373547837113420341&SRN=31039699&AGENTID=7019 /// http://192.168.1.86:807/Call/CallLog?State=1&CallType=1&DNIS=013367352313&Tel=31039699&SRID=14373547904113420496&SRN=013367352313&AGENTID=6363 /// public ActionResult CallLog(string State, string CallType, string DNIS, string Tel, string SRCTYPE) { LogHelper.Info("State:" + State.ToString() + ",CallType:" + CallType.ToString() + "DNIS:" + DNIS.ToString() + ",Tel:" + Tel.ToString() + ",SRCTYPE:" + SRCTYPE.ToString()); var _num_encypt = _BAS_PARAMETER_Q.GetModel_Patameter("SYS_CALLOUT_NUM_ENCYPTDES"); var _bol_encypt = false; if (_num_encypt != null && _num_encypt.PARAVALUE.ToLower() == "true") { _bol_encypt = true; } if (_bol_encypt) { Tel = new SecurityHelper().decyptCtiNumStr(Tel); } try { int intCallState = -1; if (!string.IsNullOrEmpty(State)) { intCallState = Convert.ToInt32(State); var resid = InsertRecord(DNIS, Tel, intCallState); if (!string.IsNullOrEmpty(resid)) { string url = string.Concat("/Csvr/CustomerInfo/CustomerDetail?calltype=", State, "&resid=", resid, "&srcType=", SRCTYPE); return Redirect(url); } } } catch (Exception ex) { LogHelper.Error("CallLog:" + Request.Url.ToString(), ex); } return null; } /// 被叫号码 /// 主叫号码 private string InsertRecord(string DNIS, string Tel, int intCallState) { string srid = Request.QueryString["SRID"]; // 电话流水号 int? agentID = Convert.ToInt32(Request.QueryString["AGENTID"]);//客服工号 string regmobile = Tel; if (intCallState == 1)//,呼出=1 regmobile = DNIS; if (regmobile.Length > 5 && regmobile.StartsWith("0086")) { regmobile = regmobile.Substring(4);//去除0086 } DateTime startTime = DateTime.Now; DateTime endTime = Convert.ToDateTime("2000-1-1"); string resid = string.Empty; if (regmobile.Length > 5) { resid = WX.CRM.Common.ResUtil.CreateResId(regmobile); if (_RES_CUSTOMER_Q.getResCustomerByResId(resid) == null) { var cusFrom = _BAS_PARAMETER_Q.GetModel_Patameter("CustomerFrom"); if (cusFrom != null) { _RES_CUSTOMER.ResgisterCustomer(regmobile, resid, cusFrom.PARAVALUE); #region 提交到资源系统 RES_APPLY applyinfo = new RES_APPLY(); applyinfo.CTIME = DateTime.Now; applyinfo.JSONDATA = string.Empty; applyinfo.JSONTYPE = 0; applyinfo.MOBILE = regmobile; applyinfo.RESID = resid; applyinfo.RESOURCETAG = cusFrom.PARAVALUE; applyinfo.RTIME = DateTime.Now; applyinfo.STATUS = 0; applyinfo.USERNAME = ""; _RES_APPLY.Create(ref errors, applyinfo); #endregion 提交到资源系统 } } } CSVR_CALLINLOG callRecord = new CSVR_CALLINLOG() { SRID = srid, CALLEDNUMBER = regmobile, //Utility.NumberFormat(regmobile), RESID = resid, CALLSTATE = intCallState, SALESEID = agentID, CTIME = DateTime.Now }; if (_CSVR_CALLINLOG.Create(ref errors, callRecord)) { return resid; } else { LogHelper.Error("Class:CallController.InsertRecord" + string.Concat(Request.RawUrl, "插入流水表出错")); return null; } } #endregion 弹屏 #region 挂断后弹出填写工单 public ActionResult CallEndHandler(string State, string Tel) { var _num_encypt = _BAS_PARAMETER_Q.GetModel_Patameter("SYS_CALLOUT_NUM_ENCYPTDES"); var _bol_encypt = false; if (_num_encypt != null && _num_encypt.PARAVALUE.ToLower() == "true") { _bol_encypt = true; } if (_bol_encypt) { //LogHelper.Info("tel:" + Tel); Tel = new SecurityHelper().decyptCtiNumStr(Tel); //LogHelper.Info("tel:" + Tel); } try { if (!string.IsNullOrEmpty(State)) { var resid = WX.CRM.Common.ResUtil.CreateResId(Tel); string url = string.Format("/Ord/Memo/SaleMemoAdd?CallType={0}&resid={1}&act={2}", State, resid, "callend"); return Redirect(url); } } catch (Exception ex) { LogHelper.Error("CallLog:" + Request.Url.ToString(), ex); } return null; } #endregion 挂断后弹出填写工单 #region 配合JS用的C#版DES加解密方法及相关函数 /// /// 加密测试函数 /// /// 待加密的字符串 /// 密钥 /// public static string encMe(string beinetstr, string beinetkey) { if (string.IsNullOrEmpty(beinetkey)) return string.Empty; return stringToHex(des(beinetkey, beinetstr, true, false, string.Empty)); } /// /// 解密测试函数 /// /// 待解密的字符串 /// 密钥 /// public static string uncMe(string beinetstr, string beinetkey) { if (string.IsNullOrEmpty(beinetkey)) return null; string ret = des(beinetkey, HexTostring(beinetstr), false, false, string.Empty); return ret; } /// /// 把字符串转换为16进制字符串 /// 如:a变成61(即10进制的97);abc变成616263 /// /// /// public static string stringToHex(string s) { string r = ""; string[] hexes = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; for (int i = 0; i < (s.Length); i++) { r += hexes[RM(s[i], 4)] + hexes[s[i] & 0xf]; } return r; } /// /// 16进制字符串转换为字符串 /// 如:61(即10进制的97)变成a;616263变成abc /// /// /// public static string HexTostring(string s) { string ret = string.Empty; for (int i = 0; i < s.Length; i += 2) { int sxx = Convert.ToInt32(s.Substring(i, 2), 16); ret += (char)sxx; } return ret; } /// /// 带符号位右移(类似于js的>>>) /// /// 用于右移的操作数 /// 右移位数 /// public static int RM(int a, int bit) { unchecked { uint b = (uint)a; b = b >> bit; return (int)b; } } /// /// 加解密主调方法 /// /// 密钥 /// 加密时为string,解密时为byte[] /// true:加密;false:解密 /// true:CBC mode;false:非CBC mode /// 初始化向量 /// public static string des(string beinetkey, string message, bool encrypt, bool mode, string iv) { //declaring this locally speeds things up a bit long[] spfunction1 = { 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 }; long[] spfunction2 = { -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, -0x7fef7fe0, 0x108000 }; long[] spfunction3 = { 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 }; long[] spfunction4 = { 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 }; long[] spfunction5 = { 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100 }; long[] spfunction6 = { 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 }; long[] spfunction7 = { 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 }; long[] spfunction8 = { 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 }; //create the 16 or 48 subkeys we will need int[] keys = des_createKeys(beinetkey); int m = 0; int i, j; int temp, right1, right2, left, right; int[] looping; int cbcleft = 0, cbcleft2 = 0, cbcright = 0, cbcright2 = 0; int endloop; int loopinc; int len = message.Length; int chunk = 0; //set up the loops for single and triple des var iterations = keys.Length == 32 ? 3 : 9;//single or triple des if (iterations == 3) { looping = encrypt ? new int[] { 0, 32, 2 } : new int[] { 30, -2, -2 }; } else { looping = encrypt ? new int[] { 0, 32, 2, 62, 30, -2, 64, 96, 2 } : new int[] { 94, 62, -2, 32, 64, 2, 30, -2, -2 }; } if (encrypt) { message += "\0\0\0\0\0\0\0\0";//pad the message out with null bytes } //store the result here //List result = new List(); //List tempresult = new List(); string result = string.Empty; string tempresult = string.Empty; if (mode) {//CBC mode int[] tmp = { 0, 0, 0, 0, 0, 0, 0, 0 }; int pos = 24; int iTmp = 0; while (m < iv.Length && iTmp < tmp.Length) { if (pos < 0) pos = 24; tmp[iTmp++] = iv[m++] << pos; pos -= 8; } cbcleft = tmp[0] | tmp[1] | tmp[2] | tmp[3]; cbcright = tmp[4] | tmp[5] | tmp[6] | tmp[7]; //cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; //cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; m = 0; } //loop through each 64 bit chunk of the message while (m < len) { if (encrypt) {/*加密时按双字节操作*/ left = (message[m++] << 16) | message[m++]; right = (message[m++] << 16) | message[m++]; } else { left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; } //for Cipher Block Chaining mode,xor the message with the previous result if (mode) { if (encrypt) { left ^= cbcleft; right ^= cbcright; } else { cbcleft2 = cbcleft; cbcright2 = cbcright; cbcleft = left; cbcright = right; } } //first each 64 but chunk of the message must be permuted according to IP temp = (RM(left, 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4); temp = (RM(left, 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16); temp = (RM(right, 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2); temp = (RM(right, 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8); temp = (RM(left, 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1); left = ((left << 1) | RM(left, 31)); right = ((right << 1) | RM(right, 31)); //do this either 1 or 3 times for each chunk of the message for (j = 0; j < iterations; j += 3) { endloop = looping[j + 1]; loopinc = looping[j + 2]; //now go through and perform the encryption or decryption for (i = looping[j]; i != endloop; i += loopinc) {//for efficiency right1 = right ^ keys[i]; right2 = (RM(right, 4) | (right << 28)) ^ keys[i + 1]; //the result is attained by passing these bytes through the S selection functions temp = left; left = right; right = (int)(temp ^ (spfunction2[RM(right1, 24) & 0x3f] | spfunction4[RM(right1, 16) & 0x3f] | spfunction6[RM(right1, 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[RM(right2, 24) & 0x3f] | spfunction3[RM(right2, 16) & 0x3f] | spfunction5[RM(right2, 8) & 0x3f] | spfunction7[right2 & 0x3f])); } temp = left; left = right; right = temp;//unreverse left and right }//for either 1 or 3 iterations //move then each one bit to the right left = (RM(left, 1) | (left << 31)); right = (RM(right, 1) | (right << 31)); //now perform IP-1,which is IP in the opposite direction temp = (RM(left, 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1); temp = (RM(right, 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8); temp = (RM(right, 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2); temp = (RM(left, 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16); temp = (RM(left, 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4); //for Cipher Block Chaining mode,xor the message with the previous result if (mode) { if (encrypt) { cbcleft = left; cbcright = right; } else { left ^= cbcleft2; right ^= cbcright2; } } //int[] arrInt; if (encrypt) { //arrInt = new int[]{ RM(left, 24), (RM(left, 16) & 0xff), (RM(left, 8) & 0xff), (left & 0xff), RM(right, 24), (RM(right, 16) & 0xff), (RM(right, 8) & 0xff), (right & 0xff) }; tempresult += String.Concat((char)RM(left, 24), (char)(RM(left, 16) & 0xff), (char)(RM(left, 8) & 0xff), (char)(left & 0xff), (char)RM(right, 24), (char)(RM(right, 16) & 0xff), (char)(RM(right, 8) & 0xff), (char)(right & 0xff)); } else { // 解密时,最后一个字符如果是\0,去除 //arrInt = new int[] { (RM(left, 16) & 0xffff), (left & 0xffff), (RM(right, 16) & 0xffff), (right & 0xffff) }; int tmpch = (RM(left, 16) & 0xffff); if (tmpch != 0) tempresult += (char)tmpch; tmpch = (left & 0xffff); if (tmpch != 0) tempresult += (char)tmpch; tmpch = (RM(right, 16) & 0xffff); if (tmpch != 0) tempresult += (char)tmpch; tmpch = (right & 0xffff); if (tmpch != 0) tempresult += (char)tmpch; //tempresult += String.Concat((char)(RM(left, 16) & 0xffff), // (char)(left & 0xffff), // (char)(RM(right, 16) & 0xffff), // (char)(right & 0xffff)); }/*解密时输出双字节*/ //byte[] arrByte = new byte[arrInt.Length]; //for (int loop = 0; loop < arrInt.Length; loop++) //{ // tempresult.Add(byte.Parse(arrInt[loop].ToString())); // //arrByte[loop] = byte.Parse(arrInt[loop].ToString()); //} //tempresult.Add(arrByte;// System.Text.Encoding.Unicode.GetString(arrByte); chunk += encrypt ? 16 : 8; if (chunk == 512) { //result.AddRange(tempresult);tempresult.Clear(); result += tempresult; tempresult = string.Empty; chunk = 0; } }//for every 8 characters,or 64 bits in the message //return the result as an array //result.AddRange(tempresult); //return result.ToArray(); return result + tempresult; }//end of des /// /// this takes as input a 64 bit beinetkey(even though only 56 bits are used) /// as an array of 2 integers,and returns 16 48 bit keys /// /// /// private static int[] des_createKeys(string beinetkey) { //declaring this locally speeds things up a bit int[] pc2bytes0 = { 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 }; int[] pc2bytes1 = { 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 }; int[] pc2bytes2 = { 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808 }; int[] pc2bytes3 = { 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 }; int[] pc2bytes4 = { 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, 0x41000, 0x1010, 0x41010 }; int[] pc2bytes5 = { 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420 }; int[] pc2bytes6 = { 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 }; int[] pc2bytes7 = { 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 }; int[] pc2bytes8 = { 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002 }; int[] pc2bytes9 = { 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 }; int[] pc2bytes10 = { 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, 0x102000, 0x102020, 0x102000, 0x102020 }; int[] pc2bytes11 = { 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 }; int[] pc2bytes12 = { 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 }; int[] pc2bytes13 = { 0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105 }; //how many iterations(1 for des,3 for triple des) int iterations = beinetkey.Length >= 24 ? 3 : 1; //stores the return keys int[] keys = new int[32 * iterations]; //now define the left shifts which need to be done int[] shifts = { 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 }; //other variables int left, right; int lefttemp; int righttemp; int m = 0, n = 0; int temp; for (int j = 0; j < iterations; j++) {//either 1 or 3 iterations int[] tmp = { 0, 0, 0, 0, 0, 0, 0, 0 }; int pos = 24; int iTmp = 0; while (m < beinetkey.Length && iTmp < tmp.Length) { if (pos < 0) pos = 24; tmp[iTmp++] = beinetkey[m++] << pos; pos -= 8; } left = tmp[0] | tmp[1] | tmp[2] | tmp[3]; right = tmp[4] | tmp[5] | tmp[6] | tmp[7]; //left = (beinetkey[m++] << 24) | (beinetkey[m++] << 16) | (beinetkey[m++] << 8) | beinetkey[m++]; //right = (beinetkey[m++] << 24) | (beinetkey[m++] << 16) | (beinetkey[m++] << 8) | beinetkey[m++]; temp = (RM(left, 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4); temp = (RM(right, -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16); temp = (RM(left, 2) ^ right) & 0x33333333; right ^= temp; left ^= (temp << 2); temp = (RM(right, -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16); temp = (RM(left, 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1); temp = (RM(right, 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8); temp = (RM(left, 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1); //the right side needs to be shifted and to get the last four bits of the left side temp = (left << 8) | (RM(right, 20) & 0x000000f0); //left needs to be put upside down left = (right << 24) | ((right << 8) & 0xff0000) | (RM(right, 8) & 0xff00) | (RM(right, 24) & 0xf0); right = temp; //now go through and perform these shifts on the left and right keys for (int i = 0; i < shifts.Length; i++) { //shift the keys either one or two bits to the left if (shifts[i] == 1) { left = (left << 2) | RM(left, 26); right = (right << 2) | RM(right, 26); } else { left = (left << 1) | RM(left, 27); right = (right << 1) | RM(right, 27); } left &= -0xf; right &= -0xf; //now apply PC-2,in such a way that E is easier when encrypting or decrypting //this conversion will look like PC-2 except only the last 6 bits of each byte are used //rather than 48 consecutive bits and the order of lines will be according to //how the S selection functions will be applied:S2,S4,S6,S8,S1,S3,S5,S7 lefttemp = pc2bytes0[RM(left, 28)] | pc2bytes1[RM(left, 24) & 0xf] | pc2bytes2[RM(left, 20) & 0xf] | pc2bytes3[RM(left, 16) & 0xf] | pc2bytes4[RM(left, 12) & 0xf] | pc2bytes5[RM(left, 8) & 0xf] | pc2bytes6[RM(left, 4) & 0xf]; righttemp = pc2bytes7[RM(right, 28)] | pc2bytes8[RM(right, 24) & 0xf] | pc2bytes9[RM(right, 20) & 0xf] | pc2bytes10[RM(right, 16) & 0xf] | pc2bytes11[RM(right, 12) & 0xf] | pc2bytes12[RM(right, 8) & 0xf] | pc2bytes13[RM(right, 4) & 0xf]; temp = (RM(righttemp, 16) ^ lefttemp) & 0x0000ffff; keys[n++] = lefttemp ^ temp; keys[n++] = righttemp ^ (temp << 16); } }//for each iterations //return the keys we"ve created return keys; }//end of des_createKeys #endregion 配合JS用的C#版DES加解密方法及相关函数 } }