public static void InitRC4Encryption(byte[] secretKey, byte[] pubKeyIn, int inOffset, byte[] pubKeyOut, int outOffset, out byte[] rc4keyIn, out byte[] rc4keyOut)
        {
            byte[] digest = new byte[RTMPConst.SHA256_DIGEST_LENGTH];

            System.Security.Cryptography.HMAC hmac = System.Security.Cryptography.HMACSHA256.Create("HMACSHA256");
            hmac.Key = secretKey;

            byte[] actualpubKeyIn = new byte[128];
            Array.Copy(pubKeyIn, inOffset, actualpubKeyIn, 0, 128);
            digest = hmac.ComputeHash(actualpubKeyIn);

            rc4keyOut = new byte[16];
            Array.Copy(digest, rc4keyOut, 16);
            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "[CDR.LibRTMP.RTMPHelper] RC4 Out Key: ");
            LibRTMPLogger.LogHex(LibRTMPLogLevel.Trace, rc4keyOut, 0, 16);

            hmac     = System.Security.Cryptography.HMACSHA256.Create("HMACSHA256");
            hmac.Key = secretKey;

            byte[] actualpubKeyOut = new byte[128];
            Array.Copy(pubKeyOut, outOffset, actualpubKeyOut, 0, 128);
            digest = hmac.ComputeHash(actualpubKeyOut);

            rc4keyIn = new byte[16];
            Array.Copy(digest, rc4keyIn, 16);
            LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "[CDR.LibRTMP.RTMPHelper] RC4 In Key: ");
            LibRTMPLogger.LogHex(LibRTMPLogLevel.Trace, rc4keyIn, 0, 16);
        }
Exemple #2
0
        public void Dump(LibRTMPLogLevel loglevel = LibRTMPLogLevel.Trace)
        {
            if (type == AMFDataType.AMF_INVALID)
            {
                LibRTMPLogger.Log(loglevel, "AMFObjectProperty.Dump: Property: INVALID");
                return;
            }

            if (type == AMFDataType.AMF_NULL)
            {
                LibRTMPLogger.Log(loglevel, "AMFObjectProperty.Dump: Property: NULL");
                return;
            }

            if (type == AMFDataType.AMF_OBJECT)
            {
                LibRTMPLogger.Log(loglevel, "AMFObjectProperty.Dump : Property: OBJECT ====>");
                objVal.Dump();
                return;
            }

            string strRes = "no-name. ";

            if (stringName != string.Empty)
            {
                strRes = "Name: " + stringName + ",  ";
            }

            string strVal;

            switch (type)
            {
            case AMFDataType.AMF_NUMBER:
                strVal = string.Format("NUMBER: {0}", numVal);
                break;

            case AMFDataType.AMF_BOOLEAN:
                strVal = string.Format("BOOLEAN: {0}", numVal == 1.0 ? "TRUE" : "FALSE");
                break;

            case AMFDataType.AMF_STRING:
                strVal = string.Format("STRING: {0}", stringVal.Length < 256 ? stringVal : "Length: " + stringVal.Length.ToString());
                break;

            default:
                strVal = string.Format("INVALID TYPE {0}", type);
                break;
            } //switch

            strRes += strVal;
            LibRTMPLogger.Log(loglevel, string.Format("Property: {0}", strRes));
        }
        public static uint GetDHOffset2(byte[] handshake, int bufferoffset, uint len)
        {
            uint offset = 0;

            bufferoffset += 768;

            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset];

            uint res = (offset % 632) + 8;

            if (res + 128 > 767)
            {
                string msg = string.Format("[CDR.LibRTMP.RTMPHelper] Couldn't calculate correct DH offset (got {0}), exiting!", res);
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, msg);
                throw new Exception(msg);
            }
            return(res);
        }
        public static uint GetDigestOffset2(byte[] handshake, int bufferoffset, uint len)
        {
            uint offset = 0;

            bufferoffset += 772;
            //assert(12 <= len);

            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset];// (*ptr);

            uint res = (offset % 728) + 776;

            if (res + 32 > 1535)
            {
                string msg = string.Format("[CDR.LibRTMP.RTMPHelper] Couldn't calculate correct digest offset (got {0}), exiting", res);
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, msg);
                throw new Exception(msg);
            }
            return(res);
        }
        public static uint GetDigestOffset1(byte[] handshake, int bufferoffset, uint len)
        {
            int offset = 0;

            bufferoffset += 8;

            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset];

            int res = (offset % 728) + 12;

            if (res + 32 > 771)
            {
                string msg = string.Format("[CDR.LibRTMP.RTMPHelper] Couldn't calculate digest offset (got {0}), exiting!", res);
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, msg);
                throw new Exception(msg);
            }

            return((uint)res);
        }
        public static uint GetDHOffset1(byte[] handshake, int bufferoffset, uint len)
        {
            int offset = 0;

            bufferoffset += 1532;

            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset]; bufferoffset++;
            offset += handshake[bufferoffset];// (*ptr);

            int res = (offset % 632) + 772;

            if (res + 128 > 1531)
            {
                string msg = string.Format("[CDR.LibRTMP.RTMPHelper] Couldn't calculate DH offset (got {0}), exiting!", res);
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, msg);
                throw new Exception(msg);
            }

            return((uint)res);
        }
        /// <summary>
        /// Check is the key is valid see RFC 2631, Section 2.1.5, http://www.ietf.org/rfc/rfc2631.txt
        /// </summary>
        public static bool IsValidPublicKey(Org.BouncyCastle.Math.BigInteger y, Org.BouncyCastle.Math.BigInteger p, Org.BouncyCastle.Math.BigInteger q)
        {
            Org.BouncyCastle.Math.BigInteger bn;

            // y must lie in [2,p-1]
            // check y < 2 then failed
            bn = new Org.BouncyCastle.Math.BigInteger("2");
            if (y.CompareTo(bn) < 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.RTMPHelper.IsValidPublicKey] DH public key must be at least 2");
                return(false);
            }

            // y must lie in [2,p-1]
            bn = new Org.BouncyCastle.Math.BigInteger(p.ToString());
            bn = bn.Subtract(new Org.BouncyCastle.Math.BigInteger("1"));
            if (y.CompareTo(bn) > 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.RTMPHelper.IsValidPublicKey] DH public key must be at most p-2");
                return(false);
            }


            // Verify with Sophie-Germain prime
            //
            // This is a nice test to make sure the public key position is calculated
            // correctly. This test will fail in about 50% of the cases if applied to
            // random data.
            bn = y.ModPow(q, p);
            if (bn.CompareTo(new Org.BouncyCastle.Math.BigInteger("1")) != 0)
            {
                LibRTMPLogger.Log(LibRTMPLogLevel.Warning, "[CDR.LibRTMP.RTMPHelper.IsValidPublicKey] DH public key does not fulfill y^q mod p = 1");
                return(false);
            }

            return(true);
        }
Exemple #8
0
        public void Encode(List <byte> output)
        {
            if (type == AMFDataType.AMF_INVALID)
            {
                return;
            }

            switch (type)
            {
            case AMFDataType.AMF_NUMBER:
                if (string.IsNullOrEmpty(stringName))
                {
                    RTMPHelper.EncodeNumber(output, NumberValue);
                }
                else
                {
                    RTMPHelper.EncodeNumber(output, stringName, NumberValue);
                }
                break;

            case AMFDataType.AMF_BOOLEAN:
                if (string.IsNullOrEmpty(stringName))
                {
                    RTMPHelper.EncodeBoolean(output, BooleanValue);
                }
                else
                {
                    RTMPHelper.EncodeBoolean(output, stringName, BooleanValue);
                }
                break;

            case AMFDataType.AMF_STRING:
                if (string.IsNullOrEmpty(stringName))
                {
                    RTMPHelper.EncodeString(output, StringValue);
                }
                else
                {
                    RTMPHelper.EncodeString(output, stringName, StringValue);
                }
                break;

            case AMFDataType.AMF_NULL:
                output.Add(0x05);
                break;

            case AMFDataType.AMF_OBJECT:
                if (!string.IsNullOrEmpty(stringName))
                {
                    short length = System.Net.IPAddress.HostToNetworkOrder((short)stringName.Length);
                    output.AddRange(BitConverter.GetBytes(length));
                    output.AddRange(Encoding.ASCII.GetBytes(stringName));
                }
                objVal.Encode(output);
                break;

            default:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("AMFObjectProperty.Encode invalid type: {0}", type));
                break;
            } //switch
        }
Exemple #9
0
        public int Decode(byte[] buffer, int bufferOffset, int size, bool bDecodeName)
        {
            int originalSize = size;

            if (size == 0 || buffer == null)
            {
                return(-1);
            }

            if (buffer[bufferOffset] == 0x05)
            {
                type = AMFDataType.AMF_NULL;
                return(1);
            }

            if (bDecodeName && size < 4) // at least name (length + at least 1 byte) and 1 byte of data
            {
                return(-1);
            }

            if (bDecodeName)
            {
                ushort nNameSize = RTMPHelper.ReadInt16(buffer, bufferOffset);
                if (nNameSize > size - (short)sizeof(short))
                {
                    return(-1);
                }

                stringName    = RTMPHelper.ReadString(buffer, bufferOffset);
                size         -= sizeof(short) + stringName.Length;
                bufferOffset += sizeof(short) + stringName.Length;
            }

            if (size == 0)
            {
                return(-1);
            }

            size--;

            int stringSize = 0;
            int result     = 0;

            switch (buffer[bufferOffset])
            {
            case (byte)AMFDataType.AMF_NUMBER:
                if (size < (int)sizeof(double))
                {
                    return(-1);
                }
                numVal = RTMPHelper.ReadNumber(buffer, bufferOffset + 1);
                size  -= sizeof(double);
                type   = AMFDataType.AMF_NUMBER;
                break;

            case (byte)AMFDataType.AMF_BOOLEAN:
                if (size < 1)
                {
                    return(-1);
                }
                numVal = Convert.ToDouble(RTMPHelper.ReadBool(buffer, bufferOffset + 1));
                size--;
                type = AMFDataType.AMF_BOOLEAN;
                break;

            case (byte)AMFDataType.AMF_STRING:
                stringSize = RTMPHelper.ReadInt16(buffer, bufferOffset + 1);
                if (size < stringSize + (int)sizeof(short))
                {
                    return(-1);
                }
                stringVal = RTMPHelper.ReadString(buffer, bufferOffset + 1);
                size     -= sizeof(short) + stringSize;
                type      = AMFDataType.AMF_STRING;
                break;

            case (byte)AMFDataType.AMF_OBJECT:
                objVal = new AMFObject();
                result = objVal.Decode(buffer, bufferOffset + 1, size, true);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_MOVIECLIP:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMF_MOVIECLIP reserved!");
                return(-1);

            case (byte)AMFDataType.AMF_NULL:
            case (byte)AMFDataType.AMF_UNDEFINED:
            case (byte)AMFDataType.AMF_UNSUPPORTED:
                type = AMFDataType.AMF_NULL;
                break;

            case (byte)AMFDataType.AMF_REFERENCE:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMF_REFERENCE not supported!");
                return(-1);

            case (byte)AMFDataType.AMF_ECMA_ARRAY:
                size -= 4;

                // next comes the rest, mixed array has a final 0x000009 mark and names, so its an object
                objVal = new AMFObject();
                result = objVal.Decode(buffer, bufferOffset + 5, size, true);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_OBJECT_END:
                return(-1);

            case (byte)AMFDataType.AMF_STRICT_ARRAY:
                int nArrayLen = RTMPHelper.ReadInt32(buffer, bufferOffset + 1);
                size -= 4;

                objVal = new AMFObject();
                result = objVal.DecodeArray(buffer, bufferOffset + 5, size, nArrayLen, false);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_DATE:
                if (size < 10)
                {
                    return(-1);
                }
                date          = RTMPHelper.ReadNumber(buffer, bufferOffset + 1);
                dateUTCOffset = RTMPHelper.ReadInt16(buffer, bufferOffset + 9);
                size         -= 10;
                break;

            case (byte)AMFDataType.AMF_LONG_STRING:
                stringSize = RTMPHelper.ReadInt32(buffer, bufferOffset + 1);
                if (size < stringSize + 4)
                {
                    return(-1);
                }
                stringVal = RTMPHelper.ReadLongString(buffer, bufferOffset + 1);
                size     -= (4 + stringSize);
                type      = AMFDataType.AMF_STRING;
                break;

            case (byte)AMFDataType.AMF_RECORDSET:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_RECORDSET reserved!");
                return(-1);

            case (byte)AMFDataType.AMF_XML_DOC:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_XML_DOC not supported!");
                return(-1);

            case (byte)AMFDataType.AMF_TYPED_OBJECT:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_TYPED_OBJECT not supported!");
                return(-1);

            default:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("AMFObjectProperty.Decode Unknown datatype {0}", buffer[bufferOffset]));
                return(-1);
            } //switch

            return(originalSize - size);
        }
 public void Dump()
 {
     LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("[CDR.LibRTMP.RTMPPACKET] packet type: 0x%02x. channel: 0x%02x. info 1: %d info 2: %d. Body size: %lu. body: 0x%02x", packetType, channel, timeStamp, infoField2, bodySize, body != null ? body[0].ToString() : "0"));
 }