Home | History | Annotate | Download | only in x9
      1 package org.bouncycastle.asn1.x9;
      2 
      3 import java.math.BigInteger;
      4 
      5 import org.bouncycastle.asn1.ASN1EncodableVector;
      6 import org.bouncycastle.asn1.ASN1Integer;
      7 import org.bouncycastle.asn1.ASN1Object;
      8 import org.bouncycastle.asn1.ASN1OctetString;
      9 import org.bouncycastle.asn1.ASN1Primitive;
     10 import org.bouncycastle.asn1.ASN1Sequence;
     11 import org.bouncycastle.asn1.DERSequence;
     12 import org.bouncycastle.math.ec.ECCurve;
     13 import org.bouncycastle.math.ec.ECPoint;
     14 
     15 /**
     16  * ASN.1 def for Elliptic-Curve ECParameters structure. See
     17  * X9.62, for further details.
     18  */
     19 public class X9ECParameters
     20     extends ASN1Object
     21     implements X9ObjectIdentifiers
     22 {
     23     private static final BigInteger   ONE = BigInteger.valueOf(1);
     24 
     25     private X9FieldID           fieldID;
     26     private ECCurve             curve;
     27     private ECPoint             g;
     28     private BigInteger          n;
     29     private BigInteger          h;
     30     private byte[]              seed;
     31 
     32     private X9ECParameters(
     33         ASN1Sequence  seq)
     34     {
     35         if (!(seq.getObjectAt(0) instanceof ASN1Integer)
     36            || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE))
     37         {
     38             throw new IllegalArgumentException("bad version in X9ECParameters");
     39         }
     40 
     41         X9Curve     x9c = new X9Curve(
     42                         X9FieldID.getInstance(seq.getObjectAt(1)),
     43                         ASN1Sequence.getInstance(seq.getObjectAt(2)));
     44 
     45         this.curve = x9c.getCurve();
     46         Object p = seq.getObjectAt(3);
     47 
     48         if (p instanceof X9ECPoint)
     49         {
     50             this.g = ((X9ECPoint)p).getPoint();
     51         }
     52         else
     53         {
     54             this.g = new X9ECPoint(curve, (ASN1OctetString)p).getPoint();
     55         }
     56 
     57         this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue();
     58         this.seed = x9c.getSeed();
     59 
     60         if (seq.size() == 6)
     61         {
     62             this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue();
     63         }
     64     }
     65 
     66     public static X9ECParameters getInstance(Object obj)
     67     {
     68         if (obj instanceof X9ECParameters)
     69         {
     70             return (X9ECParameters)obj;
     71         }
     72 
     73         if (obj != null)
     74         {
     75             return new X9ECParameters(ASN1Sequence.getInstance(obj));
     76         }
     77 
     78         return null;
     79     }
     80 
     81     public X9ECParameters(
     82         ECCurve     curve,
     83         ECPoint     g,
     84         BigInteger  n)
     85     {
     86         this(curve, g, n, ONE, null);
     87     }
     88 
     89     public X9ECParameters(
     90         ECCurve     curve,
     91         ECPoint     g,
     92         BigInteger  n,
     93         BigInteger  h)
     94     {
     95         this(curve, g, n, h, null);
     96     }
     97 
     98     public X9ECParameters(
     99         ECCurve     curve,
    100         ECPoint     g,
    101         BigInteger  n,
    102         BigInteger  h,
    103         byte[]      seed)
    104     {
    105         this.curve = curve;
    106         this.g = g.normalize();
    107         this.n = n;
    108         this.h = h;
    109         this.seed = seed;
    110 
    111         if (curve instanceof ECCurve.Fp)
    112         {
    113             this.fieldID = new X9FieldID(((ECCurve.Fp)curve).getQ());
    114         }
    115         else
    116         {
    117             if (curve instanceof ECCurve.F2m)
    118             {
    119                 ECCurve.F2m curveF2m = (ECCurve.F2m)curve;
    120                 this.fieldID = new X9FieldID(curveF2m.getM(), curveF2m.getK1(),
    121                     curveF2m.getK2(), curveF2m.getK3());
    122             }
    123         }
    124     }
    125 
    126     public ECCurve getCurve()
    127     {
    128         return curve;
    129     }
    130 
    131     public ECPoint getG()
    132     {
    133         return g;
    134     }
    135 
    136     public BigInteger getN()
    137     {
    138         return n;
    139     }
    140 
    141     public BigInteger getH()
    142     {
    143         if (h == null)
    144         {
    145             return ONE;        // TODO - this should be calculated, it will cause issues with custom curves.
    146         }
    147 
    148         return h;
    149     }
    150 
    151     public byte[] getSeed()
    152     {
    153         return seed;
    154     }
    155 
    156     /**
    157      * Produce an object suitable for an ASN1OutputStream.
    158      * <pre>
    159      *  ECParameters ::= SEQUENCE {
    160      *      version         INTEGER { ecpVer1(1) } (ecpVer1),
    161      *      fieldID         FieldID {{FieldTypes}},
    162      *      curve           X9Curve,
    163      *      base            X9ECPoint,
    164      *      order           INTEGER,
    165      *      cofactor        INTEGER OPTIONAL
    166      *  }
    167      * </pre>
    168      */
    169     public ASN1Primitive toASN1Primitive()
    170     {
    171         ASN1EncodableVector v = new ASN1EncodableVector();
    172 
    173         v.add(new ASN1Integer(1));
    174         v.add(fieldID);
    175         v.add(new X9Curve(curve, seed));
    176         v.add(new X9ECPoint(g));
    177         v.add(new ASN1Integer(n));
    178 
    179         if (h != null)
    180         {
    181             v.add(new ASN1Integer(h));
    182         }
    183 
    184         return new DERSequence(v);
    185     }
    186 }
    187