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.ECCurve; 13 import org.bouncycastle.math.ec.ECPoint; 14 15 /** 16 * ASN.1 def for Elliptic-Curve ECParameters structure. See 17 * X9.62, for further details. 18 */ 19 public class X9ECParameters 20 extends ASN1Object 21 implements X9ObjectIdentifiers 22 { 23 private static final BigInteger ONE = BigInteger.valueOf(1); 24 25 private X9FieldID fieldID; 26 private ECCurve curve; 27 private ECPoint g; 28 private BigInteger n; 29 private BigInteger h; 30 private byte[] seed; 31 32 private X9ECParameters( 33 ASN1Sequence seq) 34 { 35 if (!(seq.getObjectAt(0) instanceof ASN1Integer) 36 || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE)) 37 { 38 throw new IllegalArgumentException("bad version in X9ECParameters"); 39 } 40 41 X9Curve x9c = new X9Curve( 42 X9FieldID.getInstance(seq.getObjectAt(1)), 43 ASN1Sequence.getInstance(seq.getObjectAt(2))); 44 45 this.curve = x9c.getCurve(); 46 Object p = seq.getObjectAt(3); 47 48 if (p instanceof X9ECPoint) 49 { 50 this.g = ((X9ECPoint)p).getPoint(); 51 } 52 else 53 { 54 this.g = new X9ECPoint(curve, (ASN1OctetString)p).getPoint(); 55 } 56 57 this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue(); 58 this.seed = x9c.getSeed(); 59 60 if (seq.size() == 6) 61 { 62 this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue(); 63 } 64 } 65 66 public static X9ECParameters getInstance(Object obj) 67 { 68 if (obj instanceof X9ECParameters) 69 { 70 return (X9ECParameters)obj; 71 } 72 73 if (obj != null) 74 { 75 return new X9ECParameters(ASN1Sequence.getInstance(obj)); 76 } 77 78 return null; 79 } 80 81 public X9ECParameters( 82 ECCurve curve, 83 ECPoint g, 84 BigInteger n) 85 { 86 this(curve, g, n, ONE, null); 87 } 88 89 public X9ECParameters( 90 ECCurve curve, 91 ECPoint g, 92 BigInteger n, 93 BigInteger h) 94 { 95 this(curve, g, n, h, null); 96 } 97 98 public X9ECParameters( 99 ECCurve curve, 100 ECPoint g, 101 BigInteger n, 102 BigInteger h, 103 byte[] seed) 104 { 105 this.curve = curve; 106 this.g = g.normalize(); 107 this.n = n; 108 this.h = h; 109 this.seed = seed; 110 111 if (curve instanceof ECCurve.Fp) 112 { 113 this.fieldID = new X9FieldID(((ECCurve.Fp)curve).getQ()); 114 } 115 else 116 { 117 if (curve instanceof ECCurve.F2m) 118 { 119 ECCurve.F2m curveF2m = (ECCurve.F2m)curve; 120 this.fieldID = new X9FieldID(curveF2m.getM(), curveF2m.getK1(), 121 curveF2m.getK2(), curveF2m.getK3()); 122 } 123 } 124 } 125 126 public ECCurve getCurve() 127 { 128 return curve; 129 } 130 131 public ECPoint getG() 132 { 133 return g; 134 } 135 136 public BigInteger getN() 137 { 138 return n; 139 } 140 141 public BigInteger getH() 142 { 143 if (h == null) 144 { 145 return ONE; // TODO - this should be calculated, it will cause issues with custom curves. 146 } 147 148 return h; 149 } 150 151 public byte[] getSeed() 152 { 153 return seed; 154 } 155 156 /** 157 * Produce an object suitable for an ASN1OutputStream. 158 * <pre> 159 * ECParameters ::= SEQUENCE { 160 * version INTEGER { ecpVer1(1) } (ecpVer1), 161 * fieldID FieldID {{FieldTypes}}, 162 * curve X9Curve, 163 * base X9ECPoint, 164 * order INTEGER, 165 * cofactor INTEGER OPTIONAL 166 * } 167 * </pre> 168 */ 169 public ASN1Primitive toASN1Primitive() 170 { 171 ASN1EncodableVector v = new ASN1EncodableVector(); 172 173 v.add(new ASN1Integer(1)); 174 v.add(fieldID); 175 v.add(new X9Curve(curve, seed)); 176 v.add(new X9ECPoint(g)); 177 v.add(new ASN1Integer(n)); 178 179 if (h != null) 180 { 181 v.add(new ASN1Integer(h)); 182 } 183 184 return new DERSequence(v); 185 } 186 } 187