/** * 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 virtual ECPoint DecodePoint(byte[] encoded) { ECPoint p = null; int expectedLength = (FieldSize + 7) / 8; byte type = encoded[0]; switch (type) { case 0x00: // infinity { if (encoded.Length != 1) { throw new ArgumentException("Incorrect length for infinity encoding", "encoded"); } p = Infinity; break; } case 0x02: // compressed case 0x03: // compressed { if (encoded.Length != (expectedLength + 1)) { throw new ArgumentException("Incorrect length for compressed encoding", "encoded"); } int yTilde = type & 1; BigInteger X = new BigInteger(1, encoded, 1, expectedLength); p = DecompressPoint(yTilde, X); if (!p.ImplIsValid(true, true)) { throw new ArgumentException("Invalid point"); } break; } case 0x04: // uncompressed { if (encoded.Length != (2 * expectedLength + 1)) { throw new ArgumentException("Incorrect length for uncompressed encoding", "encoded"); } BigInteger X = new BigInteger(1, encoded, 1, expectedLength); BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength); p = ValidatePoint(X, Y); break; } case 0x06: // hybrid case 0x07: // hybrid { if (encoded.Length != (2 * expectedLength + 1)) { throw new ArgumentException("Incorrect length for hybrid encoding", "encoded"); } BigInteger X = new BigInteger(1, encoded, 1, expectedLength); BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength); if (Y.TestBit(0) != (type == 0x07)) { throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded"); } p = ValidatePoint(X, Y); break; } default: throw new FormatException("Invalid point encoding " + type); } if (type != 0x00 && p.IsInfinity) { throw new ArgumentException("Invalid infinity encoding", "encoded"); } return(p); }