Пример #1
0
        /// <summary>
        /// 解密MAC
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="Key"></param>
        /// <param name="MAC"></param>
        /// <returns></returns>
        public static bool MACDecrypt(byte[] buffer, string Key, string MAC)
        {
            //去除 mac8字节
            byte[] macBuffer = new byte[buffer.Length - 8];
            //拷贝需要校验MAC的内容
            Array.Copy(buffer, 0, macBuffer, 0, macBuffer.Length);
            //计算MAC的值
            string mac = LCDES.MACEncrypt(macBuffer, Key, 0);

            return(MAC == mac ? true : false);
        }
Пример #2
0
        /*
         *  POS终端采用ECB的加密方式,简述如下:
         *  a)  将欲发送给POS中心的消息中,从消息类型(MTI)到63域之间的部分构成MAC ELEMEMENT BLOCK (MAB)。
         *  b)  对MAB,按每8个字节做异或(不管信息中的字符格式),如果最后不满8个字节,则添加“0X00”。
         *  示例	:
         *  MAB = M1 M2 M3 M4
         *  其中:
         *  M1 = MS11 MS12 MS13 MS14 MS15 MS16 MS17 MS18
         *  M2 = MS21 MS22 MS23 MS24 MS25 MS26 MS27 MS28
         *  M3 = MS31 MS32 MS33 MS34 MS35 MS36 MS37 MS38
         *  M4 = MS41 MS42 MS43 MS44 MS45 MS46 MS47 MS48
         *
         *  按如下规则进行异或运算:
         *                          MS11 MS12 MS13 MS14 MS15 MS16 MS17 MS18
         *  XOR)			MS21 MS22 MS23 MS24 MS25 MS26 MS27 MS28
         *  ---------------------------------------------------
         *  TEMP BLOCK1 =	TM11 TM12 TM13 TM14 TM15 TM16 TM17 TM18
         *
         *  然后,进行下一步的运算:
         *  TM11 TM12 TM13 TM14 TM15 TM16 TM17 TM18
         *  XOR)			MS31 MS32 MS33 MS34 MS35 MS36 MS37 MS38
         *  ---------------------------------------------------
         *  TEMP BLOCK2 =	TM21 TM22 TM23 TM24 TM25 TM26 TM27 TM28
         *
         *  再进行下一步的运算:
         *  TM21 TM22 TM23 TM24 TM25 TM26 TM27 TM28
         *  XOR)			MS41 MS42 MS43 MS44 MS45 MS46 MS47 MS48
         *  ---------------------------------------------------
         *  RESULT BLOCK =	TM31 TM32 TM33 TM34 TM35 TM36 TM37 TM38
         *
         *  c)  将异或运算后的最后8个字节(RESULT BLOCK)转换成16 个HEXDECIMAL:
         *  RESULT BLOCK = TM31 TM32 TM33 TM34 TM35 TM36 TM37 TM38
         *                   = TM311 TM312 TM321 TM322 TM331 TM332 TM341 TM342 ||
         *                         TM351 TM352 TM361 TM362 TM371 TM372 TM381 TM382
         *
         *  d)  取前8 个字节用MAK加密:
         *  ENC BLOCK1 = eMAK(TM311 TM312 TM321 TM322 TM331 TM332 TM341 TM342)
         *                          = EN11 EN12 EN13 EN14 EN15 EN16 EN17 EN18
         *
         *  e)  将加密后的结果与后8 个字节异或:
         *  EN11  EN12  EN13  EN14  EN15  EN16  EN17  EN18
         *  XOR)        TM351 TM352 TM361 TM362 TM371 TM372 TM381 TM382
         *  ------------------------------------------------------------
         *  TEMP BLOCK=	TE11  TE12  TE13  TE14  TE15  TE16  TE17  TE18
         *
         *  f)  用异或的结果TEMP BLOCK 再进行一次单倍长密钥算法运算。
         *  ENC BLOCK2 = eMAK(TE11 TE12 TE13 TE14 TE15 TE16 TE17 TE18)
         *                     = EN21 EN22 EN23 EN24 EN25 EN26 EN27 EN28
         *
         *  g)  将运算后的结果(ENC BLOCK2)转换成16 个HEXDECIMAL:
         *  ENC BLOCK2 = EN21 EN22 EN23 EN24 EN25 EN26 EN27 EN28
         *  = EM211 EM212 EM221 EM222 EM231 EM232 EM241 EM242 ||
         *                           EM251 EM252 EM261 EM262 EM271 EM272 EM281 EM282
         *  示例	:
         *  ENC RESULT= %H84, %H56, %HB1, %HCD, %H5A, %H3F, %H84, %H84
         *  转换成16 个HEXDECIMAL:
         *  “8456B1CD5A3F8484”
         *  h)  取前8个字节作为MAC值。
         *  取”8456B1CD”为MAC值。
         */
        /// <summary>
        /// 加密MAC
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="Key">工作密钥</param>
        /// <returns></returns>
        public static string MACEncrypt(byte[] buffer, string Key, int idx)
        {
            try
            {
                //-------------------------------------------------------------------------------------------------------------------------

                /* 文档中的描述
                 * 下面的内容是组成MAC ELEMEMENT BLOCK (MAB)的
                 * 文档中的描述
                 * a)  将欲发送给POS中心的消息中,从消息类型(MTI)到63域之间的部分构成MAC ELEMEMENT BLOCK (MAB)。
                 */
                //因为计算MAC时不需要报文头,所以去掉报文头的11字节
                byte[] macBuffer = new byte[buffer.Length - 11 - idx];
                Array.Copy(buffer, 11 + idx, macBuffer, 0, macBuffer.Length);
                //因为数据并不包含64域的内容,所以不需要去除最后64域的内容
                //计算后 macBuffer 的内容就是需要计算的内容

                //-------------------------------------------------------------------------------------------------------------------------

                /*
                 * 文档中的描述
                 * b)  对MAB,按每8个字节做异或(不管信息中的字符格式),如果最后不满8个字节,则添加“0X00”。
                 *      示例	:
                 *      MAB = M1 M2 M3 M4
                 *      其中:
                 *      M1 = MS11 MS12 MS13 MS14 MS15 MS16 MS17 MS18
                 *      M2 = MS21 MS22 MS23 MS24 MS25 MS26 MS27 MS28
                 *      M3 = MS31 MS32 MS33 MS34 MS35 MS36 MS37 MS38
                 *      M4 = MS41 MS42 MS43 MS44 MS45 MS46 MS47 MS48
                 *
                 *      按如下规则进行异或运算:
                 *                              MS11 MS12 MS13 MS14 MS15 MS16 MS17 MS18
                 *      XOR)			MS21 MS22 MS23 MS24 MS25 MS26 MS27 MS28
                 *      ---------------------------------------------------
                 *      TEMP BLOCK1 =	TM11 TM12 TM13 TM14 TM15 TM16 TM17 TM18
                 *
                 *      然后,进行下一步的运算:
                 *      TM11 TM12 TM13 TM14 TM15 TM16 TM17 TM18
                 *      XOR)			MS31 MS32 MS33 MS34 MS35 MS36 MS37 MS38
                 *      ---------------------------------------------------
                 *      TEMP BLOCK2 =	TM21 TM22 TM23 TM24 TM25 TM26 TM27 TM28
                 *
                 *      再进行下一步的运算:
                 *      TM21 TM22 TM23 TM24 TM25 TM26 TM27 TM28
                 *      XOR)			MS41 MS42 MS43 MS44 MS45 MS46 MS47 MS48
                 *      ---------------------------------------------------
                 *      RESULT BLOCK =	TM31 TM32 TM33 TM34 TM35 TM36 TM37 TM38
                 */
                int index = 0;
                //取前两个需要异或的Block
                byte[] temp_block = new byte[8];
                byte[] sub_Mac    = GetSubMac(macBuffer, index++ *8);
                while (sub_Mac != null)
                {
                    for (int i = 0; i < 8; i++)
                    {
                        //每8个字节异或
                        temp_block[i] = Convert.ToByte(sub_Mac[i] ^ temp_block[i]);
                    }
                    //获取下一个需要异或的8字节
                    //GetSubMac方法有具体的描述
                    sub_Mac = GetSubMac(macBuffer, index++ *8);
                }

                //-------------------------------------------------------------------------------------------------------------------------

                /*文档中的描述
                 * c)  将异或运算后的最后8个字节(RESULT BLOCK)转换成16 个HEXDECIMAL:
                 *  RESULT BLOCK = TM31 TM32 TM33 TM34 TM35 TM36 TM37 TM38
                 *              = TM311 TM312 TM321 TM322 TM331 TM332 TM341 TM342 ||
                 *                    TM351 TM352 TM361 TM362 TM371 TM372 TM381 TM382
                 */
                string result_block = "";
                //因为后面暂时只用到了转换后的前8个字节,所以只处理一般长度 temp_block.Length / 2
                for (int i = 0; i < temp_block.Length / 2; i++)
                {
                    //将temp_block[i]中的值由10进制转化为16进制,如果不足2位左补0
                    result_block += SendConvertString(temp_block[i].ToString(), 10, 16).PadLeft(2, '0');
                }
                //转换为大写 关键
                result_block = result_block.ToUpper();

                //-------------------------------------------------------------------------------------------------------------------------

                /*文档中的描述
                 *  d)  取前8 个字节用MAK加密:
                 *  ENC BLOCK1 = eMAK(TM311 TM312 TM321 TM322 TM331 TM332 TM341 TM342)
                 *                          = EN11 EN12 EN13 EN14 EN15 EN16 EN17 EN18
                 */
                //存放加密后的内容
                byte[] enc_block = new byte[8];
                //加密 result_block的内容是之前计算好的HEXDECIMAL
                enc_block = LCDES.DesEncrypt(System.Text.Encoding.Default.GetBytes(result_block), Key);

                //-------------------------------------------------------------------------------------------------------------------------

                /* 文档中的描述
                 *  e)  将加密后的结果与后8 个字节异或:
                 *      EN11  EN12  EN13  EN14  EN15  EN16  EN17  EN18
                 *      XOR)        TM351 TM352 TM361 TM362 TM371 TM372 TM381 TM382
                 *      ------------------------------------------------------------
                 *      TEMP BLOCK=	TE11  TE12  TE13  TE14  TE15  TE16  TE17  TE18
                 */
                //首先取后8个字节的内容 temp_block.Length / 2
                result_block = "";
                for (int i = temp_block.Length / 2; i < temp_block.Length; i++)
                {
                    //将temp_block[i]中的值由10进制转化为16进制,如果不足2位左补0
                    result_block += SendConvertString(temp_block[i].ToString(), 10, 16).PadLeft(2, '0');
                }
                //转换为大写 关键
                result_block = result_block.ToUpper();

                //将后8个字节的HEXDECIMAL转化为byte[]
                temp_block = System.Text.Encoding.Default.GetBytes(result_block);
                //将加密后的结果与后8 个字节异或
                for (int i = 0; i < 8; i++)
                {
                    temp_block[i] = Convert.ToByte(enc_block[i] ^ temp_block[i]);
                }

                //-------------------------------------------------------------------------------------------------------------------------

                /* 文档中的描述
                 * f)  用异或的结果TEMP BLOCK 再进行一次单倍长密钥算法运算。
                 *      ENC BLOCK2 = eMAK(TE11 TE12 TE13 TE14 TE15 TE16 TE17 TE18)
                 *             = EN21 EN22 EN23 EN24 EN25 EN26 EN27 EN28
                 */
                //存放加密后的结果
                byte[] enc_block2 = new byte[8];
                enc_block2 = LCDES.DesEncrypt(temp_block, Key);
                //-------------------------------------------------------------------------------------------------------------------------

                /* 文档中的描述
                 * g)  将运算后的结果(ENC BLOCK2)转换成16 个HEXDECIMAL:
                 *      ENC BLOCK2 = EN21 EN22 EN23 EN24 EN25 EN26 EN27 EN28
                 *      = EM211 EM212 EM221 EM222 EM231 EM232 EM241 EM242 ||
                 *                   EM251 EM252 EM261 EM262 EM271 EM272 EM281 EM282
                 * h)  取前8个字节作为MAC值。
                 */
                result_block = "";
                //因为只取前8个字节作为MAC值,所以计算的长度是加密数组的一半 enc_block2.Length / 2
                for (int i = 0; i < enc_block2.Length / 2; i++)
                {
                    //将enc_block2[i]中的值由10进制转化为16进制,如果不足2位左补0
                    result_block += SendConvertString(enc_block2[i].ToString(), 10, 16).PadLeft(2, '0');
                }
                result_block = result_block.ToUpper();

                //-------------------------------------------------------------------------------------------------------------------------
                //到这里result_block的值就应该是MAC的值
                temp_block = System.Text.Encoding.Default.GetBytes(result_block);
                string ret = "";
                for (int i = 0; i < result_block.Length; i++)
                {
                    ret += SendConvertString(temp_block[i].ToString(), 10, 16).PadLeft(2, '0');
                }
                return(ret);
            }
            catch (Exception)
            {
            }
            return("");
        }