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 if (fieldIdentifier.equals(characteristic_two_field)) 58 { 59 // Characteristic two field 60 ASN1Sequence parameters = ASN1Sequence.getInstance(fieldID.getParameters()); 61 int m = ((ASN1Integer)parameters.getObjectAt(0)).getValue(). 62 intValue(); 63 ASN1ObjectIdentifier representation 64 = (ASN1ObjectIdentifier)parameters.getObjectAt(1); 65 66 int k1 = 0; 67 int k2 = 0; 68 int k3 = 0; 69 70 if (representation.equals(tpBasis)) 71 { 72 // Trinomial basis representation 73 k1 = ASN1Integer.getInstance(parameters.getObjectAt(2)).getValue().intValue(); 74 } 75 else if (representation.equals(ppBasis)) 76 { 77 // Pentanomial basis representation 78 ASN1Sequence pentanomial = ASN1Sequence.getInstance(parameters.getObjectAt(2)); 79 k1 = ASN1Integer.getInstance(pentanomial.getObjectAt(0)).getValue().intValue(); 80 k2 = ASN1Integer.getInstance(pentanomial.getObjectAt(1)).getValue().intValue(); 81 k3 = ASN1Integer.getInstance(pentanomial.getObjectAt(2)).getValue().intValue(); 82 } 83 else 84 { 85 throw new IllegalArgumentException("This type of EC basis is not implemented"); 86 } 87 X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0)); 88 X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1)); 89 // TODO Is it possible to get the order (n) and cofactor(h) too? 90 curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger()); 91 } 92 else 93 { 94 throw new IllegalArgumentException("This type of ECCurve is not implemented"); 95 } 96 97 if (seq.size() == 3) 98 { 99 seed = ((DERBitString)seq.getObjectAt(2)).getBytes(); 100 } 101 } 102 103 private void setFieldIdentifier() 104 { 105 if (curve instanceof ECCurve.Fp) 106 { 107 fieldIdentifier = prime_field; 108 } 109 else if (curve instanceof ECCurve.F2m) 110 { 111 fieldIdentifier = characteristic_two_field; 112 } 113 else 114 { 115 throw new IllegalArgumentException("This type of ECCurve is not 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