TG.WXCRM.V4/WEB/Controllers/Csvr/CallController.cs

842 lines
40 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
/// <summary>
/// 呼叫状态
/// </summary>
public enum EnumCallState
{
= 0,
= 1,
= 2
}
/// <summary>
/// 电话类型
/// </summary>
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
/// <summary>
/// 判断是否黑名单
/// </summary>
/// <returns></returns>
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);
}
}
/// <summary>
/// 十六进制换算为十进制
/// </summary>
/// <param name="strColorValue"></param>
/// <returns></returns>
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'));
}
/// <summary>
/// 将字符串转成二进制
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
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
/// <summary>
///
/// </summary>
/// <param name="State">呼出呼入状态 State参数必须传入 三种状态 呼入=0,呼出=1,预览呼出=2</param>
/// <param name="CallType">呼叫类型:销售=1服务=2</param>
/// <param name="DNIS">被叫号码</param>
/// <param name="Tel">主叫号码</param>
/// 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
/// <returns></returns>
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;
}
/// <param name="DNIS">被叫号码</param>
/// <param name="Tel">主叫号码</param>
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加解密方法及相关函数
/// <summary>
/// 加密测试函数
/// </summary>
/// <param name="beinetstr">待加密的字符串</param>
/// <param name="beinetkey">密钥</param>
/// <returns></returns>
public static string encMe(string beinetstr, string beinetkey)
{
if (string.IsNullOrEmpty(beinetkey))
return string.Empty;
return stringToHex(des(beinetkey, beinetstr, true, false, string.Empty));
}
/// <summary>
/// 解密测试函数
/// </summary>
/// <param name="beinetstr">待解密的字符串</param>
/// <param name="beinetkey">密钥</param>
/// <returns></returns>
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;
}
/// <summary>
/// 把字符串转换为16进制字符串
/// 如a变成61即10进制的97abc变成616263
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 16进制字符串转换为字符串
/// 如61即10进制的97变成a616263变成abc
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 带符号位右移类似于js的>>>
/// </summary>
/// <param name="a">用于右移的操作数</param>
/// <param name="bit">右移位数</param>
/// <returns></returns>
public static int RM(int a, int bit)
{
unchecked
{
uint b = (uint)a;
b = b >> bit;
return (int)b;
}
}
/// <summary>
/// 加解密主调方法
/// </summary>
/// <param name="beinetkey">密钥</param>
/// <param name="message">加密时为string解密时为byte[]</param>
/// <param name="encrypt">true加密false解密</param>
/// <param name="mode">trueCBC modefalse非CBC mode</param>
/// <param name="iv">初始化向量</param>
/// <returns></returns>
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<byte> result = new List<byte>();
//List<byte> tempresult = new List<byte>();
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
/// <summary>
/// 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
/// </summary>
/// <param name="beinetkey"></param>
/// <returns></returns>
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加解密方法及相关函数
}
}