public override GroupElement DeriveElement()

in UProveCrypto/Math/bc/SubgroupGroupBCImpl.cs [241:307]


        public override GroupElement DeriveElement(
            byte[] context, 
            byte index, 
            out int counter)
        {
            byte[] ggen = new byte[] { (byte)0x67, (byte)0x67, (byte)0x65, (byte)0x6E };

            string hashAlg = null;
            int bitlength = qValue.BitLength;
            if (bitlength >= 512)
            {
                hashAlg = "SHA-512";
            }
            else if (bitlength >= 256)
            {
                hashAlg = "SHA-256";
            }
            else if (bitlength >= 160)
            {
                hashAlg = "SHA1";
            }
            else
            {
                throw new ArgumentException("q is too small");
            }
            HashFunction hash = new HashFunction(hashAlg);

            // references to "step x" in comments refer to alg from apendix A.2.3 of FIPS 186-3
            // int N = this.q.BitLength; // step 2 (usused)
            BCBigInt e = (pValue - BCBigInt.One) / qValue; // step 3
            
            // prepare U array =  context || "ggen" || index || count
            byte[] contextBytes = (context == null ? new byte[] {} : context);
            int contextLength = (contextBytes == null ? 0 : contextBytes.Length);
            byte[] U = new byte[contextLength + 
                ggen.Length + 2];
            int arrayIndex = 0;
            if (contextLength > 0)
            {
                Array.Copy(contextBytes, 0, U, arrayIndex, contextLength);
                arrayIndex += contextLength;
            }
            Array.Copy(ggen, 0, U, arrayIndex, ggen.Length);
            U[U.Length - 2] = index;

            byte count = 0; // step 4
            BCBigInt g = BCBigInt.Zero;
            while (g < BCBigInt.Two) // step 10
            {
                if (count == 255)
                {
                    throw new InvalidUProveArtifactException(
                        "can't derive an element; count exceeded");
                }
                count++; // step 5
                // complete U array
                U[U.Length - 1] = count; // step 7
                hash.HashWithoutFormatting(U);

                // BUGBUG: is that ok, will that wrap correctly?
                BCBigInt W = new BCBigInt(1, hash.Digest); // step 8 
                g = W.ModPow(e, pValue); // step 9
            }

            counter = count;
            return new SubgroupGroupElementBCImpl(g, pValue);
        }