blob: 8f46c075a1df594a3cead2a0549960e03828f496 [file] [log] [blame]
package org.bouncycastle.asn1.x9;
import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERObject;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.math.ec.ECCurve;
/**
* ASN.1 def for Elliptic-Curve Curve structure. See
* X9.62, for further details.
*/
public class X9Curve
extends ASN1Encodable
implements X9ObjectIdentifiers
{
private ECCurve curve;
private byte[] seed;
private DERObjectIdentifier fieldIdentifier = null;
public X9Curve(
ECCurve curve)
{
this.curve = curve;
this.seed = null;
setFieldIdentifier();
}
public X9Curve(
ECCurve curve,
byte[] seed)
{
this.curve = curve;
this.seed = seed;
setFieldIdentifier();
}
public X9Curve(
X9FieldID fieldID,
ASN1Sequence seq)
{
fieldIdentifier = fieldID.getIdentifier();
if (fieldIdentifier.equals(prime_field))
{
BigInteger p = ((DERInteger)fieldID.getParameters()).getValue();
X9FieldElement x9A = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(0));
X9FieldElement x9B = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(1));
curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
}
else
{
if (fieldIdentifier.equals(characteristic_two_field))
{
// Characteristic two field
DERSequence parameters = (DERSequence)fieldID.getParameters();
int m = ((DERInteger)parameters.getObjectAt(0)).getValue().
intValue();
DERObjectIdentifier representation
= (DERObjectIdentifier)parameters.getObjectAt(1);
int k1 = 0;
int k2 = 0;
int k3 = 0;
if (representation.equals(tpBasis))
{
// Trinomial basis representation
k1 = ((DERInteger)parameters.getObjectAt(2)).getValue().
intValue();
}
else
{
// Pentanomial basis representation
DERSequence pentanomial
= (DERSequence)parameters.getObjectAt(2);
k1 = ((DERInteger)pentanomial.getObjectAt(0)).getValue().
intValue();
k2 = ((DERInteger)pentanomial.getObjectAt(1)).getValue().
intValue();
k3 = ((DERInteger)pentanomial.getObjectAt(2)).getValue().
intValue();
}
X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0));
X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1));
// TODO Is it possible to get the order (n) and cofactor(h) too?
curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
}
}
if (seq.size() == 3)
{
seed = ((DERBitString)seq.getObjectAt(2)).getBytes();
}
}
private void setFieldIdentifier()
{
if (curve instanceof ECCurve.Fp)
{
fieldIdentifier = prime_field;
}
else if (curve instanceof ECCurve.F2m)
{
fieldIdentifier = characteristic_two_field;
}
else
{
throw new IllegalArgumentException("This type of ECCurve is not "
+ "implemented");
}
}
public ECCurve getCurve()
{
return curve;
}
public byte[] getSeed()
{
return seed;
}
/**
* Produce an object suitable for an ASN1OutputStream.
* <pre>
* Curve ::= SEQUENCE {
* a FieldElement,
* b FieldElement,
* seed BIT STRING OPTIONAL
* }
* </pre>
*/
public DERObject toASN1Object()
{
ASN1EncodableVector v = new ASN1EncodableVector();
if (fieldIdentifier.equals(prime_field))
{
v.add(new X9FieldElement(curve.getA()).getDERObject());
v.add(new X9FieldElement(curve.getB()).getDERObject());
}
else if (fieldIdentifier.equals(characteristic_two_field))
{
v.add(new X9FieldElement(curve.getA()).getDERObject());
v.add(new X9FieldElement(curve.getB()).getDERObject());
}
if (seed != null)
{
v.add(new DERBitString(seed));
}
return new DERSequence(v);
}
}