content: package local.org.bouncycastle.asn1.x9;
  
  import java.math.BigInteger;
  
  import local.org.bouncycastle.asn1.ASN1EncodableVector;
  import local.org.bouncycastle.asn1.ASN1Integer;
  import local.org.bouncycastle.asn1.ASN1Object;
  import local.org.bouncycastle.asn1.ASN1OctetString;
  import local.org.bouncycastle.asn1.ASN1Primitive;
  import local.org.bouncycastle.asn1.ASN1Sequence;
  import local.org.bouncycastle.asn1.DERSequence;
  import local.org.bouncycastle.math.ec.ECCurve;
  import local.org.bouncycastle.math.ec.ECPoint;
  
  
  /**
   * ASN.1 def for Elliptic-Curve ECParameters structure. See
   * X9.62, for further details.
   */
  public class X9ECParameters
      extends ASN1Object
      implements X9ObjectIdentifiers
  {
      private static final BigInteger   ONE = BigInteger.valueOf(1);
  
      private X9FieldID           fieldID;
      private ECCurve             curve;
      private ECPoint             g;
      private BigInteger          n;
      private BigInteger          h;
      private byte[]              seed;
  
      private X9ECParameters(
          ASN1Sequence  seq)
      {
          if (!(seq.getObjectAt(0) instanceof ASN1Integer)
             || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE))
          {
              throw new IllegalArgumentException("bad version in X9ECParameters");
          }
  
          X9Curve     x9c = new X9Curve(
                          new X9FieldID((ASN1Sequence)seq.getObjectAt(1)),
                          (ASN1Sequence)seq.getObjectAt(2));
  
          this.curve = x9c.getCurve();
          this.g = new X9ECPoint(curve, (ASN1OctetString)seq.getObjectAt(3)).getPoint();
          this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue();
          this.seed = x9c.getSeed();
  
          if (seq.size() == 6)
          {
              this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue();
          }
      }
  
      public static X9ECParameters getInstance(Object obj)
      {
          if (obj instanceof X9ECParameters)
          {
              return (X9ECParameters)obj;
          }
  
          if (obj != null)
          {
              return new X9ECParameters(ASN1Sequence.getInstance(obj));
          }
  
          return null;
      }
  
      public X9ECParameters(
          ECCurve     curve,
          ECPoint     g,
          BigInteger  n)
      {
          this(curve, g, n, ONE, null);
      }
  
      public X9ECParameters(
          ECCurve     curve,
          ECPoint     g,
          BigInteger  n,
          BigInteger  h)
      {
          this(curve, g, n, h, null);
      }
  
      public X9ECParameters(
          ECCurve     curve,
          ECPoint     g,
          BigInteger  n,
          BigInteger  h,
          byte[]      seed)
      {
          this.curve = curve;
          this.g = g;
          this.n = n;
          this.h = h;
          this.seed = seed;
  
          if (curve instanceof ECCurve.Fp)
          {
              this.fieldID = new X9FieldID(((ECCurve.Fp)curve).getQ());
          }
          else
          {
              if (curve instanceof ECCurve.F2m)
              {
                  ECCurve.F2m curveF2m = (ECCurve.F2m)curve;
                  this.fieldID = new X9FieldID(curveF2m.getM(), curveF2m.getK1(),
                      curveF2m.getK2(), curveF2m.getK3());
              }
          }
      }
  
      public ECCurve getCurve()
      {
          return curve;
      }
  
      public ECPoint getG()
      {
          return g;
      }
  
      public BigInteger getN()
      {
          return n;
      }
  
      public BigInteger getH()
      {
          if (h == null)
          {
              return ONE;        // TODO - this should be calculated, it will cause issues with custom curves.
          }
  
          return h;
      }
  
      public byte[] getSeed()
      {
          return seed;
      }
  
      /**
       * Produce an object suitable for an ASN1OutputStream.
       * <pre>
       *  ECParameters ::= SEQUENCE {
       *      version         INTEGER { ecpVer1(1) } (ecpVer1),
       *      fieldID         FieldID {{FieldTypes}},
       *      curve           X9Curve,
       *      base            X9ECPoint,
       *      order           INTEGER,
       *      cofactor        INTEGER OPTIONAL
       *  }
       * </pre>
       */
      public ASN1Primitive toASN1Primitive()
      {
          ASN1EncodableVector v = new ASN1EncodableVector();
  
          v.add(new ASN1Integer(1));
          v.add(fieldID);
          v.add(new X9Curve(curve, seed));
          v.add(new X9ECPoint(g));
          v.add(new ASN1Integer(n));
  
          if (h != null)
          {
              v.add(new ASN1Integer(h));
          }
  
          return new DERSequence(v);
      }
  }
  