Example #1
0
 public override bool EnqueueForOutbound(MemoryStream outputStream,int offset = 0)
 {
     var pOutputBuffer = _nearProtocol.OutputBuffer;
     if (pOutputBuffer == null) return true;
     var buffer = new BufferWithOffset(pOutputBuffer,true) {Offset = (int) _skipBytes};
     Utils.RC4(buffer, _pKeyOut, buffer.Length);
     _skipBytes = 0;
     buffer.Offset = 0;
     OutputBuffer.Write(buffer.Buffer, buffer.Offset, buffer.Length);
     return _farProtocol == null || _farProtocol.EnqueueForOutbound(outputStream);
 }
        }; // 62

        public static byte[] HMACsha256(BufferWithOffset pData, uint dataLength, byte[] key, uint keyLength)
        {
            byte[] _key;
            if (keyLength != key.Length)
            {
                _key = new byte[keyLength];
                Buffer.BlockCopy(key, 0, _key, 0, (int) keyLength);
            }
            else
                _key = key;
            var hmac = new HMACSHA256(_key);
           return hmac.ComputeHash(pData.Buffer, pData.Offset, (int)dataLength);
        }
Example #3
0
 //public override bool SignalOutputData(MemoryStream ouputStream = null)
 //{
 //    while (Protocol.OutputBuffer!=null)
 //    {
 //        var outputBuffer = Protocol.OutputBuffer;
 //        SocketError errorCode;
 //        var sendCount = OutboundFd.Send(outputBuffer.GetBuffer(),
 //            (int)outputBuffer.Consumed,
 //            (int)outputBuffer.Length, SocketFlags.None, out errorCode);
 //        if (errorCode!=SocketError.Success || sendCount <= 0)
 //        {
 //            Logger.FATAL("Unable to send data.{0}:{1}", NearIP, NearPort);
 //            IOHandlerManager.EnqueueForDelete(this);
 //            break;
 //        }
 //        outputBuffer.Ignore((uint)sendCount);
 //    }
 //    //Protocol.OutputBuffer.Recycle(true);
 //    return true;
 //}
 public override bool SignalOutputData(EndPoint address, MemoryStream outputStream)
 {
     var outputBuffer = new BufferWithOffset(outputStream);
     while (outputBuffer.Length>0)
     {
         var sendCount = Socket.SendTo(outputBuffer.Buffer,
             outputBuffer.Offset,
             outputBuffer.Length, SocketFlags.None, address);
         if (sendCount < 0)
         {
             Logger.FATAL("Unable to send data.{0}:{1}", NearIP, NearPort);
             IOHandlerManager.EnqueueForDelete(this);
             break;
         }
         outputBuffer.Offset += sendCount;
     }
     outputStream.SetLength(0);
     return true;
 }
Example #4
0
        public static void RC4(BufferWithOffset buffer, RC4_KEY key, long length)
        {
            var   state = new byte[256];
            short counter;
            byte  x = key.x;
            byte  y = key.y;

            Buffer.BlockCopy(key.data, 0, state, 0, 256);
            for (counter = 0; counter < length; counter++)
            {
                x = (byte)((x + 1) % 256);
                y = (byte)((state[x] + y) % 256);
                var temp = state[x];
                state[x] = state[y];
                state[y] = temp;
                var xorIndex = (byte)((state[x] + state[y]) % 256);
                buffer[counter] ^= state[xorIndex];
            }
            Buffer.BlockCopy(state, 0, buffer.Buffer, 0, 256);
            key.x = x;
            key.y = y;
        }
        //public override bool AllowNearProtocol(ulong type)
        //{
        //    Logger.FATAL("This protocol doesn't allow any near protocols");
        //    return false;
        //}

        //public override bool AllowFarProtocol(ulong type)
        //{
        //    return type == ProtocolTypes.PT_TCP || type == ProtocolTypes.PT_RTMPE || type == ProtocolTypes.PT_INBOUND_SSL ||
        //           type == ProtocolTypes.PT_INBOUND_HTTP_FOR_RTMP;
        //}
        public void ChunkAmfMessage( Header header,BufferWithOffset input, MemoryStream output)
        {
            var channel = GetChannel(header.ChannelId);
            long available;
            while ((available = input.Length) != 0)
            {
                header.Write(channel, output);
                if (available > _outboundChunkSize)
                {
                    available = _outboundChunkSize;
                }
                output.Write(input.Buffer, input.Offset, (int)available);
                channel.lastOutProcBytes += (uint)available;
                input.Offset += (int)available;
            }
            channel.lastOutProcBytes = 0;
        }
 protected override bool FeedOtherType()
 {
     if (_currentFrame.Type == MediaFrameType.Message && OutStreams.Last() is BaseOutNetRTMPStream)
     {
         if (!_pFile.SeekTo(_currentFrame.Start))
         {
             FATAL("Unable to seek to position {0}", _currentFrame.Start);
             return false;
         }
         var buffer = new BufferWithOffset(_amf0Reader.BaseStream, false, (int) _currentFrame.Length);
         SendStreamMessage(buffer);
         _pFile.Position = _currentFrame.Start + _currentFrame.Length;
         //message.Recycle();
         _currentFrameIndex++;
         return true;
     }
     //todo 这里会导致播放中断,对于其他协议要修改
     Paused = true;
     return base.FeedOtherType();
 }
 public OutboundConnectivity(bool forceTcp, RtspProtocol pRTSPProtocol)
 {
     _forceTcp = forceTcp;
     _rtspProtocol = pRTSPProtocol;
     _dataMessage = new MsgHdr();
     _rtcpMessage = new MsgHdr {Buffers = new[] {new byte[28]}};
     _rtcpMessage.Buffers[0][0] = 0x80;
     _rtcpMessage.Buffers[0][1] = 0xc8;
     _rtcpMessage.Buffers[0].Write(2, (ushort) 6);
     _rtcpNTP = new BufferWithOffset(_rtcpMessage.Buffers[0], 8);
     _rtcpRTP = new BufferWithOffset(_rtcpMessage.Buffers[0], 16);
     _rtcpSPC = new BufferWithOffset(_rtcpMessage.Buffers[0], 20);
     _rtcpSOC = new BufferWithOffset(_rtcpMessage.Buffers[0], 24);
     _startupTime = DateTime.Now;
 }
Example #8
0
        public void Decrypt(BufferWithOffset encryptArray)
        {
            int len = encryptArray.Length;
            int turn = 0;
            int start = 0, end;
            Array.Clear(_iv, 0, _iv.Length);
            while (len >= AES_BLOCK_SIZE)
            {
                start = AES_BLOCK_SIZE*turn;
                //end = AES_BLOCK_SIZE*turn + 15;
                Buffer.BlockCopy(encryptArray.Buffer, encryptArray.Offset + start, tmp, 0, AES_BLOCK_SIZE);
                Decrypt16Byte(encryptArray, start, _key);

                for (int n = 0; n < AES_BLOCK_SIZE; ++n)
                {
                    encryptArray[start + n] ^= _iv[n];
                    //_iv[n] = encryptArray[start + n];
                }
                Buffer.BlockCopy(tmp, 0, _iv, 0, AES_BLOCK_SIZE);
                //for (int n = 0; n < AES_BLOCK_SIZE; ++n)
                //    iv[n] = encryptArray[start + n];

                len -= AES_BLOCK_SIZE;
                turn++;
            }
            
            if (len > 0)
            {
                start += AES_BLOCK_SIZE*turn;
                Decrypt16Byte(encryptArray, start, _key); //==temp 只有16个字节 (已经处理了)

                for (int n = 0; n < len; ++n)
                    encryptArray[start + n]  ^= _iv[n];
                //for (int n = 0; n < AES_BLOCK_SIZE; ++n)
                //    iv[n] = encryptArray[start + n];
            }
     
            //memcpy(ivec,iv,AES_BLOCK_SIZE);
        }
 public uint GetDigestOffset(BufferWithOffset pBuffer, byte schemeNumber)
 {
     switch (schemeNumber)
     {
         case 0:
             return GetDigestOffset0(pBuffer);
         case 1:
             return GetDigestOffset1(pBuffer);
         default:
             WARN("Invalid scheme number: {0}. Defaulting to 0", schemeNumber);
             return GetDigestOffset0(pBuffer);
     }
 }
 private bool ValidateClientScheme(InputStream inputBuffer, byte scheme)
 {
     var pBuffer = new BufferWithOffset(inputBuffer);
     var clientDigestOffset = GetDigestOffset(pBuffer, scheme);
     var pTempBuffer = new byte[1536 - 32];
     Buffer.BlockCopy(pBuffer.Buffer, pBuffer.Offset, pTempBuffer, 0, (int)clientDigestOffset);
     Buffer.BlockCopy(pBuffer.Buffer, (int)(pBuffer.Offset + clientDigestOffset + 32), pTempBuffer, (int)clientDigestOffset, (int)(1536 - clientDigestOffset - 32));
     var pTempHash = HMACsha256(pTempBuffer, 1536 - 32, GenuineFpKey, 30);//Hmacsha256.ComputeHash(pTempBuffer, 0, 1536 - 32);
     for (var i = 0; i < 32; i++)
         if (pBuffer[(int)(clientDigestOffset + i)] != pTempHash[i])
             return false;
     return true;
 }
        bool PerformHandshake(InputStream buffer, bool encrypted)
        {
            if (!ValidateClient(buffer))
            {
                if (encrypted || _pProtocolHandler.ValidateHandshake)
                {
                    Logger.FATAL("Unable to validate client");
                    return false;
                }
                else
                {
                    Logger.WARN("Client not validated");
                    _validationScheme = 0;
                }
            }
            _pOutputBuffer = Utils.GenerateRandomBytes(3072);
            _pOutputBuffer.Write(0, (uint)DateTime.Now.SecondsFrom1970());
            _pOutputBuffer.Write(0, (uint)0);
            var serverBytes = Encoding.ASCII.GetBytes(Defines.HTTP_HEADERS_SERVER_US);
            for (var i = 0; i < 10; i++)
            {
                var index = Utils.Random.Next(0, 3072 - Defines.HTTP_HEADERS_SERVER_US_LEN);
                Buffer.BlockCopy(serverBytes, 0, _pOutputBuffer, index, serverBytes.Length);
            }

            var _pOutputBufferWithOffset = new BufferWithOffset(_pOutputBuffer);
            var pInputBuffer = new BufferWithOffset(buffer);
            var serverDHOffset = GetDHOffset(_pOutputBufferWithOffset, _validationScheme);
            var clientDHOffset = GetDHOffset(pInputBuffer, _validationScheme);
            var dhWrapper = new DHWrapper();
            var pubKeyIn = new byte[128];
            Buffer.BlockCopy(buffer.GetBuffer(), (int)(buffer.Position + clientDHOffset), pubKeyIn, 0, 128);
            var sharedkey = dhWrapper.CreateSharedKey(pubKeyIn);
            var pubKeyOut = dhWrapper.PublicKey;
            Buffer.BlockCopy(pubKeyOut, 0, _pOutputBuffer, (int)serverDHOffset, 128);
            if (encrypted)
            {
                _pKeyIn = new RC4_KEY();
                _pKeyOut = new RC4_KEY();
                Utils.InitRC4Encryption(sharedkey, pubKeyIn, pubKeyOut, _pKeyIn, _pKeyOut);
                var data = new byte[1536];
                Utils.RC4(data, _pKeyIn, 1536);
                Utils.RC4(data, _pKeyOut, 1536);
            }
            var serverDigestOffset = GetDigestOffset(_pOutputBufferWithOffset, _validationScheme);
            var pTempBuffer = new byte[1536 - 32];
            Buffer.BlockCopy(_pOutputBuffer, 0, pTempBuffer, 0, (int)serverDigestOffset);
            Buffer.BlockCopy(_pOutputBuffer, (int)serverDigestOffset + 32, pTempBuffer, (int)serverDigestOffset, (int)(1536 - serverDigestOffset - 32));
            var pTempHash = HMACsha256(pTempBuffer, 1536 - 32, GenuineFmsKey, 36);
            Buffer.BlockCopy(pTempHash, 0, _pOutputBuffer, (int)serverDigestOffset, 32);
            var keyChallengeIndex = GetDigestOffset(pInputBuffer, _validationScheme);
            pInputBuffer.Offset += (int)keyChallengeIndex;
            pTempHash = HMACsha256(pInputBuffer, 32, GenuineFmsKey, 68);
            Buffer.BlockCopy(_pOutputBuffer, 1536, pTempBuffer, 0, 1536 - 32);
            pTempBuffer = new HMACSHA256(pTempHash).ComputeHash(pTempBuffer, 0, 1536 - 32);
            Buffer.BlockCopy(pTempBuffer, 0, _pOutputBuffer, 1536 * 2 - 32, 32);
            OutputBuffer.WriteByte((byte)(encrypted ? 6 : 3));
            OutputBuffer.Write(_pOutputBuffer, 0, 3072);
            buffer.Recycle(true);
            if (!EnqueueForOutbound(OutputBuffer))
            {
                Logger.FATAL("Unable to signal outbound data");
                return false;
            }
            _rtmpState = RTMPState.RTMP_STATE_SERVER_RESPONSE_SENT;
            return true;
        }
Example #12
0
        public static void ToBytes(this string source, BufferWithOffset buffer)
        {
            var charArray = source.ToCharArray().Select(x => (byte)x).ToArray();

            Buffer.BlockCopy(charArray, 0, buffer.Buffer, buffer.Offset, charArray.Length);
        }
Example #13
0
        private void Decrypt16Byte(BufferWithOffset inArray,int start, UInt32[] key)
        {
            UInt32 s0, s1, s2, s3, t0, t1, t2, t3;

            ByteArrayToU32(inArray.Buffer, start+inArray.Offset, out s0, out s1, out s2, out s3);
            s0 = s0 ^ key[0];
            s1 = s1 ^ key[1];
            s2 = s2 ^ key[2];
            s3 = s3 ^ key[3];
            int r = rounds >> 1;
            int i = 0;
            for (;;)
            {
                t0 =
                    Td0[(s0 >> 24)] ^
                    Td1[(s3 >> 16) & 0xff] ^
                    Td2[(s2 >> 8) & 0xff] ^
                    Td3[(s1) & 0xff] ^
                    key[4 + 8*i];
                t1 =
                    Td0[(s1 >> 24)] ^
                    Td1[(s0 >> 16) & 0xff] ^
                    Td2[(s3 >> 8) & 0xff] ^
                    Td3[(s2) & 0xff] ^
                    key[5 + 8*i];
                t2 =
                    Td0[(s2 >> 24)] ^
                    Td1[(s1 >> 16) & 0xff] ^
                    Td2[(s0 >> 8) & 0xff] ^
                    Td3[(s3) & 0xff] ^
                    key[6 + 8*i];
                t3 =
                    Td0[(s3 >> 24)] ^
                    Td1[(s2 >> 16) & 0xff] ^
                    Td2[(s1 >> 8) & 0xff] ^
                    Td3[(s0) & 0xff] ^
                    key[7 + 8*i];
                i++;
                if (--r == 0)
                {
                    break;
                }

                s0 =
                    Td0[(t0 >> 24)] ^
                    Td1[(t3 >> 16) & 0xff] ^
                    Td2[(t2 >> 8) & 0xff] ^
                    Td3[(t1) & 0xff] ^
                    key[0 + 8*i];
                s1 =
                    Td0[(t1 >> 24)] ^
                    Td1[(t0 >> 16) & 0xff] ^
                    Td2[(t3 >> 8) & 0xff] ^
                    Td3[(t2) & 0xff] ^
                    key[1 + 8*i];
                s2 =
                    Td0[(t2 >> 24)] ^
                    Td1[(t1 >> 16) & 0xff] ^
                    Td2[(t0 >> 8) & 0xff] ^
                    Td3[(t3) & 0xff] ^
                    key[2 + 8*i];
                s3 =
                    Td0[(t3 >> 24)] ^
                    Td1[(t2 >> 16) & 0xff] ^
                    Td2[(t1 >> 8) & 0xff] ^
                    Td3[(t0) & 0xff] ^
                    key[3 + 8*i];
            }

            s0 =
                (Td4[(t0 >> 24)] << 24) ^
                (Td4[(t3 >> 16) & 0xff] << 16) ^
                (Td4[(t2 >> 8) & 0xff] << 8) ^
                (Td4[(t1) & 0xff]) ^
                key[0 + 8*i];

            s1 =
                (Td4[(t1 >> 24)] << 24) ^
                (Td4[(t0 >> 16) & 0xff] << 16) ^
                (Td4[(t3 >> 8) & 0xff] << 8) ^
                (Td4[(t2) & 0xff]) ^
                key[1 + 8*i];

            s2 =
                (Td4[(t2 >> 24)] << 24) ^
                (Td4[(t1 >> 16) & 0xff] << 16) ^
                (Td4[(t0 >> 8) & 0xff] << 8) ^
                (Td4[(t3) & 0xff]) ^
                key[2 + 8*i];

            s3 =
                (Td4[(t3 >> 24)] << 24) ^
                (Td4[(t2 >> 16) & 0xff] << 16) ^
                (Td4[(t1 >> 8) & 0xff] << 8) ^
                (Td4[(t0) & 0xff]) ^
                key[3 + 8*i];

            U32ToByteArray(s0, s1, s2, s3, inArray.Buffer, start+inArray.Offset);
        }
Example #14
0
 public uint GetDHOffset0(BufferWithOffset pBuffer)
 {
     var offset = (uint)(pBuffer[1532] + pBuffer[1533] + pBuffer[1534] + pBuffer[1535]);
     offset = offset % 632;
     offset = offset + 772;
     if (offset + 128 >= 1536) ASSERT("Invalid DH offset");
     return offset;
 }
 private bool VerifyServer(InputStream inputBuffer)
 {
     var pBuffer = new BufferWithOffset(inputBuffer);
     pBuffer.Offset++;
     var serverDigestPos = GetDigestOffset(pBuffer, _usedScheme);
     var pTempBuffer = new byte[1536 - 32];
     Buffer.BlockCopy(inputBuffer.GetBuffer(), pBuffer.Offset, pTempBuffer, 0, (int)serverDigestPos);
     Buffer.BlockCopy(inputBuffer.GetBuffer(), (int)(pBuffer.Offset+serverDigestPos + 32), pTempBuffer, (int)serverDigestPos, (int)(1536 - serverDigestPos - 32));
     var pDigest = HMACsha256(pTempBuffer, 1536 - 32, GenuineFmsKey, 36);
     for (var i = 0; i < 32; i++)
     {
         if (pDigest[i] != pBuffer[(int) (i + serverDigestPos)])
         {
             Logger.FATAL("Server not verified");
             return false;
         }
     }
     pBuffer.Offset += 1536;
     var pChallange = HMACsha256(_pClientDigest, 32, GenuineFmsKey, 68);
     pDigest = new HMACSHA256(pChallange).ComputeHash(pBuffer.Buffer, pBuffer.Offset, 1536 - 32);
     for (var i = 0; i < 32; i++)
     {
         if (pDigest[i] != pBuffer[i + 1536 - 32])
         {
             Logger.FATAL("Server not verified");
             return false;
         }
     }
     return true;
 }
Example #16
0
 public uint GetDHOffset1(BufferWithOffset pBuffer)
 {
     var offset = (uint)(pBuffer[768] + pBuffer[769] + pBuffer[770] + pBuffer[771]);
     offset = offset % 632;
     offset = offset + 8;
     if (offset + 128 >= 1536)
     {
         ASSERT("Invalid DH offset");
     }
     return offset;
 }
        private bool PerformHandshakeStage2(InputStream inputBuffer, bool encrypted)
        {
            if (encrypted || _pProtocolHandler.ValidateHandshake)
            {
                if (!VerifyServer(inputBuffer))
                {
                    Logger.FATAL("Unable to verify server");
                    return false;
                }
            }
            var pBuffer = new BufferWithOffset(inputBuffer);
            pBuffer.Offset++;
            var serverDHOffset = GetDHOffset(pBuffer, _usedScheme);
            if (_pDHWrapper == null)
            {
               Logger.FATAL("dh wrapper not initialized");
                return false;
            }
            var pubKey= new byte[128];
            Buffer.BlockCopy(pBuffer.Buffer, (pBuffer.Offset + (int)serverDHOffset), pubKey, 0, 128);

            var secretKey = _pDHWrapper.CreateSharedKey(pubKey);
	        
            if (encrypted)
            {
                _pKeyIn = new RC4_KEY();
                _pKeyOut = new RC4_KEY();
                var pubKeyIn = new byte[128];
                Buffer.BlockCopy(pBuffer.Buffer,(int) (pBuffer.Offset+serverDHOffset),pubKeyIn,0,128);
                Utils.InitRC4Encryption(secretKey, pubKeyIn, _pClientPublicKey,_pKeyIn,_pKeyOut);
            }
            var serverDigestOffset = GetDigestOffset(pBuffer, _usedScheme);
            _pOutputBuffer = Utils.GenerateRandomBytes(1536);

            pBuffer.Offset += (int)serverDigestOffset;
            var pChallangeKey = HMACsha256(pBuffer, 32, GenuineFpKey, 62);//Hmacsha256.ComputeHash(pBuffer.Buffer, pBuffer.Offset, 32);
            var pDigest = new HMACSHA256(pChallangeKey).ComputeHash(_pOutputBuffer, 0, 1536 - 32);
            Buffer.BlockCopy(pDigest,0,_pOutputBuffer,1536-32,32);
            OutputBuffer.Write(_pOutputBuffer, 0, 1536);
            _pOutputBuffer = null;
            _rtmpState = RTMPState.RTMP_STATE_DONE;
            return true;
        }
Example #18
0
 public uint GetDigestOffset0(BufferWithOffset pBuffer)
 {
     var offset = (uint)(pBuffer[8] + pBuffer[9] + pBuffer[10] + pBuffer[11]);
     offset = offset % 728;
     offset = offset + 12;
     if (offset + 32 >= 1536)
     {
         ASSERT("Invalid digest offset");
     }
     return offset;
 }
Example #19
0
 public bool SignalOutputData(EndPoint address, MemoryStream outputStream)
 {
     var outputBuffer = new BufferWithOffset(outputStream);
     while (outputBuffer.Length > 0)
     {
         var sendCount = Socket.SendTo(outputBuffer.Buffer,
             outputBuffer.Offset,
             outputBuffer.Length, SocketFlags.None, address);
         if (sendCount < 0)
         {
             break;
         }
         outputBuffer.Offset += sendCount;
     }
     outputStream.SetLength(0);
     return true;
 }
Example #20
0
 public uint GetDigestOffset1(BufferWithOffset pBuffer)
 {
     var offset = (uint)(pBuffer[772] + pBuffer[773] + pBuffer[774] + pBuffer[775]);
     offset = offset % 728;
     offset = offset + 776;
     if (offset + 32 >= 1536)
     {
         ASSERT("Invalid digest offset");
     }
     return offset;
 }
Example #21
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="inStr"></param>
        /// <param name="outStr"></param>
        /// <param name="length"></param>
        /// <param name="Encrypkey"></param>
        /// <param name="ivec"></param>
        /// <param name="enc">加密或解密的标志. 0为加密, 1为解密</param>
        /// <returns></returns>
        public void Encrypt(BufferWithOffset inArray)
        {
            int len = inArray.Length;
            //byte[] outArray = new byte[len%16 == 0 ? len : (len/16 + 1)*16];
            int turn = 0;
            int start = 0, end;
            Array.Clear(_iv,0,_iv.Length);
            while (len >= AES_BLOCK_SIZE)
            {
                start = AES_BLOCK_SIZE*turn;
                //end = AES_BLOCK_SIZE*turn + 15;
                for (int n = 0; n < AES_BLOCK_SIZE; n++)
                {
                    //outArray[start + n] = (byte)(inArray[start + n] ^ _iv[n]);
                    inArray[start + n] ^= _iv[n];
                }

                Encrypt16Byte(inArray.Buffer, start + inArray.Offset, _key);
                Buffer.BlockCopy(inArray.Buffer, start + inArray.Offset, _iv, 0, AES_BLOCK_SIZE);
                //for (int i = 0; i < AES_BLOCK_SIZE; i++)
                //    _iv[i] = outArray[start + i];
                len -= AES_BLOCK_SIZE;
                turn++;
            }
            if (len > 0)
            {
                start = AES_BLOCK_SIZE*turn;
                for (int n = 0; n < len; ++n) inArray[start + n] ^= _iv[n];
                    //outArray[start + n] = (byte)(inArray[start + n] ^ _iv[n]);
                for (int n = len; n < AES_BLOCK_SIZE; ++n)
                    inArray[start + n] = _iv[n];
                    //outArray[start + n] = _iv[n];
                Encrypt16Byte( inArray.Buffer, start + inArray.Offset, _key);
                /////////////////
                //var myTemp = Compute(outArray);
                /////////////////
                //for (int i = 0; i < AES_BLOCK_SIZE; i++)
                //    iv[i] = outArray[start + i]; //==? 是 start + 1 还是 start + i
            }
            //memcpy(ivec,iv,AES_BLOCK_SIZE);
            //Buffer.BlockCopy(outArray,0,inArray.Buffer,inArray.Offset,outArray.Length);
        }