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 new X9FieldID((ASN1Sequence)seq.getObjectAt(1)), 43 (ASN1Sequence)seq.getObjectAt(2)); 44 45 this.curve = x9c.getCurve(); 46 this.g = new X9ECPoint(curve, (ASN1OctetString)seq.getObjectAt(3)).getPoint(); 47 this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue(); 48 this.seed = x9c.getSeed(); 49 50 if (seq.size() == 6) 51 { 52 this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue(); 53 } 54 } 55 56 public static X9ECParameters getInstance(Object obj) 57 { 58 if (obj instanceof X9ECParameters) 59 { 60 return (X9ECParameters)obj; 61 } 62 63 if (obj != null) 64 { 65 return new X9ECParameters(ASN1Sequence.getInstance(obj)); 66 } 67 68 return null; 69 } 70 71 public X9ECParameters( 72 ECCurve curve, 73 ECPoint g, 74 BigInteger n) 75 { 76 this(curve, g, n, ONE, null); 77 } 78 79 public X9ECParameters( 80 ECCurve curve, 81 ECPoint g, 82 BigInteger n, 83 BigInteger h) 84 { 85 this(curve, g, n, h, null); 86 } 87 88 public X9ECParameters( 89 ECCurve curve, 90 ECPoint g, 91 BigInteger n, 92 BigInteger h, 93 byte[] seed) 94 { 95 this.curve = curve; 96 this.g = g; 97 this.n = n; 98 this.h = h; 99 this.seed = seed; 100 101 if (curve instanceof ECCurve.Fp) 102 { 103 this.fieldID = new X9FieldID(((ECCurve.Fp)curve).getQ()); 104 } 105 else 106 { 107 if (curve instanceof ECCurve.F2m) 108 { 109 ECCurve.F2m curveF2m = (ECCurve.F2m)curve; 110 this.fieldID = new X9FieldID(curveF2m.getM(), curveF2m.getK1(), 111 curveF2m.getK2(), curveF2m.getK3()); 112 } 113 } 114 } 115 116 public ECCurve getCurve() 117 { 118 return curve; 119 } 120 121 public ECPoint getG() 122 { 123 return g; 124 } 125 126 public BigInteger getN() 127 { 128 return n; 129 } 130 131 public BigInteger getH() 132 { 133 if (h == null) 134 { 135 return ONE; // TODO - this should be calculated, it will cause issues with custom curves. 136 } 137 138 return h; 139 } 140 141 public byte[] getSeed() 142 { 143 return seed; 144 } 145 146 /** 147 * Produce an object suitable for an ASN1OutputStream. 148 * <pre> 149 * ECParameters ::= SEQUENCE { 150 * version INTEGER { ecpVer1(1) } (ecpVer1), 151 * fieldID FieldID {{FieldTypes}}, 152 * curve X9Curve, 153 * base X9ECPoint, 154 * order INTEGER, 155 * cofactor INTEGER OPTIONAL 156 * } 157 * </pre> 158 */ 159 public ASN1Primitive toASN1Primitive() 160 { 161 ASN1EncodableVector v = new ASN1EncodableVector(); 162 163 v.add(new ASN1Integer(1)); 164 v.add(fieldID); 165 v.add(new X9Curve(curve, seed)); 166 v.add(new X9ECPoint(g)); 167 v.add(new ASN1Integer(n)); 168 169 if (h != null) 170 { 171 v.add(new ASN1Integer(h)); 172 } 173 174 return new DERSequence(v); 175 } 176 } 177