/** * 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.SatisfiesCofactor()) { 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); }
public virtual ECPoint DecodePoint(byte[] encoded) { ECPoint eCPoint = null; int num = (FieldSize + 7) / 8; byte b = encoded[0]; switch (b) { case 0: if (encoded.Length != 1) { throw new ArgumentException("Incorrect length for infinity encoding", "encoded"); } eCPoint = Infinity; break; case 2: case 3: { if (encoded.Length != num + 1) { throw new ArgumentException("Incorrect length for compressed encoding", "encoded"); } int yTilde = b & 1; BigInteger x3 = new BigInteger(1, encoded, 1, num); eCPoint = DecompressPoint(yTilde, x3); if (!eCPoint.SatisfiesCofactor()) { throw new ArgumentException("Invalid point"); } break; } case 4: { if (encoded.Length != 2 * num + 1) { throw new ArgumentException("Incorrect length for uncompressed encoding", "encoded"); } BigInteger x2 = new BigInteger(1, encoded, 1, num); BigInteger y = new BigInteger(1, encoded, 1 + num, num); eCPoint = ValidatePoint(x2, y); break; } case 6: case 7: { if (encoded.Length != 2 * num + 1) { throw new ArgumentException("Incorrect length for hybrid encoding", "encoded"); } BigInteger x = new BigInteger(1, encoded, 1, num); BigInteger bigInteger = new BigInteger(1, encoded, 1 + num, num); if (bigInteger.TestBit(0) != (b == 7)) { throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded"); } eCPoint = ValidatePoint(x, bigInteger); break; } default: throw new FormatException("Invalid point encoding " + b); } if (b != 0 && eCPoint.IsInfinity) { throw new ArgumentException("Invalid infinity encoding", "encoded"); } return(eCPoint); }