1 package org.bouncycastle.asn1.x9; 2 3 import java.math.BigInteger; 4 5 import org.bouncycastle.asn1.ASN1EncodableVector; 6 import org.bouncycastle.asn1.ASN1Integer; 7 import org.bouncycastle.asn1.ASN1Object; 8 import org.bouncycastle.asn1.ASN1OctetString; 9 import org.bouncycastle.asn1.ASN1Primitive; 10 import org.bouncycastle.asn1.ASN1Sequence; 11 import org.bouncycastle.asn1.DERSequence; 12 import org.bouncycastle.math.ec.ECAlgorithms; 13 import org.bouncycastle.math.ec.ECCurve; 14 import org.bouncycastle.math.ec.ECPoint; 15 import org.bouncycastle.math.field.PolynomialExtensionField; 16 17 /** 18 * ASN.1 def for Elliptic-Curve ECParameters structure. See 19 * X9.62, for further details. 20 */ 21 public class X9ECParameters 22 extends ASN1Object 23 implements X9ObjectIdentifiers 24 { 25 private static final BigInteger ONE = BigInteger.valueOf(1); 26 27 private X9FieldID fieldID; 28 private ECCurve curve; 29 private X9ECPoint g; 30 private BigInteger n; 31 private BigInteger h; 32 private byte[] seed; 33 X9ECParameters( ASN1Sequence seq)34 private X9ECParameters( 35 ASN1Sequence seq) 36 { 37 if (!(seq.getObjectAt(0) instanceof ASN1Integer) 38 || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE)) 39 { 40 throw new IllegalArgumentException("bad version in X9ECParameters"); 41 } 42 43 X9Curve x9c = new X9Curve( 44 X9FieldID.getInstance(seq.getObjectAt(1)), 45 ASN1Sequence.getInstance(seq.getObjectAt(2))); 46 47 this.curve = x9c.getCurve(); 48 Object p = seq.getObjectAt(3); 49 50 if (p instanceof X9ECPoint) 51 { 52 this.g = ((X9ECPoint)p); 53 } 54 else 55 { 56 this.g = new X9ECPoint(curve, (ASN1OctetString)p); 57 } 58 59 this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue(); 60 this.seed = x9c.getSeed(); 61 62 if (seq.size() == 6) 63 { 64 this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue(); 65 } 66 } 67 getInstance(Object obj)68 public static X9ECParameters getInstance(Object obj) 69 { 70 if (obj instanceof X9ECParameters) 71 { 72 return (X9ECParameters)obj; 73 } 74 75 if (obj != null) 76 { 77 return new X9ECParameters(ASN1Sequence.getInstance(obj)); 78 } 79 80 return null; 81 } 82 X9ECParameters( ECCurve curve, ECPoint g, BigInteger n)83 public X9ECParameters( 84 ECCurve curve, 85 ECPoint g, 86 BigInteger n) 87 { 88 this(curve, g, n, null, null); 89 } 90 X9ECParameters( ECCurve curve, X9ECPoint g, BigInteger n, BigInteger h)91 public X9ECParameters( 92 ECCurve curve, 93 X9ECPoint g, 94 BigInteger n, 95 BigInteger h) 96 { 97 this(curve, g, n, h, null); 98 } 99 X9ECParameters( ECCurve curve, ECPoint g, BigInteger n, BigInteger h)100 public X9ECParameters( 101 ECCurve curve, 102 ECPoint g, 103 BigInteger n, 104 BigInteger h) 105 { 106 this(curve, g, n, h, null); 107 } 108 X9ECParameters( ECCurve curve, ECPoint g, BigInteger n, BigInteger h, byte[] seed)109 public X9ECParameters( 110 ECCurve curve, 111 ECPoint g, 112 BigInteger n, 113 BigInteger h, 114 byte[] seed) 115 { 116 this(curve, new X9ECPoint(g), n, h, seed); 117 } 118 X9ECParameters( ECCurve curve, X9ECPoint g, BigInteger n, BigInteger h, byte[] seed)119 public X9ECParameters( 120 ECCurve curve, 121 X9ECPoint g, 122 BigInteger n, 123 BigInteger h, 124 byte[] seed) 125 { 126 this.curve = curve; 127 this.g = g; 128 this.n = n; 129 this.h = h; 130 this.seed = seed; 131 132 if (ECAlgorithms.isFpCurve(curve)) 133 { 134 this.fieldID = new X9FieldID(curve.getField().getCharacteristic()); 135 } 136 else if (ECAlgorithms.isF2mCurve(curve)) 137 { 138 PolynomialExtensionField field = (PolynomialExtensionField)curve.getField(); 139 int[] exponents = field.getMinimalPolynomial().getExponentsPresent(); 140 if (exponents.length == 3) 141 { 142 this.fieldID = new X9FieldID(exponents[2], exponents[1]); 143 } 144 else if (exponents.length == 5) 145 { 146 this.fieldID = new X9FieldID(exponents[4], exponents[1], exponents[2], exponents[3]); 147 } 148 else 149 { 150 throw new IllegalArgumentException("Only trinomial and pentomial curves are supported"); 151 } 152 } 153 else 154 { 155 throw new IllegalArgumentException("'curve' is of an unsupported type"); 156 } 157 } 158 getCurve()159 public ECCurve getCurve() 160 { 161 return curve; 162 } 163 getG()164 public ECPoint getG() 165 { 166 return g.getPoint(); 167 } 168 getN()169 public BigInteger getN() 170 { 171 return n; 172 } 173 getH()174 public BigInteger getH() 175 { 176 return h; 177 } 178 getSeed()179 public byte[] getSeed() 180 { 181 return seed; 182 } 183 184 /** 185 * Return the ASN.1 entry representing the Curve. 186 * 187 * @return the X9Curve for the curve in these parameters. 188 */ getCurveEntry()189 public X9Curve getCurveEntry() 190 { 191 return new X9Curve(curve, seed); 192 } 193 194 /** 195 * Return the ASN.1 entry representing the FieldID. 196 * 197 * @return the X9FieldID for the FieldID in these parameters. 198 */ getFieldIDEntry()199 public X9FieldID getFieldIDEntry() 200 { 201 return fieldID; 202 } 203 204 /** 205 * Return the ASN.1 entry representing the base point G. 206 * 207 * @return the X9ECPoint for the base point in these parameters. 208 */ getBaseEntry()209 public X9ECPoint getBaseEntry() 210 { 211 return g; 212 } 213 214 /** 215 * Produce an object suitable for an ASN1OutputStream. 216 * <pre> 217 * ECParameters ::= SEQUENCE { 218 * version INTEGER { ecpVer1(1) } (ecpVer1), 219 * fieldID FieldID {{FieldTypes}}, 220 * curve X9Curve, 221 * base X9ECPoint, 222 * order INTEGER, 223 * cofactor INTEGER OPTIONAL 224 * } 225 * </pre> 226 */ toASN1Primitive()227 public ASN1Primitive toASN1Primitive() 228 { 229 ASN1EncodableVector v = new ASN1EncodableVector(); 230 231 v.add(new ASN1Integer(ONE)); 232 v.add(fieldID); 233 v.add(new X9Curve(curve, seed)); 234 v.add(g); 235 v.add(new ASN1Integer(n)); 236 237 if (h != null) 238 { 239 v.add(new ASN1Integer(h)); 240 } 241 242 return new DERSequence(v); 243 } 244 } 245