美文网首页
简单的网络数据加密算法

简单的网络数据加密算法

作者: 狐度计算 | 来源:发表于2019-11-17 23:46 被阅读0次

    在客户端和服务端交互数据时,经常会用到网络数据加密,以免被抓包后就能直接看出其中的内容。但是越复杂的加解密,对性能的要求就越高,这对于网络交互频繁的场景来说,开销未免过大,所以在这里写了一个比较简单的网络加密,使用的语言是c#。
    这个加密方法是客户端发送到服务端的数据加密,和服务端发送到客户端的数据加密方式不一致的,在简单的基础上增加了一点点安全性。
    此示例仅仅只是流程,最终结果是由具体需求而定。

    具体流程:
    定义:_passArr自定义的秘钥盒数组
    客户端发送到服务端:
    (1)客户端获取此时的unique_Idx(16进制,这里设置初始为99)
    (2)将unique_Idx与_passArr长度进行模运算,获得此时的起始key
    (3)将数据包中的每个字节数据与key自加后_passArr长度进行模运算取得的索引值进行'异或'运算
    (4)将数据存入结构体

    服务端发送到客户端:
    (1)服务端将要发送的(协议号*10+子协议号)与与_passArr长度进行模运算,获得此时的起始key
    (2)将数据包中的每个字节数据与key自加后_passArr长度进行模运算取得的索引值进行'异或'运算
    (3)将数据存入结构体

    服务端发送到客户端(1)部分可由服务端和客户端协商好固定算法,只是此处用协议号和子协议号来进行计算。

    具体代码实现:

    using System;
    using System.Collections.Generic;
    
    namespace NetNodeTest
    {
        class Program
        {
            //用于存储网络包的结构体
            public struct NetPacket
            {
                public byte[] packet;
                public byte mId;
                public byte sId;
            }
            //秘钥盒,可打乱顺序自定义
            private static readonly byte[] _passArr =
            {
                1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
                31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,
                58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,
                84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,
                108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
                128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,
                148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,
                168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,
                188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
                208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,
                228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
                248,249,250,251,252,253,254,255,
    
            };
            //秘钥盒长度
            private static UInt16 _len = (UInt16)(_passArr.Length-1);
            //默认唯一起始秘钥索引
            private static uint unique_Idx = 99;
            static void Main(string[] args)
            {
                byte[] array =
                {
                    8,9,87,91,97,88,92,63
                };
    
                Console.Write("原始数据:");
                PrintArray(array);
                Console.Write("\n");
    
                Console.Write("客户端发送给服务端的加密数据:");
                NetPacket packet = C2SPacketSend(array, 1, 2);
                PrintArray(packet.packet);
                Console.Write("\n");
    
                Console.Write("服务端接收客户端的数据解密:");
                PrintArray(C2SPacketReceive(packet).packet);
                Console.Write("\n");
    
                Console.Write("服务端发送给客户端加密的数据:");
                packet = S2CPacketSend(array, 1, 2);
                PrintArray(packet.packet);
                Console.Write("\n");
    
                Console.Write("服务端接收客户端的数据解密:");
                PrintArray(S2CPacketReceive(packet).packet);
            }
    
            //获取唯一id索引,当大于16位后重新回到初始数值,初始索引可以自己定义,这里用99
            static UInt16 GetUniIndex()
            {
                if (unique_Idx > 65536) unique_Idx = 99;
                unique_Idx += 1;
                return (UInt16)unique_Idx;
            }
    
            /*
                返回客户端发送给服务端的数据消息
                packet:客户端数据包,sId:协议号,mId:子协议号
            */
            public static NetPacket C2SPacketSend(byte[] packet, byte sId, byte mId)
            {
                UInt16 index = GetUniIndex(); //获取唯一id,每次获取后唯一id都会往上加1
                uint key = (UInt16)(index % _len); //将获取的唯一id与len进行模运算获得秘钥索引key
                NetPacket c2SPacket;
                c2SPacket.packet = new byte[packet.Length + 2];
                c2SPacket.packet[0] = (byte)(index >> 8); //右移8位,取出高8位放入(秘钥key为16位,无法放入字节数组中,则右移8位后取高8位,放入数据包索引0的位置,用于服务端获取索引值解密)
    
                c2SPacket.packet[1] = (byte) index; //直接舍弃高8位放入(放入低八位时直接强制转换,舍去高8位,放入数据包索引1的位置,用于服务端获取索引值解密)
    
                c2SPacket.sId = sId;//存入协议号
                c2SPacket.mId = mId;//存子协议号
                for (int i = 2; i < c2SPacket.packet.Length; i++, key = ((key + 1) % _len))
                {
                    c2SPacket.packet[i] = (byte)(packet[i-2] ^ _passArr[key]);//对数据包的每个字节与秘钥盒对应的key的索引进行异或(加密)
                }
                return c2SPacket;
            }
    
            /*
                返回客户端发送给服务端解密后的数据消息
                packet:接收客户端数据包
            */
            public static NetPacket C2SPacketReceive(NetPacket netPacket)
            {
                UInt16 index = (UInt16)(netPacket.packet[0] << 8 | netPacket.packet[1]); //将秘钥包的0索引左移8位,得到高8位是0的16进制数,再与低8(索引1)位作'与'运算,得出整个16位index
                uint key = (UInt16) (index%_len);//将获取的唯一id与len进行模运算获得秘钥索引key
    
                NetPacket c2SPacket;
                c2SPacket.packet = new byte[netPacket.packet.Length - 2];
                c2SPacket.sId = netPacket.sId;//存入协议号
                c2SPacket.mId = netPacket.mId;//存子协议号
                for (int i = 0; i < c2SPacket.packet.Length; i++, key = ((key + 1) % _len))
                {
                    c2SPacket.packet[i] = (byte)(netPacket.packet[i+2] ^ _passArr[key]);//对数据包的每个字节与秘钥盒对应的key的索引进行异或(解密)
                }
                return c2SPacket;
            }
    
            /*
                返回服务端发送给客户端解密后的数据消息
                packet:接收服务端数据包
            */
            public static NetPacket S2CPacketReceive(NetPacket netPacket)
            {
                uint key = (UInt16)((netPacket.sId * 10 + netPacket.mId) % _len); //key由前后端定好的规则算出(此处的sId和mId分别为用于前后端通信,收发数据包的协议号和子协议号)
                NetPacket s2CPacket;
                s2CPacket.packet = new byte[netPacket.packet.Length];
                s2CPacket.sId = netPacket.sId;//存入协议号
                s2CPacket.mId = netPacket.mId;//存子协议号
                for (int i = 0; i < s2CPacket.packet.Length; i++, key = (key + 1) % _len)
                {
                    s2CPacket.packet[i] = (byte)(netPacket.packet[i] ^ _passArr[key]);//对数据包的每个字节与秘钥盒对应的key的索引进行异或(解密)
                }
                return s2CPacket;
            }
    
            /*
                返回服务端发送给客户端解密后的数据消息
                packet:接收服务端数据包
            */
            public static NetPacket S2CPacketSend(byte[] packet, byte sId, byte mId)
            {
                uint key = (UInt16)((sId * 10 + mId) % _len); //key由前后端定好的规则算出(此处的sId和mId分别为用于前后端通信,收发数据包的协议号和子协议号)
                NetPacket s2CPacket;
    
                s2CPacket.sId = sId;//存入协议号
                s2CPacket.mId = mId;//存子协议号
                s2CPacket.packet = new byte[packet.Length];
    
                for (int i = 0; i < s2CPacket.packet.Length; i++, key = (key + 1) % _len)
                {
                    s2CPacket.packet[i] = (byte)(packet[i] ^ _passArr[key]);//对数据包的每个字节与秘钥盒对应的key的索引进行异或(加密)
                }
                return s2CPacket;
            }
    
            //打印数组
            public static void PrintArray(byte[] packet)
            {
                foreach (var value in packet)
                {
                    Console.Write(value + ",");
                }
            }
    
        }
    }
    
    

    结果如下:


    打印结果.png

    ps:客户端发送给服务端数据的前2位分别是index的高8位和低8位,其后才是数据位

    相关文章

      网友评论

          本文标题:简单的网络数据加密算法

          本文链接:https://www.haomeiwen.com/subject/hpimictx.html