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