public static DHWrapper BeginDiffieHellman(ref byte[] pubKey, bool initiator = false) { var dh = new DHWrapper(); var size = dh.Keysize; byte[] newPubKey; if (initiator) { newPubKey = new byte[4 + size]; newPubKey[0] = 0x81; newPubKey[1] = 0x02; newPubKey[2] = 0x1D; newPubKey[3] = 0x02; pubKey = newPubKey; Buffer.BlockCopy(dh.PublicKey, 0, newPubKey, 4, size); return dh; } var index = pubKey.Length; newPubKey = new byte[index + 4 + size]; Buffer.BlockCopy(pubKey,0,newPubKey,0,index); var byte2 = (byte) (KEY_SIZE - size); if (byte2 > 2) { Logger.WARN("Generation DH key with less of 126 bytes!"); byte2 = 2; } byte2 = (byte) (2 - byte2); newPubKey[index++] = 0x81; newPubKey[index++] = byte2; newPubKey[index++] = 0x0D; newPubKey[index++] = 0x02; Buffer.BlockCopy(dh.PublicKey, 0, newPubKey, index, size); pubKey = newPubKey; return dh; }
private bool PerformHandshakeStage1(bool encrypted) { OutputBuffer.WriteByte((byte)(encrypted ? 6 : 3)); _pOutputBuffer=new byte[1536]; var rand = new Random(); for (var i = 0; i < 1536; i++) { _pOutputBuffer[i] = (byte) (rand.Next()%256); } _pOutputBuffer[0] = _pOutputBuffer[1] = _pOutputBuffer[2] = _pOutputBuffer[3] = 0; // 5. Put the flash version. We impersonate with 9.0.124.2 _pOutputBuffer[4] = 9; _pOutputBuffer[5] = 0; _pOutputBuffer[6] = 124; _pOutputBuffer[7] = 2; var clientDHOffset = GetDHOffset(_pOutputBuffer, _usedScheme); _pDHWrapper = new DHWrapper(1024); _pClientPublicKey = _pDHWrapper.PublicKey; Buffer.BlockCopy(_pClientPublicKey, 0, _pOutputBuffer, (int)clientDHOffset, 128); var clientDigestOffset = GetDigestOffset(_pOutputBuffer, _usedScheme); var pTempBuffer = new byte[1536 - 32]; Buffer.BlockCopy(_pOutputBuffer, 0, pTempBuffer, 0, (int)clientDigestOffset); Buffer.BlockCopy(_pOutputBuffer, (int) (clientDigestOffset + 32), pTempBuffer, (int)clientDigestOffset, (int) (1536 - clientDigestOffset - 32)); //var pTempHash = new byte[512]; var pTempHash = HMACsha256(pTempBuffer,1536-32,GenuineFpKey,30 ); // Hmacsha256.ComputeHash(pTempBuffer, 0,1536 - 32); Buffer.BlockCopy(pTempHash, 0, _pOutputBuffer, (int) clientDigestOffset,32); _pClientDigest = new byte[32]; Buffer.BlockCopy(pTempHash, 0, _pClientDigest, 0, 32); OutputBuffer.Write(_pOutputBuffer, 0, 1536); //_outputBuffer222.Write(_pOutputBuffer, 0, 1536); _pOutputBuffer = null; if (!EnqueueForOutbound(OutputBuffer)) { Logger.FATAL("Unable to signal ouput data"); return false; } _rtmpState = RTMPState.RTMP_STATE_CLIENT_REQUEST_SENT; return true; }
public Target(IPEndPoint address, Cookie cookie = null) { Address = address; IsPeer = cookie != null; if (address.Port == 0) { Address = new IPEndPoint(address.Address, RtmfpUtils.RTMFP_DEFAULT_PORT); } if (IsPeer) { DH = cookie.CookieComputing.DH; PublicKey = new byte[cookie.CookieComputing.Nonce.Length-7]; Buffer.BlockCopy(cookie.CookieComputing.Nonce, 7, PublicKey,0,PublicKey.Length); PublicKey[3] = 0x1D; // uint s = 0; Id = Sha256.ComputeHash(PublicKey, 0, PublicKey.Length); //Native.EVP_Digest(PublicKey, (uint) PublicKey.Length, Id, ref s, Native.EVP_sha256(), IntPtr.Zero); cookie.CookieComputing.DH = null; } }
public void Run() { if(DH == null) { DH = RtmfpUtils.BeginDiffieHellman(ref Nonce); return; } // Compute Diffie-Hellman secret SharedSecret = DH.CreateSharedKey(InitiatorKey); // Compute Keys RtmfpUtils.ComputeAsymetricKeys(SharedSecret, InitiatorNonce, Nonce, out DecryptKey,out EncryptKey); var pSession = _handshake?.CreateSession(Value); if (pSession != null) { pSession.Peer.UserState = this; } }
public CookieComputing(OutboundHandshake handshake) { Nonce = new byte[0]; DH = RtmfpUtils.BeginDiffieHellman(ref Nonce, true); }
public override void PacketHandler(N2HBinaryReader reader) { if(Checked){ lock (Writer) { base.PacketHandler(reader); } return; } var marker = reader.ReadByte(); if (marker != 0x0b) { Logger.FATAL("Marker hand shake wrong:should be 0b and not {0:X}", marker); return; } var time = reader.ReadUInt16(); var type = reader.ReadByte(); var length = reader.ReadUInt16(); byte[] tag; Logger.Debug("handshake {0:X} len:{1}",type,length); switch (type) { case 0x70: tag = reader.ReadBytes(reader.ReadByte()); var cookieBytes = reader.ReadBytes(reader.ReadByte()); var targetCertificat = reader.ReadBytes((int)reader.BaseStream.GetAvaliableByteCounts()); var nonce = new byte[0]; _dh = RtmfpUtils.BeginDiffieHellman(ref nonce, true); Peer.Id = Target.Sha256.ComputeHash(nonce, 0, nonce.Length); HandShake38(cookieBytes, nonce); _handshake = () => HandShake38(cookieBytes, nonce); break; case 0x71: tag = reader.ReadBytes(reader.ReadByte()); var flag = reader.ReadByte(); var address = new IPEndPoint(new IPAddress(reader.ReadBytes(4)), reader.ReadInt16()); Target.Address.Port = address.Port; Logger.Debug("redirect to {0}",address.ToString()); Handler.FarProtocol.IOHandler.Socket.Connect(Target.Address); _handshake(); break; case 0x78: FarId = reader.ReadUInt32(); var targetNonce = reader.ReadBytes((int)reader.Read7BitLongValue()); var must58 = reader.ReadByte(); Debug.WriteLineIf(must58!=0x58,$"must58!{must58}"); var key = new byte[RtmfpUtils.KEY_SIZE]; Buffer.BlockCopy(targetNonce, targetNonce.Length - RtmfpUtils.KEY_SIZE, key, 0, RtmfpUtils.KEY_SIZE); var sharedSecret = _dh.CreateSharedKey(key); byte[] decryptKey; byte[] encryptKey; RtmfpUtils.ComputeAsymetricKeys(sharedSecret, _certificat, targetNonce, out encryptKey, out decryptKey); Checked = true; _handshakeTimeoutTimer.Stop(); AesEncrypt = new AESEngine(encryptKey, AESEngine.Direction.ENCRYPT); AesDecrypt = new AESEngine(decryptKey); PrevAesType = AESEngine.AESType.DEFAULT; Application = Handler.Application; Handler.CreateSession(Peer, null); break; default: break; } }
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; }