X9Curve.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.asn1.x9;
2
3import java.math.BigInteger;
4
5import org.bouncycastle.asn1.ASN1EncodableVector;
6import org.bouncycastle.asn1.ASN1Integer;
7import org.bouncycastle.asn1.ASN1Object;
8import org.bouncycastle.asn1.ASN1ObjectIdentifier;
9import org.bouncycastle.asn1.ASN1OctetString;
10import org.bouncycastle.asn1.ASN1Primitive;
11import org.bouncycastle.asn1.ASN1Sequence;
12import org.bouncycastle.asn1.DERBitString;
13import org.bouncycastle.asn1.DERSequence;
14import org.bouncycastle.math.ec.ECCurve;
15
16/**
17 * ASN.1 def for Elliptic-Curve Curve structure. See
18 * X9.62, for further details.
19 */
20public class X9Curve
21    extends ASN1Object
22    implements X9ObjectIdentifiers
23{
24    private ECCurve     curve;
25    private byte[]      seed;
26    private ASN1ObjectIdentifier fieldIdentifier = null;
27
28    public X9Curve(
29        ECCurve     curve)
30    {
31        this.curve = curve;
32        this.seed = null;
33        setFieldIdentifier();
34    }
35
36    public X9Curve(
37        ECCurve     curve,
38        byte[]      seed)
39    {
40        this.curve = curve;
41        this.seed = seed;
42        setFieldIdentifier();
43    }
44
45    public X9Curve(
46        X9FieldID     fieldID,
47        ASN1Sequence  seq)
48    {
49        fieldIdentifier = fieldID.getIdentifier();
50        if (fieldIdentifier.equals(prime_field))
51        {
52            BigInteger      p = ((ASN1Integer)fieldID.getParameters()).getValue();
53            X9FieldElement  x9A = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(0));
54            X9FieldElement  x9B = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(1));
55            curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
56        }
57        else
58        {
59            if (fieldIdentifier.equals(characteristic_two_field))
60            {
61                // Characteristic two field
62                ASN1Sequence parameters = ASN1Sequence.getInstance(fieldID.getParameters());
63                int m = ((ASN1Integer)parameters.getObjectAt(0)).getValue().
64                    intValue();
65                ASN1ObjectIdentifier representation
66                    = (ASN1ObjectIdentifier)parameters.getObjectAt(1);
67
68                int k1 = 0;
69                int k2 = 0;
70                int k3 = 0;
71                if (representation.equals(tpBasis))
72                {
73                    // Trinomial basis representation
74                    k1 = ((ASN1Integer)parameters.getObjectAt(2)).getValue().
75                        intValue();
76                }
77                else
78                {
79                    // Pentanomial basis representation
80                    DERSequence pentanomial
81                        = (DERSequence)parameters.getObjectAt(2);
82                    k1 = ((ASN1Integer)pentanomial.getObjectAt(0)).getValue().
83                        intValue();
84                    k2 = ((ASN1Integer)pentanomial.getObjectAt(1)).getValue().
85                        intValue();
86                    k3 = ((ASN1Integer)pentanomial.getObjectAt(2)).getValue().
87                        intValue();
88                }
89                X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0));
90                X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1));
91                // TODO Is it possible to get the order (n) and cofactor(h) too?
92                curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
93            }
94        }
95
96        if (seq.size() == 3)
97        {
98            seed = ((DERBitString)seq.getObjectAt(2)).getBytes();
99        }
100    }
101
102    private void setFieldIdentifier()
103    {
104        if (curve instanceof ECCurve.Fp)
105        {
106            fieldIdentifier = prime_field;
107        }
108        else if (curve instanceof ECCurve.F2m)
109        {
110            fieldIdentifier = characteristic_two_field;
111        }
112        else
113        {
114            throw new IllegalArgumentException("This type of ECCurve is not "
115                    + "implemented");
116        }
117    }
118
119    public ECCurve  getCurve()
120    {
121        return curve;
122    }
123
124    public byte[]   getSeed()
125    {
126        return seed;
127    }
128
129    /**
130     * Produce an object suitable for an ASN1OutputStream.
131     * <pre>
132     *  Curve ::= SEQUENCE {
133     *      a               FieldElement,
134     *      b               FieldElement,
135     *      seed            BIT STRING      OPTIONAL
136     *  }
137     * </pre>
138     */
139    public ASN1Primitive toASN1Primitive()
140    {
141        ASN1EncodableVector v = new ASN1EncodableVector();
142
143        if (fieldIdentifier.equals(prime_field))
144        {
145            v.add(new X9FieldElement(curve.getA()).toASN1Primitive());
146            v.add(new X9FieldElement(curve.getB()).toASN1Primitive());
147        }
148        else if (fieldIdentifier.equals(characteristic_two_field))
149        {
150            v.add(new X9FieldElement(curve.getA()).toASN1Primitive());
151            v.add(new X9FieldElement(curve.getB()).toASN1Primitive());
152        }
153
154        if (seed != null)
155        {
156            v.add(new DERBitString(seed));
157        }
158
159        return new DERSequence(v);
160    }
161}
162