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