001package org.apache.commons.ssl.org.bouncycastle.asn1.x9;
002
003import java.math.BigInteger;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1ObjectIdentifier;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
011import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
012
013/**
014 * ASN.1 def for Elliptic-Curve Field ID structure. See
015 * X9.62, for further details.
016 */
017public class X9FieldID
018    extends ASN1Object
019    implements X9ObjectIdentifiers
020{
021    private ASN1ObjectIdentifier     id;
022    private ASN1Primitive parameters;
023
024    /**
025     * Constructor for elliptic curves over prime fields
026     * <code>F<sub>2</sub></code>.
027     * @param primeP The prime <code>p</code> defining the prime field.
028     */
029    public X9FieldID(BigInteger primeP)
030    {
031        this.id = prime_field;
032        this.parameters = new ASN1Integer(primeP);
033    }
034
035    /**
036     * Constructor for elliptic curves over binary fields
037     * <code>F<sub>2<sup>m</sup></sub></code>.
038     * @param m  The exponent <code>m</code> of
039     * <code>F<sub>2<sup>m</sup></sub></code>.
040     * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
041     * x<sup>k1</sup> + 1</code>
042     * represents the reduction polynomial <code>f(z)</code>.
043     */
044    public X9FieldID(int m, int k1)
045    {
046        this(m, k1, 0, 0);
047    }
048
049    /**
050     * Constructor for elliptic curves over binary fields
051     * <code>F<sub>2<sup>m</sup></sub></code>.
052     * @param m  The exponent <code>m</code> of
053     * <code>F<sub>2<sup>m</sup></sub></code>.
054     * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
055     * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
056     * represents the reduction polynomial <code>f(z)</code>.
057     * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
058     * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
059     * represents the reduction polynomial <code>f(z)</code>.
060     * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
061     * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
062     * represents the reduction polynomial <code>f(z)</code>..
063     */
064    public X9FieldID(int m, int k1, int k2, int k3)
065    {
066        this.id = characteristic_two_field;
067        ASN1EncodableVector fieldIdParams = new ASN1EncodableVector();
068        fieldIdParams.add(new ASN1Integer(m));
069        
070        if (k2 == 0) 
071        {
072            if (k3 != 0)
073            {
074                throw new IllegalArgumentException("inconsistent k values");
075            }
076
077            fieldIdParams.add(tpBasis);
078            fieldIdParams.add(new ASN1Integer(k1));
079        } 
080        else 
081        {
082            if (k2 <= k1 || k3 <= k2)
083            {
084                throw new IllegalArgumentException("inconsistent k values");
085            }
086
087            fieldIdParams.add(ppBasis);
088            ASN1EncodableVector pentanomialParams = new ASN1EncodableVector();
089            pentanomialParams.add(new ASN1Integer(k1));
090            pentanomialParams.add(new ASN1Integer(k2));
091            pentanomialParams.add(new ASN1Integer(k3));
092            fieldIdParams.add(new DERSequence(pentanomialParams));
093        }
094        
095        this.parameters = new DERSequence(fieldIdParams);
096    }
097
098    private X9FieldID(
099        ASN1Sequence  seq)
100    {
101        this.id = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
102        this.parameters = seq.getObjectAt(1).toASN1Primitive();
103    }
104
105    public static X9FieldID getInstance(Object obj)
106    {
107        if (obj instanceof X9FieldID)
108        {
109            return (X9FieldID)obj;
110        }
111
112        if (obj != null)
113        {
114            return new X9FieldID(ASN1Sequence.getInstance(obj));
115        }
116
117        return null;
118    }
119
120    public ASN1ObjectIdentifier getIdentifier()
121    {
122        return id;
123    }
124
125    public ASN1Primitive getParameters()
126    {
127        return parameters;
128    }
129
130    /**
131     * Produce a DER encoding of the following structure.
132     * <pre>
133     *  FieldID ::= SEQUENCE {
134     *      fieldType       FIELD-ID.&amp;id({IOSet}),
135     *      parameters      FIELD-ID.&amp;Type({IOSet}{&#64;fieldType})
136     *  }
137     * </pre>
138     */
139    public ASN1Primitive toASN1Primitive()
140    {
141        ASN1EncodableVector v = new ASN1EncodableVector();
142
143        v.add(this.id);
144        v.add(this.parameters);
145
146        return new DERSequence(v);
147    }
148}