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加解密方法及相关函数
}
}