package org.spongycastle.asn1.x9; import java.math.BigInteger; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.DERSequence; import org.spongycastle.math.ec.ECCurve; /** * ASN.1 def for Elliptic-Curve Curve structure. See * X9.62, for further details. */ public class X9Curve extends ASN1Object implements X9ObjectIdentifiers { private ECCurve curve; private byte[] seed; private ASN1ObjectIdentifier 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 = ((ASN1Integer)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 ASN1Sequence parameters = ASN1Sequence.getInstance(fieldID.getParameters()); int m = ((ASN1Integer)parameters.getObjectAt(0)).getValue(). intValue(); ASN1ObjectIdentifier representation = (ASN1ObjectIdentifier)parameters.getObjectAt(1); int k1 = 0; int k2 = 0; int k3 = 0; if (representation.equals(tpBasis)) { // Trinomial basis representation k1 = ((ASN1Integer)parameters.getObjectAt(2)).getValue(). intValue(); } else { // Pentanomial basis representation DERSequence pentanomial = (DERSequence)parameters.getObjectAt(2); k1 = ((ASN1Integer)pentanomial.getObjectAt(0)).getValue(). intValue(); k2 = ((ASN1Integer)pentanomial.getObjectAt(1)).getValue(). intValue(); k3 = ((ASN1Integer)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 ASN1Primitive toASN1Primitive() { ASN1EncodableVector v = new ASN1EncodableVector(); if (fieldIdentifier.equals(prime_field)) { v.add(new X9FieldElement(curve.getA()).toASN1Primitive()); v.add(new X9FieldElement(curve.getB()).toASN1Primitive()); } else if (fieldIdentifier.equals(characteristic_two_field)) { v.add(new X9FieldElement(curve.getA()).toASN1Primitive()); v.add(new X9FieldElement(curve.getB()).toASN1Primitive()); } if (seed != null) { v.add(new DERBitString(seed)); } return new DERSequence(v); } }