/**
* Decode a point on this curve from its ASN.1 encoding. The different
* encodings are taken account of, including point compression for
* <code>F<sub>p</sub><code> (X9.62 s 4.2.1 pg 17).
* @return The decoded point.
*/
public override ECPoint DecodePoint(
byte[] encoded)
{
ECPoint p = null;
switch (encoded[0])
{
// compressed
case 0x02:
case 0x03:
int ytilde = encoded[0] & 1;
byte[] i = new byte[encoded.Length - 1];
Array.Copy(encoded, 1, i, 0, i.Length);
ECFieldElement x = new FpFieldElement(this.q, new BigInteger(1, i));
ECFieldElement alpha = x.Multiply(x.Square()).Add(x.Multiply(a).Add(b));
ECFieldElement beta = alpha.Sqrt();
//
// if we can't find a sqrt we haven't got a point on the
// curve - run!
//
if (beta == null)
{
throw new ArithmeticException("Invalid point compression");
}
BigInteger betaValue = beta.ToBigInteger();
int bit0 = betaValue.TestBit(0) ? 1 : 0;
if (bit0 != ytilde)
{
// Use the other root
beta = new FpFieldElement(q, q.Subtract(betaValue));
}
p = new FpPoint(this, x, beta, true);
break;
case 0x04:
byte[] xEnc = new byte[(encoded.Length - 1) / 2];
byte[] yEnc = new byte[(encoded.Length - 1) / 2];
Array.Copy(encoded, 1, xEnc, 0, xEnc.Length);
Array.Copy(encoded, xEnc.Length + 1, yEnc, 0, yEnc.Length);
p = new FpPoint(this,
new FpFieldElement(this.q, new BigInteger(1, xEnc)),
new FpFieldElement(this.q, new BigInteger(1, yEnc)));
break;
default:
throw new FormatException("Invalid point encoding " + encoded[0]);
}
return(p);
}