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); }
//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; }
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; }
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; }
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); }
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); }
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; }
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; }
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; }
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; }
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; }
/// <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); }