834 lines
40 KiB
C#
834 lines
40 KiB
C#
|
||
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; }
|
||
ValidationErrors errors = new ValidationErrors();
|
||
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, 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, out string remark)
|
||
{
|
||
bool result = false;
|
||
remark = ""; //解密后的手机号,如果是黑名单用户,那么就是黑名单理由
|
||
var list = _CSVR_BLACKNUMBER.GetBlackNumberByRESID(resid, 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);
|
||
if (Request.QueryString["mytoken"] != null)
|
||
{
|
||
url += "&hgCustomer=1&isFromHg=1&mytoken=" + Request.QueryString["mytoken"];
|
||
|
||
}
|
||
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进制的97);abc变成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)变成a;616263变成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">true:CBC mode;false:非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>
|
||
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
|
||
}
|
||
}
|